@auto-engineer/server-generator-apollo-emmett 0.8.5 → 0.8.6

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 (148) hide show
  1. package/.turbo/turbo-build.log +2 -2
  2. package/CHANGELOG.md +8 -0
  3. package/dist/src/codegen/scaffoldFromSchema.d.ts +3 -3
  4. package/dist/src/codegen/scaffoldFromSchema.d.ts.map +1 -1
  5. package/dist/src/codegen/scaffoldFromSchema.js +54 -18
  6. package/dist/src/codegen/scaffoldFromSchema.js.map +1 -1
  7. package/dist/{codegen → src/codegen}/templates/command/commands.specs.ts +1 -2
  8. package/dist/{codegen → src/codegen}/templates/command/decide.specs.specs.ts +3 -3
  9. package/dist/{codegen → src/codegen}/templates/command/decide.specs.ts +1 -5
  10. package/dist/{codegen → src/codegen}/templates/command/events.specs.ts +1 -2
  11. package/dist/{codegen → src/codegen}/templates/command/evolve.specs.ts +1 -2
  12. package/dist/{codegen → src/codegen}/templates/command/handle.specs.ts +1 -3
  13. package/dist/src/codegen/templates/command/mutation.resolver.specs.ts +363 -0
  14. package/dist/src/codegen/templates/command/mutation.resolver.ts.ejs +99 -0
  15. package/dist/{codegen → src/codegen}/templates/command/register.specs.ts +1 -2
  16. package/dist/{codegen → src/codegen}/templates/command/state.specs.ts +1 -2
  17. package/dist/{codegen → src/codegen}/templates/query/projection.specs.specs..ts +3 -3
  18. package/dist/{codegen → src/codegen}/templates/query/projection.specs.ts +5 -9
  19. package/dist/{codegen → src/codegen}/templates/query/query.resolver.specs.ts +194 -23
  20. package/dist/src/codegen/templates/query/query.resolver.ts.ejs +137 -0
  21. package/dist/{codegen → src/codegen}/templates/query/state.specs.ts +1 -2
  22. package/dist/{codegen → src/codegen}/templates/react/react.specs.specs.ts +2 -2
  23. package/dist/{codegen → src/codegen}/templates/react/react.specs.ts +3 -3
  24. package/dist/{codegen → src/codegen}/templates/react/register.specs.ts +3 -3
  25. package/dist/src/codegen/test-data/specVariant1.d.ts +1 -1
  26. package/dist/src/codegen/test-data/specVariant1.d.ts.map +1 -1
  27. package/dist/src/codegen/test-data/specVariant1.js +4 -2
  28. package/dist/src/codegen/test-data/specVariant1.js.map +1 -1
  29. package/dist/src/commands/generate-server.d.ts.map +1 -1
  30. package/dist/src/commands/generate-server.js +34 -24
  31. package/dist/src/commands/generate-server.js.map +1 -1
  32. package/dist/tsconfig.tsbuildinfo +1 -1
  33. package/package.json +8 -7
  34. package/src/codegen/scaffoldFromSchema.ts +52 -20
  35. package/src/codegen/templates/command/commands.specs.ts +1 -2
  36. package/src/codegen/templates/command/decide.specs.specs.ts +3 -3
  37. package/src/codegen/templates/command/decide.specs.ts +1 -5
  38. package/src/codegen/templates/command/events.specs.ts +1 -2
  39. package/src/codegen/templates/command/evolve.specs.ts +1 -2
  40. package/src/codegen/templates/command/handle.specs.ts +1 -3
  41. package/src/codegen/templates/command/mutation.resolver.specs.ts +247 -8
  42. package/src/codegen/templates/command/mutation.resolver.ts.ejs +86 -12
  43. package/src/codegen/templates/command/register.specs.ts +1 -2
  44. package/src/codegen/templates/command/state.specs.ts +1 -2
  45. package/src/codegen/templates/query/projection.specs.specs..ts +3 -3
  46. package/src/codegen/templates/query/projection.specs.ts +5 -9
  47. package/src/codegen/templates/query/query.resolver.specs.ts +194 -23
  48. package/src/codegen/templates/query/query.resolver.ts.ejs +84 -45
  49. package/src/codegen/templates/query/state.specs.ts +1 -2
  50. package/src/codegen/templates/react/react.specs.specs.ts +2 -2
  51. package/src/codegen/templates/react/react.specs.ts +3 -3
  52. package/src/codegen/templates/react/register.specs.ts +3 -3
  53. package/src/codegen/test-data/specVariant1.ts +5 -3
  54. package/src/commands/generate-server.ts +38 -30
  55. package/tsconfig.test.json +9 -0
  56. package/.turbo/turbo-test.log +0 -14
  57. package/.turbo/turbo-type-check.log +0 -4
  58. package/dist/codegen/templates/command/mutation.resolver.specs.ts +0 -124
  59. package/dist/codegen/templates/command/mutation.resolver.ts.ejs +0 -25
  60. package/dist/codegen/templates/query/query.resolver.ts.ejs +0 -98
  61. package/dist/src/codegen/templates/command/commands.specs.d.ts +0 -2
  62. package/dist/src/codegen/templates/command/commands.specs.d.ts.map +0 -1
  63. package/dist/src/codegen/templates/command/commands.specs.js +0 -96
  64. package/dist/src/codegen/templates/command/commands.specs.js.map +0 -1
  65. package/dist/src/codegen/templates/command/decide.specs.d.ts +0 -2
  66. package/dist/src/codegen/templates/command/decide.specs.d.ts.map +0 -1
  67. package/dist/src/codegen/templates/command/decide.specs.js +0 -567
  68. package/dist/src/codegen/templates/command/decide.specs.js.map +0 -1
  69. package/dist/src/codegen/templates/command/decide.specs.specs.d.ts +0 -2
  70. package/dist/src/codegen/templates/command/decide.specs.specs.d.ts.map +0 -1
  71. package/dist/src/codegen/templates/command/decide.specs.specs.js +0 -278
  72. package/dist/src/codegen/templates/command/decide.specs.specs.js.map +0 -1
  73. package/dist/src/codegen/templates/command/events.specs.d.ts +0 -2
  74. package/dist/src/codegen/templates/command/events.specs.d.ts.map +0 -1
  75. package/dist/src/codegen/templates/command/events.specs.js +0 -112
  76. package/dist/src/codegen/templates/command/events.specs.js.map +0 -1
  77. package/dist/src/codegen/templates/command/evolve.specs.d.ts +0 -2
  78. package/dist/src/codegen/templates/command/evolve.specs.d.ts.map +0 -1
  79. package/dist/src/codegen/templates/command/evolve.specs.js +0 -108
  80. package/dist/src/codegen/templates/command/evolve.specs.js.map +0 -1
  81. package/dist/src/codegen/templates/command/handle.specs.d.ts +0 -2
  82. package/dist/src/codegen/templates/command/handle.specs.d.ts.map +0 -1
  83. package/dist/src/codegen/templates/command/handle.specs.js +0 -326
  84. package/dist/src/codegen/templates/command/handle.specs.js.map +0 -1
  85. package/dist/src/codegen/templates/command/mutation.resolver.specs.d.ts +0 -2
  86. package/dist/src/codegen/templates/command/mutation.resolver.specs.d.ts.map +0 -1
  87. package/dist/src/codegen/templates/command/mutation.resolver.specs.js +0 -121
  88. package/dist/src/codegen/templates/command/mutation.resolver.specs.js.map +0 -1
  89. package/dist/src/codegen/templates/command/register.specs.d.ts +0 -2
  90. package/dist/src/codegen/templates/command/register.specs.d.ts.map +0 -1
  91. package/dist/src/codegen/templates/command/register.specs.js +0 -113
  92. package/dist/src/codegen/templates/command/register.specs.js.map +0 -1
  93. package/dist/src/codegen/templates/command/state.specs.d.ts +0 -2
  94. package/dist/src/codegen/templates/command/state.specs.d.ts.map +0 -1
  95. package/dist/src/codegen/templates/command/state.specs.js +0 -133
  96. package/dist/src/codegen/templates/command/state.specs.js.map +0 -1
  97. package/dist/src/codegen/templates/query/projection.specs.d.ts +0 -2
  98. package/dist/src/codegen/templates/query/projection.specs.d.ts.map +0 -1
  99. package/dist/src/codegen/templates/query/projection.specs.js +0 -363
  100. package/dist/src/codegen/templates/query/projection.specs.js.map +0 -1
  101. package/dist/src/codegen/templates/query/projection.specs.specs..d.ts +0 -2
  102. package/dist/src/codegen/templates/query/projection.specs.specs..d.ts.map +0 -1
  103. package/dist/src/codegen/templates/query/projection.specs.specs..js +0 -293
  104. package/dist/src/codegen/templates/query/projection.specs.specs..js.map +0 -1
  105. package/dist/src/codegen/templates/query/query.resolver.specs.d.ts +0 -2
  106. package/dist/src/codegen/templates/query/query.resolver.specs.d.ts.map +0 -1
  107. package/dist/src/codegen/templates/query/query.resolver.specs.js +0 -249
  108. package/dist/src/codegen/templates/query/query.resolver.specs.js.map +0 -1
  109. package/dist/src/codegen/templates/query/state.specs.d.ts +0 -2
  110. package/dist/src/codegen/templates/query/state.specs.d.ts.map +0 -1
  111. package/dist/src/codegen/templates/query/state.specs.js +0 -67
  112. package/dist/src/codegen/templates/query/state.specs.js.map +0 -1
  113. package/dist/src/codegen/templates/react/react.specs.d.ts +0 -2
  114. package/dist/src/codegen/templates/react/react.specs.d.ts.map +0 -1
  115. package/dist/src/codegen/templates/react/react.specs.js +0 -265
  116. package/dist/src/codegen/templates/react/react.specs.js.map +0 -1
  117. package/dist/src/codegen/templates/react/react.specs.specs.d.ts +0 -2
  118. package/dist/src/codegen/templates/react/react.specs.specs.d.ts.map +0 -1
  119. package/dist/src/codegen/templates/react/react.specs.specs.js +0 -229
  120. package/dist/src/codegen/templates/react/react.specs.specs.js.map +0 -1
  121. package/dist/src/codegen/templates/react/register.specs.d.ts +0 -2
  122. package/dist/src/codegen/templates/react/register.specs.d.ts.map +0 -1
  123. package/dist/src/codegen/templates/react/register.specs.js +0 -246
  124. package/dist/src/codegen/templates/react/register.specs.js.map +0 -1
  125. /package/dist/{codegen → src/codegen}/templates/command/commands.ts.ejs +0 -0
  126. /package/dist/{codegen → src/codegen}/templates/command/decide.specs.ts.ejs +0 -0
  127. /package/dist/{codegen → src/codegen}/templates/command/decide.ts.ejs +0 -0
  128. /package/dist/{codegen → src/codegen}/templates/command/events.ts.ejs +0 -0
  129. /package/dist/{codegen → src/codegen}/templates/command/evolve.ts.ejs +0 -0
  130. /package/dist/{codegen → src/codegen}/templates/command/handle.ts.ejs +0 -0
  131. /package/dist/{codegen → src/codegen}/templates/command/register.ts.ejs +0 -0
  132. /package/dist/{codegen → src/codegen}/templates/command/state.ts.ejs +0 -0
  133. /package/dist/{codegen → src/codegen}/templates/query/projection.specs.ts.ejs +0 -0
  134. /package/dist/{codegen → src/codegen}/templates/query/projection.ts.ejs +0 -0
  135. /package/dist/{codegen → src/codegen}/templates/query/state.ts.ejs +0 -0
  136. /package/dist/{codegen → src/codegen}/templates/react/react.specs.ts.ejs +0 -0
  137. /package/dist/{codegen → src/codegen}/templates/react/react.ts.ejs +0 -0
  138. /package/dist/{codegen → src/codegen}/templates/react/register.ts.ejs +0 -0
  139. /package/dist/{domain → src/domain}/shared/ReadModel.ts +0 -0
  140. /package/dist/{domain → src/domain}/shared/index.ts +0 -0
  141. /package/dist/{domain → src/domain}/shared/reactorSpecification.ts +0 -0
  142. /package/dist/{domain → src/domain}/shared/sendCommand.ts +0 -0
  143. /package/dist/{domain → src/domain}/shared/types.ts +0 -0
  144. /package/dist/{server.ts → src/server.ts} +0 -0
  145. /package/dist/{utils → src/utils}/index.ts +0 -0
  146. /package/dist/{utils → src/utils}/loadProjections.ts +0 -0
  147. /package/dist/{utils → src/utils}/loadRegisterFiles.ts +0 -0
  148. /package/dist/{utils → src/utils}/loadResolvers.ts +0 -0
@@ -1,133 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { generateScaffoldFilePlans } from '../../scaffoldFromSchema.js';
3
- describe('state.ts.ejs', () => {
4
- it('should generate an initial state', async () => {
5
- const spec = {
6
- variant: 'specs',
7
- flows: [
8
- {
9
- name: 'Host creates a listing',
10
- slices: [
11
- {
12
- type: 'command',
13
- name: 'Create listing',
14
- client: {
15
- description: 'test',
16
- specs: [],
17
- },
18
- server: {
19
- description: 'test',
20
- specs: {
21
- name: 'Create listing command',
22
- rules: [
23
- {
24
- description: 'Should create listing successfully',
25
- examples: [
26
- {
27
- description: 'User creates listing with valid data',
28
- when: {
29
- commandRef: 'CreateListing',
30
- exampleData: {
31
- propertyId: 'listing_123',
32
- title: 'nice apartment',
33
- pricePerNight: 250,
34
- available: true,
35
- rating: 4.8,
36
- metadata: { foo: 'bar' },
37
- },
38
- },
39
- then: [
40
- {
41
- eventRef: 'ListingCreated',
42
- exampleData: {
43
- propertyId: 'listing_123',
44
- listedAt: '2024-01-15T10:00:00Z',
45
- rating: 4.8,
46
- metadata: { foo: 'bar' },
47
- },
48
- },
49
- ],
50
- },
51
- ],
52
- },
53
- ],
54
- },
55
- },
56
- },
57
- ],
58
- },
59
- ],
60
- messages: [
61
- {
62
- type: 'command',
63
- name: 'CreateListing',
64
- fields: [],
65
- },
66
- {
67
- type: 'event',
68
- name: 'ListingCreated',
69
- source: 'internal',
70
- fields: [
71
- { name: 'propertyId', type: 'string', required: true },
72
- { name: 'listedAt', type: 'Date', required: true },
73
- { name: 'rating', type: 'number', required: true },
74
- { name: 'metadata', type: 'object', required: true },
75
- ],
76
- },
77
- ],
78
- };
79
- const plans = await generateScaffoldFilePlans(spec.flows, spec.messages, undefined, 'src/domain/flows');
80
- const stateFile = plans.find((p) => p.outputPath.endsWith('state.ts'));
81
- expect(stateFile?.contents).toMatchInlineSnapshot(`
82
- "/**
83
- * ## IMPLEMENTATION INSTRUCTIONS ##
84
- *
85
- * Define the shape of the domain state for the current slice below. This state is used by \`decide.ts\`
86
- * to determine whether a command is valid.
87
- *
88
- * The state is evolved over time by applying domain events (in \`evolve.ts\`).
89
- * Each event updates the state incrementally based on business rules.
90
- *
91
- * Guidelines:
92
- * - Include only fields that are **read** during command validation.
93
- * - Use discriminated unions (e.g., \`status: 'Pending' | 'Done'\`) to model state transitions.
94
- * - Prefer primitive types: \`string\`, \`boolean\`, \`number\`.
95
- * - Use objects or maps only when structure is essential for decision logic.
96
- *
97
- * Do NOT include:
98
- * - Redundant data already emitted in events unless required to enforce business rules.
99
- * - Fields used only for projections, UI, or query purposes.
100
- *
101
- * ### Example (for a Task domain):
102
- *
103
- * \`\`\`ts
104
- * export type PendingTask = {
105
- * status: 'Pending';
106
- * };
107
- *
108
- * export type InProgressTask = {
109
- * status: 'InProgress';
110
- * startedAt: string;
111
- * };
112
- *
113
- * export type CompletedTask = {
114
- * status: 'Completed';
115
- * completedAt: string;
116
- * };
117
- *
118
- * export type State = PendingTask | InProgressTask | CompletedTask;
119
- * \`\`\`
120
- */
121
-
122
- // TODO: Replace with a discriminated union of domain states for the current slice
123
- export type State = {};
124
-
125
- // TODO: Replace the Return with the initial domain state of the current slice
126
- export const initialState = (): State => {
127
- return {};
128
- };
129
- "
130
- `);
131
- });
132
- });
133
- //# sourceMappingURL=state.specs.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"state.specs.js","sourceRoot":"","sources":["../../../../../src/codegen/templates/command/state.specs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AAGrE,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;IAC5B,EAAE,CAAC,kCAAkC,EAAE,KAAK,IAAI,EAAE;QAChD,MAAM,IAAI,GAAgB;YACxB,OAAO,EAAE,OAAO;YAChB,KAAK,EAAE;gBACL;oBACE,IAAI,EAAE,wBAAwB;oBAC9B,MAAM,EAAE;wBACN;4BACE,IAAI,EAAE,SAAS;4BACf,IAAI,EAAE,gBAAgB;4BACtB,MAAM,EAAE;gCACN,WAAW,EAAE,MAAM;gCACnB,KAAK,EAAE,EAAE;6BACV;4BACD,MAAM,EAAE;gCACN,WAAW,EAAE,MAAM;gCACnB,KAAK,EAAE;oCACL,IAAI,EAAE,wBAAwB;oCAC9B,KAAK,EAAE;wCACL;4CACE,WAAW,EAAE,oCAAoC;4CACjD,QAAQ,EAAE;gDACR;oDACE,WAAW,EAAE,sCAAsC;oDACnD,IAAI,EAAE;wDACJ,UAAU,EAAE,eAAe;wDAC3B,WAAW,EAAE;4DACX,UAAU,EAAE,aAAa;4DACzB,KAAK,EAAE,gBAAgB;4DACvB,aAAa,EAAE,GAAG;4DAClB,SAAS,EAAE,IAAI;4DACf,MAAM,EAAE,GAAG;4DACX,QAAQ,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE;yDACzB;qDACF;oDACD,IAAI,EAAE;wDACJ;4DACE,QAAQ,EAAE,gBAAgB;4DAC1B,WAAW,EAAE;gEACX,UAAU,EAAE,aAAa;gEACzB,QAAQ,EAAE,sBAAsB;gEAChC,MAAM,EAAE,GAAG;gEACX,QAAQ,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE;6DACzB;yDACF;qDACF;iDACF;6CACF;yCACF;qCACF;iCACF;6BACF;yBACF;qBACF;iBACF;aACF;YACD,QAAQ,EAAE;gBACR;oBACE,IAAI,EAAE,SAAS;oBACf,IAAI,EAAE,eAAe;oBACrB,MAAM,EAAE,EAAE;iBACX;gBACD;oBACE,IAAI,EAAE,OAAO;oBACb,IAAI,EAAE,gBAAgB;oBACtB,MAAM,EAAE,UAAU;oBAClB,MAAM,EAAE;wBACN,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE;wBACtD,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE;wBAClD,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE;wBAClD,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE;qBACrD;iBACF;aACF;SACF,CAAC;QAEF,MAAM,KAAK,GAAG,MAAM,yBAAyB,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,EAAE,SAAS,EAAE,kBAAkB,CAAC,CAAC;QACxG,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC;QAEvE,MAAM,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC,qBAAqB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;SAiD7C,CAAC,CAAC;IACT,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=projection.specs.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"projection.specs.d.ts","sourceRoot":"","sources":["../../../../../src/codegen/templates/query/projection.specs.ts"],"names":[],"mappings":""}
@@ -1,363 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { generateScaffoldFilePlans } from '../../scaffoldFromSchema.js';
3
- describe('projection.ts.ejs', () => {
4
- it('should generate a valid projection file with correct relative event import path from producing slice', async () => {
5
- const spec = {
6
- variant: 'specs',
7
- flows: [
8
- {
9
- name: 'listing-flow',
10
- slices: [
11
- {
12
- type: 'command',
13
- name: 'create-listing',
14
- stream: 'listing-${propertyId}',
15
- client: {
16
- description: 'create listing UI',
17
- specs: [],
18
- },
19
- server: {
20
- description: 'handles create/remove listing',
21
- specs: {
22
- name: 'Create/remove listing command',
23
- rules: [
24
- {
25
- description: 'Should handle listing operations',
26
- examples: [
27
- {
28
- description: 'User creates listing successfully',
29
- when: {
30
- commandRef: 'CreateListing',
31
- exampleData: {
32
- propertyId: 'listing_123',
33
- title: 'Sea View Flat',
34
- pricePerNight: 120,
35
- location: 'Brighton',
36
- maxGuests: 4,
37
- },
38
- },
39
- then: [
40
- {
41
- eventRef: 'ListingCreated',
42
- exampleData: {
43
- propertyId: 'listing_123',
44
- title: 'Sea View Flat',
45
- pricePerNight: 120,
46
- location: 'Brighton',
47
- maxGuests: 4,
48
- },
49
- },
50
- ],
51
- },
52
- {
53
- description: 'User removes listing successfully',
54
- when: {
55
- commandRef: 'RemoveListing',
56
- exampleData: {
57
- propertyId: 'listing_123',
58
- },
59
- },
60
- then: [
61
- {
62
- eventRef: 'ListingRemoved',
63
- exampleData: {},
64
- },
65
- ],
66
- },
67
- ],
68
- },
69
- ],
70
- },
71
- },
72
- },
73
- {
74
- type: 'query',
75
- name: 'search-listings',
76
- stream: 'listings',
77
- client: {
78
- description: 'search listings UI',
79
- specs: [],
80
- },
81
- server: {
82
- description: 'projection for available listings',
83
- data: [
84
- {
85
- target: {
86
- type: 'State',
87
- name: 'AvailableListings',
88
- },
89
- origin: {
90
- type: 'projection',
91
- name: 'AvailablePropertiesProjection',
92
- idField: 'propertyId',
93
- },
94
- },
95
- ],
96
- specs: {
97
- name: 'Search listings query',
98
- rules: [
99
- {
100
- description: 'Should project listings correctly',
101
- examples: [
102
- {
103
- description: 'Listing created shows in search results',
104
- when: [
105
- {
106
- eventRef: 'ListingCreated',
107
- exampleData: {
108
- propertyId: 'listing_123',
109
- title: 'Sea View Flat',
110
- pricePerNight: 120,
111
- location: 'Brighton',
112
- maxGuests: 4,
113
- },
114
- },
115
- ],
116
- then: [
117
- {
118
- stateRef: 'AvailableListings',
119
- exampleData: {
120
- propertyId: 'listing_123',
121
- title: 'Sea View Flat',
122
- pricePerNight: 120,
123
- location: 'Brighton',
124
- maxGuests: 4,
125
- },
126
- },
127
- ],
128
- },
129
- {
130
- description: 'Listing removed disappears from search results',
131
- when: [
132
- {
133
- eventRef: 'ListingRemoved',
134
- exampleData: {
135
- propertyId: 'listing_123',
136
- },
137
- },
138
- ],
139
- then: [
140
- {
141
- stateRef: 'AvailableListings',
142
- exampleData: {},
143
- },
144
- ],
145
- },
146
- ],
147
- },
148
- ],
149
- },
150
- },
151
- },
152
- ],
153
- },
154
- ],
155
- messages: [
156
- {
157
- type: 'command',
158
- name: 'CreateListing',
159
- fields: [
160
- { name: 'propertyId', type: 'string', required: true },
161
- { name: 'title', type: 'string', required: true },
162
- { name: 'pricePerNight', type: 'number', required: true },
163
- { name: 'location', type: 'string', required: true },
164
- { name: 'maxGuests', type: 'number', required: true },
165
- ],
166
- },
167
- {
168
- type: 'command',
169
- name: 'RemoveListing',
170
- fields: [{ name: 'propertyId', type: 'string', required: true }],
171
- },
172
- {
173
- type: 'event',
174
- name: 'ListingCreated',
175
- source: 'internal',
176
- fields: [
177
- { name: 'propertyId', type: 'string', required: true },
178
- { name: 'title', type: 'string', required: true },
179
- { name: 'pricePerNight', type: 'number', required: true },
180
- { name: 'location', type: 'string', required: true },
181
- { name: 'maxGuests', type: 'number', required: true },
182
- ],
183
- },
184
- {
185
- type: 'event',
186
- name: 'ListingRemoved',
187
- source: 'internal',
188
- fields: [{ name: 'propertyId', type: 'string', required: true }],
189
- },
190
- {
191
- type: 'state',
192
- name: 'AvailableListings',
193
- fields: [
194
- { name: 'propertyId', type: 'string', required: true },
195
- { name: 'title', type: 'string', required: true },
196
- { name: 'pricePerNight', type: 'number', required: true },
197
- { name: 'location', type: 'string', required: true },
198
- { name: 'maxGuests', type: 'number', required: true },
199
- ],
200
- },
201
- ],
202
- };
203
- const plans = await generateScaffoldFilePlans(spec.flows, spec.messages, undefined, 'src/domain/flows');
204
- const projectionFile = plans.find((p) => p.outputPath.endsWith('projection.ts'));
205
- expect(projectionFile?.contents).toMatchInlineSnapshot(`
206
- "import {
207
- inMemorySingleStreamProjection,
208
- type ReadEvent,
209
- type InMemoryReadEventMetadata,
210
- } from '@event-driven-io/emmett';
211
- import type { AvailableListings } from './state.js';
212
- import type { ListingCreated, ListingRemoved } from '../create-listing/events.js';
213
-
214
- type AllEvents = ListingCreated | ListingRemoved;
215
-
216
- export const projection = inMemorySingleStreamProjection<AvailableListings, AllEvents>({
217
- collectionName: 'AvailablePropertiesProjection',
218
- canHandle: ['ListingCreated', 'ListingRemoved'],
219
- getDocumentId: (event) => event.data.propertyId,
220
- evolve: (
221
- document: AvailableListings | null,
222
- event: ReadEvent<AllEvents, InMemoryReadEventMetadata>,
223
- ): AvailableListings | null => {
224
- switch (event.type) {
225
- case 'ListingCreated': {
226
- /**
227
- * ## IMPLEMENTATION INSTRUCTIONS ##
228
- * This event adds or updates the document.
229
- * Implement the correct fields as needed for your read model.
230
- */
231
- return {
232
- propertyId: /* TODO: map from event.data */ '',
233
- title: /* TODO: map from event.data */ '',
234
- pricePerNight: /* TODO: map from event.data */ 0,
235
- location: /* TODO: map from event.data */ '',
236
- maxGuests: /* TODO: map from event.data */ 0,
237
- };
238
- }
239
-
240
- case 'ListingRemoved': {
241
- /**
242
- * ## IMPLEMENTATION INSTRUCTIONS ##
243
- * This event might indicate removal of a AvailableListings.
244
- *
245
- * - If the intent is to **remove the document**, return \`null\`.
246
- * - If the intent is to **soft delete**, consider adding a \`status\` field (e.g., \`status: 'removed'\`).
247
- * - Ensure consumers of this projection (e.g., UI) handle the chosen approach appropriately.
248
- */
249
- return null;
250
- }
251
- default:
252
- return document;
253
- }
254
- },
255
- });
256
-
257
- export default projection;
258
- "
259
- `);
260
- });
261
- it('should generate a valid query resolver using ID type', async () => {
262
- const spec = {
263
- variant: 'specs',
264
- flows: [
265
- {
266
- name: 'wishlist-flow',
267
- slices: [
268
- {
269
- type: 'query',
270
- name: 'view-wishlist',
271
- request: `
272
- query GetWishlist($sessionId: ID!) {
273
- wishlist(sessionId: $sessionId) {
274
- sessionId
275
- items
276
- }
277
- }
278
- `,
279
- client: {
280
- description: '',
281
- specs: [],
282
- },
283
- server: {
284
- description: '',
285
- data: [
286
- {
287
- origin: {
288
- type: 'projection',
289
- idField: 'sessionId',
290
- name: 'WishlistProjection',
291
- },
292
- target: {
293
- type: 'State',
294
- name: 'Wishlist',
295
- },
296
- },
297
- ],
298
- specs: { name: '', rules: [] },
299
- },
300
- },
301
- ],
302
- },
303
- ],
304
- messages: [
305
- {
306
- type: 'state',
307
- name: 'Wishlist',
308
- fields: [
309
- { name: 'sessionId', type: 'string', required: true },
310
- { name: 'items', type: 'string', required: true },
311
- ],
312
- },
313
- ],
314
- };
315
- const plans = await generateScaffoldFilePlans(spec.flows, spec.messages, undefined, 'src/domain/flows');
316
- const resolverFile = plans.find((p) => p.outputPath.endsWith('query.resolver.ts'));
317
- expect(resolverFile?.contents).toMatchInlineSnapshot(`
318
- "import { Query, Resolver, Arg, Ctx, ObjectType, Field, ID } from 'type-graphql';
319
- import { type GraphQLContext, ReadModel } from '../../../shared.js';
320
-
321
- @ObjectType()
322
- export class Wishlist {
323
- @Field(() => String)
324
- sessionId!: string;
325
-
326
- @Field(() => String)
327
- items!: string;
328
-
329
- [key: string]: unknown;
330
- }
331
-
332
- @Resolver()
333
- export class ViewWishlistQueryResolver {
334
- @Query(() => [Wishlist])
335
- async wishlist(
336
- @Ctx() ctx: GraphQLContext,
337
- @Arg('sessionId', () => ID, { nullable: true }) sessionId?: string,
338
- ): Promise<Wishlist[]> {
339
- const model = new ReadModel<Wishlist>(ctx.eventStore, 'WishlistProjection');
340
-
341
- // ## IMPLEMENTATION INSTRUCTIONS ##
342
- // You can query the projection using the ReadModel API:
343
- //
344
- // - model.getAll() — fetch all documents
345
- // - model.getById(id) — fetch a single document by ID (default key: 'id')
346
- // - model.find(filterFn) — filter documents using a predicate
347
- // - model.first(filterFn) — fetch the first document matching a predicate
348
- //
349
- // Example below uses \`.find()\` to filter
350
- // change the logic for the query as needed to meet the requirements for the current slice.
351
-
352
- return model.find((item) => {
353
- if (sessionId !== undefined && item.sessionId !== sessionId) return false;
354
-
355
- return true;
356
- });
357
- }
358
- }
359
- "
360
- `);
361
- });
362
- });
363
- //# sourceMappingURL=projection.specs.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"projection.specs.js","sourceRoot":"","sources":["../../../../../src/codegen/templates/query/projection.specs.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=projection.specs.specs..d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"projection.specs.specs..d.ts","sourceRoot":"","sources":["../../../../../src/codegen/templates/query/projection.specs.specs..ts"],"names":[],"mappings":""}