jettypod 4.4.104 → 4.4.105
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.jettypod-backup/work.db +0 -0
- package/jettypod.js +10 -0
- package/lib/git-hooks/index.js +113 -2
- package/package.json +1 -3
package/.jettypod-backup/work.db
CHANGED
|
Binary file
|
package/jettypod.js
CHANGED
|
@@ -1207,6 +1207,16 @@ const [,, command, ...args] = process.argv;
|
|
|
1207
1207
|
// Run startup validation for commands that use the database
|
|
1208
1208
|
// Skip for commands that don't need it (init, help, version)
|
|
1209
1209
|
const commandsWithoutDb = ['init', 'help', undefined, '--help', '-h', '--version', '-v'];
|
|
1210
|
+
// Ensure git hooks are up-to-date (silent auto-update)
|
|
1211
|
+
if (fs.existsSync('.git')) {
|
|
1212
|
+
try {
|
|
1213
|
+
const { ensureHooksUpdated } = require('./lib/git-hooks');
|
|
1214
|
+
ensureHooksUpdated();
|
|
1215
|
+
} catch (err) {
|
|
1216
|
+
// Don't fail CLI if hook check fails
|
|
1217
|
+
}
|
|
1218
|
+
}
|
|
1219
|
+
|
|
1210
1220
|
if (!commandsWithoutDb.includes(command) && fs.existsSync('.jettypod')) {
|
|
1211
1221
|
try {
|
|
1212
1222
|
const { validateOnStartup } = require('./lib/database');
|
package/lib/git-hooks/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
2
|
const path = require('path');
|
|
3
|
+
const crypto = require('crypto');
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Install JettyPod git hooks into .git/hooks directory
|
|
@@ -88,8 +89,118 @@ function areHooksInstalled() {
|
|
|
88
89
|
}
|
|
89
90
|
}
|
|
90
91
|
|
|
92
|
+
/**
|
|
93
|
+
* Compute MD5 hash of content
|
|
94
|
+
* @param {string} content - Content to hash
|
|
95
|
+
* @returns {string} MD5 hash hex string
|
|
96
|
+
*/
|
|
97
|
+
function hashContent(content) {
|
|
98
|
+
return crypto.createHash('md5').update(content).digest('hex');
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Check if hooks need updating and reinstall if outdated
|
|
103
|
+
* Uses content hashing - any change to hook source triggers update
|
|
104
|
+
* Called on every CLI invocation to ensure hooks stay current
|
|
105
|
+
* @returns {boolean} True if hooks were updated, false if already current
|
|
106
|
+
*/
|
|
107
|
+
function ensureHooksUpdated() {
|
|
108
|
+
const gitHooksDir = path.join(process.cwd(), '.git', 'hooks');
|
|
109
|
+
const jettypodHooksDir = path.join(__dirname);
|
|
110
|
+
|
|
111
|
+
if (!fs.existsSync(gitHooksDir)) {
|
|
112
|
+
return false; // Not a git repo
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const hooks = ['pre-commit', 'post-commit', 'post-merge'];
|
|
116
|
+
let needsUpdate = false;
|
|
117
|
+
|
|
118
|
+
for (const hook of hooks) {
|
|
119
|
+
const sourcePath = path.join(jettypodHooksDir, hook);
|
|
120
|
+
const installedPath = path.join(gitHooksDir, hook);
|
|
121
|
+
|
|
122
|
+
if (!fs.existsSync(sourcePath)) {
|
|
123
|
+
continue; // Source hook doesn't exist
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const sourceContent = fs.readFileSync(sourcePath, 'utf-8');
|
|
127
|
+
|
|
128
|
+
// Check installed hook
|
|
129
|
+
if (!fs.existsSync(installedPath)) {
|
|
130
|
+
needsUpdate = true;
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const installedContent = fs.readFileSync(installedPath, 'utf-8');
|
|
135
|
+
|
|
136
|
+
// Compare hashes - any difference triggers update
|
|
137
|
+
if (hashContent(sourceContent) !== hashContent(installedContent)) {
|
|
138
|
+
needsUpdate = true;
|
|
139
|
+
break;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (needsUpdate) {
|
|
144
|
+
// Silently reinstall - don't spam the user
|
|
145
|
+
try {
|
|
146
|
+
installHooksSilent();
|
|
147
|
+
return true;
|
|
148
|
+
} catch (err) {
|
|
149
|
+
// Don't fail the CLI command if hook update fails
|
|
150
|
+
return false;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return false;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Install hooks without console output (for auto-updates)
|
|
159
|
+
*/
|
|
160
|
+
function installHooksSilent() {
|
|
161
|
+
const gitHooksDir = path.join(process.cwd(), '.git', 'hooks');
|
|
162
|
+
const jettypodHooksDir = path.join(__dirname);
|
|
163
|
+
|
|
164
|
+
if (!fs.existsSync(gitHooksDir)) {
|
|
165
|
+
return false;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const hooks = ['pre-commit', 'post-commit', 'post-merge'];
|
|
169
|
+
|
|
170
|
+
hooks.forEach(hook => {
|
|
171
|
+
let sourcePath = path.join(jettypodHooksDir, hook);
|
|
172
|
+
if (!fs.existsSync(sourcePath)) {
|
|
173
|
+
sourcePath = path.join(process.cwd(), '.jettypod', 'hooks', hook);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (!fs.existsSync(sourcePath)) {
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const targetPath = path.join(gitHooksDir, hook);
|
|
181
|
+
|
|
182
|
+
let hookContent = fs.readFileSync(sourcePath, 'utf-8');
|
|
183
|
+
const jettypodRoot = path.resolve(__dirname, '..', '..');
|
|
184
|
+
const modulesPath = path.join(jettypodRoot, 'node_modules');
|
|
185
|
+
|
|
186
|
+
if (hookContent.includes('require(\'sqlite3\')')) {
|
|
187
|
+
hookContent = hookContent.replace(
|
|
188
|
+
'#!/usr/bin/env node',
|
|
189
|
+
`#!/usr/bin/env node\n\n// Injected module path\nprocess.env.NODE_PATH = '${modulesPath}' + ':' + (process.env.NODE_PATH || '');require('module').Module._initPaths();`
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
hookContent = hookContent.replace(/__JETTYPOD_ROOT__/g, jettypodRoot);
|
|
194
|
+
|
|
195
|
+
fs.writeFileSync(targetPath, hookContent);
|
|
196
|
+
fs.chmodSync(targetPath, 0o755);
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
return true;
|
|
200
|
+
}
|
|
201
|
+
|
|
91
202
|
module.exports = {
|
|
92
203
|
installHooks,
|
|
93
|
-
areHooksInstalled
|
|
204
|
+
areHooksInstalled,
|
|
205
|
+
ensureHooksUpdated
|
|
94
206
|
};
|
|
95
|
-
// test
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jettypod",
|
|
3
|
-
"version": "4.4.
|
|
3
|
+
"version": "4.4.105",
|
|
4
4
|
"description": "AI-powered development workflow manager with TDD, BDD, and automatic test generation",
|
|
5
5
|
"main": "jettypod.js",
|
|
6
6
|
"bin": {
|
|
@@ -69,5 +69,3 @@
|
|
|
69
69
|
"node": ">=18"
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
|
-
|
|
73
|
-
|