@auto-engineer/narrative 0.16.0 → 0.17.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/CHANGELOG.md +15 -0
- package/dist/src/getNarratives.js +1 -1
- package/dist/src/getNarratives.js.map +1 -1
- package/dist/src/id/addAutoIds.d.ts.map +1 -1
- package/dist/src/id/addAutoIds.js +15 -0
- package/dist/src/id/addAutoIds.js.map +1 -1
- package/dist/src/id/hasAllIds.d.ts.map +1 -1
- package/dist/src/id/hasAllIds.js +6 -1
- package/dist/src/id/hasAllIds.js.map +1 -1
- package/dist/src/index.d.ts +5 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/loader/runtime-cjs.d.ts.map +1 -1
- package/dist/src/loader/runtime-cjs.js +3 -2
- package/dist/src/loader/runtime-cjs.js.map +1 -1
- package/dist/src/schema.d.ts +301 -143
- package/dist/src/schema.d.ts.map +1 -1
- package/dist/src/schema.js +26 -0
- package/dist/src/schema.js.map +1 -1
- package/dist/src/transformers/model-to-narrative/cross-module-imports.d.ts +6 -0
- package/dist/src/transformers/model-to-narrative/cross-module-imports.d.ts.map +1 -0
- package/dist/src/transformers/model-to-narrative/cross-module-imports.js +63 -0
- package/dist/src/transformers/model-to-narrative/cross-module-imports.js.map +1 -0
- package/dist/src/transformers/model-to-narrative/generators/flow.d.ts +1 -4
- package/dist/src/transformers/model-to-narrative/generators/flow.d.ts.map +1 -1
- package/dist/src/transformers/model-to-narrative/generators/flow.js.map +1 -1
- package/dist/src/transformers/model-to-narrative/generators/module-code.d.ts +9 -0
- package/dist/src/transformers/model-to-narrative/generators/module-code.d.ts.map +1 -0
- package/dist/src/transformers/model-to-narrative/generators/module-code.js +102 -0
- package/dist/src/transformers/model-to-narrative/generators/module-code.js.map +1 -0
- package/dist/src/transformers/model-to-narrative/index.d.ts +6 -4
- package/dist/src/transformers/model-to-narrative/index.d.ts.map +1 -1
- package/dist/src/transformers/model-to-narrative/index.js +10 -6
- package/dist/src/transformers/model-to-narrative/index.js.map +1 -1
- package/dist/src/transformers/model-to-narrative/ordering.d.ts +10 -0
- package/dist/src/transformers/model-to-narrative/ordering.d.ts.map +1 -0
- package/dist/src/transformers/model-to-narrative/ordering.js +37 -0
- package/dist/src/transformers/model-to-narrative/ordering.js.map +1 -0
- package/dist/src/transformers/model-to-narrative/spec-traversal.d.ts +3 -0
- package/dist/src/transformers/model-to-narrative/spec-traversal.d.ts.map +1 -0
- package/dist/src/transformers/model-to-narrative/spec-traversal.js +54 -0
- package/dist/src/transformers/model-to-narrative/spec-traversal.js.map +1 -0
- package/dist/src/transformers/model-to-narrative/types.d.ts +12 -0
- package/dist/src/transformers/model-to-narrative/types.d.ts.map +1 -0
- package/dist/src/transformers/model-to-narrative/types.js +2 -0
- package/dist/src/transformers/model-to-narrative/types.js.map +1 -0
- package/dist/src/transformers/model-to-narrative/validate-modules.d.ts +8 -0
- package/dist/src/transformers/model-to-narrative/validate-modules.d.ts.map +1 -0
- package/dist/src/transformers/model-to-narrative/validate-modules.js +121 -0
- package/dist/src/transformers/model-to-narrative/validate-modules.js.map +1 -0
- package/dist/src/transformers/narrative-to-model/assemble.d.ts.map +1 -1
- package/dist/src/transformers/narrative-to-model/assemble.js +5 -1
- package/dist/src/transformers/narrative-to-model/assemble.js.map +1 -1
- package/dist/src/transformers/narrative-to-model/derive-modules.d.ts +3 -0
- package/dist/src/transformers/narrative-to-model/derive-modules.d.ts.map +1 -0
- package/dist/src/transformers/narrative-to-model/derive-modules.js +29 -0
- package/dist/src/transformers/narrative-to-model/derive-modules.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -4
- package/src/getNarratives.specs.ts +214 -1
- package/src/getNarratives.ts +1 -1
- package/src/id/addAutoIds.specs.ts +180 -0
- package/src/id/addAutoIds.ts +16 -1
- package/src/id/hasAllIds.specs.ts +87 -0
- package/src/id/hasAllIds.ts +10 -2
- package/src/index.ts +7 -0
- package/src/loader/runtime-cjs.ts +3 -2
- package/src/model-to-narrative.specs.ts +467 -17
- package/src/schema.ts +28 -0
- package/src/transformers/model-to-narrative/cross-module-imports.specs.ts +450 -0
- package/src/transformers/model-to-narrative/cross-module-imports.ts +83 -0
- package/src/transformers/model-to-narrative/generators/flow.ts +11 -10
- package/src/transformers/model-to-narrative/generators/module-code.ts +186 -0
- package/src/transformers/model-to-narrative/index.ts +19 -7
- package/src/transformers/model-to-narrative/modules.specs.ts +625 -0
- package/src/transformers/model-to-narrative/ordering.specs.ts +104 -0
- package/src/transformers/model-to-narrative/ordering.ts +46 -0
- package/src/transformers/model-to-narrative/spec-traversal.specs.ts +418 -0
- package/src/transformers/model-to-narrative/spec-traversal.ts +63 -0
- package/src/transformers/model-to-narrative/types.ts +13 -0
- package/src/transformers/model-to-narrative/validate-modules.ts +159 -0
- package/src/transformers/narrative-to-model/assemble.ts +7 -2
- package/src/transformers/narrative-to-model/derive-modules.specs.ts +121 -0
- package/src/transformers/narrative-to-model/derive-modules.ts +36 -0
- package/tsconfig.test.json +2 -1
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import type { Model } from '../../index';
|
|
2
|
+
import { toMessageKey } from './ordering';
|
|
3
|
+
|
|
4
|
+
export interface ValidationError {
|
|
5
|
+
type:
|
|
6
|
+
| 'duplicate_id'
|
|
7
|
+
| 'derived_id_mismatch'
|
|
8
|
+
| 'narrative_unassigned'
|
|
9
|
+
| 'narrative_multi_assigned'
|
|
10
|
+
| 'message_multi_declared'
|
|
11
|
+
| 'message_undeclared'
|
|
12
|
+
| 'narrative_not_found';
|
|
13
|
+
message: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function validateModules(model: Model): ValidationError[] {
|
|
17
|
+
const errors: ValidationError[] = [];
|
|
18
|
+
const modules = model.modules ?? [];
|
|
19
|
+
|
|
20
|
+
if (modules.length === 0) {
|
|
21
|
+
return errors;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
errors.push(...validateUniqueModuleIds(modules));
|
|
25
|
+
errors.push(...validateDerivedModuleIds(modules));
|
|
26
|
+
|
|
27
|
+
const authoredModules = modules.filter((m) => !m.isDerived);
|
|
28
|
+
if (authoredModules.length === 0) {
|
|
29
|
+
return errors;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
errors.push(...validateNarrativeAssignments(authoredModules, model));
|
|
33
|
+
errors.push(...validateMessageDeclarations(authoredModules, model));
|
|
34
|
+
|
|
35
|
+
return errors;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function validateUniqueModuleIds(modules: Model['modules']): ValidationError[] {
|
|
39
|
+
const errors: ValidationError[] = [];
|
|
40
|
+
const idCounts = new Map<string, number>();
|
|
41
|
+
|
|
42
|
+
for (const module of modules) {
|
|
43
|
+
idCounts.set(module.id, (idCounts.get(module.id) ?? 0) + 1);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
for (const [id, count] of idCounts) {
|
|
47
|
+
if (count > 1) {
|
|
48
|
+
errors.push({
|
|
49
|
+
type: 'duplicate_id',
|
|
50
|
+
message: `Module ID '${id}' is used by ${count} modules`,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return errors;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function validateDerivedModuleIds(modules: Model['modules']): ValidationError[] {
|
|
59
|
+
const errors: ValidationError[] = [];
|
|
60
|
+
|
|
61
|
+
for (const module of modules) {
|
|
62
|
+
if (module.isDerived && module.id !== module.sourceFile) {
|
|
63
|
+
errors.push({
|
|
64
|
+
type: 'derived_id_mismatch',
|
|
65
|
+
message: `Derived module ID '${module.id}' must equal sourceFile '${module.sourceFile}'`,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return errors;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function validateNarrativeAssignments(authoredModules: Model['modules'], model: Model): ValidationError[] {
|
|
74
|
+
const errors: ValidationError[] = [];
|
|
75
|
+
const narrativeAssignments = new Map<string, string[]>();
|
|
76
|
+
|
|
77
|
+
for (const module of authoredModules) {
|
|
78
|
+
for (const narrativeId of module.contains.narrativeIds) {
|
|
79
|
+
if (!narrativeAssignments.has(narrativeId)) {
|
|
80
|
+
narrativeAssignments.set(narrativeId, []);
|
|
81
|
+
}
|
|
82
|
+
narrativeAssignments.get(narrativeId)!.push(module.id);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const modelNarrativeIds = new Set(model.narratives.map((n) => n.id).filter((id): id is string => id !== undefined));
|
|
87
|
+
|
|
88
|
+
for (const [narrativeId, moduleIds] of narrativeAssignments) {
|
|
89
|
+
if (!modelNarrativeIds.has(narrativeId)) {
|
|
90
|
+
errors.push({
|
|
91
|
+
type: 'narrative_not_found',
|
|
92
|
+
message: `Narrative '${narrativeId}' referenced by module(s) [${moduleIds.join(', ')}] does not exist`,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
if (moduleIds.length > 1) {
|
|
96
|
+
errors.push({
|
|
97
|
+
type: 'narrative_multi_assigned',
|
|
98
|
+
message: `Narrative '${narrativeId}' is assigned to multiple modules: [${moduleIds.join(', ')}]`,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const assignedNarrativeIds = new Set(narrativeAssignments.keys());
|
|
104
|
+
for (const narrative of model.narratives) {
|
|
105
|
+
if (narrative.id && !assignedNarrativeIds.has(narrative.id)) {
|
|
106
|
+
errors.push({
|
|
107
|
+
type: 'narrative_unassigned',
|
|
108
|
+
message: `Narrative '${narrative.id}' (${narrative.name}) is not assigned to any module`,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return errors;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function validateMessageDeclarations(authoredModules: Model['modules'], model: Model): ValidationError[] {
|
|
117
|
+
const errors: ValidationError[] = [];
|
|
118
|
+
const messageDeclarations = new Map<string, string[]>();
|
|
119
|
+
|
|
120
|
+
for (const module of authoredModules) {
|
|
121
|
+
for (const msg of module.declares.messages) {
|
|
122
|
+
const key = toMessageKey(msg.kind, msg.name);
|
|
123
|
+
if (!messageDeclarations.has(key)) {
|
|
124
|
+
messageDeclarations.set(key, []);
|
|
125
|
+
}
|
|
126
|
+
messageDeclarations.get(key)!.push(module.id);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
for (const [msgKey, moduleIds] of messageDeclarations) {
|
|
131
|
+
if (moduleIds.length > 1) {
|
|
132
|
+
errors.push({
|
|
133
|
+
type: 'message_multi_declared',
|
|
134
|
+
message: `Message '${msgKey}' is declared by multiple modules: [${moduleIds.join(', ')}]`,
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const declaredMessages = new Set(messageDeclarations.keys());
|
|
140
|
+
const modelMessageKeys = new Set(model.messages.map((m) => toMessageKey(m.type, m.name)));
|
|
141
|
+
|
|
142
|
+
for (const msgKey of modelMessageKeys) {
|
|
143
|
+
if (!declaredMessages.has(msgKey)) {
|
|
144
|
+
errors.push({
|
|
145
|
+
type: 'message_undeclared',
|
|
146
|
+
message: `Message '${msgKey}' exists in model but is not declared by any authored module`,
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return errors;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export function throwOnValidationErrors(errors: ValidationError[]): void {
|
|
155
|
+
if (errors.length > 0) {
|
|
156
|
+
const messages = errors.map((e) => ` - ${e.message}`).join('\n');
|
|
157
|
+
throw new Error(`Module validation failed:\n${messages}`);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
import type { Model, Narrative } from '../../index';
|
|
1
|
+
import type { Message, Model, Narrative } from '../../index';
|
|
2
|
+
import { deriveModules } from './derive-modules';
|
|
2
3
|
|
|
3
4
|
export function assembleSpecs(narratives: Narrative[], messages: unknown[], integrations: unknown[]): Model {
|
|
5
|
+
const typedMessages = messages as Message[];
|
|
6
|
+
const modules = deriveModules(narratives, typedMessages);
|
|
7
|
+
|
|
4
8
|
return {
|
|
5
9
|
variant: 'specs' as const,
|
|
6
10
|
narratives,
|
|
7
|
-
messages:
|
|
11
|
+
messages: typedMessages,
|
|
8
12
|
integrations: integrations as Model['integrations'],
|
|
13
|
+
modules,
|
|
9
14
|
};
|
|
10
15
|
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import type { Message, Narrative } from '../../index';
|
|
3
|
+
import { deriveModules } from './derive-modules';
|
|
4
|
+
|
|
5
|
+
describe('deriveModules', () => {
|
|
6
|
+
it('groups narratives by sourceFile into separate modules', () => {
|
|
7
|
+
const narratives: Narrative[] = [
|
|
8
|
+
{ name: 'Orders', id: 'orders-1', sourceFile: 'orders.narrative.ts', slices: [] },
|
|
9
|
+
{ name: 'Users', id: 'users-1', sourceFile: 'users.narrative.ts', slices: [] },
|
|
10
|
+
];
|
|
11
|
+
const messages: Message[] = [];
|
|
12
|
+
|
|
13
|
+
const modules = deriveModules(narratives, messages);
|
|
14
|
+
|
|
15
|
+
expect(modules).toHaveLength(2);
|
|
16
|
+
expect(modules.map((m) => m.sourceFile).sort()).toEqual(['orders.narrative.ts', 'users.narrative.ts']);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it('uses default sourceFile when narrative has no sourceFile', () => {
|
|
20
|
+
const narratives: Narrative[] = [{ name: 'Default', id: 'default-1', slices: [] }];
|
|
21
|
+
const messages: Message[] = [];
|
|
22
|
+
|
|
23
|
+
const modules = deriveModules(narratives, messages);
|
|
24
|
+
|
|
25
|
+
expect(modules).toHaveLength(1);
|
|
26
|
+
expect(modules[0].sourceFile).toBe('generated.narrative.ts');
|
|
27
|
+
expect(modules[0].id).toBe('generated.narrative.ts');
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('generates synthetic narrative IDs when narratives have no ID', () => {
|
|
31
|
+
const narratives: Narrative[] = [
|
|
32
|
+
{ name: 'First', slices: [] },
|
|
33
|
+
{ name: 'Second', slices: [] },
|
|
34
|
+
];
|
|
35
|
+
const messages: Message[] = [];
|
|
36
|
+
|
|
37
|
+
const modules = deriveModules(narratives, messages);
|
|
38
|
+
|
|
39
|
+
expect(modules).toHaveLength(1);
|
|
40
|
+
expect(modules[0].contains.narrativeIds).toEqual(['__derived_0_0_First', '__derived_0_1_Second']);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('sets isDerived to true for all generated modules', () => {
|
|
44
|
+
const narratives: Narrative[] = [{ name: 'Test', id: 'test-1', slices: [] }];
|
|
45
|
+
const messages: Message[] = [];
|
|
46
|
+
|
|
47
|
+
const modules = deriveModules(narratives, messages);
|
|
48
|
+
|
|
49
|
+
expect(modules[0].isDerived).toBe(true);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('includes all messages in declares for each module', () => {
|
|
53
|
+
const narratives: Narrative[] = [
|
|
54
|
+
{ name: 'Orders', id: 'orders-1', sourceFile: 'orders.narrative.ts', slices: [] },
|
|
55
|
+
{ name: 'Users', id: 'users-1', sourceFile: 'users.narrative.ts', slices: [] },
|
|
56
|
+
];
|
|
57
|
+
const messages: Message[] = [
|
|
58
|
+
{ type: 'command', name: 'CreateOrder', fields: [] },
|
|
59
|
+
{ type: 'event', source: 'internal', name: 'OrderCreated', fields: [] },
|
|
60
|
+
];
|
|
61
|
+
|
|
62
|
+
const modules = deriveModules(narratives, messages);
|
|
63
|
+
|
|
64
|
+
for (const mod of modules) {
|
|
65
|
+
expect(mod.declares.messages).toEqual([
|
|
66
|
+
{ kind: 'command', name: 'CreateOrder' },
|
|
67
|
+
{ kind: 'event', name: 'OrderCreated' },
|
|
68
|
+
]);
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it('sorts declared messages by kind:name', () => {
|
|
73
|
+
const narratives: Narrative[] = [{ name: 'Test', id: 'test-1', slices: [] }];
|
|
74
|
+
const messages: Message[] = [
|
|
75
|
+
{ type: 'state', name: 'ZState', fields: [] },
|
|
76
|
+
{ type: 'command', name: 'ACommand', fields: [] },
|
|
77
|
+
{ type: 'event', source: 'internal', name: 'MEvent', fields: [] },
|
|
78
|
+
];
|
|
79
|
+
|
|
80
|
+
const modules = deriveModules(narratives, messages);
|
|
81
|
+
|
|
82
|
+
expect(modules[0].declares.messages).toEqual([
|
|
83
|
+
{ kind: 'command', name: 'ACommand' },
|
|
84
|
+
{ kind: 'event', name: 'MEvent' },
|
|
85
|
+
{ kind: 'state', name: 'ZState' },
|
|
86
|
+
]);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('creates independent message arrays for each module', () => {
|
|
90
|
+
const narratives: Narrative[] = [
|
|
91
|
+
{ name: 'A', id: 'a', sourceFile: 'a.ts', slices: [] },
|
|
92
|
+
{ name: 'B', id: 'b', sourceFile: 'b.ts', slices: [] },
|
|
93
|
+
];
|
|
94
|
+
const messages: Message[] = [{ type: 'event', source: 'internal', name: 'SharedEvent', fields: [] }];
|
|
95
|
+
|
|
96
|
+
const modules = deriveModules(narratives, messages);
|
|
97
|
+
|
|
98
|
+
expect(modules[0].declares.messages).not.toBe(modules[1].declares.messages);
|
|
99
|
+
expect(modules[0].declares.messages).toEqual(modules[1].declares.messages);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it('returns empty array when no narratives provided', () => {
|
|
103
|
+
const modules = deriveModules([], []);
|
|
104
|
+
|
|
105
|
+
expect(modules).toEqual([]);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it('groups multiple narratives with same sourceFile into one module', () => {
|
|
109
|
+
const narratives: Narrative[] = [
|
|
110
|
+
{ name: 'Flow1', id: 'flow-1', sourceFile: 'shared.ts', slices: [] },
|
|
111
|
+
{ name: 'Flow2', id: 'flow-2', sourceFile: 'shared.ts', slices: [] },
|
|
112
|
+
{ name: 'Flow3', id: 'flow-3', sourceFile: 'shared.ts', slices: [] },
|
|
113
|
+
];
|
|
114
|
+
const messages: Message[] = [];
|
|
115
|
+
|
|
116
|
+
const modules = deriveModules(narratives, messages);
|
|
117
|
+
|
|
118
|
+
expect(modules).toHaveLength(1);
|
|
119
|
+
expect(modules[0].contains.narrativeIds).toEqual(['flow-1', 'flow-2', 'flow-3']);
|
|
120
|
+
});
|
|
121
|
+
});
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { Message, Module, Narrative } from '../../index';
|
|
2
|
+
|
|
3
|
+
const DEFAULT_SOURCE_FILE = 'generated.narrative.ts';
|
|
4
|
+
|
|
5
|
+
export function deriveModules(narratives: Narrative[], messages: Message[]): Module[] {
|
|
6
|
+
const bySourceFile = groupNarrativesBySourceFile(narratives);
|
|
7
|
+
|
|
8
|
+
return Array.from(bySourceFile.entries()).map(([sourceFile, narrs], index) => {
|
|
9
|
+
const narrativeIds = narrs.map((n, i) => n.id ?? `__derived_${index}_${i}_${n.name}`);
|
|
10
|
+
const messageRefs = messages
|
|
11
|
+
.map((m) => ({ kind: m.type, name: m.name }))
|
|
12
|
+
.sort((a, b) => `${a.kind}:${a.name}`.localeCompare(`${b.kind}:${b.name}`));
|
|
13
|
+
|
|
14
|
+
return {
|
|
15
|
+
id: sourceFile,
|
|
16
|
+
sourceFile,
|
|
17
|
+
isDerived: true,
|
|
18
|
+
contains: { narrativeIds },
|
|
19
|
+
declares: { messages: messageRefs },
|
|
20
|
+
};
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function groupNarrativesBySourceFile(narratives: Narrative[]): Map<string, Narrative[]> {
|
|
25
|
+
const groups = new Map<string, Narrative[]>();
|
|
26
|
+
|
|
27
|
+
for (const narrative of narratives) {
|
|
28
|
+
const sourceFile = narrative.sourceFile ?? DEFAULT_SOURCE_FILE;
|
|
29
|
+
if (!groups.has(sourceFile)) {
|
|
30
|
+
groups.set(sourceFile, []);
|
|
31
|
+
}
|
|
32
|
+
groups.get(sourceFile)!.push(narrative);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return groups;
|
|
36
|
+
}
|
package/tsconfig.test.json
CHANGED
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
"extends": "./tsconfig.json",
|
|
3
3
|
"compilerOptions": {
|
|
4
4
|
"composite": false,
|
|
5
|
+
"rootDir": ".",
|
|
5
6
|
"types": ["vitest/globals", "node"]
|
|
6
7
|
},
|
|
7
|
-
"include": ["src/**/*"
|
|
8
|
+
"include": ["src/**/*"],
|
|
8
9
|
"exclude": ["node_modules", "dist"]
|
|
9
10
|
}
|