claude-git-hooks 2.15.5 → 2.16.0
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/CHANGELOG.md +22 -0
- package/lib/commands/bump-version.js +346 -114
- package/lib/commands/generate-changelog.js +5 -6
- package/lib/utils/interactive-ui.js +93 -0
- package/lib/utils/version-manager.js +676 -296
- package/package.json +1 -1
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* Reuses same logic as bump-version --update-changelog
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import {
|
|
9
|
+
import { discoverVersionFiles } from '../utils/version-manager.js';
|
|
10
10
|
import { generateChangelogEntry, updateChangelogFile } from '../utils/changelog-generator.js';
|
|
11
11
|
import { getConfig } from '../config.js';
|
|
12
12
|
import { showInfo, showSuccess, showWarning, showError } from '../utils/interactive-ui.js';
|
|
@@ -84,10 +84,10 @@ export async function runGenerateChangelog(args) {
|
|
|
84
84
|
let version = options.version;
|
|
85
85
|
|
|
86
86
|
if (!version) {
|
|
87
|
-
const
|
|
87
|
+
const discovery = discoverVersionFiles();
|
|
88
88
|
|
|
89
|
-
if (
|
|
90
|
-
showError('No version files found
|
|
89
|
+
if (discovery.files.length === 0) {
|
|
90
|
+
showError('No version files found');
|
|
91
91
|
console.log('');
|
|
92
92
|
console.log('Specify version manually:');
|
|
93
93
|
console.log(' claude-hooks generate-changelog 2.7.0');
|
|
@@ -95,8 +95,7 @@ export async function runGenerateChangelog(args) {
|
|
|
95
95
|
process.exit(1);
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
-
|
|
99
|
-
version = versions.resolved;
|
|
98
|
+
version = discovery.resolvedVersion;
|
|
100
99
|
|
|
101
100
|
if (!version) {
|
|
102
101
|
showError('Could not determine version');
|
|
@@ -343,6 +343,99 @@ const showDetailedIssues = (result) => {
|
|
|
343
343
|
console.log('═══════════════════════════════════════════════════════════════');
|
|
344
344
|
};
|
|
345
345
|
|
|
346
|
+
/**
|
|
347
|
+
* Prompt user with toggle list (checkbox-style selection)
|
|
348
|
+
* Why: Allow multi-select for version files or other items
|
|
349
|
+
*
|
|
350
|
+
* @param {string} message - Header message
|
|
351
|
+
* @param {Array<{key: string, label: string, selected: boolean}>} items - Items to select
|
|
352
|
+
* @returns {Promise<string[]>} - Array of selected item keys
|
|
353
|
+
*/
|
|
354
|
+
export const promptToggleList = async (message, items) => {
|
|
355
|
+
const rl = readline.createInterface({
|
|
356
|
+
input: process.stdin,
|
|
357
|
+
output: process.stdout
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
// Clone items to track selection state
|
|
361
|
+
const state = items.map(item => ({
|
|
362
|
+
key: item.key,
|
|
363
|
+
label: item.label,
|
|
364
|
+
selected: item.selected !== undefined ? item.selected : true
|
|
365
|
+
}));
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* Display current selection state
|
|
369
|
+
*/
|
|
370
|
+
const displayList = () => {
|
|
371
|
+
console.clear();
|
|
372
|
+
console.log('');
|
|
373
|
+
console.log(message);
|
|
374
|
+
console.log('');
|
|
375
|
+
|
|
376
|
+
state.forEach((item, index) => {
|
|
377
|
+
const checkbox = item.selected ? '✓' : '✗';
|
|
378
|
+
const num = index + 1;
|
|
379
|
+
console.log(` [${num}] ${checkbox} ${item.label}`);
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
console.log('');
|
|
383
|
+
console.log('Type number to toggle, Enter to confirm');
|
|
384
|
+
console.log('');
|
|
385
|
+
};
|
|
386
|
+
|
|
387
|
+
return new Promise((resolve) => {
|
|
388
|
+
displayList();
|
|
389
|
+
|
|
390
|
+
const askForInput = () => {
|
|
391
|
+
rl.question('Toggle file #: ', (answer) => {
|
|
392
|
+
const trimmed = answer.trim();
|
|
393
|
+
|
|
394
|
+
// Empty input = confirm and exit
|
|
395
|
+
if (!trimmed) {
|
|
396
|
+
rl.close();
|
|
397
|
+
const selectedKeys = state
|
|
398
|
+
.filter(item => item.selected)
|
|
399
|
+
.map(item => item.key);
|
|
400
|
+
|
|
401
|
+
logger.debug('interactive-ui - promptToggleList', 'Selection confirmed', {
|
|
402
|
+
selectedKeys
|
|
403
|
+
});
|
|
404
|
+
|
|
405
|
+
resolve(selectedKeys);
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
// Parse number input
|
|
410
|
+
const num = parseInt(trimmed, 10);
|
|
411
|
+
|
|
412
|
+
if (!isNaN(num) && num >= 1 && num <= state.length) {
|
|
413
|
+
// Toggle the selected item
|
|
414
|
+
const index = num - 1;
|
|
415
|
+
state[index].selected = !state[index].selected;
|
|
416
|
+
|
|
417
|
+
logger.debug('interactive-ui - promptToggleList', 'Toggled item', {
|
|
418
|
+
index,
|
|
419
|
+
key: state[index].key,
|
|
420
|
+
selected: state[index].selected
|
|
421
|
+
});
|
|
422
|
+
|
|
423
|
+
// Redisplay and ask again
|
|
424
|
+
displayList();
|
|
425
|
+
askForInput();
|
|
426
|
+
} else {
|
|
427
|
+
// Invalid input, show message and ask again
|
|
428
|
+
console.log(`Invalid input. Enter a number between 1 and ${state.length}, or press Enter to confirm.`);
|
|
429
|
+
console.log('');
|
|
430
|
+
askForInput();
|
|
431
|
+
}
|
|
432
|
+
});
|
|
433
|
+
};
|
|
434
|
+
|
|
435
|
+
askForInput();
|
|
436
|
+
});
|
|
437
|
+
};
|
|
438
|
+
|
|
346
439
|
/**
|
|
347
440
|
* Prompt user to confirm commit with non-blocking issues
|
|
348
441
|
* Why: Give developers control to abort and fix issues immediately
|