@eventmodelers/cli 1.0.48 → 1.0.50
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/cli.js +93 -14
- package/package.json +1 -1
- package/stacks/node/templates/build-kit/CLAUDE.md +1 -1
- package/stacks/node/templates/build-kit/lib/check-commit-scope.cjs +1 -1
- package/stacks/node/templates/root/package.json +1 -1
- package/stacks/node/templates/root/setup-env.sh +4 -1
- package/stacks/supabase/templates/build-kit/CLAUDE.md +1 -1
- package/stacks/supabase/templates/build-kit/lib/check-commit-scope.cjs +1 -1
- package/stacks/supabase/templates/root/package.json +1 -1
- package/stacks/supabase/templates/root/setup-env.sh +4 -1
package/cli.js
CHANGED
|
@@ -918,20 +918,7 @@ async function installStack(stackKey, stackCfg, options = {}) {
|
|
|
918
918
|
if (options.hooks) {
|
|
919
919
|
const hooksSrc = join(rootSrc, '.githooks');
|
|
920
920
|
if (existsSync(hooksSrc)) {
|
|
921
|
-
|
|
922
|
-
const preCommitHook = join(targetDir, '.githooks', 'pre-commit');
|
|
923
|
-
if (existsSync(preCommitHook)) {
|
|
924
|
-
// cpSync doesn't reliably carry over the executable bit across platforms,
|
|
925
|
-
// and git silently skips a non-executable hook.
|
|
926
|
-
try { execSync(`chmod +x "${preCommitHook}"`); } catch {}
|
|
927
|
-
}
|
|
928
|
-
try {
|
|
929
|
-
execSync('git rev-parse --git-dir', { cwd: targetDir, stdio: 'ignore' });
|
|
930
|
-
execSync('git config core.hooksPath .githooks', { cwd: targetDir });
|
|
931
|
-
console.log(' ✓ Installed .githooks/ and set core.hooksPath — commits touching src/slices/ are now scope-guarded');
|
|
932
|
-
} catch {
|
|
933
|
-
console.log(' ✓ Installed .githooks/ — run `git config core.hooksPath .githooks` once this directory is a git repo to activate it');
|
|
934
|
-
}
|
|
921
|
+
configureHooks({ hooksSrc, targetDir });
|
|
935
922
|
} else {
|
|
936
923
|
console.log(' ℹ️ --hooks was given but this stack ships no .githooks/ template — nothing to install');
|
|
937
924
|
}
|
|
@@ -1188,6 +1175,33 @@ async function configureMcp(options = {}) {
|
|
|
1188
1175
|
}
|
|
1189
1176
|
}
|
|
1190
1177
|
|
|
1178
|
+
// Installs/refreshes the slice commit-scope guard (.githooks/pre-commit, running
|
|
1179
|
+
// .build-kit/lib/check-commit-scope.cjs) and wires it up via `git config
|
|
1180
|
+
// core.hooksPath .githooks`. Shared by `init --hooks`, `re-init --hooks`, and the
|
|
1181
|
+
// standalone `init-hooks` command so all three copy/chmod/git-config identically
|
|
1182
|
+
// instead of drifting apart — callers are responsible for checking `hooksSrc`
|
|
1183
|
+
// exists first, since what "no template for this stack" means differs per caller.
|
|
1184
|
+
function configureHooks({ hooksSrc, targetDir }) {
|
|
1185
|
+
copyDirContents(hooksSrc, join(targetDir, '.githooks'));
|
|
1186
|
+
const preCommitHook = join(targetDir, '.githooks', 'pre-commit');
|
|
1187
|
+
if (existsSync(preCommitHook)) {
|
|
1188
|
+
// cpSync doesn't reliably carry over the executable bit across platforms,
|
|
1189
|
+
// and git silently skips a non-executable hook.
|
|
1190
|
+
try { execSync(`chmod +x "${preCommitHook}"`); } catch {}
|
|
1191
|
+
}
|
|
1192
|
+
try {
|
|
1193
|
+
execSync('git rev-parse --git-dir', { cwd: targetDir, stdio: 'ignore' });
|
|
1194
|
+
// core.hooksPath is resolved against the repo's actual top level, not `cwd` —
|
|
1195
|
+
// a relative `.githooks` breaks silently (no error, hooks just don't run) when
|
|
1196
|
+
// targetDir is a subfolder of a larger repo rather than the repo root itself.
|
|
1197
|
+
// Use an absolute path so it's correct regardless of where the git root is.
|
|
1198
|
+
execSync(`git config core.hooksPath "${join(targetDir, '.githooks')}"`, { cwd: targetDir });
|
|
1199
|
+
console.log(' ✓ Installed .githooks/ and set core.hooksPath — commits touching src/slices/ are now scope-guarded');
|
|
1200
|
+
} catch {
|
|
1201
|
+
console.log(` ✓ Installed .githooks/ — run \`git config core.hooksPath ${join(targetDir, '.githooks')}\` once this directory is a git repo to activate it`);
|
|
1202
|
+
}
|
|
1203
|
+
}
|
|
1204
|
+
|
|
1191
1205
|
// Registers the eventmodelers MCP server in `.mcp.json` at the project root, the
|
|
1192
1206
|
// same file/shape the `connect` skill's Step 3.5 produces — kept here as a
|
|
1193
1207
|
// belt-and-suspenders guarantee, since an agent executing that skill can skip a
|
|
@@ -1773,6 +1787,71 @@ program
|
|
|
1773
1787
|
await configureAgentHosts({ hosts, global: opts.global });
|
|
1774
1788
|
});
|
|
1775
1789
|
|
|
1790
|
+
program
|
|
1791
|
+
.command('init-hooks')
|
|
1792
|
+
.description('Install/refresh the slice commit-scope guard (.githooks/pre-commit) and set `git config core.hooksPath .githooks` — same as `init --hooks`/`re-init --hooks`, for installing the latest hooks or re-pointing git config at them without a full re-scaffold')
|
|
1793
|
+
.option('--stack <name>', `Which stack's .githooks/ template to install (${Object.keys(STACKS).join(', ')}) — defaults to whichever stack is recorded in install-manifest.json`)
|
|
1794
|
+
.action(async (opts) => {
|
|
1795
|
+
const targetDir = process.cwd();
|
|
1796
|
+
|
|
1797
|
+
let stackKey = opts.stack;
|
|
1798
|
+
if (stackKey && !STACKS[stackKey]) {
|
|
1799
|
+
console.error(`❌ Unknown stack "${stackKey}". Available: ${Object.keys(STACKS).join(', ')}`);
|
|
1800
|
+
process.exit(1);
|
|
1801
|
+
}
|
|
1802
|
+
if (!stackKey) {
|
|
1803
|
+
for (const name of KIT_DIR_NAMES) {
|
|
1804
|
+
const manifest = readJsonSafe(join(targetDir, name, '.eventmodelers', 'install-manifest.json'));
|
|
1805
|
+
if (manifest.stack && STACKS[manifest.stack]) {
|
|
1806
|
+
stackKey = manifest.stack;
|
|
1807
|
+
break;
|
|
1808
|
+
}
|
|
1809
|
+
}
|
|
1810
|
+
}
|
|
1811
|
+
if (!stackKey) {
|
|
1812
|
+
console.error(`❌ Can't tell which stack's .githooks/ template to install — pass --stack <name> (${Object.keys(STACKS).join(', ')}), or run \`init\`/\`re-init\` for one of those stacks first.`);
|
|
1813
|
+
process.exit(1);
|
|
1814
|
+
}
|
|
1815
|
+
|
|
1816
|
+
const hooksSrc = join(__dirname, 'stacks', stackKey, 'templates', 'root', '.githooks');
|
|
1817
|
+
if (!existsSync(hooksSrc)) {
|
|
1818
|
+
console.error(`❌ "${stackKey}" ships no .githooks/ template — nothing to install.`);
|
|
1819
|
+
process.exit(1);
|
|
1820
|
+
}
|
|
1821
|
+
|
|
1822
|
+
console.log('🪝 Configuring git hooks...');
|
|
1823
|
+
configureHooks({ hooksSrc, targetDir });
|
|
1824
|
+
});
|
|
1825
|
+
|
|
1826
|
+
program
|
|
1827
|
+
.command('disable-hooks')
|
|
1828
|
+
.description('Turn off the slice commit-scope guard by unsetting `git config core.hooksPath` — leaves .githooks/ on disk untouched; run `init-hooks` again any time to re-enable')
|
|
1829
|
+
.action(() => {
|
|
1830
|
+
const targetDir = process.cwd();
|
|
1831
|
+
|
|
1832
|
+
try {
|
|
1833
|
+
execSync('git rev-parse --git-dir', { cwd: targetDir, stdio: 'ignore' });
|
|
1834
|
+
} catch {
|
|
1835
|
+
console.error(`❌ ${targetDir} is not a git repository — nothing to unset.`);
|
|
1836
|
+
process.exit(1);
|
|
1837
|
+
}
|
|
1838
|
+
|
|
1839
|
+
let currentHooksPath = null;
|
|
1840
|
+
try {
|
|
1841
|
+
currentHooksPath = execSync('git config --get core.hooksPath', { cwd: targetDir, stdio: ['ignore', 'pipe', 'ignore'] }).toString().trim();
|
|
1842
|
+
} catch {
|
|
1843
|
+
// core.hooksPath isn't set — nothing to do
|
|
1844
|
+
}
|
|
1845
|
+
|
|
1846
|
+
if (!currentHooksPath) {
|
|
1847
|
+
console.log(' ℹ️ core.hooksPath is not set — the guard is already off, nothing to do.');
|
|
1848
|
+
return;
|
|
1849
|
+
}
|
|
1850
|
+
|
|
1851
|
+
execSync('git config --unset core.hooksPath', { cwd: targetDir });
|
|
1852
|
+
console.log(` ✓ Unset core.hooksPath (was "${currentHooksPath}") — the commit-scope guard is now off. Run \`init-hooks\` again to turn it back on.`);
|
|
1853
|
+
});
|
|
1854
|
+
|
|
1776
1855
|
credentialFlags(program
|
|
1777
1856
|
.command('init-config')
|
|
1778
1857
|
.description('Configure credentials only — writes .eventmodelers/config.json in the current directory, or ~/.eventmodelers/config.json with --global')
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eventmodelers/cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.50",
|
|
4
4
|
"description": "Eventmodelers CLI — real-time Claude agent + skills for Claude Code, for any stack (Node, Supabase, Axon, Cratis, OpenCQRS, UmaDB, Kurrent, or modeling-only)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -75,7 +75,7 @@ It loads every check under `.build-kit/lib/checks/` and rejects the commit if an
|
|
|
75
75
|
- **tsc-build** — `npx tsc --noEmit` must still pass
|
|
76
76
|
|
|
77
77
|
If a commit is rejected, split it — commit the out-of-scope file separately from the slice work, or add
|
|
78
|
-
the missing test/fix the field — rather than passing `--no-verify`. Run `npm run
|
|
78
|
+
the missing test/fix the field — rather than passing `--no-verify`. Run `npm run run:checks` any time
|
|
79
79
|
you want to check staged files before committing. To add a new check, read
|
|
80
80
|
`.build-kit/lib/checks/README.md` and drop in a file following its interface — no other wiring needed.
|
|
81
81
|
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
// SLICE_PATTERN RegExp matching a path inside a slice's own folder
|
|
24
24
|
//
|
|
25
25
|
// Zero dependencies — plain Node, so it works from git's pre-commit hook
|
|
26
|
-
// (see ../../.githooks/pre-commit), from `npm run
|
|
26
|
+
// (see ../../.githooks/pre-commit), from `npm run run:checks`, or from CI.
|
|
27
27
|
// Invoked as: node .build-kit/lib/check-commit-scope.cjs
|
|
28
28
|
|
|
29
29
|
const { execSync } = require('child_process');
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"build": "tsc",
|
|
9
9
|
"start": "NODE_ENV=production node --env-file=.env --require ts-node/register server.ts",
|
|
10
10
|
"test": "tsx --test 'src/**/*.test.ts'",
|
|
11
|
-
"
|
|
11
|
+
"run:checks": "node .build-kit/lib/check-commit-scope.cjs"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
14
|
"@event-driven-io/emmett": "^0.42.1-alpha.1",
|
|
@@ -54,6 +54,9 @@ echo ".env created successfully."
|
|
|
54
54
|
|
|
55
55
|
if [ -f .githooks/pre-commit ] && git rev-parse --git-dir >/dev/null 2>&1; then
|
|
56
56
|
chmod +x .githooks/pre-commit 2>/dev/null || true
|
|
57
|
-
|
|
57
|
+
# core.hooksPath resolves against the repo's actual top level, not this directory —
|
|
58
|
+
# a relative ".githooks" silently breaks (no error, hooks just don't run) when this
|
|
59
|
+
# project sits in a subfolder of a larger repo instead of being the repo root itself.
|
|
60
|
+
git config core.hooksPath "$(pwd)/.githooks"
|
|
58
61
|
echo "Configured git to use .githooks/ (slice commit-scope guard)."
|
|
59
62
|
fi
|
|
@@ -79,7 +79,7 @@ and rejects the commit if any of them find a problem:
|
|
|
79
79
|
- **tsc-build** — `npx tsc --noEmit` must still pass
|
|
80
80
|
|
|
81
81
|
If a commit is rejected, split it — commit the out-of-scope file separately from the slice work, or add
|
|
82
|
-
the missing test/fix the field — rather than passing `--no-verify`. Run `npm run
|
|
82
|
+
the missing test/fix the field — rather than passing `--no-verify`. Run `npm run run:checks` any time
|
|
83
83
|
you want to check staged files before committing. To add a new check, read
|
|
84
84
|
`.build-kit/lib/checks/README.md` and drop in a file following its interface — no other wiring needed.
|
|
85
85
|
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
// SLICE_PATTERN RegExp matching a path inside a slice's own folder
|
|
24
24
|
//
|
|
25
25
|
// Zero dependencies — plain Node, so it works from git's pre-commit hook
|
|
26
|
-
// (see ../../.githooks/pre-commit), from `npm run
|
|
26
|
+
// (see ../../.githooks/pre-commit), from `npm run run:checks`, or from CI.
|
|
27
27
|
// Invoked as: node .build-kit/lib/check-commit-scope.cjs
|
|
28
28
|
|
|
29
29
|
const { execSync } = require('child_process');
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"build": "tsc",
|
|
9
9
|
"start": "NODE_ENV=production node --env-file=.env --require ts-node/register server.ts",
|
|
10
10
|
"test": "tsx --test 'src/**/*.test.ts'",
|
|
11
|
-
"
|
|
11
|
+
"run:checks": "node .build-kit/lib/check-commit-scope.cjs"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
14
|
"@event-driven-io/emmett": "^0.42.1-alpha.1",
|
|
@@ -54,6 +54,9 @@ echo ".env created successfully."
|
|
|
54
54
|
|
|
55
55
|
if [ -f .githooks/pre-commit ] && git rev-parse --git-dir >/dev/null 2>&1; then
|
|
56
56
|
chmod +x .githooks/pre-commit 2>/dev/null || true
|
|
57
|
-
|
|
57
|
+
# core.hooksPath resolves against the repo's actual top level, not this directory —
|
|
58
|
+
# a relative ".githooks" silently breaks (no error, hooks just don't run) when this
|
|
59
|
+
# project sits in a subfolder of a larger repo instead of being the repo root itself.
|
|
60
|
+
git config core.hooksPath "$(pwd)/.githooks"
|
|
58
61
|
echo "Configured git to use .githooks/ (slice commit-scope guard)."
|
|
59
62
|
fi
|