@auto-engineer/server-implementer 1.118.0 → 1.120.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/.turbo/turbo-build.log +1 -1
- package/.turbo/turbo-test.log +6 -6
- package/.turbo/turbo-type-check.log +1 -1
- package/CHANGELOG.md +46 -0
- package/dist/src/agent/runSlice.d.ts.map +1 -1
- package/dist/src/agent/runSlice.js +4 -25
- package/dist/src/agent/runSlice.js.map +1 -1
- package/dist/src/commands/implement-slice.d.ts.map +1 -1
- package/dist/src/commands/implement-slice.js +8 -124
- package/dist/src/commands/implement-slice.js.map +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/prompts/systemPrompt.d.ts +1 -1
- package/dist/src/prompts/systemPrompt.d.ts.map +1 -1
- package/dist/src/prompts/systemPrompt.js +82 -46
- package/dist/src/prompts/systemPrompt.js.map +1 -1
- package/dist/src/utils/buildContextSections.d.ts +4 -0
- package/dist/src/utils/buildContextSections.d.ts.map +1 -0
- package/dist/src/utils/buildContextSections.js +21 -0
- package/dist/src/utils/buildContextSections.js.map +1 -0
- package/dist/src/utils/buildContextSections.specs.d.ts +2 -0
- package/dist/src/utils/buildContextSections.specs.d.ts.map +1 -0
- package/dist/src/utils/buildContextSections.specs.js +87 -0
- package/dist/src/utils/buildContextSections.specs.js.map +1 -0
- package/dist/src/utils/loadContextFiles.d.ts +2 -0
- package/dist/src/utils/loadContextFiles.d.ts.map +1 -0
- package/dist/src/utils/loadContextFiles.js +15 -0
- package/dist/src/utils/loadContextFiles.js.map +1 -0
- package/dist/src/utils/loadContextFiles.specs.d.ts +2 -0
- package/dist/src/utils/loadContextFiles.specs.d.ts.map +1 -0
- package/dist/src/utils/loadContextFiles.specs.js +44 -0
- package/dist/src/utils/loadContextFiles.specs.js.map +1 -0
- package/dist/src/utils/loadSharedContext.d.ts +1 -1
- package/dist/src/utils/loadSharedContext.d.ts.map +1 -1
- package/dist/src/utils/loadSharedContext.js +5 -5
- package/dist/src/utils/loadSharedContext.js.map +1 -1
- package/dist/src/utils/loadSharedContext.specs.js +12 -7
- package/dist/src/utils/loadSharedContext.specs.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/ketchup-plan.md +7 -2
- package/package.json +4 -4
- package/src/agent/runSlice.ts +4 -28
- package/src/commands/implement-slice.ts +8 -142
- package/src/prompts/systemPrompt.ts +82 -46
- package/src/utils/buildContextSections.specs.ts +109 -0
- package/src/utils/buildContextSections.ts +30 -0
- package/src/utils/loadContextFiles.specs.ts +54 -0
- package/src/utils/loadContextFiles.ts +15 -0
- package/src/utils/loadSharedContext.specs.ts +12 -9
- package/src/utils/loadSharedContext.ts +6 -6
|
@@ -1,49 +1,85 @@
|
|
|
1
1
|
export const SYSTEM_PROMPT = `
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
-
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
-
|
|
43
|
-
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
2
|
+
## 1. ROLE & CONTEXT
|
|
3
|
+
|
|
4
|
+
You are a software engineer implementing @auto-implement files in a sliced event-driven TypeScript server.
|
|
5
|
+
|
|
6
|
+
- Architecture: event-sourced CQRS with @event-driven-io/emmett
|
|
7
|
+
- Language: TypeScript with type-graphql
|
|
8
|
+
- Sliced structure: Command, Reaction, Query slices
|
|
9
|
+
- Each slice has scaffolded files with implementation instructions marked with comments or TODOs
|
|
10
|
+
|
|
11
|
+
## 2. TASK
|
|
12
|
+
|
|
13
|
+
- Complete the logic in the target file following embedded instructions
|
|
14
|
+
- Return the entire updated file, production-ready
|
|
15
|
+
- Remove all TODO/instruction comments after implementing
|
|
16
|
+
|
|
17
|
+
## 3. EMMETT FRAMEWORK PATTERNS
|
|
18
|
+
|
|
19
|
+
decide(command, state) returns only { type, data }:
|
|
20
|
+
CORRECT:
|
|
21
|
+
return { type: 'OrderPlaced', data: { orderId: command.data.id } };
|
|
22
|
+
WRONG — framework adds kind/metadata internally:
|
|
23
|
+
return { type: 'OrderPlaced', data: {...}, kind: 'Event', metadata: {...} };
|
|
24
|
+
|
|
25
|
+
evolve(state, event) returns new state derived from event data:
|
|
26
|
+
CORRECT:
|
|
27
|
+
return { ...state, status: event.data.status, updatedAt: event.data.timestamp };
|
|
28
|
+
|
|
29
|
+
react(context) returns void — queries eventStore, sends commands:
|
|
30
|
+
CORRECT:
|
|
31
|
+
const { state } = await eventStore.aggregateStream(streamId, { evolve, initialState });
|
|
32
|
+
await commandSender.send({ type: 'ProcessItem', kind: 'Command', data: {...} });
|
|
33
|
+
|
|
34
|
+
Projection evolve(document, event) returns updated document.
|
|
35
|
+
|
|
36
|
+
## 4. IMPORT RULES
|
|
37
|
+
|
|
38
|
+
- The provided context files are the COMPLETE set of available modules.
|
|
39
|
+
If a module or type does not appear in any provided file, it does not exist.
|
|
40
|
+
- Only import from: sibling files (./), shared directory ('../../../shared'),
|
|
41
|
+
or packages already imported in the scaffolded code.
|
|
42
|
+
- Never create imports to modules not shown in the provided context.
|
|
43
|
+
- If you need a type that doesn't exist in any provided file,
|
|
44
|
+
use inline types or primitive values instead.
|
|
45
|
+
|
|
46
|
+
## 5. TEST SPECIFICATIONS GUIDANCE
|
|
47
|
+
|
|
48
|
+
- .specs.ts files show expected behavior via Given/When/Then patterns
|
|
49
|
+
- given([events]) = initial state, when({input}) = trigger, then({output}) = expected result
|
|
50
|
+
- Match the exact field names, types, and value derivations in assertions
|
|
51
|
+
- Pay attention to which values come from state vs. command/event data
|
|
52
|
+
- If a spec queries eventStore before testing, the implementation must too
|
|
53
|
+
- Derive values from inputs — never hardcode test literals
|
|
54
|
+
|
|
55
|
+
## 6. CONSTRAINTS
|
|
56
|
+
|
|
57
|
+
- Type safety: no type errors, annotate array literals with explicit types
|
|
58
|
+
- Enums: if shared types define enums, use constants (e.g., Status.ACTIVE) not string literals ('active')
|
|
59
|
+
- Immutability: functional patterns, never mutate state
|
|
60
|
+
- Include ALL required fields in object literals
|
|
61
|
+
- Preserve index signatures ([key: string]: unknown)
|
|
62
|
+
- Do not remove existing imports still referenced
|
|
63
|
+
- When mapping objects to a typed array, include ALL required fields in each object literal
|
|
64
|
+
|
|
65
|
+
## 7. SLICE CONVENTIONS
|
|
66
|
+
|
|
67
|
+
- Command slice: validate command, inspect state, emit events, never mutate state. Uses graphql mutations.
|
|
68
|
+
- Reaction slice: respond to events with commands.
|
|
69
|
+
- Query slice: maintain projections based on events, do not emit or throw. Uses graphql queries.
|
|
70
|
+
|
|
71
|
+
## 8. AVOID
|
|
72
|
+
|
|
73
|
+
- Adding dependencies
|
|
74
|
+
- Refactoring unrelated code
|
|
75
|
+
- Inventing types, enums, or modules not present in provided files
|
|
76
|
+
- String literals for enum-typed fields
|
|
77
|
+
- Hardcoding values that should be computed from inputs
|
|
78
|
+
- Reproducing literal values from test examples
|
|
79
|
+
|
|
80
|
+
## 9. OUTPUT
|
|
81
|
+
|
|
82
|
+
Return only the entire updated file. No commentary, no markdown fences.
|
|
83
|
+
Ensure the output is valid TypeScript.
|
|
48
84
|
`;
|
|
49
85
|
//# sourceMappingURL=systemPrompt.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"systemPrompt.js","sourceRoot":"","sources":["../../../src/prompts/systemPrompt.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,aAAa,GAAG
|
|
1
|
+
{"version":3,"file":"systemPrompt.js","sourceRoot":"","sources":["../../../src/prompts/systemPrompt.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,aAAa,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmF5B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buildContextSections.d.ts","sourceRoot":"","sources":["../../../src/utils/buildContextSections.ts"],"names":[],"mappings":"AAAA,wBAAgB,oBAAoB,CAClC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,OAAO,CAAC,EAAE;IAAE,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,GAClC,MAAM,CAyBR"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export function buildContextSections(targetFile, context, options) {
|
|
2
|
+
const sharedFiles = Object.entries(context).filter(([name]) => name.startsWith('shared/'));
|
|
3
|
+
const specs = Object.entries(context).filter(([name]) => name.endsWith('.specs.ts'));
|
|
4
|
+
const sliceFiles = Object.entries(context).filter(([name]) => name !== targetFile && !name.startsWith('shared/') && !name.endsWith('.specs.ts'));
|
|
5
|
+
let result = '';
|
|
6
|
+
if (sharedFiles.length > 0) {
|
|
7
|
+
result += `---\n📦 Shared domain types (importable from '../../../shared'):\n`;
|
|
8
|
+
result += sharedFiles.map(([name, content]) => `// File: ${name}\n${content}`).join('\n\n');
|
|
9
|
+
if (options?.enumExamples)
|
|
10
|
+
result += `\n\n${options.enumExamples}`;
|
|
11
|
+
result += '\n\n';
|
|
12
|
+
}
|
|
13
|
+
result += `---\n🧠 Other files in the same slice:\n`;
|
|
14
|
+
result += sliceFiles.map(([name, content]) => `// File: ${name}\n${content}`).join('\n\n');
|
|
15
|
+
if (specs.length > 0) {
|
|
16
|
+
result += `\n\n---\n🧪 Test specifications (READ-ONLY reference):\n`;
|
|
17
|
+
result += specs.map(([name, content]) => `// File: ${name}\n${content}`).join('\n\n');
|
|
18
|
+
}
|
|
19
|
+
return result;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=buildContextSections.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buildContextSections.js","sourceRoot":"","sources":["../../../src/utils/buildContextSections.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,oBAAoB,CAClC,UAAkB,EAClB,OAA+B,EAC/B,OAAmC;IAEnC,MAAM,WAAW,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC;IAC3F,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC;IACrF,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,CAC/C,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,IAAI,KAAK,UAAU,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAC9F,CAAC;IAEF,IAAI,MAAM,GAAG,EAAE,CAAC;IAEhB,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,oEAAoE,CAAC;QAC/E,MAAM,IAAI,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,YAAY,IAAI,KAAK,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC5F,IAAI,OAAO,EAAE,YAAY;YAAE,MAAM,IAAI,OAAO,OAAO,CAAC,YAAY,EAAE,CAAC;QACnE,MAAM,IAAI,MAAM,CAAC;IACnB,CAAC;IAED,MAAM,IAAI,0CAA0C,CAAC;IACrD,MAAM,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,YAAY,IAAI,KAAK,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAE3F,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrB,MAAM,IAAI,0DAA0D,CAAC;QACrE,MAAM,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,YAAY,IAAI,KAAK,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACxF,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buildContextSections.specs.d.ts","sourceRoot":"","sources":["../../../src/utils/buildContextSections.specs.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { buildContextSections } from './buildContextSections.js';
|
|
3
|
+
describe('buildContextSections', () => {
|
|
4
|
+
it('separates shared files, slice files, and spec files into labeled sections', () => {
|
|
5
|
+
const context = {
|
|
6
|
+
'decide.ts': 'export function decide() {}',
|
|
7
|
+
'state.ts': 'export type State = {}',
|
|
8
|
+
'decide.specs.ts': 'it("works", () => {})',
|
|
9
|
+
'shared/types.ts': 'export type Foo = string;',
|
|
10
|
+
};
|
|
11
|
+
const result = buildContextSections('decide.ts', context);
|
|
12
|
+
expect(result).toBe([
|
|
13
|
+
'---',
|
|
14
|
+
"📦 Shared domain types (importable from '../../../shared'):",
|
|
15
|
+
'// File: shared/types.ts',
|
|
16
|
+
'export type Foo = string;',
|
|
17
|
+
'',
|
|
18
|
+
'---',
|
|
19
|
+
'🧠 Other files in the same slice:',
|
|
20
|
+
'// File: state.ts',
|
|
21
|
+
'export type State = {}',
|
|
22
|
+
'',
|
|
23
|
+
'---',
|
|
24
|
+
'🧪 Test specifications (READ-ONLY reference):',
|
|
25
|
+
'// File: decide.specs.ts',
|
|
26
|
+
'it("works", () => {})',
|
|
27
|
+
].join('\n'));
|
|
28
|
+
});
|
|
29
|
+
it('omits shared section when no shared files exist', () => {
|
|
30
|
+
const context = {
|
|
31
|
+
'decide.ts': 'export function decide() {}',
|
|
32
|
+
'state.ts': 'export type State = {}',
|
|
33
|
+
};
|
|
34
|
+
const result = buildContextSections('decide.ts', context);
|
|
35
|
+
expect(result).toBe(['---', '🧠 Other files in the same slice:', '// File: state.ts', 'export type State = {}'].join('\n'));
|
|
36
|
+
});
|
|
37
|
+
it('omits spec section when no spec files exist', () => {
|
|
38
|
+
const context = {
|
|
39
|
+
'decide.ts': 'export function decide() {}',
|
|
40
|
+
'evolve.ts': 'export function evolve() {}',
|
|
41
|
+
'shared/types.ts': 'export type Foo = string;',
|
|
42
|
+
};
|
|
43
|
+
const result = buildContextSections('decide.ts', context);
|
|
44
|
+
expect(result).toBe([
|
|
45
|
+
'---',
|
|
46
|
+
"📦 Shared domain types (importable from '../../../shared'):",
|
|
47
|
+
'// File: shared/types.ts',
|
|
48
|
+
'export type Foo = string;',
|
|
49
|
+
'',
|
|
50
|
+
'---',
|
|
51
|
+
'🧠 Other files in the same slice:',
|
|
52
|
+
'// File: evolve.ts',
|
|
53
|
+
'export function evolve() {}',
|
|
54
|
+
].join('\n'));
|
|
55
|
+
});
|
|
56
|
+
it('appends enum examples to shared section when provided', () => {
|
|
57
|
+
const context = {
|
|
58
|
+
'decide.ts': 'export function decide() {}',
|
|
59
|
+
'evolve.ts': 'export function evolve() {}',
|
|
60
|
+
'shared/types.ts': 'export enum Status { ACTIVE = "active" }',
|
|
61
|
+
};
|
|
62
|
+
const result = buildContextSections('decide.ts', context, { enumExamples: 'Use Status.ACTIVE not "active"' });
|
|
63
|
+
expect(result).toBe([
|
|
64
|
+
'---',
|
|
65
|
+
"📦 Shared domain types (importable from '../../../shared'):",
|
|
66
|
+
'// File: shared/types.ts',
|
|
67
|
+
'export enum Status { ACTIVE = "active" }',
|
|
68
|
+
'',
|
|
69
|
+
'Use Status.ACTIVE not "active"',
|
|
70
|
+
'',
|
|
71
|
+
'---',
|
|
72
|
+
'🧠 Other files in the same slice:',
|
|
73
|
+
'// File: evolve.ts',
|
|
74
|
+
'export function evolve() {}',
|
|
75
|
+
].join('\n'));
|
|
76
|
+
});
|
|
77
|
+
it('excludes target file from slice files section', () => {
|
|
78
|
+
const context = {
|
|
79
|
+
'decide.ts': 'export function decide() {}',
|
|
80
|
+
'evolve.ts': 'export function evolve() {}',
|
|
81
|
+
};
|
|
82
|
+
const result = buildContextSections('decide.ts', context);
|
|
83
|
+
expect(result).not.toContain('decide.ts');
|
|
84
|
+
expect(result).toContain('// File: evolve.ts');
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
//# sourceMappingURL=buildContextSections.specs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buildContextSections.specs.js","sourceRoot":"","sources":["../../../src/utils/buildContextSections.specs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loadContextFiles.d.ts","sourceRoot":"","sources":["../../../src/utils/loadContextFiles.ts"],"names":[],"mappings":"AAKA,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CASxF"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import fg from 'fast-glob';
|
|
4
|
+
import { loadSharedContext } from './loadSharedContext.js';
|
|
5
|
+
export async function loadContextFiles(sliceDir) {
|
|
6
|
+
const files = await fg(['*.ts'], { cwd: sliceDir });
|
|
7
|
+
const context = {};
|
|
8
|
+
for (const file of files) {
|
|
9
|
+
context[file] = await readFile(path.join(sliceDir, file), 'utf-8');
|
|
10
|
+
}
|
|
11
|
+
const sharedFiles = await loadSharedContext(sliceDir);
|
|
12
|
+
Object.assign(context, sharedFiles);
|
|
13
|
+
return context;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=loadContextFiles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loadContextFiles.js","sourceRoot":"","sources":["../../../src/utils/loadContextFiles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,WAAW,CAAC;AAC3B,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAExD,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,QAAgB;IACrD,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC;IACpD,MAAM,OAAO,GAA2B,EAAE,CAAC;IAC3C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,OAAO,CAAC,IAAI,CAAC,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC;IACrE,CAAC;IACD,MAAM,WAAW,GAAG,MAAM,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IACtD,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;IACpC,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loadContextFiles.specs.d.ts","sourceRoot":"","sources":["../../../src/utils/loadContextFiles.specs.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
4
|
+
import { loadContextFiles } from './loadContextFiles.js';
|
|
5
|
+
describe('loadContextFiles', () => {
|
|
6
|
+
let tmpDir;
|
|
7
|
+
let sliceDir;
|
|
8
|
+
let sharedDir;
|
|
9
|
+
beforeEach(async () => {
|
|
10
|
+
tmpDir = await fs.mkdtemp(path.join(import.meta.dirname, '.tmp-'));
|
|
11
|
+
sharedDir = path.join(tmpDir, 'shared');
|
|
12
|
+
sliceDir = path.join(tmpDir, 'src', 'slices', 'some-slice');
|
|
13
|
+
await fs.mkdir(sliceDir, { recursive: true });
|
|
14
|
+
});
|
|
15
|
+
afterEach(async () => {
|
|
16
|
+
await fs.rm(tmpDir, { recursive: true, force: true });
|
|
17
|
+
});
|
|
18
|
+
it('loads all .ts files from slice directory including specs', async () => {
|
|
19
|
+
await fs.writeFile(path.join(sliceDir, 'decide.ts'), 'export function decide() {}');
|
|
20
|
+
await fs.writeFile(path.join(sliceDir, 'state.ts'), 'export type State = {}');
|
|
21
|
+
await fs.writeFile(path.join(sliceDir, 'decide.specs.ts'), 'it("works", () => {})');
|
|
22
|
+
const result = await loadContextFiles(sliceDir);
|
|
23
|
+
expect(result).toEqual({
|
|
24
|
+
'decide.ts': 'export function decide() {}',
|
|
25
|
+
'state.ts': 'export type State = {}',
|
|
26
|
+
'decide.specs.ts': 'it("works", () => {})',
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
it('integrates shared context files with real filenames', async () => {
|
|
30
|
+
await fs.mkdir(sharedDir, { recursive: true });
|
|
31
|
+
await fs.writeFile(path.join(sliceDir, 'decide.ts'), 'export function decide() {}');
|
|
32
|
+
await fs.writeFile(path.join(sharedDir, 'types.ts'), 'export type Foo = string;');
|
|
33
|
+
const result = await loadContextFiles(sliceDir);
|
|
34
|
+
expect(result).toEqual({
|
|
35
|
+
'decide.ts': 'export function decide() {}',
|
|
36
|
+
'shared/types.ts': 'export type Foo = string;',
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
it('returns empty record for empty slice directory', async () => {
|
|
40
|
+
const result = await loadContextFiles(sliceDir);
|
|
41
|
+
expect(result).toEqual({});
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
//# sourceMappingURL=loadContextFiles.specs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loadContextFiles.specs.js","sourceRoot":"","sources":["../../../src/utils/loadContextFiles.specs.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare function loadSharedContext(sliceDir: string): Promise<string
|
|
1
|
+
export declare function loadSharedContext(sliceDir: string): Promise<Record<string, string>>;
|
|
2
2
|
//# sourceMappingURL=loadSharedContext.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loadSharedContext.d.ts","sourceRoot":"","sources":["../../../src/utils/loadSharedContext.ts"],"names":[],"mappings":"AAKA,wBAAsB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"loadSharedContext.d.ts","sourceRoot":"","sources":["../../../src/utils/loadSharedContext.ts"],"names":[],"mappings":"AAKA,wBAAsB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAYzF"}
|
|
@@ -5,14 +5,14 @@ import fg from 'fast-glob';
|
|
|
5
5
|
export async function loadSharedContext(sliceDir) {
|
|
6
6
|
const sharedDir = path.resolve(sliceDir, '../../../shared');
|
|
7
7
|
if (!existsSync(sharedDir))
|
|
8
|
-
return
|
|
8
|
+
return {};
|
|
9
9
|
const sharedFiles = await fg(['*.ts'], { cwd: sharedDir });
|
|
10
10
|
if (sharedFiles.length === 0)
|
|
11
|
-
return
|
|
12
|
-
const
|
|
11
|
+
return {};
|
|
12
|
+
const result = {};
|
|
13
13
|
for (const file of sharedFiles.sort()) {
|
|
14
|
-
|
|
14
|
+
result[`shared/${file}`] = await readFile(path.join(sharedDir, file), 'utf-8');
|
|
15
15
|
}
|
|
16
|
-
return
|
|
16
|
+
return result;
|
|
17
17
|
}
|
|
18
18
|
//# sourceMappingURL=loadSharedContext.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loadSharedContext.js","sourceRoot":"","sources":["../../../src/utils/loadSharedContext.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,WAAW,CAAC;AAE3B,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,QAAgB;IACtD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,iBAAiB,CAAC,CAAC;IAC5D,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,
|
|
1
|
+
{"version":3,"file":"loadSharedContext.js","sourceRoot":"","sources":["../../../src/utils/loadSharedContext.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,WAAW,CAAC;AAE3B,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,QAAgB;IACtD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,iBAAiB,CAAC,CAAC;IAC5D,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,EAAE,CAAC;IAEtC,MAAM,WAAW,GAAG,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC;IAC3D,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAExC,MAAM,MAAM,GAA2B,EAAE,CAAC;IAC1C,KAAK,MAAM,IAAI,IAAI,WAAW,CAAC,IAAI,EAAE,EAAE,CAAC;QACtC,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC;IACjF,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -15,26 +15,31 @@ describe('loadSharedContext', () => {
|
|
|
15
15
|
afterEach(async () => {
|
|
16
16
|
await fs.rm(tmpDir, { recursive: true, force: true });
|
|
17
17
|
});
|
|
18
|
-
it('returns
|
|
19
|
-
expect(await loadSharedContext(sliceDir)).
|
|
18
|
+
it('returns empty record when shared directory does not exist', async () => {
|
|
19
|
+
expect(await loadSharedContext(sliceDir)).toEqual({});
|
|
20
20
|
});
|
|
21
|
-
it('returns
|
|
21
|
+
it('returns empty record when shared directory has no .ts files', async () => {
|
|
22
22
|
await fs.mkdir(sharedDir, { recursive: true });
|
|
23
23
|
await fs.writeFile(path.join(sharedDir, 'readme.md'), '# Readme');
|
|
24
|
-
expect(await loadSharedContext(sliceDir)).
|
|
24
|
+
expect(await loadSharedContext(sliceDir)).toEqual({});
|
|
25
25
|
});
|
|
26
|
-
it('
|
|
26
|
+
it('returns all .ts files from shared directory keyed by real path sorted by name', async () => {
|
|
27
27
|
await fs.mkdir(sharedDir, { recursive: true });
|
|
28
28
|
await fs.writeFile(path.join(sharedDir, 'types.ts'), 'export type Foo = string;');
|
|
29
29
|
await fs.writeFile(path.join(sharedDir, 'enums.ts'), 'export enum Bar { A = "a" }');
|
|
30
30
|
const result = await loadSharedContext(sliceDir);
|
|
31
|
-
expect(result).
|
|
31
|
+
expect(result).toEqual({
|
|
32
|
+
'shared/enums.ts': 'export enum Bar { A = "a" }',
|
|
33
|
+
'shared/types.ts': 'export type Foo = string;',
|
|
34
|
+
});
|
|
32
35
|
});
|
|
33
36
|
it('returns content for a single .ts file', async () => {
|
|
34
37
|
await fs.mkdir(sharedDir, { recursive: true });
|
|
35
38
|
await fs.writeFile(path.join(sharedDir, 'types.ts'), 'export type X = number;');
|
|
36
39
|
const result = await loadSharedContext(sliceDir);
|
|
37
|
-
expect(result).
|
|
40
|
+
expect(result).toEqual({
|
|
41
|
+
'shared/types.ts': 'export type X = number;',
|
|
42
|
+
});
|
|
38
43
|
});
|
|
39
44
|
});
|
|
40
45
|
//# sourceMappingURL=loadSharedContext.specs.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loadSharedContext.specs.js","sourceRoot":"","sources":["../../../src/utils/loadSharedContext.specs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AACrE,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAExD,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IACjC,IAAI,MAAc,CAAC;IACnB,IAAI,QAAgB,CAAC;IACrB,IAAI,SAAiB,CAAC;IAEtB,UAAU,CAAC,KAAK,IAAI,EAAE;QACpB,MAAM,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;QACnE,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QACxC,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAC;QAC5D,MAAM,EAAE,CAAC,KAAK,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,KAAK,IAAI,EAAE;QACnB,MAAM,EAAE,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"loadSharedContext.specs.js","sourceRoot":"","sources":["../../../src/utils/loadSharedContext.specs.ts"],"names":[],"mappings":"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"}
|