Skip to content

Commit 59e9ac5

Browse files
ac1982Dietrich Gebert
andauthored
fix: preserve malformed Cursor hook configurations (#1059)
Co-authored-by: Dietrich Gebert <dietrichgebert@gmail.com>
1 parent d65a612 commit 59e9ac5

2 files changed

Lines changed: 29 additions & 2 deletions

File tree

‎scripts/cursor-hooks.js‎

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,18 @@ function readConfig(file) {
3636
} catch (e) {
3737
if (e.code !== 'ENOENT') throw e;
3838
}
39-
if (!config || typeof config !== 'object' || Array.isArray(config)) config = {};
40-
if (!config.hooks || typeof config.hooks !== 'object' || Array.isArray(config.hooks)) config.hooks = {};
39+
if (!config || typeof config !== 'object' || Array.isArray(config)) {
40+
throw new Error(file + ' must contain a JSON object; nothing was changed');
41+
}
42+
if (config.hooks === undefined) config.hooks = {};
43+
if (!config.hooks || typeof config.hooks !== 'object' || Array.isArray(config.hooks)) {
44+
throw new Error(file + ': hooks must be an object; nothing was changed');
45+
}
46+
for (const [event, entries] of Object.entries(config.hooks)) {
47+
if (!Array.isArray(entries)) {
48+
throw new Error(file + ': hooks.' + event + ' must be an array; nothing was changed');
49+
}
50+
}
4151
return config;
4252
}
4353

‎tests/cursor-hooks.test.js‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,3 +315,20 @@ test('installer refuses to touch a malformed hooks.json', () => {
315315
assert.equal(fs.readFileSync(file, 'utf8'), broken, 'malformed file must be left byte-for-byte intact');
316316
}
317317
});
318+
319+
for (const [name, config] of Object.entries({
320+
'root-array': [{ command: 'keep me' }],
321+
'hooks-array': { hooks: [{ command: 'keep me' }] },
322+
'event-string': { hooks: { sessionStart: 'node custom-hook.js' } },
323+
})) {
324+
test(`installer refuses ${name} without overwriting hooks.json`, () => {
325+
const c = cursorEnv(`invalid-${name}`);
326+
const file = path.join(c.home, '.cursor', 'hooks.json');
327+
fs.mkdirSync(path.dirname(file), { recursive: true });
328+
const original = JSON.stringify(config, null, 2) + '\n';
329+
fs.writeFileSync(file, original);
330+
const result = cli(['install'], c.env);
331+
assert.notEqual(result.status, 0, 'invalid config must not be silently rewritten');
332+
assert.equal(fs.readFileSync(file, 'utf8'), original);
333+
});
334+
}

0 commit comments

Comments
 (0)