jun-claude-code 0.5.0 → 0.5.1
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/dist/__tests__/merge-settings.test.js +92 -0
- package/dist/copy.js +41 -6
- package/package.json +1 -1
|
@@ -403,6 +403,98 @@ function writeJson(filePath, data) {
|
|
|
403
403
|
(0, vitest_1.expect)(result.hooks.PreToolUse[0].matcher).toBe('Bash');
|
|
404
404
|
(0, vitest_1.expect)(result.hooks.PreToolUse[1].matcher).toBe('Write');
|
|
405
405
|
});
|
|
406
|
+
(0, vitest_1.it)('should skip source group when dest group contains all source commands plus extras', () => {
|
|
407
|
+
const sourceSettings = {
|
|
408
|
+
hooks: {
|
|
409
|
+
UserPromptSubmit: [
|
|
410
|
+
{
|
|
411
|
+
hooks: [
|
|
412
|
+
{ type: 'command', command: 'skill-forced.sh' },
|
|
413
|
+
{ type: 'command', command: 'workflow-enforced.sh' },
|
|
414
|
+
],
|
|
415
|
+
},
|
|
416
|
+
],
|
|
417
|
+
},
|
|
418
|
+
};
|
|
419
|
+
writeJson(path.join(sourceDir, 'settings.json'), sourceSettings);
|
|
420
|
+
// Dest has the same commands PLUS an extra custom hook (peon-ping)
|
|
421
|
+
const destSettings = {
|
|
422
|
+
hooks: {
|
|
423
|
+
UserPromptSubmit: [
|
|
424
|
+
{
|
|
425
|
+
hooks: [
|
|
426
|
+
{ type: 'command', command: 'peon.sh' },
|
|
427
|
+
{ type: 'command', command: 'skill-forced.sh' },
|
|
428
|
+
{ type: 'command', command: 'workflow-enforced.sh' },
|
|
429
|
+
],
|
|
430
|
+
},
|
|
431
|
+
],
|
|
432
|
+
},
|
|
433
|
+
};
|
|
434
|
+
writeJson(path.join(destDir, 'settings.json'), destSettings);
|
|
435
|
+
(0, copy_1.mergeSettingsJson)(sourceDir, destDir);
|
|
436
|
+
const result = readJson(path.join(destDir, 'settings.json'));
|
|
437
|
+
// Should remain 1 group, not duplicate
|
|
438
|
+
(0, vitest_1.expect)(result.hooks.UserPromptSubmit).toHaveLength(1);
|
|
439
|
+
(0, vitest_1.expect)(result.hooks.UserPromptSubmit[0].hooks).toHaveLength(3);
|
|
440
|
+
});
|
|
441
|
+
(0, vitest_1.it)('should skip source group when dest has commands split across multiple groups', () => {
|
|
442
|
+
const sourceSettings = {
|
|
443
|
+
hooks: {
|
|
444
|
+
UserPromptSubmit: [
|
|
445
|
+
{
|
|
446
|
+
hooks: [
|
|
447
|
+
{ type: 'command', command: 'skill-forced.sh' },
|
|
448
|
+
{ type: 'command', command: 'workflow-enforced.sh' },
|
|
449
|
+
],
|
|
450
|
+
},
|
|
451
|
+
],
|
|
452
|
+
},
|
|
453
|
+
};
|
|
454
|
+
writeJson(path.join(sourceDir, 'settings.json'), sourceSettings);
|
|
455
|
+
// Dest has the same commands spread across separate groups
|
|
456
|
+
const destSettings = {
|
|
457
|
+
hooks: {
|
|
458
|
+
UserPromptSubmit: [
|
|
459
|
+
{ hooks: [{ type: 'command', command: 'skill-forced.sh' }] },
|
|
460
|
+
{ hooks: [{ type: 'command', command: 'workflow-enforced.sh' }] },
|
|
461
|
+
],
|
|
462
|
+
},
|
|
463
|
+
};
|
|
464
|
+
writeJson(path.join(destDir, 'settings.json'), destSettings);
|
|
465
|
+
(0, copy_1.mergeSettingsJson)(sourceDir, destDir);
|
|
466
|
+
const result = readJson(path.join(destDir, 'settings.json'));
|
|
467
|
+
// Should remain 2 groups, source group not duplicated
|
|
468
|
+
(0, vitest_1.expect)(result.hooks.UserPromptSubmit).toHaveLength(2);
|
|
469
|
+
});
|
|
470
|
+
(0, vitest_1.it)('should add source group when dest only has some of its commands', () => {
|
|
471
|
+
const sourceSettings = {
|
|
472
|
+
hooks: {
|
|
473
|
+
UserPromptSubmit: [
|
|
474
|
+
{
|
|
475
|
+
hooks: [
|
|
476
|
+
{ type: 'command', command: 'skill-forced.sh' },
|
|
477
|
+
{ type: 'command', command: 'new-hook.sh' },
|
|
478
|
+
],
|
|
479
|
+
},
|
|
480
|
+
],
|
|
481
|
+
},
|
|
482
|
+
};
|
|
483
|
+
writeJson(path.join(sourceDir, 'settings.json'), sourceSettings);
|
|
484
|
+
// Dest has only one of the two source commands
|
|
485
|
+
const destSettings = {
|
|
486
|
+
hooks: {
|
|
487
|
+
UserPromptSubmit: [
|
|
488
|
+
{ hooks: [{ type: 'command', command: 'skill-forced.sh' }] },
|
|
489
|
+
],
|
|
490
|
+
},
|
|
491
|
+
};
|
|
492
|
+
writeJson(path.join(destDir, 'settings.json'), destSettings);
|
|
493
|
+
(0, copy_1.mergeSettingsJson)(sourceDir, destDir);
|
|
494
|
+
const result = readJson(path.join(destDir, 'settings.json'));
|
|
495
|
+
// Source group should be added since new-hook.sh is missing
|
|
496
|
+
(0, vitest_1.expect)(result.hooks.UserPromptSubmit).toHaveLength(2);
|
|
497
|
+
});
|
|
406
498
|
(0, vitest_1.it)('should dedup when dest has .claude/ paths and source has ~/.claude/ paths', () => {
|
|
407
499
|
const sourceSettings = {
|
|
408
500
|
hooks: {
|
package/dist/copy.js
CHANGED
|
@@ -43,7 +43,6 @@ const path = __importStar(require("path"));
|
|
|
43
43
|
const readline = __importStar(require("readline"));
|
|
44
44
|
const crypto = __importStar(require("crypto"));
|
|
45
45
|
const chalk_1 = __importDefault(require("chalk"));
|
|
46
|
-
const utils_1 = require("./utils");
|
|
47
46
|
/**
|
|
48
47
|
* Prompt user for confirmation using readline
|
|
49
48
|
*/
|
|
@@ -202,13 +201,49 @@ function mergeSettingsJson(sourceDir, destDir, options) {
|
|
|
202
201
|
destHooks[event] = [];
|
|
203
202
|
}
|
|
204
203
|
const destEntries = destHooks[event];
|
|
205
|
-
//
|
|
206
|
-
const
|
|
204
|
+
// Collect all individual commands from dest entries, grouped by matcher
|
|
205
|
+
const destCommandsByMatcher = new Map();
|
|
206
|
+
for (const entry of destEntries) {
|
|
207
|
+
const matcher = entry.matcher || '';
|
|
208
|
+
if (!destCommandsByMatcher.has(matcher)) {
|
|
209
|
+
destCommandsByMatcher.set(matcher, new Set());
|
|
210
|
+
}
|
|
211
|
+
const cmds = destCommandsByMatcher.get(matcher);
|
|
212
|
+
if (entry.hooks && Array.isArray(entry.hooks)) {
|
|
213
|
+
for (const h of entry.hooks) {
|
|
214
|
+
if (h.command)
|
|
215
|
+
cmds.add(h.command);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
else if (entry.command) {
|
|
219
|
+
cmds.add(entry.command);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
207
222
|
for (const entry of sourceEntries) {
|
|
208
|
-
const
|
|
209
|
-
|
|
223
|
+
const matcher = entry.matcher || '';
|
|
224
|
+
const existingCmds = destCommandsByMatcher.get(matcher) || new Set();
|
|
225
|
+
// Extract all commands from this source entry
|
|
226
|
+
const sourceCommands = [];
|
|
227
|
+
if (entry.hooks && Array.isArray(entry.hooks)) {
|
|
228
|
+
for (const h of entry.hooks) {
|
|
229
|
+
if (h.command)
|
|
230
|
+
sourceCommands.push(h.command);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
else if (entry.command) {
|
|
234
|
+
sourceCommands.push(entry.command);
|
|
235
|
+
}
|
|
236
|
+
// Skip if all source commands already exist in dest for the same matcher
|
|
237
|
+
const allExist = sourceCommands.length > 0 && sourceCommands.every((cmd) => existingCmds.has(cmd));
|
|
238
|
+
if (!allExist) {
|
|
210
239
|
destEntries.push(entry);
|
|
211
|
-
|
|
240
|
+
// Track newly added commands for subsequent source entries
|
|
241
|
+
if (!destCommandsByMatcher.has(matcher)) {
|
|
242
|
+
destCommandsByMatcher.set(matcher, existingCmds);
|
|
243
|
+
}
|
|
244
|
+
for (const cmd of sourceCommands) {
|
|
245
|
+
existingCmds.add(cmd);
|
|
246
|
+
}
|
|
212
247
|
}
|
|
213
248
|
}
|
|
214
249
|
}
|