habit-hooks 0.1.0-beta.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/LICENSE.md +21 -0
- package/README.md +233 -0
- package/dist/baseline/commands.d.ts +12 -0
- package/dist/baseline/commands.js +131 -0
- package/dist/baseline/commands.js.map +1 -0
- package/dist/baseline/file-hash.d.ts +2 -0
- package/dist/baseline/file-hash.js +25 -0
- package/dist/baseline/file-hash.js.map +1 -0
- package/dist/baseline/filter.d.ts +8 -0
- package/dist/baseline/filter.js +31 -0
- package/dist/baseline/filter.js.map +1 -0
- package/dist/baseline/store.d.ts +18 -0
- package/dist/baseline/store.js +106 -0
- package/dist/baseline/store.js.map +1 -0
- package/dist/checks/comment-check.d.ts +3 -0
- package/dist/checks/comment-check.js +83 -0
- package/dist/checks/comment-check.js.map +1 -0
- package/dist/checks/eslint-wrap.d.ts +2 -0
- package/dist/checks/eslint-wrap.js +104 -0
- package/dist/checks/eslint-wrap.js.map +1 -0
- package/dist/checks/jscpd-wrap.d.ts +6 -0
- package/dist/checks/jscpd-wrap.js +158 -0
- package/dist/checks/jscpd-wrap.js.map +1 -0
- package/dist/checks/knip-resolve.d.ts +4 -0
- package/dist/checks/knip-resolve.js +49 -0
- package/dist/checks/knip-resolve.js.map +1 -0
- package/dist/checks/knip-schema.d.ts +32 -0
- package/dist/checks/knip-schema.js +24 -0
- package/dist/checks/knip-schema.js.map +1 -0
- package/dist/checks/knip-wrap.d.ts +4 -0
- package/dist/checks/knip-wrap.js +127 -0
- package/dist/checks/knip-wrap.js.map +1 -0
- package/dist/cli/baseline-commands.d.ts +2 -0
- package/dist/cli/baseline-commands.js +61 -0
- package/dist/cli/baseline-commands.js.map +1 -0
- package/dist/cli/emit.d.ts +7 -0
- package/dist/cli/emit.js +8 -0
- package/dist/cli/emit.js.map +1 -0
- package/dist/cli/init/detect.d.ts +8 -0
- package/dist/cli/init/detect.js +20 -0
- package/dist/cli/init/detect.js.map +1 -0
- package/dist/cli/init/git-hook.d.ts +6 -0
- package/dist/cli/init/git-hook.js +48 -0
- package/dist/cli/init/git-hook.js.map +1 -0
- package/dist/cli/init/install-commands.d.ts +6 -0
- package/dist/cli/init/install-commands.js +55 -0
- package/dist/cli/init/install-commands.js.map +1 -0
- package/dist/cli/init/package-scripts.d.ts +6 -0
- package/dist/cli/init/package-scripts.js +55 -0
- package/dist/cli/init/package-scripts.js.map +1 -0
- package/dist/cli/init/prompts.d.ts +9 -0
- package/dist/cli/init/prompts.js +33 -0
- package/dist/cli/init/prompts.js.map +1 -0
- package/dist/cli/init/reporters.d.ts +11 -0
- package/dist/cli/init/reporters.js +40 -0
- package/dist/cli/init/reporters.js.map +1 -0
- package/dist/cli/init/run.d.ts +12 -0
- package/dist/cli/init/run.js +159 -0
- package/dist/cli/init/run.js.map +1 -0
- package/dist/cli/init/scaffold-baseline.d.ts +4 -0
- package/dist/cli/init/scaffold-baseline.js +11 -0
- package/dist/cli/init/scaffold-baseline.js.map +1 -0
- package/dist/cli/init/scaffold-config.d.ts +13 -0
- package/dist/cli/init/scaffold-config.js +42 -0
- package/dist/cli/init/scaffold-config.js.map +1 -0
- package/dist/cli/init/scaffold-eslint-config.d.ts +2 -0
- package/dist/cli/init/scaffold-eslint-config.js +12 -0
- package/dist/cli/init/scaffold-eslint-config.js.map +1 -0
- package/dist/cli/init/scaffold-jscpd-config.d.ts +2 -0
- package/dist/cli/init/scaffold-jscpd-config.js +12 -0
- package/dist/cli/init/scaffold-jscpd-config.js.map +1 -0
- package/dist/cli/init/scaffold-knip-config.d.ts +2 -0
- package/dist/cli/init/scaffold-knip-config.js +12 -0
- package/dist/cli/init/scaffold-knip-config.js.map +1 -0
- package/dist/cli/init/skill.d.ts +7 -0
- package/dist/cli/init/skill.js +36 -0
- package/dist/cli/init/skill.js.map +1 -0
- package/dist/cli/init/snippet.d.ts +1 -0
- package/dist/cli/init/snippet.js +18 -0
- package/dist/cli/init/snippet.js.map +1 -0
- package/dist/cli/init/templates/eslint-config.d.ts +2 -0
- package/dist/cli/init/templates/eslint-config.js +35 -0
- package/dist/cli/init/templates/eslint-config.js.map +1 -0
- package/dist/cli/init/templates/jscpd-config.d.ts +2 -0
- package/dist/cli/init/templates/jscpd-config.js +9 -0
- package/dist/cli/init/templates/jscpd-config.js.map +1 -0
- package/dist/cli/init/templates/knip-config.d.ts +2 -0
- package/dist/cli/init/templates/knip-config.js +8 -0
- package/dist/cli/init/templates/knip-config.js.map +1 -0
- package/dist/cli/init-command.d.ts +2 -0
- package/dist/cli/init-command.js +33 -0
- package/dist/cli/init-command.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +101 -0
- package/dist/cli.js.map +1 -0
- package/dist/config/defaults.d.ts +4 -0
- package/dist/config/defaults.js +172 -0
- package/dist/config/defaults.js.map +1 -0
- package/dist/config/jiti-loader.d.ts +1 -0
- package/dist/config/jiti-loader.js +13 -0
- package/dist/config/jiti-loader.js.map +1 -0
- package/dist/config/load.d.ts +8 -0
- package/dist/config/load.js +53 -0
- package/dist/config/load.js.map +1 -0
- package/dist/config/merge.d.ts +3 -0
- package/dist/config/merge.js +90 -0
- package/dist/config/merge.js.map +1 -0
- package/dist/config/schema.d.ts +32 -0
- package/dist/config/schema.js +4 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/config/validate.d.ts +2 -0
- package/dist/config/validate.js +128 -0
- package/dist/config/validate.js.map +1 -0
- package/dist/detect/package-json.d.ts +1 -0
- package/dist/detect/package-json.js +15 -0
- package/dist/detect/package-json.js.map +1 -0
- package/dist/detect/tool.d.ts +10 -0
- package/dist/detect/tool.js +73 -0
- package/dist/detect/tool.js.map +1 -0
- package/dist/eslint-runner.d.ts +7 -0
- package/dist/eslint-runner.js +34 -0
- package/dist/eslint-runner.js.map +1 -0
- package/dist/git/exec.d.ts +8 -0
- package/dist/git/exec.js +48 -0
- package/dist/git/exec.js.map +1 -0
- package/dist/git/resolve-scope.d.ts +15 -0
- package/dist/git/resolve-scope.js +89 -0
- package/dist/git/resolve-scope.js.map +1 -0
- package/dist/git/scope.d.ts +7 -0
- package/dist/git/scope.js +58 -0
- package/dist/git/scope.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/prompts/loader.d.ts +6 -0
- package/dist/prompts/loader.js +27 -0
- package/dist/prompts/loader.js.map +1 -0
- package/dist/prompts/packaged-dir.d.ts +1 -0
- package/dist/prompts/packaged-dir.js +10 -0
- package/dist/prompts/packaged-dir.js.map +1 -0
- package/dist/prompts/registry.d.ts +3 -0
- package/dist/prompts/registry.js +68 -0
- package/dist/prompts/registry.js.map +1 -0
- package/dist/reporter.d.ts +7 -0
- package/dist/reporter.js +114 -0
- package/dist/reporter.js.map +1 -0
- package/dist/rules/registry.d.ts +3 -0
- package/dist/rules/registry.js +37 -0
- package/dist/rules/registry.js.map +1 -0
- package/dist/runner.d.ts +15 -0
- package/dist/runner.js +151 -0
- package/dist/runner.js.map +1 -0
- package/dist/types.d.ts +41 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/wrap/notices.d.ts +13 -0
- package/dist/wrap/notices.js +29 -0
- package/dist/wrap/notices.js.map +1 -0
- package/dist/wrap/resolve.d.ts +5 -0
- package/dist/wrap/resolve.js +9 -0
- package/dist/wrap/resolve.js.map +1 -0
- package/dist/wrap/run.d.ts +15 -0
- package/dist/wrap/run.js +26 -0
- package/dist/wrap/run.js.map +1 -0
- package/dist/wrap/shell.d.ts +14 -0
- package/dist/wrap/shell.js +44 -0
- package/dist/wrap/shell.js.map +1 -0
- package/package.json +46 -0
- package/src/prompts/comment-non-essential.md +7 -0
- package/src/prompts/eslint-boundaries-dependencies.md +9 -0
- package/src/prompts/eslint-complexity.md +9 -0
- package/src/prompts/eslint-eqeqeq.md +3 -0
- package/src/prompts/eslint-fatal.md +7 -0
- package/src/prompts/eslint-max-lines-per-function.md +9 -0
- package/src/prompts/eslint-max-lines.md +9 -0
- package/src/prompts/eslint-max-params.md +9 -0
- package/src/prompts/eslint-no-duplicate-imports.md +1 -0
- package/src/prompts/eslint-no-unused-vars.md +3 -0
- package/src/prompts/eslint-no-var.md +1 -0
- package/src/prompts/eslint-no-warning-comments.md +3 -0
- package/src/prompts/eslint-prefer-const.md +3 -0
- package/src/prompts/eslint-typescript-eslint-no-explicit-any.md +3 -0
- package/src/prompts/eslint-typescript-eslint-no-inferrable-types.md +3 -0
- package/src/prompts/eslint-typescript-eslint-no-non-null-assertion.md +3 -0
- package/src/prompts/jscpd-duplication.md +9 -0
- package/src/prompts/knip-classMembers.md +7 -0
- package/src/prompts/knip-dependencies.md +9 -0
- package/src/prompts/knip-exports.md +9 -0
- package/src/prompts/knip-files.md +9 -0
- package/src/prompts/knip-types.md +9 -0
- package/src/prompts/uncoached.md +3 -0
- package/src/skills/habit-hooks-review/SKILL.md +108 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"knip-wrap.js","sourceRoot":"","sources":["../../src/checks/knip-wrap.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { baselineForget, baselineGenerate, baselinePrune, baselineSnooze, baselineStatus, } from '../baseline/commands.js';
|
|
2
|
+
import { emit } from './emit.js';
|
|
3
|
+
async function runAction(action) {
|
|
4
|
+
try {
|
|
5
|
+
emit(await action());
|
|
6
|
+
}
|
|
7
|
+
catch (error) {
|
|
8
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
9
|
+
process.stderr.write(`habit-hooks: ${message}\n`);
|
|
10
|
+
process.exitCode = 2;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
function attachGenerate(baseline) {
|
|
14
|
+
baseline
|
|
15
|
+
.command('generate')
|
|
16
|
+
.description('record currently-violating files as snoozed')
|
|
17
|
+
.action(async () => {
|
|
18
|
+
await runAction(() => baselineGenerate(process.cwd()));
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
function attachStatus(baseline) {
|
|
22
|
+
baseline
|
|
23
|
+
.command('status')
|
|
24
|
+
.description('list snoozed files and their freshness')
|
|
25
|
+
.action(async () => {
|
|
26
|
+
await runAction(() => baselineStatus(process.cwd()));
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
function attachSnooze(baseline) {
|
|
30
|
+
baseline
|
|
31
|
+
.command('snooze <files...>')
|
|
32
|
+
.description('snooze the given tracked files')
|
|
33
|
+
.action(async (files) => {
|
|
34
|
+
await runAction(() => baselineSnooze(process.cwd(), files));
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
function attachForget(baseline) {
|
|
38
|
+
baseline
|
|
39
|
+
.command('forget <files...>')
|
|
40
|
+
.description('remove baseline entries for the given files')
|
|
41
|
+
.action(async (files) => {
|
|
42
|
+
await runAction(() => baselineForget(process.cwd(), files));
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
function attachPrune(baseline) {
|
|
46
|
+
baseline
|
|
47
|
+
.command('prune')
|
|
48
|
+
.description('remove stale entries (missing files or resolved violations)')
|
|
49
|
+
.action(async () => {
|
|
50
|
+
await runAction(() => baselinePrune(process.cwd()));
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
export function registerBaselineCommands(program) {
|
|
54
|
+
const baseline = program.command('baseline').description('manage the snooze baseline');
|
|
55
|
+
attachGenerate(baseline);
|
|
56
|
+
attachStatus(baseline);
|
|
57
|
+
attachSnooze(baseline);
|
|
58
|
+
attachForget(baseline);
|
|
59
|
+
attachPrune(baseline);
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=baseline-commands.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"baseline-commands.js","sourceRoot":"","sources":["../../src/cli/baseline-commands.ts"],"names":[],"mappings":"AACA,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,aAAa,EACb,cAAc,EACd,cAAc,GAEf,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,KAAK,UAAU,SAAS,CAAC,MAAoD;IAC3E,IAAI,CAAC;QACH,IAAI,CAAC,MAAM,MAAM,EAAE,CAAC,CAAC;IACvB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,gBAAgB,OAAO,IAAI,CAAC,CAAC;QAClD,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;IACvB,CAAC;AACH,CAAC;AAED,SAAS,cAAc,CAAC,QAAiB;IACvC,QAAQ;SACL,OAAO,CAAC,UAAU,CAAC;SACnB,WAAW,CAAC,6CAA6C,CAAC;SAC1D,MAAM,CAAC,KAAK,IAAI,EAAE;QACjB,MAAM,SAAS,CAAC,GAAG,EAAE,CAAC,gBAAgB,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;AACP,CAAC;AAED,SAAS,YAAY,CAAC,QAAiB;IACrC,QAAQ;SACL,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,wCAAwC,CAAC;SACrD,MAAM,CAAC,KAAK,IAAI,EAAE;QACjB,MAAM,SAAS,CAAC,GAAG,EAAE,CAAC,cAAc,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;AACP,CAAC;AAED,SAAS,YAAY,CAAC,QAAiB;IACrC,QAAQ;SACL,OAAO,CAAC,mBAAmB,CAAC;SAC5B,WAAW,CAAC,gCAAgC,CAAC;SAC7C,MAAM,CAAC,KAAK,EAAE,KAAe,EAAE,EAAE;QAChC,MAAM,SAAS,CAAC,GAAG,EAAE,CAAC,cAAc,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC;IAC9D,CAAC,CAAC,CAAC;AACP,CAAC;AAED,SAAS,YAAY,CAAC,QAAiB;IACrC,QAAQ;SACL,OAAO,CAAC,mBAAmB,CAAC;SAC5B,WAAW,CAAC,6CAA6C,CAAC;SAC1D,MAAM,CAAC,KAAK,EAAE,KAAe,EAAE,EAAE;QAChC,MAAM,SAAS,CAAC,GAAG,EAAE,CAAC,cAAc,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC;IAC9D,CAAC,CAAC,CAAC;AACP,CAAC;AAED,SAAS,WAAW,CAAC,QAAiB;IACpC,QAAQ;SACL,OAAO,CAAC,OAAO,CAAC;SAChB,WAAW,CAAC,6DAA6D,CAAC;SAC1E,MAAM,CAAC,KAAK,IAAI,EAAE;QACjB,MAAM,SAAS,CAAC,GAAG,EAAE,CAAC,aAAa,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;AACP,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,OAAgB;IACvD,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,WAAW,CAAC,4BAA4B,CAAC,CAAC;IACvF,cAAc,CAAC,QAAQ,CAAC,CAAC;IACzB,YAAY,CAAC,QAAQ,CAAC,CAAC;IACvB,YAAY,CAAC,QAAQ,CAAC,CAAC;IACvB,YAAY,CAAC,QAAQ,CAAC,CAAC;IACvB,WAAW,CAAC,QAAQ,CAAC,CAAC;AACxB,CAAC"}
|
package/dist/cli/emit.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emit.js","sourceRoot":"","sources":["../../src/cli/emit.ts"],"names":[],"mappings":"AAMA,MAAM,UAAU,IAAI,CAAC,MAAqB;IACxC,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAClE,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAClE,OAAO,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;AACrC,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type ToolName } from '../../detect/tool.js';
|
|
2
|
+
export type { ToolName };
|
|
3
|
+
export interface ToolState {
|
|
4
|
+
installed: boolean;
|
|
5
|
+
configured: boolean;
|
|
6
|
+
}
|
|
7
|
+
type ToolStateMatrix = Record<ToolName, ToolState>;
|
|
8
|
+
export declare function detectToolStates(cwd: string): ToolStateMatrix;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { detectTool, TOOL_CONFIG_FILENAMES, TOOL_PACKAGE_JSON_KEYS, } from '../../detect/tool.js';
|
|
4
|
+
import { hasPackageJsonKey } from '../../detect/package-json.js';
|
|
5
|
+
const TOOLS = ['eslint', 'knip', 'jscpd'];
|
|
6
|
+
function hasConfigFile(cwd, tool) {
|
|
7
|
+
if (TOOL_CONFIG_FILENAMES[tool].some((name) => existsSync(join(cwd, name))))
|
|
8
|
+
return true;
|
|
9
|
+
return hasPackageJsonKey(cwd, TOOL_PACKAGE_JSON_KEYS[tool]);
|
|
10
|
+
}
|
|
11
|
+
function stateFor(cwd, tool) {
|
|
12
|
+
return { installed: detectTool(cwd, tool) !== null, configured: hasConfigFile(cwd, tool) };
|
|
13
|
+
}
|
|
14
|
+
export function detectToolStates(cwd) {
|
|
15
|
+
const matrix = {};
|
|
16
|
+
for (const tool of TOOLS)
|
|
17
|
+
matrix[tool] = stateFor(cwd, tool);
|
|
18
|
+
return matrix;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=detect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect.js","sourceRoot":"","sources":["../../../src/cli/init/detect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EACL,UAAU,EACV,qBAAqB,EACrB,sBAAsB,GAEvB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAWjE,MAAM,KAAK,GAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;AAEtD,SAAS,aAAa,CAAC,GAAW,EAAE,IAAc;IAChD,IAAI,qBAAqB,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IACzF,OAAO,iBAAiB,CAAC,GAAG,EAAE,sBAAsB,CAAC,IAAI,CAAC,CAAC,CAAC;AAC9D,CAAC;AAED,SAAS,QAAQ,CAAC,GAAW,EAAE,IAAc;IAC3C,OAAO,EAAE,SAAS,EAAE,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,IAAI,EAAE,UAAU,EAAE,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,CAAC;AAC7F,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,GAAW;IAC1C,MAAM,MAAM,GAA6B,EAAE,CAAC;IAC5C,KAAK,MAAM,IAAI,IAAI,KAAK;QAAE,MAAM,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IAC7D,OAAO,MAAyB,CAAC;AACnC,CAAC"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { chmodSync, existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { detectPackageManager, runScriptCommand } from './install-commands.js';
|
|
4
|
+
function hookBodyFor(cwd) {
|
|
5
|
+
const command = runScriptCommand(detectPackageManager(cwd), 'habit-hooks');
|
|
6
|
+
return `#!/usr/bin/env sh\n${command}\n`;
|
|
7
|
+
}
|
|
8
|
+
function dependsOnHusky(cwd) {
|
|
9
|
+
const pkgPath = join(cwd, 'package.json');
|
|
10
|
+
if (!existsSync(pkgPath))
|
|
11
|
+
return false;
|
|
12
|
+
if (!existsSync(join(cwd, '.husky')))
|
|
13
|
+
return false;
|
|
14
|
+
const raw = readFileSync(pkgPath, 'utf8');
|
|
15
|
+
return raw.includes('"husky"');
|
|
16
|
+
}
|
|
17
|
+
function huskyHookPath(cwd) {
|
|
18
|
+
return join(cwd, '.husky', 'pre-commit');
|
|
19
|
+
}
|
|
20
|
+
function nativeHookPath(cwd) {
|
|
21
|
+
return join(cwd, '.git', 'hooks', 'pre-commit');
|
|
22
|
+
}
|
|
23
|
+
function writeHook(path, body) {
|
|
24
|
+
writeFileSync(path, body);
|
|
25
|
+
chmodSync(path, 0o755);
|
|
26
|
+
return { action: 'installed', path };
|
|
27
|
+
}
|
|
28
|
+
function bodyMatches(content) {
|
|
29
|
+
return content.includes(' run habit-hooks');
|
|
30
|
+
}
|
|
31
|
+
function installAt(path, body) {
|
|
32
|
+
if (existsSync(path)) {
|
|
33
|
+
const existing = readFileSync(path, 'utf8');
|
|
34
|
+
if (bodyMatches(existing))
|
|
35
|
+
return { action: 'kept', path };
|
|
36
|
+
return { action: 'conflict', path };
|
|
37
|
+
}
|
|
38
|
+
return writeHook(path, body);
|
|
39
|
+
}
|
|
40
|
+
export function installPreCommitHook(cwd) {
|
|
41
|
+
const body = hookBodyFor(cwd);
|
|
42
|
+
if (dependsOnHusky(cwd))
|
|
43
|
+
return installAt(huskyHookPath(cwd), body);
|
|
44
|
+
if (!existsSync(join(cwd, '.git')))
|
|
45
|
+
return { action: 'no-git' };
|
|
46
|
+
return installAt(nativeHookPath(cwd), body);
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=git-hook.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-hook.js","sourceRoot":"","sources":["../../../src/cli/init/git-hook.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAS/E,SAAS,WAAW,CAAC,GAAW;IAC9B,MAAM,OAAO,GAAG,gBAAgB,CAAC,oBAAoB,CAAC,GAAG,CAAC,EAAE,aAAa,CAAC,CAAC;IAC3E,OAAO,sBAAsB,OAAO,IAAI,CAAC;AAC3C,CAAC;AAED,SAAS,cAAc,CAAC,GAAW;IACjC,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;IAC1C,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,KAAK,CAAC;IACvC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IACnD,MAAM,GAAG,GAAG,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC1C,OAAO,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;AACjC,CAAC;AAED,SAAS,aAAa,CAAC,GAAW;IAChC,OAAO,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAC;AAC3C,CAAC;AAED,SAAS,cAAc,CAAC,GAAW;IACjC,OAAO,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC;AAClD,CAAC;AAED,SAAS,SAAS,CAAC,IAAY,EAAE,IAAY;IAC3C,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC1B,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IACvB,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;AACvC,CAAC;AAED,SAAS,WAAW,CAAC,OAAe;IAClC,OAAO,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAC,CAAC;AAC9C,CAAC;AAED,SAAS,SAAS,CAAC,IAAY,EAAE,IAAY;IAC3C,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACrB,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC5C,IAAI,WAAW,CAAC,QAAQ,CAAC;YAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;QAC3D,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC;IACtC,CAAC;IACD,OAAO,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,GAAW;IAC9C,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;IAC9B,IAAI,cAAc,CAAC,GAAG,CAAC;QAAE,OAAO,SAAS,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC;IACpE,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;IAChE,OAAO,SAAS,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC;AAC9C,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
type PackageManager = 'pnpm' | 'yarn' | 'bun' | 'npm';
|
|
2
|
+
export declare function detectPackageManager(cwd: string): PackageManager;
|
|
3
|
+
export declare function buildInstallCommand(pm: PackageManager, packages: string[]): string;
|
|
4
|
+
export declare function runScriptCommand(pm: PackageManager, script: string): string;
|
|
5
|
+
export declare function packagesFor(tool: 'eslint' | 'knip' | 'jscpd'): string[];
|
|
6
|
+
export {};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { existsSync, statSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
const LOCKFILES = {
|
|
4
|
+
pnpm: ['pnpm-lock.yaml'],
|
|
5
|
+
yarn: ['yarn.lock'],
|
|
6
|
+
bun: ['bun.lock', 'bun.lockb'],
|
|
7
|
+
};
|
|
8
|
+
function lockfileHitsFor(cwd, pm) {
|
|
9
|
+
const hits = [];
|
|
10
|
+
for (const file of LOCKFILES[pm]) {
|
|
11
|
+
const path = join(cwd, file);
|
|
12
|
+
if (existsSync(path))
|
|
13
|
+
hits.push({ pm, path, mtimeMs: statSync(path).mtimeMs });
|
|
14
|
+
}
|
|
15
|
+
return hits;
|
|
16
|
+
}
|
|
17
|
+
function findAllLockfileHits(cwd) {
|
|
18
|
+
const all = [];
|
|
19
|
+
for (const pm of Object.keys(LOCKFILES)) {
|
|
20
|
+
all.push(...lockfileHitsFor(cwd, pm));
|
|
21
|
+
}
|
|
22
|
+
return all;
|
|
23
|
+
}
|
|
24
|
+
function pickNewest(hits) {
|
|
25
|
+
const sorted = [...hits].sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
26
|
+
const newest = sorted[0];
|
|
27
|
+
if (newest === undefined)
|
|
28
|
+
throw new Error('pickNewest requires at least one hit');
|
|
29
|
+
return newest;
|
|
30
|
+
}
|
|
31
|
+
export function detectPackageManager(cwd) {
|
|
32
|
+
const hits = findAllLockfileHits(cwd);
|
|
33
|
+
if (hits.length === 0)
|
|
34
|
+
return 'npm';
|
|
35
|
+
return pickNewest(hits).pm;
|
|
36
|
+
}
|
|
37
|
+
const ADD_FLAGS = {
|
|
38
|
+
pnpm: ['add', '-D'],
|
|
39
|
+
yarn: ['add', '-D'],
|
|
40
|
+
bun: ['add', '-d'],
|
|
41
|
+
npm: ['install', '--save-dev'],
|
|
42
|
+
};
|
|
43
|
+
export function buildInstallCommand(pm, packages) {
|
|
44
|
+
return [pm, ...ADD_FLAGS[pm], ...packages].join(' ');
|
|
45
|
+
}
|
|
46
|
+
export function runScriptCommand(pm, script) {
|
|
47
|
+
return `${pm} run ${script}`;
|
|
48
|
+
}
|
|
49
|
+
const ESLINT_PACKAGES = ['eslint', '@eslint/js', 'typescript-eslint'];
|
|
50
|
+
export function packagesFor(tool) {
|
|
51
|
+
if (tool === 'eslint')
|
|
52
|
+
return ESLINT_PACKAGES;
|
|
53
|
+
return [tool];
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=install-commands.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install-commands.js","sourceRoot":"","sources":["../../../src/cli/init/install-commands.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAMjC,MAAM,SAAS,GAA0C;IACvD,IAAI,EAAE,CAAC,gBAAgB,CAAC;IACxB,IAAI,EAAE,CAAC,WAAW,CAAC;IACnB,GAAG,EAAE,CAAC,UAAU,EAAE,WAAW,CAAC;CAC/B,CAAC;AAQF,SAAS,eAAe,CAAC,GAAW,EAAE,EAAc;IAClD,MAAM,IAAI,GAAkB,EAAE,CAAC;IAC/B,KAAK,MAAM,IAAI,IAAI,SAAS,CAAC,EAAE,CAAC,EAAE,CAAC;QACjC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC7B,IAAI,UAAU,CAAC,IAAI,CAAC;YAAE,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;IACjF,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,mBAAmB,CAAC,GAAW;IACtC,MAAM,GAAG,GAAkB,EAAE,CAAC;IAC9B,KAAK,MAAM,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,CAAiB,EAAE,CAAC;QACxD,GAAG,CAAC,IAAI,CAAC,GAAG,eAAe,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;IACxC,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,UAAU,CAAC,IAAmB;IACrC,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC;IAC/D,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IACzB,IAAI,MAAM,KAAK,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;IAClF,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,GAAW;IAC9C,MAAM,IAAI,GAAG,mBAAmB,CAAC,GAAG,CAAC,CAAC;IACtC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACpC,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;AAC7B,CAAC;AAED,MAAM,SAAS,GAAqC;IAClD,IAAI,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC;IACnB,IAAI,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC;IACnB,GAAG,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC;IAClB,GAAG,EAAE,CAAC,SAAS,EAAE,YAAY,CAAC;CAC/B,CAAC;AAEF,MAAM,UAAU,mBAAmB,CAAC,EAAkB,EAAE,QAAkB;IACxE,OAAO,CAAC,EAAE,EAAE,GAAG,SAAS,CAAC,EAAE,CAAC,EAAE,GAAG,QAAQ,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACvD,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,EAAkB,EAAE,MAAc;IACjE,OAAO,GAAG,EAAE,QAAQ,MAAM,EAAE,CAAC;AAC/B,CAAC;AAED,MAAM,eAAe,GAAG,CAAC,QAAQ,EAAE,YAAY,EAAE,mBAAmB,CAAC,CAAC;AAEtE,MAAM,UAAU,WAAW,CAAC,IAAiC;IAC3D,IAAI,IAAI,KAAK,QAAQ;QAAE,OAAO,eAAe,CAAC;IAC9C,OAAO,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
const HABIT_HOOKS_SCRIPT = 'habit-hooks';
|
|
4
|
+
const HABIT_HOOKS_COMMAND = 'habit-hooks';
|
|
5
|
+
const CI_SCRIPT = 'ci';
|
|
6
|
+
const CI_CANDIDATES = ['lint', 'test', 'build', HABIT_HOOKS_SCRIPT];
|
|
7
|
+
function readPackageJson(cwd) {
|
|
8
|
+
const path = join(cwd, 'package.json');
|
|
9
|
+
if (!existsSync(path))
|
|
10
|
+
return null;
|
|
11
|
+
const raw = readFileSync(path, 'utf8');
|
|
12
|
+
return { path, data: JSON.parse(raw) };
|
|
13
|
+
}
|
|
14
|
+
function writePackageJson(path, data) {
|
|
15
|
+
writeFileSync(path, `${JSON.stringify(data, null, 2)}\n`);
|
|
16
|
+
}
|
|
17
|
+
function ensureScripts(data) {
|
|
18
|
+
if (!data.scripts)
|
|
19
|
+
data.scripts = {};
|
|
20
|
+
return data.scripts;
|
|
21
|
+
}
|
|
22
|
+
export function addHabitHooksScript(cwd) {
|
|
23
|
+
const pkg = readPackageJson(cwd);
|
|
24
|
+
if (pkg === null)
|
|
25
|
+
return { action: 'no-package-json' };
|
|
26
|
+
const scripts = ensureScripts(pkg.data);
|
|
27
|
+
const existing = scripts[HABIT_HOOKS_SCRIPT];
|
|
28
|
+
if (existing === HABIT_HOOKS_COMMAND)
|
|
29
|
+
return { action: 'kept', before: existing };
|
|
30
|
+
if (existing !== undefined)
|
|
31
|
+
return { action: 'conflict', before: existing };
|
|
32
|
+
scripts[HABIT_HOOKS_SCRIPT] = HABIT_HOOKS_COMMAND;
|
|
33
|
+
writePackageJson(pkg.path, pkg.data);
|
|
34
|
+
return { action: 'added' };
|
|
35
|
+
}
|
|
36
|
+
function buildCiCommand(scripts) {
|
|
37
|
+
const present = CI_CANDIDATES.filter((name) => scripts[name] !== undefined);
|
|
38
|
+
return present.map((name) => `npm run ${name}`).join(' && ');
|
|
39
|
+
}
|
|
40
|
+
export function addCiScript(cwd) {
|
|
41
|
+
const pkg = readPackageJson(cwd);
|
|
42
|
+
if (pkg === null)
|
|
43
|
+
return { action: 'no-package-json' };
|
|
44
|
+
const scripts = ensureScripts(pkg.data);
|
|
45
|
+
const desired = buildCiCommand(scripts);
|
|
46
|
+
const existing = scripts[CI_SCRIPT];
|
|
47
|
+
if (existing === desired)
|
|
48
|
+
return { action: 'kept', before: existing };
|
|
49
|
+
if (existing !== undefined)
|
|
50
|
+
return { action: 'conflict', before: existing };
|
|
51
|
+
scripts[CI_SCRIPT] = desired;
|
|
52
|
+
writePackageJson(pkg.path, pkg.data);
|
|
53
|
+
return { action: 'added' };
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=package-scripts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"package-scripts.js","sourceRoot":"","sources":["../../../src/cli/init/package-scripts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export interface PromptOptions {
|
|
2
|
+
defaultYes: boolean;
|
|
3
|
+
}
|
|
4
|
+
export interface Prompter {
|
|
5
|
+
ask(_question: string, _opts: PromptOptions): Promise<boolean>;
|
|
6
|
+
close(): void;
|
|
7
|
+
}
|
|
8
|
+
export declare function makeInteractivePrompter(): Prompter;
|
|
9
|
+
export declare function makeAutoPrompter(defaultYesForAll: boolean): Prompter;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import readline from 'node:readline';
|
|
2
|
+
function suffix(defaultYes) {
|
|
3
|
+
return defaultYes ? '[Y/n]' : '[y/N]';
|
|
4
|
+
}
|
|
5
|
+
function interpret(answer, defaultYes) {
|
|
6
|
+
const trimmed = answer.trim().toLowerCase();
|
|
7
|
+
if (trimmed.length === 0)
|
|
8
|
+
return defaultYes;
|
|
9
|
+
return trimmed === 'y' || trimmed === 'yes';
|
|
10
|
+
}
|
|
11
|
+
function askVia(rl, question, opts) {
|
|
12
|
+
return new Promise((resolve) => {
|
|
13
|
+
rl.question(`${question} ${suffix(opts.defaultYes)} `, (answer) => {
|
|
14
|
+
resolve(interpret(answer, opts.defaultYes));
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
export function makeInteractivePrompter() {
|
|
19
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
20
|
+
return {
|
|
21
|
+
ask: (q, opts) => askVia(rl, q, opts),
|
|
22
|
+
close: () => rl.close(),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
export function makeAutoPrompter(defaultYesForAll) {
|
|
26
|
+
return {
|
|
27
|
+
ask(_question, opts) {
|
|
28
|
+
return Promise.resolve(defaultYesForAll ? true : opts.defaultYes);
|
|
29
|
+
},
|
|
30
|
+
close() { },
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=prompts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../../src/cli/init/prompts.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,eAAe,CAAC;AAWrC,SAAS,MAAM,CAAC,UAAmB;IACjC,OAAO,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC;AACxC,CAAC;AAED,SAAS,SAAS,CAAC,MAAc,EAAE,UAAmB;IACpD,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC5C,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,UAAU,CAAC;IAC5C,OAAO,OAAO,KAAK,GAAG,IAAI,OAAO,KAAK,KAAK,CAAC;AAC9C,CAAC;AAED,SAAS,MAAM,CAAC,EAAsB,EAAE,QAAgB,EAAE,IAAmB;IAC3E,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,EAAE,CAAC,QAAQ,CAAC,GAAG,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC,MAAM,EAAE,EAAE;YAChE,OAAO,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;QAC9C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,uBAAuB;IACrC,MAAM,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACtF,OAAO;QACL,GAAG,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,EAAE,IAAI,CAAC;QACrC,KAAK,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE;KACxB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,gBAAyB;IACxD,OAAO;QACL,GAAG,CAAC,SAAS,EAAE,IAAI;YACjB,OAAO,OAAO,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACpE,CAAC;QACD,KAAK,KAAI,CAAC;KACX,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { HookResult } from './git-hook.js';
|
|
2
|
+
import type { ScriptResult } from './package-scripts.js';
|
|
3
|
+
import type { SkillResult } from './skill.js';
|
|
4
|
+
export interface Lines {
|
|
5
|
+
out: string[];
|
|
6
|
+
err: string[];
|
|
7
|
+
exit: number;
|
|
8
|
+
}
|
|
9
|
+
export declare function reportScriptResult(name: string, result: ScriptResult, lines: Lines): void;
|
|
10
|
+
export declare function reportHookResult(result: HookResult, lines: Lines): void;
|
|
11
|
+
export declare function reportSkillResult(result: SkillResult, lines: Lines): void;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
function emitConflict(lines, message) {
|
|
2
|
+
lines.err.push(`habit-hooks: ${message}\n`);
|
|
3
|
+
lines.exit = 2;
|
|
4
|
+
}
|
|
5
|
+
export function reportScriptResult(name, result, lines) {
|
|
6
|
+
if (result.action === 'added')
|
|
7
|
+
lines.out.push(`added '${name}' to package.json scripts\n`);
|
|
8
|
+
else if (result.action === 'kept')
|
|
9
|
+
lines.out.push(`'${name}' already set as desired in package.json\n`);
|
|
10
|
+
else if (result.action === 'no-package-json')
|
|
11
|
+
lines.out.push(`skipped '${name}': no package.json in cwd\n`);
|
|
12
|
+
else if (result.action === 'conflict') {
|
|
13
|
+
emitConflict(lines, `refusing to replace '${name}' script (currently: ${result.before ?? '<unknown>'})`);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export function reportHookResult(result, lines) {
|
|
17
|
+
if (result.action === 'installed')
|
|
18
|
+
lines.out.push(`installed pre-commit hook at ${result.path}\n`);
|
|
19
|
+
else if (result.action === 'kept')
|
|
20
|
+
lines.out.push(`pre-commit hook already installed at ${result.path}\n`);
|
|
21
|
+
else if (result.action === 'conflict') {
|
|
22
|
+
lines.out.push(`pre-commit hook already exists at ${result.path} — left untouched\n`);
|
|
23
|
+
}
|
|
24
|
+
else if (result.action === 'no-git') {
|
|
25
|
+
lines.out.push(`skipped pre-commit hook: no .git directory in cwd\n`);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
export function reportSkillResult(result, lines) {
|
|
29
|
+
if (result.action === 'installed')
|
|
30
|
+
lines.out.push(`installed reviewer skill at ${result.target}\n`);
|
|
31
|
+
else if (result.action === 'kept')
|
|
32
|
+
lines.out.push(`reviewer skill already at ${result.target}\n`);
|
|
33
|
+
else if (result.action === 'conflict') {
|
|
34
|
+
lines.out.push(`reviewer skill already exists at ${result.target} — left untouched\n`);
|
|
35
|
+
}
|
|
36
|
+
else if (result.action === 'source-missing') {
|
|
37
|
+
lines.err.push(`habit-hooks: could not find packaged SKILL.md — skipping\n`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=reporters.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reporters.js","sourceRoot":"","sources":["../../../src/cli/init/reporters.ts"],"names":[],"mappings":"AAUA,SAAS,YAAY,CAAC,KAAY,EAAE,OAAe;IACjD,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,gBAAgB,OAAO,IAAI,CAAC,CAAC;IAC5C,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,IAAY,EAAE,MAAoB,EAAE,KAAY;IACjF,IAAI,MAAM,CAAC,MAAM,KAAK,OAAO;QAAE,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,IAAI,6BAA6B,CAAC,CAAC;SACtF,IAAI,MAAM,CAAC,MAAM,KAAK,MAAM;QAAE,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,4CAA4C,CAAC,CAAC;SACnG,IAAI,MAAM,CAAC,MAAM,KAAK,iBAAiB;QAAE,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,IAAI,6BAA6B,CAAC,CAAC;SACvG,IAAI,MAAM,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;QACtC,YAAY,CAAC,KAAK,EAAE,wBAAwB,IAAI,wBAAwB,MAAM,CAAC,MAAM,IAAI,WAAW,GAAG,CAAC,CAAC;IAC3G,CAAC;AACH,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,MAAkB,EAAE,KAAY;IAC/D,IAAI,MAAM,CAAC,MAAM,KAAK,WAAW;QAAE,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,gCAAgC,MAAM,CAAC,IAAI,IAAI,CAAC,CAAC;SAC9F,IAAI,MAAM,CAAC,MAAM,KAAK,MAAM;QAAE,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,wCAAwC,MAAM,CAAC,IAAI,IAAI,CAAC,CAAC;SACtG,IAAI,MAAM,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;QACtC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,qCAAqC,MAAM,CAAC,IAAI,qBAAqB,CAAC,CAAC;IACxF,CAAC;SAAM,IAAI,MAAM,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;QACtC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,qDAAqD,CAAC,CAAC;IACxE,CAAC;AACH,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,MAAmB,EAAE,KAAY;IACjE,IAAI,MAAM,CAAC,MAAM,KAAK,WAAW;QAAE,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,+BAA+B,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC;SAC/F,IAAI,MAAM,CAAC,MAAM,KAAK,MAAM;QAAE,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,6BAA6B,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC;SAC7F,IAAI,MAAM,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;QACtC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,oCAAoC,MAAM,CAAC,MAAM,qBAAqB,CAAC,CAAC;IACzF,CAAC;SAAM,IAAI,MAAM,CAAC,MAAM,KAAK,gBAAgB,EAAE,CAAC;QAC9C,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,4DAA4D,CAAC,CAAC;IAC/E,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Prompter } from './prompts.js';
|
|
2
|
+
interface InitOptions {
|
|
3
|
+
prompter: Prompter;
|
|
4
|
+
dryRun?: boolean;
|
|
5
|
+
}
|
|
6
|
+
interface InitResult {
|
|
7
|
+
stdout: string;
|
|
8
|
+
stderr: string;
|
|
9
|
+
exitCode: number;
|
|
10
|
+
}
|
|
11
|
+
export declare function runInit(cwd: string, opts: InitOptions): Promise<InitResult>;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { scaffoldConfig } from './scaffold-config.js';
|
|
4
|
+
import { scaffoldBaseline } from './scaffold-baseline.js';
|
|
5
|
+
import { scaffoldEslintConfig } from './scaffold-eslint-config.js';
|
|
6
|
+
import { scaffoldKnipConfig } from './scaffold-knip-config.js';
|
|
7
|
+
import { scaffoldJscpdConfig } from './scaffold-jscpd-config.js';
|
|
8
|
+
import { detectToolStates } from './detect.js';
|
|
9
|
+
import { buildInstallCommand, detectPackageManager, packagesFor, } from './install-commands.js';
|
|
10
|
+
import { addCiScript, addHabitHooksScript } from './package-scripts.js';
|
|
11
|
+
import { installPreCommitHook } from './git-hook.js';
|
|
12
|
+
import { installReviewerSkill } from './skill.js';
|
|
13
|
+
import { AGENT_SNIPPET } from './snippet.js';
|
|
14
|
+
import { reportHookResult, reportScriptResult, reportSkillResult, } from './reporters.js';
|
|
15
|
+
function noteScaffold(ctx, result, label) {
|
|
16
|
+
if (result.created)
|
|
17
|
+
ctx.lines.out.push(`wrote ${result.path}\n`);
|
|
18
|
+
else
|
|
19
|
+
ctx.lines.out.push(`${label} already present at ${result.path}\n`);
|
|
20
|
+
}
|
|
21
|
+
function dryRunPath(ctx, filename, label) {
|
|
22
|
+
const path = join(ctx.cwd, filename);
|
|
23
|
+
if (existsSync(path))
|
|
24
|
+
ctx.lines.out.push(`${label} already present at ${path}\n`);
|
|
25
|
+
else
|
|
26
|
+
ctx.lines.out.push(`[dry-run] would write ${path}\n`);
|
|
27
|
+
}
|
|
28
|
+
const SCAFFOLDERS = {
|
|
29
|
+
eslint: scaffoldEslintConfig,
|
|
30
|
+
knip: scaffoldKnipConfig,
|
|
31
|
+
jscpd: scaffoldJscpdConfig,
|
|
32
|
+
};
|
|
33
|
+
const DEFAULT_FILENAMES = {
|
|
34
|
+
eslint: 'eslint.config.js',
|
|
35
|
+
knip: 'knip.json',
|
|
36
|
+
jscpd: '.jscpd.json',
|
|
37
|
+
};
|
|
38
|
+
const KNIP_STARTER_NOTE = 'knip.json written with starter entry points. Edit `entry` in knip.json to match your project.\n';
|
|
39
|
+
function noteKnipStarter(ctx, result) {
|
|
40
|
+
if (result.created)
|
|
41
|
+
ctx.lines.out.push(KNIP_STARTER_NOTE);
|
|
42
|
+
}
|
|
43
|
+
function scaffoldFor(ctx, tool) {
|
|
44
|
+
if (ctx.dryRun) {
|
|
45
|
+
dryRunPath(ctx, DEFAULT_FILENAMES[tool], `${tool} config`);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const result = SCAFFOLDERS[tool](ctx.cwd);
|
|
49
|
+
noteScaffold(ctx, result, `${tool} config`);
|
|
50
|
+
if (tool === 'knip')
|
|
51
|
+
noteKnipStarter(ctx, result);
|
|
52
|
+
}
|
|
53
|
+
function noteToolPresent(ctx, tool) {
|
|
54
|
+
ctx.lines.out.push(`${tool} already installed and configured\n`);
|
|
55
|
+
}
|
|
56
|
+
function noteConfigured(ctx, tool) {
|
|
57
|
+
ctx.lines.out.push(`${tool} config already present (binary missing)\n`);
|
|
58
|
+
}
|
|
59
|
+
function handleTool(ctx, tool, state) {
|
|
60
|
+
if (state.installed && state.configured) {
|
|
61
|
+
noteToolPresent(ctx, tool);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
if (state.configured)
|
|
65
|
+
noteConfigured(ctx, tool);
|
|
66
|
+
else
|
|
67
|
+
scaffoldFor(ctx, tool);
|
|
68
|
+
}
|
|
69
|
+
function collectMissingTools(matrix) {
|
|
70
|
+
return Object.keys(matrix).filter((t) => !matrix[t].installed);
|
|
71
|
+
}
|
|
72
|
+
function printInstallCommand(ctx, missing) {
|
|
73
|
+
if (missing.length === 0)
|
|
74
|
+
return;
|
|
75
|
+
const packages = missing.flatMap((t) => packagesFor(t));
|
|
76
|
+
const command = buildInstallCommand(detectPackageManager(ctx.cwd), packages);
|
|
77
|
+
ctx.lines.out.push(`\nTo install missing tools, run:\n ${command}\n`);
|
|
78
|
+
}
|
|
79
|
+
function runToolSteps(ctx) {
|
|
80
|
+
const matrix = detectToolStates(ctx.cwd);
|
|
81
|
+
for (const tool of Object.keys(matrix)) {
|
|
82
|
+
handleTool(ctx, tool, matrix[tool]);
|
|
83
|
+
}
|
|
84
|
+
printInstallCommand(ctx, collectMissingTools(matrix));
|
|
85
|
+
}
|
|
86
|
+
function writeConfigStep(ctx) {
|
|
87
|
+
if (ctx.dryRun) {
|
|
88
|
+
dryRunPath(ctx, 'habit-hooks.config.js', 'habit-hooks config');
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
noteScaffold(ctx, scaffoldConfig(ctx.cwd), 'habit-hooks config');
|
|
92
|
+
}
|
|
93
|
+
function writeBaselineStep(ctx) {
|
|
94
|
+
if (ctx.dryRun) {
|
|
95
|
+
dryRunPath(ctx, '.habit-hooks-baseline.json', 'baseline');
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
const result = scaffoldBaseline(ctx.cwd);
|
|
99
|
+
if (result.created)
|
|
100
|
+
ctx.lines.out.push(`wrote ${result.path}\n`);
|
|
101
|
+
else
|
|
102
|
+
ctx.lines.out.push(`baseline already present at ${result.path}\n`);
|
|
103
|
+
}
|
|
104
|
+
async function maybeAddHabitHooksScript(ctx, prompter) {
|
|
105
|
+
if (ctx.dryRun)
|
|
106
|
+
return;
|
|
107
|
+
const yes = await prompter.ask("Add 'habit-hooks' to package.json scripts?", { defaultYes: true });
|
|
108
|
+
if (!yes)
|
|
109
|
+
return;
|
|
110
|
+
reportScriptResult('habit-hooks', addHabitHooksScript(ctx.cwd), ctx.lines);
|
|
111
|
+
}
|
|
112
|
+
async function maybeAddCiScript(ctx, prompter) {
|
|
113
|
+
if (ctx.dryRun)
|
|
114
|
+
return;
|
|
115
|
+
const yes = await prompter.ask("Wire 'npm run ci' as the full quality gate?", { defaultYes: true });
|
|
116
|
+
if (!yes)
|
|
117
|
+
return;
|
|
118
|
+
reportScriptResult('ci', addCiScript(ctx.cwd), ctx.lines);
|
|
119
|
+
}
|
|
120
|
+
async function maybeInstallHook(ctx, prompter) {
|
|
121
|
+
if (ctx.dryRun)
|
|
122
|
+
return;
|
|
123
|
+
const yes = await prompter.ask('Install a git pre-commit hook?', { defaultYes: false });
|
|
124
|
+
if (!yes)
|
|
125
|
+
return;
|
|
126
|
+
reportHookResult(installPreCommitHook(ctx.cwd), ctx.lines);
|
|
127
|
+
}
|
|
128
|
+
async function maybeInstallSkill(ctx, prompter) {
|
|
129
|
+
if (ctx.dryRun)
|
|
130
|
+
return;
|
|
131
|
+
const yes = await prompter.ask("Install the bundled 'habit-hooks-review' skill into ~/.claude/skills/?", { defaultYes: false });
|
|
132
|
+
if (!yes)
|
|
133
|
+
return;
|
|
134
|
+
reportSkillResult(installReviewerSkill(), ctx.lines);
|
|
135
|
+
}
|
|
136
|
+
function printSnippet(lines) {
|
|
137
|
+
lines.out.push('\n--- paste into CLAUDE.md / AGENTS.md ---\n');
|
|
138
|
+
lines.out.push(AGENT_SNIPPET);
|
|
139
|
+
lines.out.push('--- end snippet ---\n');
|
|
140
|
+
}
|
|
141
|
+
async function runPrompts(ctx, prompter) {
|
|
142
|
+
await maybeAddHabitHooksScript(ctx, prompter);
|
|
143
|
+
await maybeAddCiScript(ctx, prompter);
|
|
144
|
+
await maybeInstallHook(ctx, prompter);
|
|
145
|
+
await maybeInstallSkill(ctx, prompter);
|
|
146
|
+
}
|
|
147
|
+
function toResult(lines) {
|
|
148
|
+
return { stdout: lines.out.join(''), stderr: lines.err.join(''), exitCode: lines.exit };
|
|
149
|
+
}
|
|
150
|
+
export async function runInit(cwd, opts) {
|
|
151
|
+
const ctx = { cwd, lines: { out: [], err: [], exit: 0 }, dryRun: opts.dryRun === true };
|
|
152
|
+
runToolSteps(ctx);
|
|
153
|
+
writeConfigStep(ctx);
|
|
154
|
+
writeBaselineStep(ctx);
|
|
155
|
+
await runPrompts(ctx, opts.prompter);
|
|
156
|
+
printSnippet(ctx.lines);
|
|
157
|
+
return toResult(ctx.lines);
|
|
158
|
+
}
|
|
159
|
+
//# sourceMappingURL=run.js.map
|