@auto-engineer/server-generator-nestjs 1.139.0 → 1.140.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/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # @auto-engineer/server-generator-nestjs
2
2
 
3
+ ## 1.140.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`2b1315d`](https://github.com/BeOnAuto/auto-engineer/commit/2b1315d27aa7fbb5137f098c174b7b1daebbb821) Thanks [@github-actions[bot]](https://github.com/github-actions%5Bbot%5D)! - - **react-gen**: domain-aware theming, flexible layouts, chain-of-thought color selection
8
+ - **global**: version packages
9
+
10
+ ### Patch Changes
11
+
12
+ - [`26e5682`](https://github.com/BeOnAuto/auto-engineer/commit/26e56821d984838ba3720baca89c74fc012357c5) Thanks [@SamHatoum](https://github.com/SamHatoum)! - - Renamed core entity hierarchy: Journey→Narrative, Narrative→Scene, Slice→Moment for clearer domain language
13
+ - Updated DSL functions and schemas to match new naming (narrative(), scene(), moment())
14
+ - Server-generated directory structure now uses narrative-prefixed paths under domain/narratives
15
+ - Narratives are now required on Model and auto-populated by assembleSpecs
16
+ - Updated dependencies [[`2b1315d`](https://github.com/BeOnAuto/auto-engineer/commit/2b1315d27aa7fbb5137f098c174b7b1daebbb821), [`26e5682`](https://github.com/BeOnAuto/auto-engineer/commit/26e56821d984838ba3720baca89c74fc012357c5)]:
17
+ - @auto-engineer/narrative@1.140.0
18
+
3
19
  ## 1.139.0
4
20
 
5
21
  ### Minor Changes
package/package.json CHANGED
@@ -40,7 +40,7 @@
40
40
  "ts-node": "^10.9.2",
41
41
  "type-fest": "^4.41.0",
42
42
  "uuid": "^11.0.0",
43
- "@auto-engineer/narrative": "1.139.0"
43
+ "@auto-engineer/narrative": "1.140.0"
44
44
  },
45
45
  "publishConfig": {
46
46
  "access": "public"
@@ -52,9 +52,9 @@
52
52
  "tsx": "^4.19.2",
53
53
  "typescript": "^5.8.3",
54
54
  "vitest": "^3.2.4",
55
- "@auto-engineer/cli": "1.139.0"
55
+ "@auto-engineer/cli": "1.140.0"
56
56
  },
57
- "version": "1.139.0",
57
+ "version": "1.140.0",
58
58
  "scripts": {
59
59
  "generate:server": "tsx src/cli/index.ts",
60
60
  "-DISABLE-build": "tsc && tsx ../../scripts/fix-esm-imports.ts && rm -rf dist/src/codegen/templates && mkdir -p dist/src/codegen && cp -r src/codegen/templates dist/src/codegen/templates && cp -r src/shared dist/src",
@@ -1,4 +1,4 @@
1
- import type { Narrative } from '@auto-engineer/narrative';
1
+ import type { Scene } from '@auto-engineer/narrative';
2
2
  import { camelCase, pascalCase } from 'change-case';
3
3
  import createDebug from 'debug';
4
4
  import { extractMessagesFromSpecs } from './extract/index.js';
@@ -28,8 +28,8 @@ function isEnumType(tsType: string): boolean {
28
28
  return /^"[^"]+"(\s*\|\s*"[^"]+")+$/.test(cleanType) || /^'[^']+'(\s*\|\s*'[^']+)+$/.test(cleanType);
29
29
  }
30
30
 
31
- function detectPrimaryKeyField(fields: EntityField[], flowName: string): string | null {
32
- const idCandidates = [`${camelCase(flowName)}Id`, 'id', `${camelCase(flowName)}ID`, 'ID'];
31
+ function detectPrimaryKeyField(fields: EntityField[], sceneName: string): string | null {
32
+ const idCandidates = [`${camelCase(sceneName)}Id`, 'id', `${camelCase(sceneName)}ID`, 'ID'];
33
33
 
34
34
  for (const candidate of idCandidates) {
35
35
  const field = fields.find((f) => f.name === candidate);
@@ -116,8 +116,8 @@ function processMessagesWithFields(
116
116
  }
117
117
  }
118
118
 
119
- function processCommandSlice(
120
- slice: Narrative['slices'][0],
119
+ function processCommandMoment(
120
+ slice: Scene['moments'][0],
121
121
  messages: MessageDefinition[],
122
122
  fieldMap: Map<string, EntityField>,
123
123
  unionToEnumName: Map<string, string>,
@@ -130,8 +130,8 @@ function processCommandSlice(
130
130
  processMessagesWithFields(extracted.events, 'Event', fieldMap, unionToEnumName, enumsUsed);
131
131
  }
132
132
 
133
- function processQuerySlice(
134
- slice: Narrative['slices'][0],
133
+ function processQueryMoment(
134
+ slice: Scene['moments'][0],
135
135
  messages: MessageDefinition[],
136
136
  fieldMap: Map<string, EntityField>,
137
137
  unionToEnumName: Map<string, string>,
@@ -143,28 +143,28 @@ function processQuerySlice(
143
143
  processMessagesWithFields(extracted.states, 'State', fieldMap, unionToEnumName, enumsUsed);
144
144
  }
145
145
 
146
- function collectFieldsFromSlices(
147
- flow: Narrative,
146
+ function collectFieldsFromMoments(
147
+ scene: Scene,
148
148
  messages: MessageDefinition[],
149
149
  fieldMap: Map<string, EntityField>,
150
150
  unionToEnumName: Map<string, string>,
151
151
  enumsUsed: Set<string>,
152
152
  ): void {
153
- for (const slice of flow.slices) {
153
+ for (const slice of scene.moments) {
154
154
  if (slice.type === 'experience') continue;
155
155
 
156
156
  if (slice.type === 'command') {
157
- processCommandSlice(slice, messages, fieldMap, unionToEnumName, enumsUsed);
157
+ processCommandMoment(slice, messages, fieldMap, unionToEnumName, enumsUsed);
158
158
  }
159
159
 
160
160
  if (slice.type === 'query') {
161
- processQuerySlice(slice, messages, fieldMap, unionToEnumName, enumsUsed);
161
+ processQueryMoment(slice, messages, fieldMap, unionToEnumName, enumsUsed);
162
162
  }
163
163
  }
164
164
  }
165
165
 
166
- function markPrimaryKeyAndIndexes(fields: EntityField[], fieldMap: Map<string, EntityField>, flowName: string): void {
167
- const primaryKeyField = detectPrimaryKeyField(fields, flowName);
166
+ function markPrimaryKeyAndIndexes(fields: EntityField[], fieldMap: Map<string, EntityField>, sceneName: string): void {
167
+ const primaryKeyField = detectPrimaryKeyField(fields, sceneName);
168
168
  if (typeof primaryKeyField === 'string' && primaryKeyField.length > 0) {
169
169
  const field = fieldMap.get(primaryKeyField);
170
170
  if (field !== undefined) {
@@ -172,7 +172,7 @@ function markPrimaryKeyAndIndexes(fields: EntityField[], fieldMap: Map<string, E
172
172
  debug(' Detected primary key: %s', primaryKeyField);
173
173
  }
174
174
  } else {
175
- debug(' WARNING: No primary key detected for flow: %s', flowName);
175
+ debug(' WARNING: No primary key detected for scene: %s', sceneName);
176
176
  }
177
177
 
178
178
  for (const field of fields) {
@@ -184,22 +184,22 @@ function markPrimaryKeyAndIndexes(fields: EntityField[], fieldMap: Map<string, E
184
184
  }
185
185
 
186
186
  export function consolidateEntityFields(
187
- flow: Narrative,
187
+ scene: Scene,
188
188
  messages: MessageDefinition[],
189
189
  unionToEnumName: Map<string, string>,
190
190
  ): ConsolidatedEntity {
191
- debug('Consolidating entity fields for flow: %s', flow.name);
191
+ debug('Consolidating entity fields for scene: %s', scene.name);
192
192
 
193
193
  const fieldMap = new Map<string, EntityField>();
194
194
  const enumsUsed = new Set<string>();
195
195
 
196
- collectFieldsFromSlices(flow, messages, fieldMap, unionToEnumName, enumsUsed);
196
+ collectFieldsFromMoments(scene, messages, fieldMap, unionToEnumName, enumsUsed);
197
197
 
198
198
  const fields = Array.from(fieldMap.values());
199
- markPrimaryKeyAndIndexes(fields, fieldMap, flow.name);
199
+ markPrimaryKeyAndIndexes(fields, fieldMap, scene.name);
200
200
 
201
- const entityName = `${pascalCase(flow.name)}Entity`;
202
- const tableName = `${camelCase(flow.name)}s`;
201
+ const entityName = `${pascalCase(scene.name)}Entity`;
202
+ const tableName = `${camelCase(scene.name)}s`;
203
203
 
204
204
  debug('Consolidated entity: %s with %d fields', entityName, fields.length);
205
205
  debug(' Enum imports: %o', Array.from(enumsUsed));
@@ -1,5 +1,5 @@
1
- import type { Slice } from '@auto-engineer/narrative';
2
- import { extractGwtSpecsFromSlice, type GwtResult } from './step-converter';
1
+ import type { Moment } from '@auto-engineer/narrative';
2
+ import { extractGwtSpecsFromMoment, type GwtResult } from './step-converter';
3
3
  import type { CommandExample } from './step-types';
4
4
 
5
5
  function resolveStreamId(stream: string, exampleData: Record<string, unknown>): string {
@@ -30,7 +30,7 @@ function extractExampleDataFromQuery(firstSpec: GwtResult): Record<string, unkno
30
30
  return {};
31
31
  }
32
32
 
33
- function extractExampleDataFromSpecs(slice: Slice, gwtSpecs: GwtResult[]): Record<string, unknown> {
33
+ function extractExampleDataFromSpecs(slice: Moment, gwtSpecs: GwtResult[]): Record<string, unknown> {
34
34
  if (gwtSpecs.length === 0) {
35
35
  return {};
36
36
  }
@@ -73,9 +73,9 @@ function processStreamSink(item: unknown, exampleData: Record<string, unknown>)
73
73
  return { streamPattern, streamId };
74
74
  }
75
75
 
76
- export function getStreamFromSink(slice: Slice): { streamPattern?: string; streamId?: string } {
76
+ export function getStreamFromSink(slice: Moment): { streamPattern?: string; streamId?: string } {
77
77
  if (!('server' in slice)) return {};
78
- const gwtSpecs = extractGwtSpecsFromSlice(slice);
78
+ const gwtSpecs = extractGwtSpecsFromMoment(slice);
79
79
  const exampleData = extractExampleDataFromSpecs(slice, gwtSpecs);
80
80
  if (!('server' in slice) || slice.server == null || !('data' in slice.server) || !Array.isArray(slice.server.data)) {
81
81
  return {};
@@ -7,35 +7,35 @@ function createEventMessage(
7
7
  eventRef: string | undefined,
8
8
  source: 'given' | 'then' | 'when',
9
9
  allMessages: MessageDefinition[],
10
- currentSliceName?: string,
11
- currentFlowName?: string,
10
+ currentMomentName?: string,
11
+ currentSceneName?: string,
12
12
  ): Message | undefined {
13
13
  if (eventRef == null) return undefined;
14
14
  const fields = extractFieldsFromMessage(eventRef, 'event', allMessages);
15
15
  const messageDef = allMessages.find((m) => m.type === 'event' && m.name === eventRef);
16
- const metadata = messageDef?.metadata as { sourceFlowName?: string; sourceSliceName?: string } | undefined;
17
- const sourceFlowName = metadata?.sourceFlowName ?? currentFlowName;
18
- const sourceSliceName = metadata?.sourceSliceName ?? currentSliceName;
16
+ const metadata = messageDef?.metadata as { sourceSceneName?: string; sourceMomentName?: string } | undefined;
17
+ const sourceSceneName = metadata?.sourceSceneName ?? currentSceneName;
18
+ const sourceMomentName = metadata?.sourceMomentName ?? currentMomentName;
19
19
 
20
20
  return {
21
21
  type: eventRef,
22
22
  fields,
23
23
  source,
24
- sourceFlowName,
25
- sourceSliceName,
24
+ sourceSceneName,
25
+ sourceMomentName,
26
26
  };
27
27
  }
28
28
 
29
29
  export function extractEventsFromThen(
30
30
  thenItems: Array<EventExample | { errorType: string; message?: string }>,
31
31
  allMessages: MessageDefinition[],
32
- currentSliceName?: string,
33
- currentFlowName?: string,
32
+ currentMomentName?: string,
33
+ currentSceneName?: string,
34
34
  ): Message[] {
35
35
  return thenItems
36
36
  .map((then): Message | undefined => {
37
37
  if (!('eventRef' in then)) return undefined;
38
- return createEventMessage(then.eventRef, 'then', allMessages, currentSliceName, currentFlowName);
38
+ return createEventMessage(then.eventRef, 'then', allMessages, currentMomentName, currentSceneName);
39
39
  })
40
40
  .filter((event): event is Message => event !== undefined);
41
41
  }
@@ -43,13 +43,13 @@ export function extractEventsFromThen(
43
43
  export function extractEventsFromGiven(
44
44
  givenEvents: EventExample[] | undefined,
45
45
  allMessages: MessageDefinition[],
46
- currentSliceName?: string,
47
- currentFlowName?: string,
46
+ currentMomentName?: string,
47
+ currentSceneName?: string,
48
48
  ): Message[] {
49
49
  if (!givenEvents) return [];
50
50
 
51
51
  return givenEvents
52
- .map((given) => createEventMessage(given.eventRef, 'given', allMessages, currentSliceName, currentFlowName))
52
+ .map((given) => createEventMessage(given.eventRef, 'given', allMessages, currentMomentName, currentSceneName))
53
53
  .filter((event): event is Message => event !== undefined);
54
54
  }
55
55
 
@@ -1,14 +1,14 @@
1
- import type { Slice } from '@auto-engineer/narrative';
1
+ import type { Moment } from '@auto-engineer/narrative';
2
2
  import type { GwtCondition } from '../types';
3
- import { extractGwtSpecsFromSlice, type GwtConditionWithRule } from './step-converter';
3
+ import { extractGwtSpecsFromMoment, type GwtConditionWithRule } from './step-converter';
4
4
  import type { CommandExample, EventExample } from './step-types';
5
5
 
6
- export function buildCommandGwtMapping(slice: Slice): Record<string, (GwtCondition & { failingFields?: string[] })[]> {
6
+ export function buildCommandGwtMapping(slice: Moment): Record<string, (GwtCondition & { failingFields?: string[] })[]> {
7
7
  if (slice.type !== 'command') {
8
8
  return {};
9
9
  }
10
10
 
11
- const gwtSpecs = extractGwtSpecsFromSlice(slice);
11
+ const gwtSpecs = extractGwtSpecsFromMoment(slice);
12
12
  const mapping = buildCommandMapping(gwtSpecs);
13
13
  return enhanceMapping(mapping);
14
14
  }
@@ -6,8 +6,8 @@ export interface ImportGroup {
6
6
  eventTypes: string[];
7
7
  }
8
8
 
9
- export interface CrossSliceImportContext {
10
- currentSliceName: string;
9
+ export interface CrossMomentImportContext {
10
+ currentMomentName: string;
11
11
  events: Message[];
12
12
  }
13
13
 
@@ -16,20 +16,20 @@ export interface CrossSliceImportContext {
16
16
  * Events from the current slice are imported from './events',
17
17
  * while cross-slice events are imported from '../other-slice/events'.
18
18
  */
19
- export function groupEventImports(context: CrossSliceImportContext): ImportGroup[] {
20
- const { currentSliceName, events } = context;
19
+ export function groupEventImports(context: CrossMomentImportContext): ImportGroup[] {
20
+ const { currentMomentName, events } = context;
21
21
  const importGroups = new Map<string, string[]>();
22
22
 
23
23
  for (const event of events) {
24
24
  if (!event.type) continue;
25
25
  let importPath: string;
26
- const isFromCurrentSlice =
27
- event.source === 'then' || event.sourceSliceName === currentSliceName || event.sourceSliceName == null;
26
+ const isFromCurrentMoment =
27
+ event.source === 'then' || event.sourceMomentName === currentMomentName || event.sourceMomentName == null;
28
28
 
29
- if (isFromCurrentSlice) {
29
+ if (isFromCurrentMoment) {
30
30
  importPath = './events';
31
31
  } else {
32
- importPath = `../${toKebabCase(event.sourceSliceName ?? currentSliceName)}/events`;
32
+ importPath = `../${toKebabCase(event.sourceMomentName ?? currentMomentName)}/events`;
33
33
  }
34
34
  if (!importGroups.has(importPath)) {
35
35
  importGroups.set(importPath, []);
@@ -1,4 +1,4 @@
1
- import type { Slice } from '@auto-engineer/narrative';
1
+ import type { Moment } from '@auto-engineer/narrative';
2
2
  import createDebug from 'debug';
3
3
  import type { Message, MessageDefinition } from '../types';
4
4
  import { extractCommandsFromGwt, extractCommandsFromThen } from './commands';
@@ -6,7 +6,7 @@ import { extractEventsFromGiven, extractEventsFromThen, extractEventsFromWhen }
6
6
  import { extractFieldsFromMessage } from './fields';
7
7
  import { extractProjectionIdField, extractProjectionSingleton } from './projection';
8
8
  import { extractStatesFromData, extractStatesFromTarget } from './states';
9
- import { extractGwtSpecsFromSlice, type GwtConditionWithRule } from './step-converter';
9
+ import { extractGwtSpecsFromMoment, type GwtConditionWithRule } from './step-converter';
10
10
  import type { CommandExample, EventExample } from './step-types';
11
11
 
12
12
  const debug = createDebug('auto:server-generator-nestjs:extract:messages');
@@ -52,15 +52,15 @@ function deduplicateMessages<T extends Message>(messages: T[]): T[] {
52
52
  return result;
53
53
  }
54
54
 
55
- function extractMessagesForCommand(slice: Slice, allMessages: MessageDefinition[]): ExtractedMessages {
55
+ function extractMessagesForCommand(slice: Moment, allMessages: MessageDefinition[]): ExtractedMessages {
56
56
  debugCommand('Extracting messages for command slice: %s', slice.name);
57
57
 
58
58
  if (slice.type !== 'command') {
59
- debugCommand(' Slice type is not command, returning empty');
59
+ debugCommand(' Moment type is not command, returning empty');
60
60
  return EMPTY_EXTRACTED_MESSAGES;
61
61
  }
62
62
 
63
- const gwtSpecs = extractGwtSpecsFromSlice(slice);
63
+ const gwtSpecs = extractGwtSpecsFromMoment(slice);
64
64
  debugCommand(' Found %d GWT specs', gwtSpecs.length);
65
65
 
66
66
  const { commands, commandSchemasByName } = extractCommandsFromGwt(gwtSpecs, allMessages);
@@ -89,15 +89,15 @@ function extractMessagesForCommand(slice: Slice, allMessages: MessageDefinition[
89
89
  return result;
90
90
  }
91
91
 
92
- function extractMessagesForQuery(slice: Slice, allMessages: MessageDefinition[]): ExtractedMessages {
92
+ function extractMessagesForQuery(slice: Moment, allMessages: MessageDefinition[]): ExtractedMessages {
93
93
  debugQuery('Extracting messages for query slice: %s', slice.name);
94
94
 
95
95
  if (slice.type !== 'query') {
96
- debugQuery(' Slice type is not query, returning empty');
96
+ debugQuery(' Moment type is not query, returning empty');
97
97
  return EMPTY_EXTRACTED_MESSAGES;
98
98
  }
99
99
 
100
- const gwtSpecs = extractGwtSpecsFromSlice(slice);
100
+ const gwtSpecs = extractGwtSpecsFromMoment(slice);
101
101
  debugQuery(' Found %d GWT specs', gwtSpecs.length);
102
102
 
103
103
  const projectionIdField = extractProjectionIdField(slice);
@@ -124,14 +124,14 @@ function extractMessagesForQuery(slice: Slice, allMessages: MessageDefinition[])
124
124
  .map((eventExample: EventExample) => {
125
125
  const fields = extractFieldsFromMessage(eventExample.eventRef, 'event', allMessages);
126
126
  const messageDef = allMessages.find((m) => m.type === 'event' && m.name === eventExample.eventRef);
127
- const metadata = messageDef?.metadata as { sourceFlowName?: string; sourceSliceName?: string } | undefined;
127
+ const metadata = messageDef?.metadata as { sourceSceneName?: string; sourceMomentName?: string } | undefined;
128
128
 
129
129
  return {
130
130
  type: eventExample.eventRef,
131
131
  fields,
132
132
  source: 'when' as const,
133
- sourceFlowName: metadata?.sourceFlowName,
134
- sourceSliceName: metadata?.sourceSliceName,
133
+ sourceSceneName: metadata?.sourceSceneName,
134
+ sourceMomentName: metadata?.sourceMomentName,
135
135
  } as Message;
136
136
  })
137
137
  .filter((event): event is Message => event.type !== undefined);
@@ -156,15 +156,15 @@ function extractMessagesForQuery(slice: Slice, allMessages: MessageDefinition[])
156
156
  return result;
157
157
  }
158
158
 
159
- function extractMessagesForReact(slice: Slice, allMessages: MessageDefinition[]): ExtractedMessages {
159
+ function extractMessagesForReact(slice: Moment, allMessages: MessageDefinition[]): ExtractedMessages {
160
160
  debugReact('Extracting messages for react slice: %s', slice.name);
161
161
 
162
162
  if (slice.type !== 'react') {
163
- debugReact(' Slice type is not react, returning empty');
163
+ debugReact(' Moment type is not react, returning empty');
164
164
  return EMPTY_EXTRACTED_MESSAGES;
165
165
  }
166
166
 
167
- const gwtSpecs = extractGwtSpecsFromSlice(slice);
167
+ const gwtSpecs = extractGwtSpecsFromMoment(slice);
168
168
  debugReact(' Found %d GWT specs', gwtSpecs.length);
169
169
 
170
170
  const reactGwtSpecs: ReactGwtSpec[] = gwtSpecs.map((gwt) => ({
@@ -198,7 +198,7 @@ function extractMessagesForReact(slice: Slice, allMessages: MessageDefinition[])
198
198
  return result;
199
199
  }
200
200
 
201
- export function extractMessagesFromSpecs(slice: Slice, allMessages: MessageDefinition[]): ExtractedMessages {
201
+ export function extractMessagesFromSpecs(slice: Moment, allMessages: MessageDefinition[]): ExtractedMessages {
202
202
  debug('Extracting messages from slice: %s (type: %s)', slice.name, slice.type);
203
203
  debug(' Total message definitions available: %d', allMessages.length);
204
204
 
@@ -215,8 +215,8 @@ export function extractMessagesFromSpecs(slice: Slice, allMessages: MessageDefin
215
215
  result = extractMessagesForReact(slice, allMessages);
216
216
  break;
217
217
  default: {
218
- const unknownSlice = slice as Slice;
219
- debug(' Unknown slice type: %s, returning empty', unknownSlice.type);
218
+ const unknownMoment = slice as Moment;
219
+ debug(' Unknown slice type: %s, returning empty', unknownMoment.type);
220
220
  result = EMPTY_EXTRACTED_MESSAGES;
221
221
  }
222
222
  }
@@ -1,4 +1,4 @@
1
- import type { Slice } from '@auto-engineer/narrative';
1
+ import type { Moment } from '@auto-engineer/narrative';
2
2
 
3
3
  interface ProjectionOrigin {
4
4
  type: 'projection';
@@ -24,7 +24,7 @@ function isProjectionOrigin(origin: unknown): origin is ProjectionOrigin {
24
24
  return obj.type === 'projection';
25
25
  }
26
26
 
27
- function extractProjectionField<K extends keyof ProjectionOrigin>(slice: Slice, fieldName: K): string | undefined {
27
+ function extractProjectionField<K extends keyof ProjectionOrigin>(slice: Moment, fieldName: K): string | undefined {
28
28
  if (!('server' in slice)) return undefined;
29
29
  const dataSource = slice.server?.data?.[0];
30
30
  if (!hasOrigin(dataSource)) return undefined;
@@ -40,15 +40,15 @@ function extractProjectionField<K extends keyof ProjectionOrigin>(slice: Slice,
40
40
  return undefined;
41
41
  }
42
42
 
43
- export function extractProjectionIdField(slice: Slice): string | undefined {
43
+ export function extractProjectionIdField(slice: Moment): string | undefined {
44
44
  return extractProjectionField(slice, 'idField');
45
45
  }
46
46
 
47
- export function extractProjectionName(slice: Slice): string | undefined {
47
+ export function extractProjectionName(slice: Moment): string | undefined {
48
48
  return extractProjectionField(slice, 'name');
49
49
  }
50
50
 
51
- export function extractProjectionSingleton(slice: Slice): boolean {
51
+ export function extractProjectionSingleton(slice: Moment): boolean {
52
52
  if (!('server' in slice)) return false;
53
53
  const dataSource = slice.server?.data?.[0];
54
54
  if (!hasOrigin(dataSource)) return false;
@@ -1,5 +1,5 @@
1
- import type { Slice } from '@auto-engineer/narrative';
2
- import { extractGwtSpecsFromSlice } from './step-converter';
1
+ import type { Moment } from '@auto-engineer/narrative';
2
+ import { extractGwtSpecsFromMoment } from './step-converter';
3
3
  import type { EventExample, StateExample } from './step-types';
4
4
 
5
5
  interface QueryGwtCondition {
@@ -9,10 +9,10 @@ interface QueryGwtCondition {
9
9
  then: Array<{ stateRef: string; exampleData: Record<string, unknown> }>;
10
10
  }
11
11
 
12
- export function buildQueryGwtMapping(slice: Slice): QueryGwtCondition[] {
12
+ export function buildQueryGwtMapping(slice: Moment): QueryGwtCondition[] {
13
13
  if (slice.type !== 'query') return [];
14
14
 
15
- const gwtSpecs = extractGwtSpecsFromSlice(slice);
15
+ const gwtSpecs = extractGwtSpecsFromMoment(slice);
16
16
 
17
17
  return gwtSpecs.map((gwt) => {
18
18
  const givenEvents = Array.isArray(gwt.given) ? gwt.given.filter((i): i is EventExample => 'eventRef' in i) : [];
@@ -1,4 +1,4 @@
1
- import type { Slice } from '@auto-engineer/narrative';
1
+ import type { Moment } from '@auto-engineer/narrative';
2
2
  import type { Message, MessageDefinition } from '../types';
3
3
  import { extractFieldsFromMessage } from './fields';
4
4
 
@@ -16,7 +16,7 @@ function createStateMessage(stateName: string, allMessages: MessageDefinition[])
16
16
  };
17
17
  }
18
18
 
19
- function hasServerData(slice: Slice): slice is Slice & { server: { data: unknown[] } } {
19
+ function hasServerData(slice: Moment): slice is Moment & { server: { data: unknown[] } } {
20
20
  return (
21
21
  'server' in slice &&
22
22
  Boolean(slice.server) &&
@@ -26,7 +26,7 @@ function hasServerData(slice: Slice): slice is Slice & { server: { data: unknown
26
26
  );
27
27
  }
28
28
 
29
- export function extractStatesFromTarget(slice: Slice, allMessages: MessageDefinition[]): Message[] {
29
+ export function extractStatesFromTarget(slice: Moment, allMessages: MessageDefinition[]): Message[] {
30
30
  if (!hasServerData(slice)) {
31
31
  return [];
32
32
  }
@@ -39,7 +39,7 @@ export function extractStatesFromTarget(slice: Slice, allMessages: MessageDefini
39
39
  return uniqueTargets.map((name) => createStateMessage(name, allMessages));
40
40
  }
41
41
 
42
- export function extractStatesFromData(slice: Slice, allMessages: MessageDefinition[]): Message[] {
42
+ export function extractStatesFromData(slice: Moment, allMessages: MessageDefinition[]): Message[] {
43
43
  if (!hasServerData(slice)) {
44
44
  return [];
45
45
  }
@@ -1,19 +1,19 @@
1
- import type { Example, Slice, Spec } from '@auto-engineer/narrative';
1
+ import type { Example, Moment, Spec } from '@auto-engineer/narrative';
2
2
  import {
3
3
  type CommandExample,
4
4
  type ErrorRef,
5
5
  type EventExample,
6
- getSliceType,
6
+ getMomentType,
7
7
  isStepWithDocString,
8
8
  isStepWithError,
9
9
  type MajorKeyword,
10
+ type MomentType,
10
11
  resolveMajorKeyword,
11
- type SliceType,
12
12
  type StateExample,
13
13
  } from './step-types';
14
14
 
15
- export type { CommandExample, ErrorRef, EventExample, SliceType, StateExample };
16
- export { getSliceType };
15
+ export type { CommandExample, ErrorRef, EventExample, MomentType, StateExample };
16
+ export { getMomentType };
17
17
 
18
18
  export interface GwtResult {
19
19
  given: EventExample[];
@@ -60,10 +60,10 @@ function parseSteps(example: Example): ParsedSteps {
60
60
  return { given, whenItems, thenItems, thenErrors };
61
61
  }
62
62
 
63
- function buildGwtResult(sliceType: SliceType, parsed: ParsedSteps, description: string): GwtResult {
63
+ function buildGwtResult(momentType: MomentType, parsed: ParsedSteps, description: string): GwtResult {
64
64
  const { given, whenItems, thenItems, thenErrors } = parsed;
65
65
 
66
- if (sliceType === 'command') {
66
+ if (momentType === 'command') {
67
67
  return {
68
68
  given,
69
69
  when: { commandRef: whenItems[0]?.text ?? '', exampleData: whenItems[0]?.exampleData ?? {} },
@@ -72,7 +72,7 @@ function buildGwtResult(sliceType: SliceType, parsed: ParsedSteps, description:
72
72
  };
73
73
  }
74
74
 
75
- if (sliceType === 'react') {
75
+ if (momentType === 'react') {
76
76
  return {
77
77
  given,
78
78
  when: whenItems.map((w) => ({ eventRef: w.text, exampleData: w.exampleData })),
@@ -89,22 +89,22 @@ function buildGwtResult(sliceType: SliceType, parsed: ParsedSteps, description:
89
89
  };
90
90
  }
91
91
 
92
- export function stepsToGwt(example: Example, sliceType: SliceType): GwtResult {
92
+ export function stepsToGwt(example: Example, momentType: MomentType): GwtResult {
93
93
  const parsed = parseSteps(example);
94
- return buildGwtResult(sliceType, parsed, example.name);
94
+ return buildGwtResult(momentType, parsed, example.name);
95
95
  }
96
96
 
97
97
  export interface GwtConditionWithRule extends GwtResult {
98
98
  ruleDescription: string;
99
99
  }
100
100
 
101
- export function extractGwtFromSpecs(specs: Spec[], sliceType: SliceType): GwtConditionWithRule[] {
101
+ export function extractGwtFromSpecs(specs: Spec[], momentType: MomentType): GwtConditionWithRule[] {
102
102
  const results: GwtConditionWithRule[] = [];
103
103
 
104
104
  for (const spec of specs) {
105
105
  for (const rule of spec.rules) {
106
106
  for (const example of rule.examples) {
107
- const gwt = stepsToGwt(example, sliceType);
107
+ const gwt = stepsToGwt(example, momentType);
108
108
  results.push({
109
109
  ...gwt,
110
110
  ruleDescription: rule.name,
@@ -116,9 +116,9 @@ export function extractGwtFromSpecs(specs: Spec[], sliceType: SliceType): GwtCon
116
116
  return results;
117
117
  }
118
118
 
119
- export function extractGwtSpecsFromSlice(slice: Slice): GwtConditionWithRule[] {
119
+ export function extractGwtSpecsFromMoment(slice: Moment): GwtConditionWithRule[] {
120
120
  if (!('server' in slice)) return [];
121
121
  const specs = slice.server?.specs;
122
122
  if (!Array.isArray(specs) || specs.length === 0) return [];
123
- return extractGwtFromSpecs(specs, getSliceType(slice));
123
+ return extractGwtFromSpecs(specs, getMomentType(slice));
124
124
  }
@@ -1,4 +1,4 @@
1
- import type { Slice, Step, StepWithDocStringSchema, StepWithErrorSchema } from '@auto-engineer/narrative';
1
+ import type { Moment, Step, StepWithDocStringSchema, StepWithErrorSchema } from '@auto-engineer/narrative';
2
2
  import type { z } from 'zod';
3
3
 
4
4
  export type StepWithDocString = z.infer<typeof StepWithDocStringSchema>;
@@ -9,9 +9,9 @@ export type MajorKeyword = Exclude<StepKeyword, 'And'>;
9
9
 
10
10
  export type ErrorType = StepWithError['error']['type'];
11
11
 
12
- export type SliceType = Extract<Slice['type'], 'command' | 'query' | 'react'>;
12
+ export type MomentType = Extract<Moment['type'], 'command' | 'query' | 'react'>;
13
13
 
14
- export function getSliceType(slice: Slice): SliceType {
14
+ export function getMomentType(slice: Moment): MomentType {
15
15
  if (slice.type === 'command' || slice.type === 'query' || slice.type === 'react') {
16
16
  return slice.type;
17
17
  }
@@ -1,7 +1,7 @@
1
1
  import fs from 'node:fs/promises';
2
2
  import path, { dirname } from 'node:path';
3
3
  import { fileURLToPath } from 'node:url';
4
- import type { Model, Narrative, Slice } from '@auto-engineer/narrative';
4
+ import type { Model, Moment, Scene } from '@auto-engineer/narrative';
5
5
  import { camelCase, pascalCase } from 'change-case';
6
6
  import createDebug from 'debug';
7
7
  import ejs from 'ejs';
@@ -10,7 +10,7 @@ import { ensureDirExists, ensureDirPath, toKebabCase } from './utils/path.js';
10
10
 
11
11
  const debug = createDebug('auto:server-generator-nestjs:scaffold');
12
12
 
13
- import { parseSliceRequest } from '@auto-engineer/narrative';
13
+ import { parseMomentRequest } from '@auto-engineer/narrative';
14
14
  import { type ConsolidatedEntity, consolidateEntityFields } from './entity-consolidation.js';
15
15
  import { getStreamFromSink } from './extract/data-sink.js';
16
16
  import {
@@ -153,10 +153,10 @@ registerEnumType(${enumDef.name}, {
153
153
  });`;
154
154
  }
155
155
 
156
- async function writeEnumsToEntitiesFolder(baseDir: string, flowName: string, enums: EnumDefinition[]): Promise<void> {
156
+ async function writeEnumsToEntitiesFolder(baseDir: string, sceneName: string, enums: EnumDefinition[]): Promise<void> {
157
157
  if (enums.length === 0) return;
158
158
 
159
- const entitiesDir = path.join(baseDir, toKebabCase(flowName), 'entities');
159
+ const entitiesDir = path.join(baseDir, toKebabCase(sceneName), 'entities');
160
160
  await ensureDirExists(entitiesDir);
161
161
 
162
162
  for (const enumDef of enums) {
@@ -287,8 +287,8 @@ async function renderTemplate(
287
287
 
288
288
  async function generateFileForTemplate(
289
289
  templateFile: string,
290
- slice: Slice,
291
- sliceDir: string,
290
+ slice: Moment,
291
+ momentDir: string,
292
292
  templateData: Record<string, unknown>,
293
293
  unionToEnumName: Map<string, string> = new Map(),
294
294
  ): Promise<FilePlan> {
@@ -297,7 +297,7 @@ async function generateFileForTemplate(
297
297
  const fileName = templateFile
298
298
  .replace(/\.ts\.ejs$/, '.ts')
299
299
  .replace(/^(command|query|handler|resolver|input|type)\./, `${toKebabCase(slice.name)}.$1.`);
300
- const outputPath = path.join(sliceDir, fileName);
300
+ const outputPath = path.join(momentDir, fileName);
301
301
 
302
302
  const contents = await renderTemplate(templatePath, templateData, unionToEnumName);
303
303
 
@@ -312,8 +312,8 @@ async function generateFileForTemplate(
312
312
  }
313
313
 
314
314
  async function prepareTemplateData(
315
- slice: Slice,
316
- flow: Narrative,
315
+ slice: Moment,
316
+ scene: Scene,
317
317
  commands: Message[],
318
318
  events: Message[],
319
319
  states: Message[],
@@ -329,18 +329,18 @@ async function prepareTemplateData(
329
329
  const projectionName = extractProjectionName(slice);
330
330
 
331
331
  const uniqueCommands = Array.from(new Map(commands.map((c) => [c.type, c])).values());
332
- const allowedForSlice = new Set(Object.keys(gwtMapping));
332
+ const allowedForMoment = new Set(Object.keys(gwtMapping));
333
333
  const filteredCommands =
334
- allowedForSlice.size > 0 ? uniqueCommands.filter((c) => allowedForSlice.has(c.type)) : uniqueCommands;
334
+ allowedForMoment.size > 0 ? uniqueCommands.filter((c) => allowedForMoment.has(c.type)) : uniqueCommands;
335
335
 
336
- const eventImportGroups = groupEventImports({ currentSliceName: slice.name, events });
336
+ const eventImportGroups = groupEventImports({ currentMomentName: slice.name, events });
337
337
  const allEventTypesArray = getAllEventTypes(events);
338
338
  const allEventTypes = createEventUnionType(events);
339
339
  const localEvents = getLocalEvents(events);
340
340
 
341
341
  return {
342
- flowName: flow.name,
343
- sliceName: slice.name,
342
+ sceneName: scene.name,
343
+ momentName: slice.name,
344
344
  slice,
345
345
  stream: { pattern: streamPattern, id: streamId },
346
346
  commands: filteredCommands,
@@ -353,7 +353,7 @@ async function prepareTemplateData(
353
353
  projectionSingleton,
354
354
  projectionName,
355
355
  projectionType: projectionName != null ? pascalCase(projectionName) : undefined,
356
- parsedRequest: parseSliceRequest(slice),
356
+ parsedRequest: parseMomentRequest(slice),
357
357
  messages: allMessages,
358
358
  message:
359
359
  slice.type === 'query' && allMessages
@@ -367,10 +367,10 @@ async function prepareTemplateData(
367
367
  };
368
368
  }
369
369
 
370
- async function generateFilesForSlice(
371
- slice: Slice,
372
- flow: Narrative,
373
- sliceDir: string,
370
+ async function generateFilesForMoment(
371
+ slice: Moment,
372
+ scene: Scene,
373
+ momentDir: string,
374
374
  messages: MessageDefinition[],
375
375
  unionToEnumName: Map<string, string>,
376
376
  integrations?: Model['integrations'],
@@ -384,7 +384,7 @@ async function generateFilesForSlice(
384
384
 
385
385
  const templateData = await prepareTemplateData(
386
386
  slice,
387
- flow,
387
+ scene,
388
388
  extracted.commands,
389
389
  extracted.events,
390
390
  extracted.states,
@@ -396,7 +396,7 @@ async function generateFilesForSlice(
396
396
  );
397
397
 
398
398
  const plans = await Promise.all(
399
- templates.map((template) => generateFileForTemplate(template, slice, sliceDir, templateData, unionToEnumName)),
399
+ templates.map((template) => generateFileForTemplate(template, slice, momentDir, templateData, unionToEnumName)),
400
400
  );
401
401
  return plans;
402
402
  }
@@ -441,23 +441,23 @@ async function generateEntityFiles(
441
441
  }
442
442
 
443
443
  async function generateDomainModule(
444
- flow: Narrative,
445
- flowDir: string,
444
+ scene: Scene,
445
+ sceneDir: string,
446
446
  unionToEnumName: Map<string, string>,
447
447
  ): Promise<FilePlan> {
448
448
  const __dirname = dirname(fileURLToPath(import.meta.url));
449
449
  const moduleTemplatePath = path.join(__dirname, './templates/module/domain-module.ts.ejs');
450
450
 
451
- const slices = flow.slices.filter((s) => s.type !== 'experience');
451
+ const slices = scene.moments.filter((s) => s.type !== 'experience');
452
452
  const templateData = {
453
- flowName: flow.name,
453
+ sceneName: scene.name,
454
454
  slices,
455
455
  pascalCase,
456
456
  toKebabCase,
457
457
  };
458
458
 
459
459
  const contents = await renderTemplate(moduleTemplatePath, templateData, unionToEnumName);
460
- const modulePath = path.join(flowDir, `${toKebabCase(flow.name)}.module.ts`);
460
+ const modulePath = path.join(sceneDir, `${toKebabCase(scene.name)}.module.ts`);
461
461
 
462
462
  const prettierConfig = await prettier.resolveConfig(modulePath);
463
463
  const formattedContents = await prettier.format(contents, {
@@ -470,7 +470,7 @@ async function generateDomainModule(
470
470
  }
471
471
 
472
472
  async function generateAppModule(
473
- flows: Narrative[],
473
+ scenes: Scene[],
474
474
  baseDir: string,
475
475
  unionToEnumName: Map<string, string>,
476
476
  ): Promise<FilePlan> {
@@ -478,7 +478,7 @@ async function generateAppModule(
478
478
  const moduleTemplatePath = path.join(__dirname, './templates/module/app-module.ts.ejs');
479
479
 
480
480
  const templateData = {
481
- flows,
481
+ scenes,
482
482
  pascalCase,
483
483
  toKebabCase,
484
484
  };
@@ -497,7 +497,7 @@ async function generateAppModule(
497
497
  }
498
498
 
499
499
  export async function generateScaffoldFilePlans(
500
- flows: Narrative[],
500
+ scenes: Scene[],
501
501
  messages: Model['messages'],
502
502
  integrations?: Model['integrations'],
503
503
  baseDir = 'src/domain',
@@ -506,27 +506,34 @@ export async function generateScaffoldFilePlans(
506
506
 
507
507
  const allPlans: FilePlan[] = [];
508
508
 
509
- for (const flow of flows) {
510
- const flowDir = ensureDirPath(baseDir, toKebabCase(flow.name));
511
- const entitiesDir = ensureDirPath(flowDir, 'entities');
509
+ for (const scene of scenes) {
510
+ const sceneDir = ensureDirPath(baseDir, toKebabCase(scene.name));
511
+ const entitiesDir = ensureDirPath(sceneDir, 'entities');
512
512
 
513
- await writeEnumsToEntitiesFolder(baseDir, flow.name, enums);
513
+ await writeEnumsToEntitiesFolder(baseDir, scene.name, enums);
514
514
 
515
- const entity = consolidateEntityFields(flow, messages ?? [], unionToEnumName);
515
+ const entity = consolidateEntityFields(scene, messages ?? [], unionToEnumName);
516
516
  const entityPlans = await generateEntityFiles(entity, entitiesDir, unionToEnumName);
517
517
  allPlans.push(...entityPlans);
518
518
 
519
- for (const slice of flow.slices) {
520
- const sliceDir = ensureDirPath(flowDir, toKebabCase(slice.name));
521
- const plans = await generateFilesForSlice(slice, flow, sliceDir, messages ?? [], unionToEnumName, integrations);
519
+ for (const slice of scene.moments) {
520
+ const momentDir = ensureDirPath(sceneDir, toKebabCase(slice.name));
521
+ const plans = await generateFilesForMoment(
522
+ slice,
523
+ scene,
524
+ momentDir,
525
+ messages ?? [],
526
+ unionToEnumName,
527
+ integrations,
528
+ );
522
529
  allPlans.push(...plans);
523
530
  }
524
531
 
525
- const modulePlan = await generateDomainModule(flow, flowDir, unionToEnumName);
532
+ const modulePlan = await generateDomainModule(scene, sceneDir, unionToEnumName);
526
533
  allPlans.push(modulePlan);
527
534
  }
528
535
 
529
- const appModulePlan = await generateAppModule(flows, baseDir, unionToEnumName);
536
+ const appModulePlan = await generateAppModule(scenes, baseDir, unionToEnumName);
530
537
  allPlans.push(appModulePlan);
531
538
 
532
539
  return allPlans;
@@ -541,10 +548,10 @@ export async function writeScaffoldFilePlans(plans: FilePlan[]): Promise<void> {
541
548
  }
542
549
 
543
550
  export async function scaffoldFromSchema(
544
- flows: Narrative[],
551
+ scenes: Scene[],
545
552
  messages: Model['messages'],
546
553
  baseDir = 'src/domain',
547
554
  ): Promise<void> {
548
- const plans = await generateScaffoldFilePlans(flows, messages, undefined, baseDir);
555
+ const plans = await generateScaffoldFilePlans(scenes, messages, undefined, baseDir);
549
556
  await writeScaffoldFilePlans(plans);
550
557
  }
@@ -1,7 +1,7 @@
1
1
  <%
2
2
  const command = commands[0];
3
3
  if (!command) return '';
4
- const entityName = pascalCase(flowName) + 'Entity';
4
+ const entityName = pascalCase(sceneName) + 'Entity';
5
5
  const enumList = collectEnumNames(command.fields);
6
6
  %>import { describe, it, expect, beforeEach, vi } from 'vitest';
7
7
  import { Test, TestingModule } from '@nestjs/testing';
@@ -1,7 +1,7 @@
1
1
  <%
2
2
  const command = commands[0];
3
3
  if (!command) return '';
4
- const entityName = pascalCase(flowName) + 'Entity';
4
+ const entityName = pascalCase(sceneName) + 'Entity';
5
5
  const enumList = collectEnumNames(command.fields);
6
6
  %>import { CommandHandler, ICommandHandler } from '@nestjs/cqrs';
7
7
  import { InjectRepository } from '@mikro-orm/nestjs';
@@ -8,20 +8,20 @@ import { Migrator } from '@mikro-orm/migrations';
8
8
  import { join } from 'path';
9
9
  import { ApolloServerPluginLandingPageLocalDefault } from '@apollo/server/plugin/landingPage/default';
10
10
 
11
- <% for (const flow of flows) { -%>
12
- import { <%= pascalCase(flow.name) %>Module } from './domain/<%= toKebabCase(flow.name) %>/<%= toKebabCase(flow.name) %>.module';
13
- import { <%= pascalCase(flow.name) %>Entity } from './domain/<%= toKebabCase(flow.name) %>/entities';
11
+ <% for (const scene of scenes) { -%>
12
+ import { <%= pascalCase(scene.name) %>Module } from './domain/<%= toKebabCase(scene.name) %>/<%= toKebabCase(scene.name) %>.module';
13
+ import { <%= pascalCase(scene.name) %>Entity } from './domain/<%= toKebabCase(scene.name) %>/entities';
14
14
  <% } -%>
15
15
 
16
16
  const domainModules = [
17
- <% for (const flow of flows) { -%>
18
- <%= pascalCase(flow.name) %>Module,
17
+ <% for (const scene of scenes) { -%>
18
+ <%= pascalCase(scene.name) %>Module,
19
19
  <% } -%>
20
20
  ];
21
21
 
22
22
  const entities = [
23
- <% for (const flow of flows) { -%>
24
- <%= pascalCase(flow.name) %>Entity,
23
+ <% for (const scene of scenes) { -%>
24
+ <%= pascalCase(scene.name) %>Entity,
25
25
  <% } -%>
26
26
  ];
27
27
 
@@ -1,6 +1,6 @@
1
1
  <%
2
- const moduleName = pascalCase(flowName) + 'Module';
3
- const entityName = pascalCase(flowName) + 'Entity';
2
+ const moduleName = pascalCase(sceneName) + 'Module';
3
+ const entityName = pascalCase(sceneName) + 'Entity';
4
4
  %>import { Module } from '@nestjs/common';
5
5
  import { CqrsModule } from '@nestjs/cqrs';
6
6
  import { MikroOrmModule } from '@mikro-orm/nestjs';
@@ -1,5 +1,5 @@
1
1
  <%
2
- const entityName = pascalCase(flowName) + 'Entity';
2
+ const entityName = pascalCase(sceneName) + 'Entity';
3
3
  const typeName = projectionType || pascalCase(sliceName) + 'State';
4
4
  const isSingleton = projectionSingleton === true;
5
5
  %>import { QueryHandler, IQueryHandler } from '@nestjs/cqrs';
@@ -6,8 +6,8 @@ export interface Message {
6
6
  type: string;
7
7
  fields: Field[];
8
8
  source?: 'when' | 'given' | 'then';
9
- sourceFlowName?: string;
10
- sourceSliceName?: string;
9
+ sourceSceneName?: string;
10
+ sourceMomentName?: string;
11
11
  }
12
12
 
13
13
  export interface Field {
@@ -55,18 +55,18 @@ export type ServerGenerationFailedEvent = Event<
55
55
  }
56
56
  >;
57
57
 
58
- export type SliceGeneratedEvent = Event<
59
- 'SliceGenerated',
58
+ export type MomentGeneratedEvent = Event<
59
+ 'MomentGenerated',
60
60
  {
61
- flowName: string;
62
- sliceName: string;
63
- sliceType: string;
61
+ sceneName: string;
62
+ momentName: string;
63
+ momentType: string;
64
64
  schemaPath: string;
65
- slicePath: string;
65
+ momentPath: string;
66
66
  }
67
67
  >;
68
68
 
69
- export type GenerateServerEvents = ServerGeneratedEvent | ServerGenerationFailedEvent | SliceGeneratedEvent;
69
+ export type GenerateServerEvents = ServerGeneratedEvent | ServerGenerationFailedEvent | MomentGeneratedEvent;
70
70
 
71
71
  export const commandHandler = defineCommandHandler({
72
72
  name: 'GenerateServer',
@@ -74,7 +74,7 @@ export const commandHandler = defineCommandHandler({
74
74
  description: 'Generate server from model',
75
75
  category: 'generate',
76
76
  icon: 'server',
77
- events: ['ServerGenerated', 'ServerGenerationFailed', 'SliceGenerated'],
77
+ events: ['ServerGenerated', 'ServerGenerationFailed', 'MomentGenerated'],
78
78
  fields: {
79
79
  model: {
80
80
  description: 'The model object',
@@ -132,9 +132,9 @@ async function generateAndWriteScaffold(spec: Model, serverDir: string): Promise
132
132
  const domainPath = join(serverDir, 'src', 'domain');
133
133
  debugScaffold('Generating scaffold file plans');
134
134
  debugScaffold(' Domain path: %s', domainPath);
135
- debugScaffold(' Number of flows: %d', spec.narratives?.length || 0);
135
+ debugScaffold(' Number of scenes: %d', spec.scenes?.length || 0);
136
136
 
137
- const filePlans = await generateScaffoldFilePlans(spec.narratives, spec.messages, spec.integrations, domainPath);
137
+ const filePlans = await generateScaffoldFilePlans(spec.scenes, spec.messages, spec.integrations, domainPath);
138
138
 
139
139
  debugScaffold('Generated %d file plans', filePlans.length);
140
140
  if (filePlans.length > 0) {
@@ -244,26 +244,26 @@ export async function handleGenerateServerCommandInternal(
244
244
 
245
245
  await generateAndWriteScaffold(spec, serverDir);
246
246
 
247
- if (Array.isArray(spec.narratives) && spec.narratives.length > 0) {
248
- for (const flow of spec.narratives) {
249
- if (Array.isArray(flow.slices) && flow.slices.length > 0) {
250
- for (const slice of flow.slices) {
247
+ if (Array.isArray(spec.scenes) && spec.scenes.length > 0) {
248
+ for (const scene of spec.scenes) {
249
+ if (Array.isArray(scene.moments) && scene.moments.length > 0) {
250
+ for (const slice of scene.moments) {
251
251
  if (slice.type === 'experience') continue;
252
- const sliceEvent: SliceGeneratedEvent = {
253
- type: 'SliceGenerated',
252
+ const sliceEvent: MomentGeneratedEvent = {
253
+ type: 'MomentGenerated',
254
254
  data: {
255
- flowName: flow.name,
256
- sliceName: slice.name,
257
- sliceType: slice.type,
255
+ sceneName: scene.name,
256
+ momentName: slice.name,
257
+ momentType: slice.type,
258
258
  schemaPath: deriveModelPath(command.data.destination),
259
- slicePath: ensureDirPath('./server/src/domain', toKebabCase(flow.name), toKebabCase(slice.name)),
259
+ momentPath: ensureDirPath('./server/src/domain', toKebabCase(scene.name), toKebabCase(slice.name)),
260
260
  },
261
261
  timestamp: new Date(),
262
262
  requestId: command.requestId,
263
263
  correlationId: command.correlationId,
264
264
  };
265
265
  events.push(sliceEvent);
266
- debug('SliceGenerated: %s.%s', flow.name, slice.name);
266
+ debug('MomentGenerated: %s.%s', scene.name, slice.name);
267
267
  }
268
268
  }
269
269
  }
package/src/index.ts CHANGED
@@ -4,7 +4,7 @@ export const COMMANDS = [generateServerHandler];
4
4
  export type {
5
5
  GenerateServerCommand,
6
6
  GenerateServerEvents,
7
+ MomentGeneratedEvent,
7
8
  ServerGeneratedEvent,
8
9
  ServerGenerationFailedEvent,
9
- SliceGeneratedEvent,
10
10
  } from './commands/generate-server.js';