@eventmodelers/cli 1.0.45 → 1.0.46
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/README.md +4 -1
- package/cli.js +53 -1
- package/package.json +2 -2
- package/shared/build-kit/lib/checks/README.md +59 -0
- package/shared/build-kit/lib/ralph.js +110 -28
- package/shared/build-kit/lib/util/find-slice.cjs +59 -0
- package/shared/build-kit/ralph-claude.js +6 -2
- package/stacks/blank/templates/build-kit/lib/backend-prompt.md +106 -102
- package/stacks/blank/templates/build-kit/lib/prompt.md +102 -106
- package/stacks/kurrent/templates/.claude/skills/build-automation/SKILL.md +422 -0
- package/stacks/kurrent/templates/.claude/skills/build-automation/references/feature-flag-patterns.md +19 -0
- package/stacks/kurrent/templates/.claude/skills/build-automation/references/idempotent-dispatch-patterns.md +65 -0
- package/stacks/kurrent/templates/.claude/skills/build-state-change/SKILL.md +418 -0
- package/stacks/kurrent/templates/.claude/skills/build-state-change/references/feature-flag-patterns.md +41 -0
- package/stacks/kurrent/templates/.claude/skills/build-state-change/references/integration-test-patterns.md +64 -0
- package/stacks/kurrent/templates/.claude/skills/build-state-view/SKILL.md +391 -0
- package/stacks/kurrent/templates/build-kit/CLAUDE.md +122 -0
- package/stacks/kurrent/templates/build-kit/lib/AGENT.md +73 -0
- package/stacks/kurrent/templates/build-kit/lib/backend-prompt.md +169 -0
- package/stacks/kurrent/templates/build-kit/lib/prompt.md +128 -0
- package/stacks/kurrent/templates/root/README.md +46 -0
- package/stacks/kurrent/templates/root/docker-compose.yml +45 -0
- package/stacks/kurrent/templates/root/mvnw +259 -0
- package/stacks/kurrent/templates/root/mvnw.cmd +149 -0
- package/stacks/kurrent/templates/root/pom.xml +152 -0
- package/stacks/kurrent/templates/root/src/main/java/com/example/quickstart/QuickstartApplication.java +12 -0
- package/stacks/kurrent/templates/root/src/main/java/com/example/quickstart/common/EventStore.java +91 -0
- package/stacks/kurrent/templates/root/src/main/java/com/example/quickstart/config/KurrentConfiguration.java +42 -0
- package/stacks/kurrent/templates/root/src/main/resources/application.properties +14 -0
- package/stacks/kurrent/templates/root/src/main/resources/static/index.html +11 -0
- package/stacks/node/templates/build-kit/CLAUDE.md +22 -0
- package/stacks/node/templates/build-kit/lib/check-commit-scope.cjs +123 -0
- package/stacks/node/templates/build-kit/lib/checks/00-blocked-paths.cjs +28 -0
- package/stacks/node/templates/build-kit/lib/checks/10-slice-scope.cjs +29 -0
- package/stacks/node/templates/build-kit/lib/checks/20-append-only-migrations.cjs +20 -0
- package/stacks/node/templates/build-kit/lib/checks/30-test-file-present.cjs +44 -0
- package/stacks/node/templates/build-kit/lib/checks/40-no-invented-fields.cjs +92 -0
- package/stacks/node/templates/build-kit/lib/checks/50-spec-coverage.cjs +50 -0
- package/stacks/node/templates/build-kit/lib/checks/90-tsc-build.cjs +22 -0
- package/stacks/node/templates/root/.githooks/pre-commit +11 -0
- package/stacks/node/templates/root/package.json +2 -1
- package/stacks/node/templates/root/setup-env.sh +7 -1
- package/stacks/opencqrs/templates/.claude/skills/build-automation/SKILL.md +434 -0
- package/stacks/opencqrs/templates/.claude/skills/build-automation/references/feature-flag-patterns.md +19 -0
- package/stacks/opencqrs/templates/.claude/skills/build-automation/references/idempotent-dispatch-patterns.md +62 -0
- package/stacks/opencqrs/templates/.claude/skills/build-state-change/SKILL.md +413 -0
- package/stacks/opencqrs/templates/.claude/skills/build-state-change/references/feature-flag-patterns.md +46 -0
- package/stacks/opencqrs/templates/.claude/skills/build-state-change/references/rest-api-patterns.md +145 -0
- package/stacks/opencqrs/templates/.claude/skills/build-state-change/references/test-fixture-patterns.md +85 -0
- package/stacks/opencqrs/templates/.claude/skills/build-state-view/SKILL.md +354 -0
- package/stacks/opencqrs/templates/build-kit/CLAUDE.md +101 -0
- package/stacks/opencqrs/templates/build-kit/lib/AGENT.md +58 -0
- package/stacks/opencqrs/templates/build-kit/lib/backend-prompt.md +169 -0
- package/stacks/opencqrs/templates/build-kit/lib/prompt.md +128 -0
- package/stacks/opencqrs/templates/root/README.md +42 -0
- package/stacks/opencqrs/templates/root/docker-compose.yml +37 -0
- package/stacks/opencqrs/templates/root/mvnw +259 -0
- package/stacks/opencqrs/templates/root/mvnw.cmd +149 -0
- package/stacks/opencqrs/templates/root/pom.xml +139 -0
- package/stacks/opencqrs/templates/root/src/main/java/com/example/quickstart/QuickstartApplication.java +12 -0
- package/stacks/opencqrs/templates/root/src/main/java/com/example/quickstart/config/CqrsConfiguration.java +74 -0
- package/stacks/opencqrs/templates/root/src/main/resources/application.properties +23 -0
- package/stacks/opencqrs/templates/root/src/main/resources/schema.sql +19 -0
- package/stacks/opencqrs/templates/root/src/main/resources/static/index.html +11 -0
- package/stacks/supabase/templates/build-kit/CLAUDE.md +25 -0
- package/stacks/supabase/templates/build-kit/lib/check-commit-scope.cjs +126 -0
- package/stacks/supabase/templates/build-kit/lib/checks/00-blocked-paths.cjs +28 -0
- package/stacks/supabase/templates/build-kit/lib/checks/10-slice-scope.cjs +34 -0
- package/stacks/supabase/templates/build-kit/lib/checks/20-append-only-migrations.cjs +21 -0
- package/stacks/supabase/templates/build-kit/lib/checks/30-test-file-present.cjs +44 -0
- package/stacks/supabase/templates/build-kit/lib/checks/40-no-invented-fields.cjs +92 -0
- package/stacks/supabase/templates/build-kit/lib/checks/50-spec-coverage.cjs +50 -0
- package/stacks/supabase/templates/build-kit/lib/checks/90-tsc-build.cjs +22 -0
- package/stacks/supabase/templates/root/.githooks/pre-commit +11 -0
- package/stacks/supabase/templates/root/package.json +2 -1
- package/stacks/supabase/templates/root/setup-env.sh +7 -1
- package/stacks/umadb/templates/.claude/skills/build-automation/SKILL.md +313 -0
- package/stacks/umadb/templates/.claude/skills/build-automation/references/feature-flag-patterns.md +42 -0
- package/stacks/umadb/templates/.claude/skills/build-state-change/SKILL.md +376 -0
- package/stacks/umadb/templates/.claude/skills/build-state-change/references/feature-flag-patterns.md +42 -0
- package/stacks/umadb/templates/.claude/skills/build-state-change/references/umadb-query-patterns.md +78 -0
- package/stacks/umadb/templates/.claude/skills/build-state-view/SKILL.md +338 -0
- package/stacks/umadb/templates/build-kit/CLAUDE.md +94 -0
- package/stacks/umadb/templates/build-kit/lib/AGENT.md +47 -0
- package/stacks/umadb/templates/build-kit/lib/backend-prompt.md +169 -0
- package/stacks/umadb/templates/build-kit/lib/prompt.md +128 -0
- package/stacks/umadb/templates/root/.mvn/wrapper/maven-wrapper.properties +19 -0
- package/stacks/umadb/templates/root/README.md +48 -0
- package/stacks/umadb/templates/root/docker-compose.yml +29 -0
- package/stacks/umadb/templates/root/mvnw +259 -0
- package/stacks/umadb/templates/root/mvnw.cmd +149 -0
- package/stacks/umadb/templates/root/pom.xml +151 -0
- package/stacks/umadb/templates/root/src/main/java/io/umadb/quickstart/QuickstartApplication.java +12 -0
- package/stacks/umadb/templates/root/src/main/java/io/umadb/quickstart/config/UmaDbConfig.java +39 -0
- package/stacks/umadb/templates/root/src/main/java/io/umadb/quickstart/eventstore/DecisionModelLoader.java +76 -0
- package/stacks/umadb/templates/root/src/main/java/io/umadb/quickstart/eventstore/EventCodec.java +40 -0
- package/stacks/umadb/templates/root/src/main/java/io/umadb/quickstart/eventstore/EventDispatcher.java +100 -0
- package/stacks/umadb/templates/root/src/main/java/io/umadb/quickstart/eventstore/OptimisticConcurrencyException.java +14 -0
- package/stacks/umadb/templates/root/src/main/java/io/umadb/quickstart/eventstore/SliceEventListener.java +23 -0
- package/stacks/umadb/templates/root/src/main/resources/application.properties +17 -0
- package/stacks/umadb/templates/root/src/test/java/io/umadb/quickstart/testsupport/InMemoryUmaDbClient.java +135 -0
- package/stacks/umadb/templates/root/src/test/resources/application.properties +8 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// Everything staged in a slice commit must be inside the slice's own folder, or
|
|
4
|
+
// one of the documented shared-infra exceptions a slice legitimately registers
|
|
5
|
+
// *into* (never rewrites wholesale). See build-kit/lib/AGENT.md and the
|
|
6
|
+
// build-state-view/build-automation SKILL.md files for what a compliant edit to
|
|
7
|
+
// an exception file looks like. Migration files have their own dedicated check
|
|
8
|
+
// (20-append-only-migrations.cjs), so they're allowed through here.
|
|
9
|
+
|
|
10
|
+
const ALLOWED_EXCEPTIONS = [
|
|
11
|
+
/^src\/slices\/[^/]+\/[A-Za-z0-9]+Events\.ts$/, // per-context event union (append-only)
|
|
12
|
+
/^src\/common\/loadPostgresEventstore\.ts$/, // projection registration / schema.migrate()
|
|
13
|
+
];
|
|
14
|
+
|
|
15
|
+
const MIGRATION_PATTERN = /^migrations\/V\d+__.*\.sql$/;
|
|
16
|
+
|
|
17
|
+
module.exports = {
|
|
18
|
+
name: 'slice-scope',
|
|
19
|
+
run(ctx) {
|
|
20
|
+
const violations = [];
|
|
21
|
+
for (const { path: p } of ctx.changes) {
|
|
22
|
+
if (ctx.SLICE_PATTERN.test(p)) continue;
|
|
23
|
+
if (MIGRATION_PATTERN.test(p)) continue;
|
|
24
|
+
if (ALLOWED_EXCEPTIONS.some((r) => r.test(p))) continue;
|
|
25
|
+
violations.push({ path: p, reason: 'outside src/slices/{context}/{slice}/ and not a documented exception' });
|
|
26
|
+
}
|
|
27
|
+
return violations;
|
|
28
|
+
},
|
|
29
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// migrations/V{n}__*.sql may only be ADDED, never modified or deleted — migrations
|
|
4
|
+
// are append-only; a fix belongs in a new migration, not an edit to an old one.
|
|
5
|
+
|
|
6
|
+
const MIGRATION_PATTERN = /^migrations\/V\d+__.*\.sql$/;
|
|
7
|
+
|
|
8
|
+
module.exports = {
|
|
9
|
+
name: 'append-only-migrations',
|
|
10
|
+
run(ctx) {
|
|
11
|
+
const violations = [];
|
|
12
|
+
for (const { status, path: p } of ctx.changes) {
|
|
13
|
+
if (!MIGRATION_PATTERN.test(p)) continue;
|
|
14
|
+
if (status !== 'A') {
|
|
15
|
+
violations.push({ path: p, reason: 'existing migrations are append-only; add a new V{n} file instead of editing this one' });
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return violations;
|
|
19
|
+
},
|
|
20
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// A slice commit that adds/changes a command handler, projection, or processor
|
|
4
|
+
// must also include a *.test.ts for that slice — catches the agent skipping the
|
|
5
|
+
// matching build skill's test step (build-state-change Step 4 / build-state-view
|
|
6
|
+
// Step 5 / build-automation's DeciderSpecification tests).
|
|
7
|
+
|
|
8
|
+
const { execSync } = require('child_process');
|
|
9
|
+
|
|
10
|
+
const IMPLEMENTATION_FILE = /^src\/slices\/([^/]+)\/([^/]+)\/(?:[A-Za-z0-9]+Command|[A-Za-z0-9]+Projection|processor(?:-[A-Za-z0-9]+)?)\.ts$/;
|
|
11
|
+
|
|
12
|
+
module.exports = {
|
|
13
|
+
name: 'test-file-present',
|
|
14
|
+
run(ctx) {
|
|
15
|
+
const sliceDirs = new Set();
|
|
16
|
+
for (const { path: p } of ctx.changes) {
|
|
17
|
+
const m = IMPLEMENTATION_FILE.exec(p);
|
|
18
|
+
if (m) sliceDirs.add(`src/slices/${m[1]}/${m[2]}`);
|
|
19
|
+
}
|
|
20
|
+
if (sliceDirs.size === 0) return [];
|
|
21
|
+
|
|
22
|
+
let tracked = [];
|
|
23
|
+
try {
|
|
24
|
+
tracked = execSync('git ls-files -- src/slices', { cwd: ctx.repoRoot, encoding: 'utf8' })
|
|
25
|
+
.split('\n')
|
|
26
|
+
.filter(Boolean);
|
|
27
|
+
} catch {
|
|
28
|
+
// best-effort — fall through with whatever's staged
|
|
29
|
+
}
|
|
30
|
+
const known = new Set([...tracked, ...ctx.changes.map((c) => c.path)]);
|
|
31
|
+
|
|
32
|
+
const violations = [];
|
|
33
|
+
for (const dir of sliceDirs) {
|
|
34
|
+
const hasTest = [...known].some((f) => f.startsWith(`${dir}/`) && f.endsWith('.test.ts'));
|
|
35
|
+
if (!hasTest) {
|
|
36
|
+
violations.push({
|
|
37
|
+
path: dir,
|
|
38
|
+
reason: 'no *.test.ts found for this slice — command handlers/projections/processors need test coverage',
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return violations;
|
|
43
|
+
},
|
|
44
|
+
};
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// Heuristic: flags a field name used in a slice's Command/ReadModel type literal
|
|
4
|
+
// that doesn't appear anywhere in that slice's own slice.json. Not a real
|
|
5
|
+
// TS/schema-aware check (no parser dependency) — it regex-extracts the fields
|
|
6
|
+
// declared inside `Command<'Name', { ... }, ...>` and `type XReadModel = { ... }`
|
|
7
|
+
// literals, so unusual formatting (nested object/array field types, nonstandard
|
|
8
|
+
// generics) can slip past undetected. It only ever adds violations for fields it
|
|
9
|
+
// is confident about; when slice.json can't be found/parsed for a slice, that
|
|
10
|
+
// slice's files are skipped entirely rather than guessed at.
|
|
11
|
+
|
|
12
|
+
const fs = require('fs');
|
|
13
|
+
const path = require('path');
|
|
14
|
+
const { findSliceJson, normalize } = require('../util/find-slice.cjs');
|
|
15
|
+
|
|
16
|
+
const COMMON_ALLOWED = new Set(
|
|
17
|
+
['id', 'userId', 'correlationId', 'causationId', 'streamName', 'type', 'data', 'metadata', 'createdAt', 'updatedAt', 'timestamp'].map(normalize),
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
const TYPE_LITERALS = [
|
|
21
|
+
/(?:Command|Event)<\s*'[^']+'\s*,\s*{([^}]*)}/g,
|
|
22
|
+
/type\s+[A-Za-z0-9_]+ReadModel\s*=\s*{([^}]*)}/g,
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
const FIELD_LINE = /^\s*([A-Za-z_][A-Za-z0-9_]*)\??\s*:/gm;
|
|
26
|
+
|
|
27
|
+
function collectDeclaredFields(node, out) {
|
|
28
|
+
if (Array.isArray(node)) {
|
|
29
|
+
for (const item of node) collectDeclaredFields(item, out);
|
|
30
|
+
} else if (node && typeof node === 'object') {
|
|
31
|
+
if (typeof node.name === 'string' && ('type' in node || 'optional' in node)) {
|
|
32
|
+
out.add(normalize(node.name));
|
|
33
|
+
}
|
|
34
|
+
for (const key of Object.keys(node)) collectDeclaredFields(node[key], out);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
module.exports = {
|
|
39
|
+
name: 'no-invented-fields',
|
|
40
|
+
run(ctx) {
|
|
41
|
+
const bySlice = new Map(); // "context/SliceName" -> { context, sliceName, files: [] }
|
|
42
|
+
|
|
43
|
+
for (const { path: p } of ctx.changes) {
|
|
44
|
+
if (!p.endsWith('.ts') || p.endsWith('.test.ts')) continue;
|
|
45
|
+
const m = /^src\/slices\/([^/]+)\/([^/]+)\//.exec(p);
|
|
46
|
+
if (!m) continue;
|
|
47
|
+
const key = `${m[1]}/${m[2]}`;
|
|
48
|
+
if (!bySlice.has(key)) bySlice.set(key, { context: m[1], sliceName: m[2], files: [] });
|
|
49
|
+
bySlice.get(key).files.push(p);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const violations = [];
|
|
53
|
+
|
|
54
|
+
for (const { context, sliceName, files } of bySlice.values()) {
|
|
55
|
+
const slice = findSliceJson(ctx.repoRoot, context, sliceName);
|
|
56
|
+
if (!slice) continue; // can't verify — don't block
|
|
57
|
+
|
|
58
|
+
const declared = new Set();
|
|
59
|
+
collectDeclaredFields(slice, declared);
|
|
60
|
+
if (declared.size === 0) continue; // slice.json shape not recognized — don't block
|
|
61
|
+
|
|
62
|
+
for (const file of files) {
|
|
63
|
+
let content;
|
|
64
|
+
try {
|
|
65
|
+
content = fs.readFileSync(path.join(ctx.repoRoot, file), 'utf8');
|
|
66
|
+
} catch {
|
|
67
|
+
continue; // deleted/unreadable — nothing to check
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
for (const pattern of TYPE_LITERALS) {
|
|
71
|
+
pattern.lastIndex = 0;
|
|
72
|
+
let typeMatch;
|
|
73
|
+
while ((typeMatch = pattern.exec(content))) {
|
|
74
|
+
FIELD_LINE.lastIndex = 0;
|
|
75
|
+
let fieldMatch;
|
|
76
|
+
while ((fieldMatch = FIELD_LINE.exec(typeMatch[1]))) {
|
|
77
|
+
const raw = fieldMatch[1];
|
|
78
|
+
const norm = normalize(raw);
|
|
79
|
+
if (COMMON_ALLOWED.has(norm) || declared.has(norm)) continue;
|
|
80
|
+
violations.push({
|
|
81
|
+
path: file,
|
|
82
|
+
reason: `field "${raw}" is not declared anywhere in slice.json for this slice — check for an invented field`,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return violations;
|
|
91
|
+
},
|
|
92
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// Heuristic: a slice's *.test.ts must have at least as many `it(...)` blocks as
|
|
4
|
+
// slice.json has `specifications[]` entries. Doesn't verify each spec is
|
|
5
|
+
// actually tested (that would need matching scenario content, not just count),
|
|
6
|
+
// just that nobody's silently short a test case. Skipped (not blocked) when
|
|
7
|
+
// slice.json can't be found or has no specifications[] array.
|
|
8
|
+
|
|
9
|
+
const fs = require('fs');
|
|
10
|
+
const path = require('path');
|
|
11
|
+
const { findSliceJson } = require('../util/find-slice.cjs');
|
|
12
|
+
|
|
13
|
+
const TEST_FILE = /^src\/slices\/([^/]+)\/([^/]+)\/[^/]+\.test\.ts$/;
|
|
14
|
+
const IT_BLOCK = /\bit(?:\.(?:only|skip))?\s*\(/g;
|
|
15
|
+
|
|
16
|
+
module.exports = {
|
|
17
|
+
name: 'spec-coverage',
|
|
18
|
+
run(ctx) {
|
|
19
|
+
const violations = [];
|
|
20
|
+
|
|
21
|
+
for (const { path: p } of ctx.changes) {
|
|
22
|
+
TEST_FILE.lastIndex = 0;
|
|
23
|
+
const m = TEST_FILE.exec(p);
|
|
24
|
+
if (!m) continue;
|
|
25
|
+
const [, context, sliceName] = m;
|
|
26
|
+
|
|
27
|
+
const slice = findSliceJson(ctx.repoRoot, context, sliceName);
|
|
28
|
+
if (!slice || !Array.isArray(slice.specifications) || slice.specifications.length === 0) continue;
|
|
29
|
+
|
|
30
|
+
let content;
|
|
31
|
+
try {
|
|
32
|
+
content = fs.readFileSync(path.join(ctx.repoRoot, p), 'utf8');
|
|
33
|
+
} catch {
|
|
34
|
+
continue; // deleted — nothing to check
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const specCount = slice.specifications.length;
|
|
38
|
+
const itCount = (content.match(IT_BLOCK) || []).length;
|
|
39
|
+
|
|
40
|
+
if (itCount < specCount) {
|
|
41
|
+
violations.push({
|
|
42
|
+
path: p,
|
|
43
|
+
reason: `slice.json declares ${specCount} specification(s) but this test file only has ${itCount} it(...) block(s)`,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return violations;
|
|
49
|
+
},
|
|
50
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// The project must still typecheck after the slice change. Uses the project's
|
|
4
|
+
// own `typescript` devDependency via `npx tsc --noEmit` — no new dependency,
|
|
5
|
+
// but it does mean this check needs node_modules already installed (same
|
|
6
|
+
// prerequisite `npm run build` already has).
|
|
7
|
+
|
|
8
|
+
const { execSync } = require('child_process');
|
|
9
|
+
|
|
10
|
+
module.exports = {
|
|
11
|
+
name: 'tsc-build',
|
|
12
|
+
skipIfAlreadyFailing: true, // slow — don't bother once the commit is rejected already
|
|
13
|
+
run(ctx) {
|
|
14
|
+
try {
|
|
15
|
+
execSync('npx tsc --noEmit', { cwd: ctx.repoRoot, stdio: 'pipe' });
|
|
16
|
+
return [];
|
|
17
|
+
} catch (err) {
|
|
18
|
+
const output = String(err.stdout || err.message || '').trim().split('\n').slice(0, 20).join('\n');
|
|
19
|
+
return [{ path: '(tsc --noEmit)', reason: `TypeScript build failed:\n${output}` }];
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# Installed via setup-env.sh (`git config core.hooksPath .githooks`), so this file
|
|
3
|
+
# is versioned and shared by every clone instead of living only in .git/hooks/.
|
|
4
|
+
set -e
|
|
5
|
+
|
|
6
|
+
repo_root=$(git rev-parse --show-toplevel)
|
|
7
|
+
script="$repo_root/.build-kit/lib/check-commit-scope.cjs"
|
|
8
|
+
|
|
9
|
+
if [ -f "$script" ]; then
|
|
10
|
+
node "$script"
|
|
11
|
+
fi
|
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
"dev": "node --env-file=.env --require ts-node/register server.ts",
|
|
8
8
|
"build": "tsc",
|
|
9
9
|
"start": "NODE_ENV=production node --env-file=.env --require ts-node/register server.ts",
|
|
10
|
-
"test": "tsx --test 'src/**/*.test.ts'"
|
|
10
|
+
"test": "tsx --test 'src/**/*.test.ts'",
|
|
11
|
+
"check:scope": "node .build-kit/lib/check-commit-scope.cjs"
|
|
11
12
|
},
|
|
12
13
|
"dependencies": {
|
|
13
14
|
"@event-driven-io/emmett": "^0.42.1-alpha.1",
|
|
@@ -50,4 +50,10 @@ FLYWAY_PASSWORD=${DB_PASSWORD}
|
|
|
50
50
|
EOF
|
|
51
51
|
|
|
52
52
|
echo ""
|
|
53
|
-
echo ".env created successfully."
|
|
53
|
+
echo ".env created successfully."
|
|
54
|
+
|
|
55
|
+
if [ -f .githooks/pre-commit ] && git rev-parse --git-dir >/dev/null 2>&1; then
|
|
56
|
+
chmod +x .githooks/pre-commit 2>/dev/null || true
|
|
57
|
+
git config core.hooksPath .githooks
|
|
58
|
+
echo "Configured git to use .githooks/ (slice commit-scope guard)."
|
|
59
|
+
fi
|