@auto-engineer/server-generator-apollo-emmett 0.11.9 → 0.11.11

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.
Files changed (134) hide show
  1. package/.turbo/turbo-build.log +5 -6
  2. package/.turbo/turbo-format.log +1 -1
  3. package/.turbo/turbo-lint.log +1 -1
  4. package/.turbo/turbo-test.log +4 -4
  5. package/.turbo/turbo-type-check.log +1 -1
  6. package/CHANGELOG.md +18 -0
  7. package/dist/src/codegen/extract/commands.d.ts +1 -1
  8. package/dist/src/codegen/extract/commands.d.ts.map +1 -1
  9. package/dist/src/codegen/extract/data-sink.d.ts +1 -1
  10. package/dist/src/codegen/extract/data-sink.d.ts.map +1 -1
  11. package/dist/src/codegen/extract/events.d.ts +1 -1
  12. package/dist/src/codegen/extract/events.d.ts.map +1 -1
  13. package/dist/src/codegen/extract/gwt.d.ts +1 -1
  14. package/dist/src/codegen/extract/gwt.d.ts.map +1 -1
  15. package/dist/src/codegen/extract/index.d.ts +1 -0
  16. package/dist/src/codegen/extract/index.d.ts.map +1 -1
  17. package/dist/src/codegen/extract/index.js +1 -0
  18. package/dist/src/codegen/extract/index.js.map +1 -1
  19. package/dist/src/codegen/extract/messages.d.ts +1 -1
  20. package/dist/src/codegen/extract/messages.d.ts.map +1 -1
  21. package/dist/src/codegen/extract/projection.d.ts +1 -1
  22. package/dist/src/codegen/extract/projection.d.ts.map +1 -1
  23. package/dist/src/codegen/extract/query.d.ts +1 -1
  24. package/dist/src/codegen/extract/query.d.ts.map +1 -1
  25. package/dist/src/codegen/extract/states.d.ts +1 -1
  26. package/dist/src/codegen/extract/states.d.ts.map +1 -1
  27. package/dist/src/codegen/extract/type-helpers.d.ts +13 -0
  28. package/dist/src/codegen/extract/type-helpers.d.ts.map +1 -0
  29. package/dist/src/codegen/extract/type-helpers.js +98 -0
  30. package/dist/src/codegen/extract/type-helpers.js.map +1 -0
  31. package/dist/src/codegen/scaffoldFromSchema.d.ts +3 -3
  32. package/dist/src/codegen/scaffoldFromSchema.d.ts.map +1 -1
  33. package/dist/src/codegen/scaffoldFromSchema.js +202 -19
  34. package/dist/src/codegen/scaffoldFromSchema.js.map +1 -1
  35. package/dist/src/codegen/templates/command/commands.specs.ts +3 -3
  36. package/dist/src/codegen/templates/command/commands.ts.ejs +14 -9
  37. package/dist/src/codegen/templates/command/decide.specs.specs.ts +54 -54
  38. package/dist/src/codegen/templates/command/decide.specs.ts +13 -9
  39. package/dist/src/codegen/templates/command/decide.ts.ejs +1 -0
  40. package/dist/src/codegen/templates/command/events.specs.ts +3 -3
  41. package/dist/src/codegen/templates/command/events.ts.ejs +16 -13
  42. package/dist/src/codegen/templates/command/evolve.specs.ts +3 -3
  43. package/dist/src/codegen/templates/command/handle.specs.ts +10 -5
  44. package/dist/src/codegen/templates/command/mutation.resolver.specs.ts +8 -7
  45. package/dist/src/codegen/templates/command/mutation.resolver.ts.ejs +2 -23
  46. package/dist/src/codegen/templates/command/register.specs.ts +4 -4
  47. package/dist/src/codegen/templates/command/register.ts.ejs +1 -4
  48. package/dist/src/codegen/templates/command/state.specs.ts +54 -50
  49. package/dist/src/codegen/templates/command/state.ts.ejs +8 -4
  50. package/dist/src/codegen/templates/query/projection.specs.specs.ts +7 -7
  51. package/dist/src/codegen/templates/query/projection.specs.ts +24 -7
  52. package/dist/src/codegen/templates/query/projection.ts.ejs +64 -12
  53. package/dist/src/codegen/templates/query/query.resolver.specs.ts +19 -16
  54. package/dist/src/codegen/templates/query/query.resolver.ts.ejs +11 -49
  55. package/dist/src/codegen/templates/query/state.specs.ts +3 -3
  56. package/dist/src/codegen/templates/react/react.specs.specs.ts +3 -3
  57. package/dist/src/codegen/templates/react/react.specs.ts +3 -3
  58. package/dist/src/codegen/templates/react/react.ts.ejs +0 -1
  59. package/dist/src/codegen/templates/react/register.specs.ts +3 -3
  60. package/dist/src/codegen/templates/react/register.ts.ejs +0 -1
  61. package/dist/src/codegen/test-data/specVariant1.d.ts +1 -1
  62. package/dist/src/codegen/test-data/specVariant1.d.ts.map +1 -1
  63. package/dist/src/codegen/test-data/specVariant1.js +1 -1
  64. package/dist/src/codegen/test-data/specVariant1.js.map +1 -1
  65. package/dist/src/codegen/types.d.ts +1 -1
  66. package/dist/src/codegen/types.d.ts.map +1 -1
  67. package/dist/src/commands/generate-server.d.ts +0 -1
  68. package/dist/src/commands/generate-server.d.ts.map +1 -1
  69. package/dist/src/commands/generate-server.js +53 -31
  70. package/dist/src/commands/generate-server.js.map +1 -1
  71. package/dist/src/domain/shared/graphql-types.d.ts +10 -0
  72. package/dist/src/domain/shared/graphql-types.d.ts.map +1 -0
  73. package/dist/src/domain/shared/graphql-types.js +40 -0
  74. package/dist/src/domain/shared/graphql-types.js.map +1 -0
  75. package/dist/src/domain/shared/graphql-types.ts +20 -0
  76. package/dist/src/domain/shared/index.d.ts +1 -0
  77. package/dist/src/domain/shared/index.d.ts.map +1 -1
  78. package/dist/src/domain/shared/index.js +1 -0
  79. package/dist/src/domain/shared/index.js.map +1 -1
  80. package/dist/src/domain/shared/index.ts +1 -0
  81. package/dist/src/domain/shared/sendCommand.d.ts +1 -1
  82. package/dist/src/domain/shared/sendCommand.d.ts.map +1 -1
  83. package/dist/src/domain/shared/sendCommand.ts +1 -1
  84. package/dist/src/domain/shared/types.d.ts +5 -7
  85. package/dist/src/domain/shared/types.d.ts.map +1 -1
  86. package/dist/src/domain/shared/types.js +11 -38
  87. package/dist/src/domain/shared/types.js.map +1 -1
  88. package/dist/src/domain/shared/types.ts +10 -16
  89. package/dist/tsconfig.tsbuildinfo +1 -1
  90. package/package.json +4 -4
  91. package/src/codegen/extract/commands.ts +1 -1
  92. package/src/codegen/extract/data-sink.ts +1 -1
  93. package/src/codegen/extract/events.ts +1 -1
  94. package/src/codegen/extract/gwt.ts +1 -1
  95. package/src/codegen/extract/index.ts +1 -0
  96. package/src/codegen/extract/messages.ts +1 -1
  97. package/src/codegen/extract/projection.ts +1 -1
  98. package/src/codegen/extract/query.ts +1 -1
  99. package/src/codegen/extract/states.ts +1 -1
  100. package/src/codegen/extract/type-helpers.ts +102 -0
  101. package/src/codegen/scaffoldFromSchema.ts +283 -25
  102. package/src/codegen/templates/command/commands.specs.ts +3 -3
  103. package/src/codegen/templates/command/commands.ts.ejs +14 -9
  104. package/src/codegen/templates/command/decide.specs.specs.ts +54 -54
  105. package/src/codegen/templates/command/decide.specs.ts +13 -9
  106. package/src/codegen/templates/command/decide.ts.ejs +1 -0
  107. package/src/codegen/templates/command/events.specs.ts +3 -3
  108. package/src/codegen/templates/command/events.ts.ejs +16 -13
  109. package/src/codegen/templates/command/evolve.specs.ts +3 -3
  110. package/src/codegen/templates/command/handle.specs.ts +10 -5
  111. package/src/codegen/templates/command/mutation.resolver.specs.ts +8 -7
  112. package/src/codegen/templates/command/mutation.resolver.ts.ejs +2 -23
  113. package/src/codegen/templates/command/register.specs.ts +4 -4
  114. package/src/codegen/templates/command/register.ts.ejs +1 -4
  115. package/src/codegen/templates/command/state.specs.ts +54 -50
  116. package/src/codegen/templates/command/state.ts.ejs +8 -4
  117. package/src/codegen/templates/query/projection.specs.specs.ts +7 -7
  118. package/src/codegen/templates/query/projection.specs.ts +24 -7
  119. package/src/codegen/templates/query/projection.ts.ejs +64 -12
  120. package/src/codegen/templates/query/query.resolver.specs.ts +19 -16
  121. package/src/codegen/templates/query/query.resolver.ts.ejs +11 -49
  122. package/src/codegen/templates/query/state.specs.ts +3 -3
  123. package/src/codegen/templates/react/react.specs.specs.ts +3 -3
  124. package/src/codegen/templates/react/react.specs.ts +3 -3
  125. package/src/codegen/templates/react/react.ts.ejs +0 -1
  126. package/src/codegen/templates/react/register.specs.ts +3 -3
  127. package/src/codegen/templates/react/register.ts.ejs +0 -1
  128. package/src/codegen/test-data/specVariant1.ts +2 -2
  129. package/src/codegen/types.ts +1 -1
  130. package/src/commands/generate-server.ts +63 -34
  131. package/src/domain/shared/graphql-types.ts +20 -0
  132. package/src/domain/shared/index.ts +1 -0
  133. package/src/domain/shared/sendCommand.ts +1 -1
  134. package/src/domain/shared/types.ts +10 -16
@@ -1,11 +1,16 @@
1
- import { Command } from "@event-driven-io/emmett";
1
+ <%
2
+ const enumList = collectEnumNames(commands.flatMap(c => c.fields));
3
+ %>import { Command } from "@event-driven-io/emmett";
4
+ <% if (enumList.length > 0) { -%>
5
+ import { <%= enumList.join(', ') %> } from '../../../shared';
6
+ <% } -%>
2
7
  <% for (const command of commands) { -%>
3
- export type <%= pascalCase(command.type) %> = Command<
4
- '<%= command.type %>',
5
- {
6
- <% for (const field of command.fields) { -%>
7
- <%- field.name %>: <%- field.tsType %>;
8
- <% } -%>
9
- }
10
- >;
8
+ export type <%= pascalCase(command.type) %> = Command<
9
+ '<%= command.type %>',
10
+ {
11
+ <% for (const field of command.fields) { -%>
12
+ <%- field.name %>: <%- toTsFieldType(field.tsType) %>;
13
+ <% } -%>
14
+ }
15
+ >;
11
16
  <% } -%>
@@ -1,12 +1,12 @@
1
1
  import { describe, it, expect } from 'vitest';
2
- import { Model as SpecsSchema } from '@auto-engineer/flow';
2
+ import { Model as SpecsSchema } from '@auto-engineer/narrative';
3
3
  import { generateScaffoldFilePlans } from '../../scaffoldFromSchema';
4
4
 
5
5
  describe('spec.ts.ejs', () => {
6
6
  it('should generate a valid spec file', async () => {
7
7
  const spec: SpecsSchema = {
8
8
  variant: 'specs',
9
- flows: [
9
+ narratives: [
10
10
  {
11
11
  name: 'Host creates a listing',
12
12
  slices: [
@@ -91,66 +91,66 @@ describe('spec.ts.ejs', () => {
91
91
  ],
92
92
  };
93
93
 
94
- const plans = await generateScaffoldFilePlans(spec.flows, spec.messages, undefined, 'src/domain/flows');
94
+ const plans = await generateScaffoldFilePlans(spec.narratives, spec.messages, undefined, 'src/domain/flows');
95
95
  const specFile = plans.find((p) => p.outputPath.endsWith('specs.ts'));
96
96
 
97
97
  expect(specFile?.contents).toMatchInlineSnapshot(`
98
- "import { describe, it } from 'vitest';
99
- import { DeciderSpecification } from '@event-driven-io/emmett';
100
- import { decide } from './decide';
101
- import { evolve } from './evolve';
102
- import { initialState, State } from './state';
103
- import type { ListingCreated } from './events';
104
- import type { CreateListing } from './commands';
98
+ "import { describe, it } from 'vitest';
99
+ import { DeciderSpecification } from '@event-driven-io/emmett';
100
+ import { decide } from './decide';
101
+ import { evolve } from './evolve';
102
+ import { initialState, State } from './state';
103
+ import type { ListingCreated } from './events';
104
+ import type { CreateListing } from './commands';
105
105
 
106
- describe('Should create listing successfully', () => {
107
- type Events = ListingCreated;
106
+ describe('Should create listing successfully', () => {
107
+ type Events = ListingCreated;
108
108
 
109
- const given = DeciderSpecification.for<CreateListing, Events, State>({
110
- decide,
111
- evolve,
112
- initialState,
113
- });
109
+ const given = DeciderSpecification.for<CreateListing, Events, State>({
110
+ decide,
111
+ evolve,
112
+ initialState,
113
+ });
114
114
 
115
- it('User creates listing with valid data', () => {
116
- given([])
117
- .when({
118
- type: 'CreateListing',
119
- data: {
120
- propertyId: 'listing_123',
121
- title: 'blah',
122
- pricePerNight: 250,
123
- maxGuests: 4,
124
- amenities: ['wifi', 'kitchen'],
125
- available: true,
126
- tags: ['some tag'],
127
- rating: 4.8,
128
- metadata: { foo: 'bar' },
129
- listedAt: new Date('2024-01-15T10:00:00Z'),
130
- },
131
- metadata: { now: new Date() },
132
- })
115
+ it('User creates listing with valid data', () => {
116
+ given([])
117
+ .when({
118
+ type: 'CreateListing',
119
+ data: {
120
+ propertyId: 'listing_123',
121
+ title: 'blah',
122
+ pricePerNight: 250,
123
+ maxGuests: 4,
124
+ amenities: ['wifi', 'kitchen'],
125
+ available: true,
126
+ tags: ['some tag'],
127
+ rating: 4.8,
128
+ metadata: { foo: 'bar' },
129
+ listedAt: new Date('2024-01-15T10:00:00Z'),
130
+ },
131
+ metadata: { now: new Date() },
132
+ })
133
133
 
134
- .then([
135
- {
136
- type: 'ListingCreated',
137
- data: {
138
- propertyId: 'listing_123',
139
- listedAt: new Date('2024-01-15T10:00:00Z'),
140
- rating: 4.8,
141
- metadata: { foo: 'bar' },
142
- },
143
- },
144
- ]);
145
- });
146
- });
147
- "
148
- `);
134
+ .then([
135
+ {
136
+ type: 'ListingCreated',
137
+ data: {
138
+ propertyId: 'listing_123',
139
+ listedAt: new Date('2024-01-15T10:00:00Z'),
140
+ rating: 4.8,
141
+ metadata: { foo: 'bar' },
142
+ },
143
+ },
144
+ ]);
145
+ });
146
+ });
147
+ "
148
+ `);
149
149
  });
150
150
  it('should include given events in the spec file when provided', async () => {
151
151
  const spec: SpecsSchema = {
152
152
  variant: 'specs',
153
- flows: [
153
+ narratives: [
154
154
  {
155
155
  name: 'Guest removes a listing',
156
156
  slices: [
@@ -233,7 +233,7 @@ describe('spec.ts.ejs', () => {
233
233
  ],
234
234
  };
235
235
 
236
- const plans = await generateScaffoldFilePlans(spec.flows, spec.messages, undefined, 'src/domain/flows');
236
+ const plans = await generateScaffoldFilePlans(spec.narratives, spec.messages, undefined, 'src/domain/flows');
237
237
  const specFile = plans.find((p) => p.outputPath.endsWith('specs.ts'));
238
238
 
239
239
  expect(specFile?.contents).toMatchInlineSnapshot(`
@@ -292,7 +292,7 @@ describe('spec.ts.ejs', () => {
292
292
  it('should generate separate tests for multiple examples with different scenarios', async () => {
293
293
  const spec: SpecsSchema = {
294
294
  variant: 'specs',
295
- flows: [
295
+ narratives: [
296
296
  {
297
297
  name: 'Questionnaires',
298
298
  slices: [
@@ -421,7 +421,7 @@ describe('spec.ts.ejs', () => {
421
421
  ],
422
422
  };
423
423
 
424
- const plans = await generateScaffoldFilePlans(spec.flows, spec.messages, undefined, 'src/domain/flows');
424
+ const plans = await generateScaffoldFilePlans(spec.narratives, spec.messages, undefined, 'src/domain/flows');
425
425
  const specFile = plans.find((p) => p.outputPath.endsWith('specs.ts'));
426
426
 
427
427
  expect(specFile?.contents).toMatchInlineSnapshot(`
@@ -1,12 +1,12 @@
1
1
  import { describe, it, expect } from 'vitest';
2
- import { Model as SpecsSchema } from '@auto-engineer/flow';
2
+ import { Model as SpecsSchema } from '@auto-engineer/narrative';
3
3
  import { generateScaffoldFilePlans } from '../../scaffoldFromSchema';
4
4
 
5
5
  describe('decide.ts.ejs', () => {
6
6
  it('should generate a valid decide file when both command and event exist', async () => {
7
7
  const spec: SpecsSchema = {
8
8
  variant: 'specs',
9
- flows: [
9
+ narratives: [
10
10
  {
11
11
  name: 'Host creates a listing',
12
12
  slices: [
@@ -72,7 +72,7 @@ describe('decide.ts.ejs', () => {
72
72
  ],
73
73
  };
74
74
 
75
- const plans = await generateScaffoldFilePlans(spec.flows, spec.messages, undefined, 'src/domain/flows');
75
+ const plans = await generateScaffoldFilePlans(spec.narratives, spec.messages, undefined, 'src/domain/flows');
76
76
  const decideFile = plans.find((p) => p.outputPath.endsWith('decide.ts'));
77
77
 
78
78
  expect(decideFile?.contents).toMatchInlineSnapshot(`
@@ -93,6 +93,7 @@ describe('decide.ts.ejs', () => {
93
93
  * - Validate the command input fields
94
94
  * - Inspect the current domain \`state\` to determine if the command is allowed
95
95
  * - If invalid, throw one of the following domain errors: \`NotFoundError\`, \`ValidationError\`, or \`IllegalStateError\`
96
+ * ⚠️ Error constructors: NotFoundError takes { id, type, message? }, while IllegalStateError/ValidationError take string
96
97
  * - If valid, return one or more events with the correct structure
97
98
  *
98
99
  * ⚠️ Only read from inputs — never mutate them. \`evolve.ts\` handles state updates.
@@ -116,7 +117,7 @@ describe('decide.ts.ejs', () => {
116
117
  it('should include implementation instructions when prior events are required', async () => {
117
118
  const spec: SpecsSchema = {
118
119
  variant: 'specs',
119
- flows: [
120
+ narratives: [
120
121
  {
121
122
  name: 'Host removes a listing',
122
123
  slices: [
@@ -197,7 +198,7 @@ describe('decide.ts.ejs', () => {
197
198
  ],
198
199
  };
199
200
 
200
- const plans = await generateScaffoldFilePlans(spec.flows, spec.messages, undefined, 'src/domain/flows');
201
+ const plans = await generateScaffoldFilePlans(spec.narratives, spec.messages, undefined, 'src/domain/flows');
201
202
  const decideFile = plans.find((p) => p.outputPath.endsWith('decide.ts'));
202
203
 
203
204
  expect(decideFile?.contents).toMatchInlineSnapshot(`
@@ -218,6 +219,7 @@ describe('decide.ts.ejs', () => {
218
219
  * - Validate the command input fields
219
220
  * - Inspect the current domain \`state\` to determine if the command is allowed
220
221
  * - If invalid, throw one of the following domain errors: \`NotFoundError\`, \`ValidationError\`, or \`IllegalStateError\`
222
+ * ⚠️ Error constructors: NotFoundError takes { id, type, message? }, while IllegalStateError/ValidationError take string
221
223
  * - If valid, return one or more events with the correct structure
222
224
  *
223
225
  * ⚠️ Only read from inputs — never mutate them. \`evolve.ts\` handles state updates.
@@ -241,7 +243,7 @@ describe('decide.ts.ejs', () => {
241
243
  it('should generate a decide file that handles multiple GWTs including an error', async () => {
242
244
  const spec: SpecsSchema = {
243
245
  variant: 'specs',
244
- flows: [
246
+ narratives: [
245
247
  {
246
248
  name: 'Host creates a listing',
247
249
  slices: [
@@ -337,7 +339,7 @@ describe('decide.ts.ejs', () => {
337
339
  ],
338
340
  };
339
341
 
340
- const plans = await generateScaffoldFilePlans(spec.flows, spec.messages, undefined, 'src/domain/flows');
342
+ const plans = await generateScaffoldFilePlans(spec.narratives, spec.messages, undefined, 'src/domain/flows');
341
343
  const decideFile = plans.find((p) => p.outputPath.endsWith('decide.ts'));
342
344
 
343
345
  expect(decideFile?.contents).toMatchInlineSnapshot(`
@@ -358,6 +360,7 @@ describe('decide.ts.ejs', () => {
358
360
  * - Validate the command input fields
359
361
  * - Inspect the current domain \`state\` to determine if the command is allowed
360
362
  * - If invalid, throw one of the following domain errors: \`NotFoundError\`, \`ValidationError\`, or \`IllegalStateError\`
363
+ * ⚠️ Error constructors: NotFoundError takes { id, type, message? }, while IllegalStateError/ValidationError take string
361
364
  * - If valid, return one or more events with the correct structure
362
365
  *
363
366
  * ⚠️ Only read from inputs — never mutate them. \`evolve.ts\` handles state updates.
@@ -385,7 +388,7 @@ describe('decide.ts.ejs', () => {
385
388
  it('should include integration return type and usage in decide function', async () => {
386
389
  const spec: SpecsSchema = {
387
390
  variant: 'specs',
388
- flows: [
391
+ narratives: [
389
392
  {
390
393
  name: 'Assistant suggests items',
391
394
  slices: [
@@ -522,7 +525,7 @@ describe('decide.ts.ejs', () => {
522
525
  ],
523
526
  };
524
527
 
525
- const plans = await generateScaffoldFilePlans(spec.flows, spec.messages, spec.integrations);
528
+ const plans = await generateScaffoldFilePlans(spec.narratives, spec.messages, spec.integrations);
526
529
  const decideFile = plans.find((p) => p.outputPath.endsWith('decide.ts'));
527
530
 
528
531
  expect(decideFile?.contents).toMatchInlineSnapshot(`
@@ -545,6 +548,7 @@ describe('decide.ts.ejs', () => {
545
548
  * - Inspect the current domain \`state\` to determine if the command is allowed
546
549
  * - Use \`products\` (integration result) to enrich or filter the output
547
550
  * - If invalid, throw one of the following domain errors: \`NotFoundError\`, \`ValidationError\`, or \`IllegalStateError\`
551
+ * ⚠️ Error constructors: NotFoundError takes { id, type, message? }, while IllegalStateError/ValidationError take string
548
552
  * - If valid, return one or more events with the correct structure
549
553
  *
550
554
  * ⚠️ Only read from inputs — never mutate them. \`evolve.ts\` handles state updates.
@@ -71,6 +71,7 @@ case '<%= command %>': {
71
71
  * - Use `<%= camelCase(integrationReturnType) %>` (integration result) to enrich or filter the output
72
72
  <% } -%>
73
73
  * - If invalid, throw one of the following domain errors: `NotFoundError`, `ValidationError`, or `IllegalStateError`
74
+ * ⚠️ Error constructors: NotFoundError takes { id, type, message? }, while IllegalStateError/ValidationError take string
74
75
  * - If valid, return one or more events with the correct structure
75
76
  *
76
77
  * ⚠️ Only read from inputs — never mutate them. `evolve.ts` handles state updates.
@@ -1,12 +1,12 @@
1
1
  import { describe, it, expect } from 'vitest';
2
- import { Model as SpecsSchema } from '@auto-engineer/flow';
2
+ import { Model as SpecsSchema } from '@auto-engineer/narrative';
3
3
  import { generateScaffoldFilePlans } from '../../scaffoldFromSchema';
4
4
 
5
5
  describe('events.ts.ejs', () => {
6
6
  it('should generate an event file', async () => {
7
7
  const spec: SpecsSchema = {
8
8
  variant: 'specs',
9
- flows: [
9
+ narratives: [
10
10
  {
11
11
  name: 'Host creates a listing',
12
12
  slices: [
@@ -93,7 +93,7 @@ describe('events.ts.ejs', () => {
93
93
  ],
94
94
  };
95
95
 
96
- const plans = await generateScaffoldFilePlans(spec.flows, spec.messages, undefined, 'src/domain/flows');
96
+ const plans = await generateScaffoldFilePlans(spec.narratives, spec.messages, undefined, 'src/domain/flows');
97
97
  const eventFile = plans.find((p) => p.outputPath.endsWith('events.ts'));
98
98
 
99
99
  expect(eventFile?.contents).toMatchInlineSnapshot(`
@@ -1,14 +1,17 @@
1
- <% if (localEvents.length) { -%>
2
- import type { Event } from '@event-driven-io/emmett';
3
-
4
- <% for (const event of localEvents) { -%>
5
- export type <%= pascalCase(event.type) %> = Event<
6
- '<%= event.type %>',
7
- {
8
- <% for (const field of event.fields) { -%>
9
- <%- field.name %>: <%- field.tsType %>;
10
- <% } -%>
11
- }
12
- >;
13
- <% } -%>
1
+ <%
2
+ const enumList = collectEnumNames(localEvents.flatMap(e => e.fields));
3
+ %><% if (localEvents.length) { -%>
4
+ import type { Event } from '@event-driven-io/emmett';
5
+ <% if (enumList.length > 0) { %>import { <%= enumList.join(', ') %> } from '../../../shared';
6
+ <% } %>
7
+ <% for (const event of localEvents) { -%>
8
+ export type <%= pascalCase(event.type) %> = Event<
9
+ '<%= event.type %>',
10
+ {
11
+ <% for (const field of event.fields) { -%>
12
+ <%- field.name %>: <%- toTsFieldType(field.tsType) %>;
13
+ <% } -%>
14
+ }
15
+ >;
16
+ <% } -%>
14
17
  <% } -%>
@@ -1,12 +1,12 @@
1
1
  import { describe, it, expect } from 'vitest';
2
- import { Model as SpecsSchema } from '@auto-engineer/flow';
2
+ import { Model as SpecsSchema } from '@auto-engineer/narrative';
3
3
  import { generateScaffoldFilePlans } from '../../scaffoldFromSchema';
4
4
 
5
5
  describe('evolve.ts.ejs', () => {
6
6
  it('should generate a valid evolve file from event structure', async () => {
7
7
  const spec: SpecsSchema = {
8
8
  variant: 'specs',
9
- flows: [
9
+ narratives: [
10
10
  {
11
11
  name: 'Host creates a listing',
12
12
  slices: [
@@ -72,7 +72,7 @@ describe('evolve.ts.ejs', () => {
72
72
  ],
73
73
  };
74
74
 
75
- const plans = await generateScaffoldFilePlans(spec.flows, spec.messages, undefined, 'src/domain/flows');
75
+ const plans = await generateScaffoldFilePlans(spec.narratives, spec.messages, undefined, 'src/domain/flows');
76
76
  const evolveFile = plans.find((p) => p.outputPath.endsWith('evolve.ts'));
77
77
 
78
78
  expect(evolveFile?.contents).toMatchInlineSnapshot(`
@@ -1,12 +1,12 @@
1
1
  import { describe, it, expect } from 'vitest';
2
2
  import { generateScaffoldFilePlans } from '../../scaffoldFromSchema';
3
- import { Model as SpecsSchema } from '@auto-engineer/flow';
3
+ import { Model as SpecsSchema } from '@auto-engineer/narrative';
4
4
 
5
5
  describe('generateScaffoldFilePlans', () => {
6
6
  it('should generate a valid handle file', async () => {
7
7
  const spec: SpecsSchema = {
8
8
  variant: 'specs',
9
- flows: [
9
+ narratives: [
10
10
  {
11
11
  name: 'Host creates a listing',
12
12
  slices: [
@@ -97,7 +97,7 @@ describe('generateScaffoldFilePlans', () => {
97
97
  ],
98
98
  };
99
99
 
100
- const plans = await generateScaffoldFilePlans(spec.flows, spec.messages, undefined, 'src/domain/flows');
100
+ const plans = await generateScaffoldFilePlans(spec.narratives, spec.messages, undefined, 'src/domain/flows');
101
101
  const handleFile = plans.find((p) => p.outputPath.endsWith('handle.ts'));
102
102
 
103
103
  expect(handleFile?.contents).toMatchInlineSnapshot(`
@@ -131,7 +131,7 @@ describe('generateScaffoldFilePlans', () => {
131
131
  it('should generate a valid handle file with integration', async () => {
132
132
  const spec: SpecsSchema = {
133
133
  variant: 'specs',
134
- flows: [
134
+ narratives: [
135
135
  {
136
136
  name: 'Assistant suggests items',
137
137
  slices: [
@@ -268,7 +268,12 @@ describe('generateScaffoldFilePlans', () => {
268
268
  ],
269
269
  };
270
270
 
271
- const plans = await generateScaffoldFilePlans(spec.flows, spec.messages, spec.integrations, 'src/domain/flows');
271
+ const plans = await generateScaffoldFilePlans(
272
+ spec.narratives,
273
+ spec.messages,
274
+ spec.integrations,
275
+ 'src/domain/flows',
276
+ );
272
277
  const handleFile = plans.find((p) => p.outputPath.endsWith('handle.ts'));
273
278
 
274
279
  expect(handleFile?.contents).toMatchInlineSnapshot(`
@@ -1,12 +1,12 @@
1
1
  import { describe, it, expect } from 'vitest';
2
2
  import { generateScaffoldFilePlans } from '../../scaffoldFromSchema';
3
- import { Model as SpecsSchema } from '@auto-engineer/flow';
3
+ import { Model as SpecsSchema } from '@auto-engineer/narrative';
4
4
 
5
5
  describe('mutation.resolver.ts.ejs', () => {
6
6
  it('should generate a valid mutation resolver file', async () => {
7
7
  const spec: SpecsSchema = {
8
8
  variant: 'specs',
9
- flows: [
9
+ narratives: [
10
10
  {
11
11
  name: 'Host creates a listing',
12
12
  slices: [
@@ -72,7 +72,7 @@ describe('mutation.resolver.ts.ejs', () => {
72
72
  ],
73
73
  };
74
74
 
75
- const plans = await generateScaffoldFilePlans(spec.flows, spec.messages, undefined, 'src/domain/flows');
75
+ const plans = await generateScaffoldFilePlans(spec.narratives, spec.messages, undefined, 'src/domain/flows');
76
76
  const mutationFile = plans.find((p) => p.outputPath.endsWith('mutation.resolver.ts'));
77
77
 
78
78
  expect(mutationFile?.contents).toMatchInlineSnapshot(`
@@ -134,7 +134,7 @@ describe('mutation.resolver.ts.ejs', () => {
134
134
  it('should generate the mutation resolver for AnswerQuestion', async () => {
135
135
  const spec: SpecsSchema = {
136
136
  variant: 'specs',
137
- flows: [
137
+ narratives: [
138
138
  {
139
139
  name: 'Questionnaires',
140
140
  slices: [
@@ -220,7 +220,7 @@ describe('mutation.resolver.ts.ejs', () => {
220
220
  integrations: [],
221
221
  };
222
222
 
223
- const plans = await generateScaffoldFilePlans(spec.flows, spec.messages, undefined, 'src/domain/flows');
223
+ const plans = await generateScaffoldFilePlans(spec.narratives, spec.messages, undefined, 'src/domain/flows');
224
224
  const mutationFile = plans.find(
225
225
  (p) =>
226
226
  p.outputPath.endsWith('mutation.resolver.ts') && p.contents.includes('export class AnswerQuestionResolver'),
@@ -267,7 +267,7 @@ describe('mutation.resolver.ts.ejs', () => {
267
267
  it('generates nested input types for inline object arrays in a mutation', async () => {
268
268
  const spec: SpecsSchema = {
269
269
  variant: 'specs',
270
- flows: [
270
+ narratives: [
271
271
  {
272
272
  name: 'Cart',
273
273
  slices: [
@@ -315,7 +315,7 @@ describe('mutation.resolver.ts.ejs', () => {
315
315
  ],
316
316
  };
317
317
 
318
- const plans = await generateScaffoldFilePlans(spec.flows, spec.messages, undefined, 'src/domain/flows');
318
+ const plans = await generateScaffoldFilePlans(spec.narratives, spec.messages, undefined, 'src/domain/flows');
319
319
  const mutationFile = plans.find(
320
320
  (p) =>
321
321
  p.outputPath.endsWith('mutation.resolver.ts') && p.contents.includes('export class AddItemsToCartResolver'),
@@ -323,6 +323,7 @@ describe('mutation.resolver.ts.ejs', () => {
323
323
 
324
324
  expect(mutationFile?.contents).toMatchInlineSnapshot(`
325
325
  "import { Mutation, Resolver, Arg, Ctx, Field, InputType } from 'type-graphql';
326
+ import { GraphQLJSON } from 'graphql-type-json';
326
327
  import { type GraphQLContext, sendCommand, MutationResponse } from '../../../shared';
327
328
 
328
329
  @InputType()
@@ -1,29 +1,8 @@
1
1
  <%
2
- function isInlineObject(ts) {
3
- return /^\{[\s\S]*\}$/.test((ts ?? '').trim());
4
- }
5
- function isInlineObjectArray(ts) {
6
- const t = (ts ?? '').trim();
7
- return /^Array<\{[\s\S]*\}>$/.test(t) || /^\{[\s\S]*\}\[\]$/.test(t);
8
- }
9
- function baseTs(ts) {
10
- return (ts ?? 'string').replace(/\s*\|\s*null\b/g, '').trim();
11
- }
12
- function fieldUsesDate(ts) {
13
- const b = baseTs(ts);
14
- if (b === 'Date') return true;
15
- if (isInlineObject(b) || isInlineObjectArray(b)) return /:\s*Date\b/.test(b);
16
- return false;
17
- }
18
- function fieldUsesJSON(ts) {
19
- const b = baseTs(ts);
20
- if (b === 'unknown' || b === 'any' || b === 'object') return true;
21
- if (isInlineObject(b) || isInlineObjectArray(b)) return /:\s*(unknown|any|object)\b/.test(b);
22
- return false;
23
- }
24
2
  const cmd = commands[0];
25
3
  const usesDate = cmd.fields.some(f => fieldUsesDate(f.tsType));
26
4
  const usesJSON = cmd.fields.some(f => fieldUsesJSON(f.tsType));
5
+ const enumList = collectEnumNames(cmd.fields);
27
6
 
28
7
  const embeddedInputs = [];
29
8
  for (const f of cmd.fields) {
@@ -38,7 +17,7 @@ for (const f of cmd.fields) {
38
17
  %>
39
18
  import { Mutation, Resolver, Arg, Ctx, Field, InputType<% if (usesDate) { %>, GraphQLISODateTime<% } %> } from 'type-graphql';
40
19
  <% if (usesJSON) { %>import { GraphQLJSON } from 'graphql-type-json';
41
- <% } %>import { type GraphQLContext, sendCommand, MutationResponse } from '../../../shared';
20
+ <% } %>import { type GraphQLContext, sendCommand, MutationResponse<% if (enumList.length > 0) { %>, <%= enumList.join(', ') %><% } %> } from '../../../shared';
42
21
 
43
22
  <% for (const { typeName, tsType } of embeddedInputs) {
44
23
  const inner = tsType.trim().startsWith('Array<')
@@ -1,12 +1,12 @@
1
1
  import { describe, it, expect } from 'vitest';
2
2
  import { generateScaffoldFilePlans } from '../../scaffoldFromSchema';
3
- import { Model as SpecsSchema } from '@auto-engineer/flow';
3
+ import { Model as SpecsSchema } from '@auto-engineer/narrative';
4
4
 
5
5
  describe('generateScaffoldFilePlans', () => {
6
6
  it('should generate a valid register file', async () => {
7
7
  const spec: SpecsSchema = {
8
8
  variant: 'specs',
9
- flows: [
9
+ narratives: [
10
10
  {
11
11
  name: 'Host creates a listing',
12
12
  slices: [
@@ -98,7 +98,7 @@ describe('generateScaffoldFilePlans', () => {
98
98
  ],
99
99
  };
100
100
 
101
- const plans = await generateScaffoldFilePlans(spec.flows, spec.messages, undefined, 'src/domain/flows');
101
+ const plans = await generateScaffoldFilePlans(spec.narratives, spec.messages, undefined, 'src/domain/flows');
102
102
  const registerFile = plans.find((p) => p.outputPath.endsWith('register.ts'));
103
103
 
104
104
  expect(registerFile?.contents).toMatchInlineSnapshot(`
@@ -107,7 +107,7 @@ describe('generateScaffoldFilePlans', () => {
107
107
  import type { CreateListing } from './commands';
108
108
 
109
109
  export function register(messageBus: CommandProcessor, eventStore: EventStore) {
110
- messageBus.handle((command: CreateListing) => handle(eventStore, command), 'CreateListing');
110
+ messageBus.handle<CreateListing>((command: CreateListing) => handle(eventStore, command), 'CreateListing');
111
111
  }
112
112
  "
113
113
  `);
@@ -4,9 +4,6 @@ import type { <%= commands.map(c => pascalCase(c.type)).join(', ') %> } from './
4
4
 
5
5
  export function register(messageBus: CommandProcessor, eventStore: EventStore) {
6
6
  <% for (const command of commands) { -%>
7
- messageBus.handle(
8
- (command: <%= pascalCase(command.type) %>) => handle(eventStore, command),
9
- '<%= command.type %>'
10
- );
7
+ messageBus.handle<<%= pascalCase(command.type) %>>((command: <%= pascalCase(command.type) %>) => handle(eventStore, command), '<%= command.type %>');
11
8
  <% } -%>
12
9
  }