@auto-engineer/server-generator-nestjs 0.19.0 → 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +5 -0
- package/.turbo/turbo-test.log +13 -0
- package/.turbo/turbo-type-check.log +4 -0
- package/CHANGELOG.md +7 -0
- package/dist/src/codegen/entity-consolidation.d.ts +19 -0
- package/dist/src/codegen/entity-consolidation.d.ts.map +1 -0
- package/dist/src/codegen/entity-consolidation.js +134 -0
- package/dist/src/codegen/entity-consolidation.js.map +1 -0
- package/dist/src/codegen/extract/commands.d.ts +25 -0
- package/dist/src/codegen/extract/commands.d.ts.map +1 -0
- package/dist/src/codegen/extract/commands.js +67 -0
- package/dist/src/codegen/extract/commands.js.map +1 -0
- package/dist/src/codegen/extract/data-sink.d.ts +6 -0
- package/dist/src/codegen/extract/data-sink.d.ts.map +1 -0
- package/dist/src/codegen/extract/data-sink.js +78 -0
- package/dist/src/codegen/extract/data-sink.js.map +1 -0
- package/dist/src/codegen/extract/events.d.ts +10 -0
- package/dist/src/codegen/extract/events.d.ts.map +1 -0
- package/dist/src/codegen/extract/events.js +42 -0
- package/dist/src/codegen/extract/events.js.map +1 -0
- package/dist/src/codegen/extract/fields.d.ts +3 -0
- package/dist/src/codegen/extract/fields.d.ts.map +1 -0
- package/dist/src/codegen/extract/fields.js +9 -0
- package/dist/src/codegen/extract/fields.js.map +1 -0
- package/dist/src/codegen/extract/graphql.d.ts +14 -0
- package/dist/src/codegen/extract/graphql.d.ts.map +1 -0
- package/dist/src/codegen/extract/graphql.js +81 -0
- package/dist/src/codegen/extract/graphql.js.map +1 -0
- package/dist/src/codegen/extract/gwt.d.ts +6 -0
- package/dist/src/codegen/extract/gwt.d.ts.map +1 -0
- package/dist/src/codegen/extract/gwt.js +64 -0
- package/dist/src/codegen/extract/gwt.js.map +1 -0
- package/dist/src/codegen/extract/imports.d.ts +29 -0
- package/dist/src/codegen/extract/imports.d.ts.map +1 -0
- package/dist/src/codegen/extract/imports.js +55 -0
- package/dist/src/codegen/extract/imports.js.map +1 -0
- package/dist/src/codegen/extract/index.d.ts +10 -0
- package/dist/src/codegen/extract/index.d.ts.map +1 -0
- package/dist/src/codegen/extract/index.js +10 -0
- package/dist/src/codegen/extract/index.js.map +1 -0
- package/dist/src/codegen/extract/messages.d.ts +17 -0
- package/dist/src/codegen/extract/messages.d.ts.map +1 -0
- package/dist/src/codegen/extract/messages.js +172 -0
- package/dist/src/codegen/extract/messages.js.map +1 -0
- package/dist/src/codegen/extract/projection.d.ts +5 -0
- package/dist/src/codegen/extract/projection.d.ts.map +1 -0
- package/dist/src/codegen/extract/projection.js +44 -0
- package/dist/src/codegen/extract/projection.js.map +1 -0
- package/dist/src/codegen/extract/query.d.ts +14 -0
- package/dist/src/codegen/extract/query.d.ts.map +1 -0
- package/dist/src/codegen/extract/query.js +17 -0
- package/dist/src/codegen/extract/query.js.map +1 -0
- package/dist/src/codegen/extract/states.d.ts +5 -0
- package/dist/src/codegen/extract/states.d.ts.map +1 -0
- package/dist/src/codegen/extract/states.js +48 -0
- package/dist/src/codegen/extract/states.js.map +1 -0
- package/dist/src/codegen/extract/step-converter.d.ts +17 -0
- package/dist/src/codegen/extract/step-converter.d.ts.map +1 -0
- package/dist/src/codegen/extract/step-converter.js +82 -0
- package/dist/src/codegen/extract/step-converter.js.map +1 -0
- package/dist/src/codegen/extract/step-types.d.ts +29 -0
- package/dist/src/codegen/extract/step-types.d.ts.map +1 -0
- package/dist/src/codegen/extract/step-types.js +16 -0
- package/dist/src/codegen/extract/step-types.js.map +1 -0
- package/dist/src/codegen/extract/type-helpers.d.ts +13 -0
- package/dist/src/codegen/extract/type-helpers.d.ts.map +1 -0
- package/dist/src/codegen/extract/type-helpers.js +98 -0
- package/dist/src/codegen/extract/type-helpers.js.map +1 -0
- package/dist/src/codegen/scaffoldFromSchema.d.ts +9 -0
- package/dist/src/codegen/scaffoldFromSchema.d.ts.map +1 -0
- package/dist/src/codegen/scaffoldFromSchema.js +389 -0
- package/dist/src/codegen/scaffoldFromSchema.js.map +1 -0
- package/dist/src/codegen/templates/command/command.ts.ejs +16 -0
- package/dist/src/codegen/templates/command/handler.specs.ts.ejs +50 -0
- package/dist/src/codegen/templates/command/handler.ts.ejs +30 -0
- package/dist/src/codegen/templates/command/input.ts.ejs +23 -0
- package/dist/src/codegen/templates/command/resolver.ts.ejs +56 -0
- package/dist/src/codegen/templates/entity/entity.ts.ejs +35 -0
- package/dist/src/codegen/templates/entity/index.ts.ejs +6 -0
- package/dist/src/codegen/templates/module/app-module.ts.ejs +65 -0
- package/dist/src/codegen/templates/module/domain-module.ts.ejs +46 -0
- package/dist/src/codegen/templates/query/handler.ts.ejs +25 -0
- package/dist/src/codegen/templates/query/query.ts.ejs +1 -0
- package/dist/src/codegen/templates/query/resolver.ts.ejs +20 -0
- package/dist/src/codegen/templates/query/type.ts.ejs +24 -0
- package/dist/src/codegen/types.d.ts +38 -0
- package/dist/src/codegen/types.d.ts.map +1 -0
- package/dist/src/codegen/types.js +2 -0
- package/dist/src/codegen/types.js.map +1 -0
- package/dist/src/codegen/utils/path.d.ts +4 -0
- package/dist/src/codegen/utils/path.d.ts.map +1 -0
- package/dist/src/codegen/utils/path.js +18 -0
- package/dist/src/codegen/utils/path.js.map +1 -0
- package/dist/src/commands/generate-server.d.ts +28 -0
- package/dist/src/commands/generate-server.d.ts.map +1 -0
- package/dist/src/commands/generate-server.js +421 -0
- package/dist/src/commands/generate-server.js.map +1 -0
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +3 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/shared/graphql-types.ts +19 -0
- package/dist/src/shared/main.ts +27 -0
- package/dist/src/shared/mikro-orm.config.ts +18 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +3 -3
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
import { camelCase, pascalCase } from 'change-case';
|
|
2
|
+
import createDebug from 'debug';
|
|
3
|
+
import ejs from 'ejs';
|
|
4
|
+
import fs from 'fs/promises';
|
|
5
|
+
import path, { dirname } from 'path';
|
|
6
|
+
import prettier from 'prettier';
|
|
7
|
+
import { fileURLToPath } from 'url';
|
|
8
|
+
import { ensureDirExists, ensureDirPath, toKebabCase } from './utils/path.js';
|
|
9
|
+
const debug = createDebug('auto:server-generator-nestjs:scaffold');
|
|
10
|
+
import { consolidateEntityFields } from './entity-consolidation.js';
|
|
11
|
+
import { getStreamFromSink } from './extract/data-sink.js';
|
|
12
|
+
import { parseGraphQlRequest } from './extract/graphql.js';
|
|
13
|
+
import { baseTs, buildCommandGwtMapping, buildQueryGwtMapping, createCollectEnumNames, createEventUnionType, createFieldUsesDate, createFieldUsesFloat, createFieldUsesJSON, createIsEnumType, extractMessagesFromSpecs, extractProjectionName, getAllEventTypes, getLocalEvents, groupEventImports, isInlineObjectArray as isInlineObjectArrayHelper, isInlineObject as isInlineObjectHelper, } from './extract/index.js';
|
|
14
|
+
const defaultFilesByType = {
|
|
15
|
+
command: ['command.ts.ejs', 'input.ts.ejs', 'handler.ts.ejs', 'resolver.ts.ejs', 'handler.specs.ts.ejs'],
|
|
16
|
+
query: ['query.ts.ejs', 'type.ts.ejs', 'handler.ts.ejs', 'resolver.ts.ejs'],
|
|
17
|
+
react: [],
|
|
18
|
+
};
|
|
19
|
+
function isStringLiteralUnion(s) {
|
|
20
|
+
return /^"[^"]+"(\s*\|\s*"[^"]+")+$/.test(s.trim()) || /^'[^']+'(\s*\|\s*'[^']+)+$/.test(s.trim());
|
|
21
|
+
}
|
|
22
|
+
function extractStringLiteralValues(unionString) {
|
|
23
|
+
const doubleQuoted = unionString.match(/"([^"]+)"/g);
|
|
24
|
+
const singleQuoted = unionString.match(/'([^']+)'/g);
|
|
25
|
+
const matches = doubleQuoted ?? singleQuoted;
|
|
26
|
+
if (matches === null)
|
|
27
|
+
return [];
|
|
28
|
+
return matches.map((m) => m.slice(1, -1));
|
|
29
|
+
}
|
|
30
|
+
function normalizeUnionString(values) {
|
|
31
|
+
return values
|
|
32
|
+
.slice()
|
|
33
|
+
.sort()
|
|
34
|
+
.map((v) => `'${v}'`)
|
|
35
|
+
.join(' | ');
|
|
36
|
+
}
|
|
37
|
+
function generateEnumName(fieldName, existingNames) {
|
|
38
|
+
const baseName = pascalCase(fieldName);
|
|
39
|
+
if (!existingNames.has(baseName)) {
|
|
40
|
+
return baseName;
|
|
41
|
+
}
|
|
42
|
+
let counter = 2;
|
|
43
|
+
while (existingNames.has(`${baseName}${counter}`)) {
|
|
44
|
+
counter++;
|
|
45
|
+
}
|
|
46
|
+
return `${baseName}${counter}`;
|
|
47
|
+
}
|
|
48
|
+
function processFieldForEnum(field, messageName, unionToEnumName, existingEnumNames) {
|
|
49
|
+
const tsType = field.type;
|
|
50
|
+
if (tsType === null || tsType === undefined)
|
|
51
|
+
return null;
|
|
52
|
+
const cleanType = tsType.replace(/\s*\|\s*null\b/g, '').trim();
|
|
53
|
+
const isUnion = isStringLiteralUnion(cleanType);
|
|
54
|
+
if (!isUnion)
|
|
55
|
+
return null;
|
|
56
|
+
const values = extractStringLiteralValues(cleanType);
|
|
57
|
+
if (values.length === 0)
|
|
58
|
+
return null;
|
|
59
|
+
const normalized = normalizeUnionString(values);
|
|
60
|
+
if (unionToEnumName.has(normalized)) {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
const enumName = generateEnumName(`${messageName}${pascalCase(field.name)}`, existingEnumNames);
|
|
64
|
+
existingEnumNames.add(enumName);
|
|
65
|
+
const enumDef = {
|
|
66
|
+
name: enumName,
|
|
67
|
+
values,
|
|
68
|
+
unionString: normalized,
|
|
69
|
+
};
|
|
70
|
+
unionToEnumName.set(normalized, enumName);
|
|
71
|
+
return enumDef;
|
|
72
|
+
}
|
|
73
|
+
function extractEnumsFromMessages(messages) {
|
|
74
|
+
const unionToEnumName = new Map();
|
|
75
|
+
const enums = [];
|
|
76
|
+
const existingEnumNames = new Set();
|
|
77
|
+
for (const message of messages) {
|
|
78
|
+
if (message.fields === undefined || message.fields === null)
|
|
79
|
+
continue;
|
|
80
|
+
for (const field of message.fields) {
|
|
81
|
+
const enumDef = processFieldForEnum(field, message.name, unionToEnumName, existingEnumNames);
|
|
82
|
+
if (enumDef !== null) {
|
|
83
|
+
enums.push(enumDef);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return { enums, unionToEnumName };
|
|
88
|
+
}
|
|
89
|
+
function generateEnumTypeScript(enumDef) {
|
|
90
|
+
const entries = enumDef.values.map((val) => {
|
|
91
|
+
const key = val.toUpperCase().replace(/[^A-Z0-9]/g, '_');
|
|
92
|
+
return ` ${key} = '${val}',`;
|
|
93
|
+
});
|
|
94
|
+
return `import { registerEnumType } from '@nestjs/graphql';
|
|
95
|
+
|
|
96
|
+
export enum ${enumDef.name} {
|
|
97
|
+
${entries.join('\n')}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
registerEnumType(${enumDef.name}, {
|
|
101
|
+
name: '${enumDef.name}',
|
|
102
|
+
});`;
|
|
103
|
+
}
|
|
104
|
+
async function writeEnumsToEntitiesFolder(baseDir, flowName, enums) {
|
|
105
|
+
if (enums.length === 0)
|
|
106
|
+
return;
|
|
107
|
+
const entitiesDir = path.join(baseDir, toKebabCase(flowName), 'entities');
|
|
108
|
+
await ensureDirExists(entitiesDir);
|
|
109
|
+
for (const enumDef of enums) {
|
|
110
|
+
const enumFilePath = path.join(entitiesDir, `${toKebabCase(enumDef.name)}.enum.ts`);
|
|
111
|
+
try {
|
|
112
|
+
await fs.access(enumFilePath);
|
|
113
|
+
debug('Enum file already exists: %s, skipping', enumFilePath);
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
const content = generateEnumTypeScript(enumDef);
|
|
117
|
+
const prettierConfig = await prettier.resolveConfig(enumFilePath);
|
|
118
|
+
const formatted = await prettier.format(content, {
|
|
119
|
+
...prettierConfig,
|
|
120
|
+
parser: 'typescript',
|
|
121
|
+
filepath: enumFilePath,
|
|
122
|
+
});
|
|
123
|
+
await fs.writeFile(enumFilePath, formatted, 'utf8');
|
|
124
|
+
debug('Written enum file: %s', enumFilePath);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
async function renderTemplate(templatePath, data, unionToEnumName = new Map()) {
|
|
129
|
+
const content = await fs.readFile(templatePath, 'utf8');
|
|
130
|
+
const template = ejs.compile(content, {
|
|
131
|
+
async: true,
|
|
132
|
+
escape: (text) => text,
|
|
133
|
+
});
|
|
134
|
+
const isInlineObject = isInlineObjectHelper;
|
|
135
|
+
const isInlineObjectArray = isInlineObjectArrayHelper;
|
|
136
|
+
const convertPrimitiveType = (base) => {
|
|
137
|
+
if (base === 'ID')
|
|
138
|
+
return 'ID';
|
|
139
|
+
if (base === 'Int')
|
|
140
|
+
return 'Int';
|
|
141
|
+
if (base === 'Float')
|
|
142
|
+
return 'Float';
|
|
143
|
+
if (base === 'string')
|
|
144
|
+
return 'String';
|
|
145
|
+
if (base === 'number')
|
|
146
|
+
return 'Float';
|
|
147
|
+
if (base === 'boolean')
|
|
148
|
+
return 'Boolean';
|
|
149
|
+
if (base === 'Date')
|
|
150
|
+
return 'Date';
|
|
151
|
+
return 'String';
|
|
152
|
+
};
|
|
153
|
+
const resolveEnumOrString = (base) => {
|
|
154
|
+
if (!isStringLiteralUnion(base))
|
|
155
|
+
return 'String';
|
|
156
|
+
const values = extractStringLiteralValues(base);
|
|
157
|
+
const normalized = normalizeUnionString(values);
|
|
158
|
+
const enumName = unionToEnumName.get(normalized);
|
|
159
|
+
return enumName ?? 'String';
|
|
160
|
+
};
|
|
161
|
+
const graphqlType = (rawTs) => {
|
|
162
|
+
const t = (rawTs ?? '').trim();
|
|
163
|
+
if (!t)
|
|
164
|
+
return 'String';
|
|
165
|
+
const base = t.replace(/\s*\|\s*null\b/g, '').trim();
|
|
166
|
+
const arr1 = base.match(/^Array<(.*)>$/);
|
|
167
|
+
const arr2 = base.match(/^(.*)\[\]$/);
|
|
168
|
+
if (arr1 !== null)
|
|
169
|
+
return `[${graphqlType(arr1[1].trim())}]`;
|
|
170
|
+
if (arr2 !== null)
|
|
171
|
+
return `[${graphqlType(arr2[1].trim())}]`;
|
|
172
|
+
if (base === 'unknown' || base === 'any')
|
|
173
|
+
return 'GraphQLJSON';
|
|
174
|
+
if (base === 'object')
|
|
175
|
+
return 'JSON';
|
|
176
|
+
if (isInlineObject(base))
|
|
177
|
+
return 'JSON';
|
|
178
|
+
if (isStringLiteralUnion(base))
|
|
179
|
+
return resolveEnumOrString(base);
|
|
180
|
+
return convertPrimitiveType(base);
|
|
181
|
+
};
|
|
182
|
+
const toTsFieldType = (ts) => {
|
|
183
|
+
if (!ts)
|
|
184
|
+
return 'string';
|
|
185
|
+
const t = ts.trim();
|
|
186
|
+
const cleanType = t.replace(/\s*\|\s*null\b/g, '').trim();
|
|
187
|
+
const arr = cleanType.match(/^Array<(.*)>$/);
|
|
188
|
+
if (arr !== null)
|
|
189
|
+
return `${toTsFieldType(arr[1].trim())}[]`;
|
|
190
|
+
if (isStringLiteralUnion(cleanType)) {
|
|
191
|
+
const values = extractStringLiteralValues(cleanType);
|
|
192
|
+
const normalized = normalizeUnionString(values);
|
|
193
|
+
const enumName = unionToEnumName.get(normalized);
|
|
194
|
+
if (enumName !== undefined)
|
|
195
|
+
return enumName;
|
|
196
|
+
}
|
|
197
|
+
return t;
|
|
198
|
+
};
|
|
199
|
+
const isNullable = (rawTs) => /\|\s*null\b/.test(rawTs);
|
|
200
|
+
const isEnumType = createIsEnumType(toTsFieldType);
|
|
201
|
+
const fieldUsesDate = createFieldUsesDate(graphqlType);
|
|
202
|
+
const fieldUsesJSON = createFieldUsesJSON(graphqlType);
|
|
203
|
+
const fieldUsesFloat = createFieldUsesFloat(graphqlType);
|
|
204
|
+
const collectEnumNames = createCollectEnumNames(isEnumType, toTsFieldType);
|
|
205
|
+
const result = await template({
|
|
206
|
+
...data,
|
|
207
|
+
pascalCase,
|
|
208
|
+
toKebabCase,
|
|
209
|
+
camelCase,
|
|
210
|
+
graphqlType,
|
|
211
|
+
isNullable,
|
|
212
|
+
toTsFieldType,
|
|
213
|
+
messages: data.messages,
|
|
214
|
+
message: data.message,
|
|
215
|
+
isInlineObject,
|
|
216
|
+
isInlineObjectArray,
|
|
217
|
+
baseTs,
|
|
218
|
+
isEnumType,
|
|
219
|
+
fieldUsesDate,
|
|
220
|
+
fieldUsesJSON,
|
|
221
|
+
fieldUsesFloat,
|
|
222
|
+
collectEnumNames,
|
|
223
|
+
});
|
|
224
|
+
return result;
|
|
225
|
+
}
|
|
226
|
+
async function generateFileForTemplate(templateFile, slice, sliceDir, templateData, unionToEnumName = new Map()) {
|
|
227
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
228
|
+
const templatePath = path.join(__dirname, './templates', slice.type, templateFile);
|
|
229
|
+
const fileName = templateFile
|
|
230
|
+
.replace(/\.ts\.ejs$/, '.ts')
|
|
231
|
+
.replace(/^(command|query|handler|resolver|input|type)\./, `${toKebabCase(slice.name)}.$1.`);
|
|
232
|
+
const outputPath = path.join(sliceDir, fileName);
|
|
233
|
+
const contents = await renderTemplate(templatePath, templateData, unionToEnumName);
|
|
234
|
+
const prettierConfig = await prettier.resolveConfig(outputPath);
|
|
235
|
+
const formattedContents = await prettier.format(contents, {
|
|
236
|
+
...prettierConfig,
|
|
237
|
+
parser: 'typescript',
|
|
238
|
+
filepath: outputPath,
|
|
239
|
+
});
|
|
240
|
+
return { outputPath, contents: formattedContents };
|
|
241
|
+
}
|
|
242
|
+
async function prepareTemplateData(slice, flow, commands, events, states, commandSchemasByName, projectionIdField, projectionSingleton, allMessages, integrations) {
|
|
243
|
+
const { streamPattern, streamId } = getStreamFromSink(slice);
|
|
244
|
+
const gwtMapping = buildCommandGwtMapping(slice);
|
|
245
|
+
const queryGwtMapping = buildQueryGwtMapping(slice);
|
|
246
|
+
const projectionName = extractProjectionName(slice);
|
|
247
|
+
const uniqueCommands = Array.from(new Map(commands.map((c) => [c.type, c])).values());
|
|
248
|
+
const allowedForSlice = new Set(Object.keys(gwtMapping));
|
|
249
|
+
const filteredCommands = allowedForSlice.size > 0 ? uniqueCommands.filter((c) => allowedForSlice.has(c.type)) : uniqueCommands;
|
|
250
|
+
const eventImportGroups = groupEventImports({ currentSliceName: slice.name, events });
|
|
251
|
+
const allEventTypesArray = getAllEventTypes(events);
|
|
252
|
+
const allEventTypes = createEventUnionType(events);
|
|
253
|
+
const localEvents = getLocalEvents(events);
|
|
254
|
+
return {
|
|
255
|
+
flowName: flow.name,
|
|
256
|
+
sliceName: slice.name,
|
|
257
|
+
slice,
|
|
258
|
+
stream: { pattern: streamPattern, id: streamId },
|
|
259
|
+
commands: filteredCommands,
|
|
260
|
+
events,
|
|
261
|
+
states,
|
|
262
|
+
gwtMapping,
|
|
263
|
+
queryGwtMapping,
|
|
264
|
+
commandSchemasByName,
|
|
265
|
+
projectionIdField,
|
|
266
|
+
projectionSingleton,
|
|
267
|
+
projectionName,
|
|
268
|
+
projectionType: projectionName != null ? pascalCase(projectionName) : undefined,
|
|
269
|
+
parsedRequest: slice.type === 'query' && slice.request != null ? parseGraphQlRequest(slice.request) : undefined,
|
|
270
|
+
messages: allMessages,
|
|
271
|
+
message: slice.type === 'query' && allMessages
|
|
272
|
+
? allMessages.find((m) => m.name === slice.server?.data?.[0]?.target?.name)
|
|
273
|
+
: undefined,
|
|
274
|
+
integrations,
|
|
275
|
+
eventImportGroups,
|
|
276
|
+
allEventTypes,
|
|
277
|
+
allEventTypesArray,
|
|
278
|
+
localEvents,
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
async function generateFilesForSlice(slice, flow, sliceDir, messages, flows, unionToEnumName, integrations) {
|
|
282
|
+
const templates = defaultFilesByType[slice.type];
|
|
283
|
+
if (!templates?.length) {
|
|
284
|
+
return [];
|
|
285
|
+
}
|
|
286
|
+
const extracted = extractMessagesFromSpecs(slice, messages);
|
|
287
|
+
const templateData = await prepareTemplateData(slice, flow, extracted.commands, extracted.events, extracted.states, extracted.commandSchemasByName, extracted.projectionIdField, extracted.projectionSingleton, messages, integrations);
|
|
288
|
+
const plans = await Promise.all(templates.map((template) => generateFileForTemplate(template, slice, sliceDir, templateData, unionToEnumName)));
|
|
289
|
+
return plans;
|
|
290
|
+
}
|
|
291
|
+
async function generateEntityFiles(entity, entitiesDir, unionToEnumName) {
|
|
292
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
293
|
+
const plans = [];
|
|
294
|
+
const entityTemplatePath = path.join(__dirname, './templates/entity/entity.ts.ejs');
|
|
295
|
+
const indexTemplatePath = path.join(__dirname, './templates/entity/index.ts.ejs');
|
|
296
|
+
const entityTemplateData = { entity, toTsFieldType: (ts) => ts, toKebabCase };
|
|
297
|
+
const entityContents = await renderTemplate(entityTemplatePath, entityTemplateData, unionToEnumName);
|
|
298
|
+
const entityFileName = `${toKebabCase(entity.entityName)}.entity.ts`;
|
|
299
|
+
const entityPath = path.join(entitiesDir, entityFileName);
|
|
300
|
+
const prettierConfig = await prettier.resolveConfig(entityPath);
|
|
301
|
+
const formattedEntity = await prettier.format(entityContents, {
|
|
302
|
+
...prettierConfig,
|
|
303
|
+
parser: 'typescript',
|
|
304
|
+
filepath: entityPath,
|
|
305
|
+
});
|
|
306
|
+
plans.push({ outputPath: entityPath, contents: formattedEntity });
|
|
307
|
+
const indexTemplateData = { entity, toKebabCase };
|
|
308
|
+
const indexContents = await renderTemplate(indexTemplatePath, indexTemplateData, unionToEnumName);
|
|
309
|
+
const indexPath = path.join(entitiesDir, 'index.ts');
|
|
310
|
+
const formattedIndex = await prettier.format(indexContents, {
|
|
311
|
+
...prettierConfig,
|
|
312
|
+
parser: 'typescript',
|
|
313
|
+
filepath: indexPath,
|
|
314
|
+
});
|
|
315
|
+
plans.push({ outputPath: indexPath, contents: formattedIndex });
|
|
316
|
+
return plans;
|
|
317
|
+
}
|
|
318
|
+
async function generateDomainModule(flow, flowDir, unionToEnumName) {
|
|
319
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
320
|
+
const moduleTemplatePath = path.join(__dirname, './templates/module/domain-module.ts.ejs');
|
|
321
|
+
const slices = flow.slices.filter((s) => s.type !== 'experience');
|
|
322
|
+
const templateData = {
|
|
323
|
+
flowName: flow.name,
|
|
324
|
+
slices,
|
|
325
|
+
pascalCase,
|
|
326
|
+
toKebabCase,
|
|
327
|
+
};
|
|
328
|
+
const contents = await renderTemplate(moduleTemplatePath, templateData, unionToEnumName);
|
|
329
|
+
const modulePath = path.join(flowDir, `${toKebabCase(flow.name)}.module.ts`);
|
|
330
|
+
const prettierConfig = await prettier.resolveConfig(modulePath);
|
|
331
|
+
const formattedContents = await prettier.format(contents, {
|
|
332
|
+
...prettierConfig,
|
|
333
|
+
parser: 'typescript',
|
|
334
|
+
filepath: modulePath,
|
|
335
|
+
});
|
|
336
|
+
return { outputPath: modulePath, contents: formattedContents };
|
|
337
|
+
}
|
|
338
|
+
async function generateAppModule(flows, baseDir, unionToEnumName) {
|
|
339
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
340
|
+
const moduleTemplatePath = path.join(__dirname, './templates/module/app-module.ts.ejs');
|
|
341
|
+
const templateData = {
|
|
342
|
+
flows,
|
|
343
|
+
pascalCase,
|
|
344
|
+
toKebabCase,
|
|
345
|
+
};
|
|
346
|
+
const contents = await renderTemplate(moduleTemplatePath, templateData, unionToEnumName);
|
|
347
|
+
const appModulePath = path.join(baseDir, '../app.module.ts');
|
|
348
|
+
const prettierConfig = await prettier.resolveConfig(appModulePath);
|
|
349
|
+
const formattedContents = await prettier.format(contents, {
|
|
350
|
+
...prettierConfig,
|
|
351
|
+
parser: 'typescript',
|
|
352
|
+
filepath: appModulePath,
|
|
353
|
+
});
|
|
354
|
+
return { outputPath: appModulePath, contents: formattedContents };
|
|
355
|
+
}
|
|
356
|
+
export async function generateScaffoldFilePlans(flows, messages, integrations, baseDir = 'src/domain') {
|
|
357
|
+
const { enums, unionToEnumName } = extractEnumsFromMessages(messages ?? []);
|
|
358
|
+
const allPlans = [];
|
|
359
|
+
for (const flow of flows) {
|
|
360
|
+
const flowDir = ensureDirPath(baseDir, toKebabCase(flow.name));
|
|
361
|
+
const entitiesDir = ensureDirPath(flowDir, 'entities');
|
|
362
|
+
await writeEnumsToEntitiesFolder(baseDir, flow.name, enums);
|
|
363
|
+
const entity = consolidateEntityFields(flow, messages ?? [], unionToEnumName);
|
|
364
|
+
const entityPlans = await generateEntityFiles(entity, entitiesDir, unionToEnumName);
|
|
365
|
+
allPlans.push(...entityPlans);
|
|
366
|
+
for (const slice of flow.slices) {
|
|
367
|
+
const sliceDir = ensureDirPath(flowDir, toKebabCase(slice.name));
|
|
368
|
+
const plans = await generateFilesForSlice(slice, flow, sliceDir, messages ?? [], flows, unionToEnumName, integrations);
|
|
369
|
+
allPlans.push(...plans);
|
|
370
|
+
}
|
|
371
|
+
const modulePlan = await generateDomainModule(flow, flowDir, unionToEnumName);
|
|
372
|
+
allPlans.push(modulePlan);
|
|
373
|
+
}
|
|
374
|
+
const appModulePlan = await generateAppModule(flows, baseDir, unionToEnumName);
|
|
375
|
+
allPlans.push(appModulePlan);
|
|
376
|
+
return allPlans;
|
|
377
|
+
}
|
|
378
|
+
export async function writeScaffoldFilePlans(plans) {
|
|
379
|
+
for (const { outputPath, contents } of plans) {
|
|
380
|
+
const dir = path.dirname(outputPath);
|
|
381
|
+
await ensureDirExists(dir);
|
|
382
|
+
await fs.writeFile(outputPath, contents, 'utf8');
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
export async function scaffoldFromSchema(flows, messages, baseDir = 'src/domain') {
|
|
386
|
+
const plans = await generateScaffoldFilePlans(flows, messages, undefined, baseDir);
|
|
387
|
+
await writeScaffoldFilePlans(plans);
|
|
388
|
+
}
|
|
389
|
+
//# sourceMappingURL=scaffoldFromSchema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scaffoldFromSchema.js","sourceRoot":"","sources":["../../../src/codegen/scaffoldFromSchema.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<%
|
|
2
|
+
const command = commands[0];
|
|
3
|
+
if (!command) return '';
|
|
4
|
+
const enumList = collectEnumNames(command.fields);
|
|
5
|
+
%><% if (enumList.length > 0) { -%>
|
|
6
|
+
import { <%= enumList.join(', ') %> } from '../entities';
|
|
7
|
+
<% } -%>
|
|
8
|
+
|
|
9
|
+
export class <%= pascalCase(command.type) %>Command {
|
|
10
|
+
constructor(
|
|
11
|
+
<% for (let i = 0; i < command.fields.length; i++) { const field = command.fields[i]; -%>
|
|
12
|
+
public readonly <%= field.name %>: <%= toTsFieldType(field.tsType) %>,
|
|
13
|
+
<% } -%>
|
|
14
|
+
public readonly now?: Date,
|
|
15
|
+
) {}
|
|
16
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
<%
|
|
2
|
+
const command = commands[0];
|
|
3
|
+
if (!command) return '';
|
|
4
|
+
const entityName = pascalCase(flowName) + 'Entity';
|
|
5
|
+
const enumList = collectEnumNames(command.fields);
|
|
6
|
+
%>import { describe, it, expect, beforeEach, vi } from 'vitest';
|
|
7
|
+
import { Test, TestingModule } from '@nestjs/testing';
|
|
8
|
+
import { getRepositoryToken } from '@mikro-orm/nestjs';
|
|
9
|
+
import { <%= pascalCase(command.type) %>Handler } from './<%= toKebabCase(sliceName) %>.handler';
|
|
10
|
+
import { <%= pascalCase(command.type) %>Command } from './<%= toKebabCase(sliceName) %>.command';
|
|
11
|
+
import { <%= entityName %><% if (enumList.length > 0) { %>, <%= enumList.join(', ') %><% } %> } from '../entities';
|
|
12
|
+
|
|
13
|
+
describe('<%= pascalCase(command.type) %>Handler', () => {
|
|
14
|
+
let handler: <%= pascalCase(command.type) %>Handler;
|
|
15
|
+
let mockRepository: Record<string, unknown>;
|
|
16
|
+
|
|
17
|
+
beforeEach(async () => {
|
|
18
|
+
mockRepository = {
|
|
19
|
+
create: vi.fn(),
|
|
20
|
+
findOne: vi.fn(),
|
|
21
|
+
getEntityManager: vi.fn(() => ({
|
|
22
|
+
persistAndFlush: vi.fn(),
|
|
23
|
+
})),
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const module: TestingModule = await Test.createTestingModule({
|
|
27
|
+
providers: [
|
|
28
|
+
<%= pascalCase(command.type) %>Handler,
|
|
29
|
+
{
|
|
30
|
+
provide: getRepositoryToken(<%= entityName %>),
|
|
31
|
+
useValue: mockRepository,
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
}).compile();
|
|
35
|
+
|
|
36
|
+
handler = module.get<<%= pascalCase(command.type) %>Handler>(<%= pascalCase(command.type) %>Handler);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('should be defined', () => {
|
|
40
|
+
expect(handler).toBeDefined();
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// TODO: Add test cases based on GWT specs
|
|
44
|
+
// Example:
|
|
45
|
+
// it('should handle <%= command.type %>', async () => {
|
|
46
|
+
// const command = new <%= pascalCase(command.type) %>Command(...);
|
|
47
|
+
// await handler.execute(command);
|
|
48
|
+
// expect(mockRepository.create).toHaveBeenCalled();
|
|
49
|
+
// });
|
|
50
|
+
});
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
<%
|
|
2
|
+
const command = commands[0];
|
|
3
|
+
if (!command) return '';
|
|
4
|
+
const entityName = pascalCase(flowName) + 'Entity';
|
|
5
|
+
const enumList = collectEnumNames(command.fields);
|
|
6
|
+
%>import { CommandHandler, ICommandHandler } from '@nestjs/cqrs';
|
|
7
|
+
import { InjectRepository } from '@mikro-orm/nestjs';
|
|
8
|
+
import { EntityRepository } from '@mikro-orm/core';
|
|
9
|
+
import { <%= pascalCase(command.type) %>Command } from './<%= toKebabCase(sliceName) %>.command';
|
|
10
|
+
import { <%= entityName %><% if (enumList.length > 0) { %>, <%= enumList.join(', ') %><% } %> } from '../entities';
|
|
11
|
+
|
|
12
|
+
@CommandHandler(<%= pascalCase(command.type) %>Command)
|
|
13
|
+
export class <%= pascalCase(command.type) %>Handler implements ICommandHandler<<%= pascalCase(command.type) %>Command> {
|
|
14
|
+
constructor(
|
|
15
|
+
@InjectRepository(<%= entityName %>)
|
|
16
|
+
private readonly repository: EntityRepository<<%= entityName %>>,
|
|
17
|
+
) {}
|
|
18
|
+
|
|
19
|
+
async execute(command: <%= pascalCase(command.type) %>Command): Promise<void> {
|
|
20
|
+
// TODO: Implement command handler logic
|
|
21
|
+
// This is a generated stub - implement based on your business rules
|
|
22
|
+
// Example for create operation:
|
|
23
|
+
// const entity = this.repository.create({
|
|
24
|
+
// ...command fields...
|
|
25
|
+
// });
|
|
26
|
+
// await this.repository.getEntityManager().persistAndFlush(entity);
|
|
27
|
+
|
|
28
|
+
throw new Error('Not yet implemented: <%= command.type %>');
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<%
|
|
2
|
+
const command = commands[0];
|
|
3
|
+
if (!command) return '';
|
|
4
|
+
const usesID = command.fields.some(f => graphqlType(f.tsType) === 'ID');
|
|
5
|
+
const usesFloat = command.fields.some(f => fieldUsesFloat(f.tsType));
|
|
6
|
+
const usesJSON = command.fields.some(f => fieldUsesJSON(f.tsType));
|
|
7
|
+
const enumList = collectEnumNames(command.fields);
|
|
8
|
+
%>import { InputType, Field<% if (usesID) { %>, ID<% } %><% if (usesFloat) { %>, Float<% } %> } from '@nestjs/graphql';
|
|
9
|
+
<% if (usesJSON) { -%>
|
|
10
|
+
import GraphQLJSON from 'graphql-type-json';
|
|
11
|
+
<% } -%>
|
|
12
|
+
<% if (enumList.length > 0) { -%>
|
|
13
|
+
import { <%= enumList.join(', ') %> } from '../entities';
|
|
14
|
+
<% } -%>
|
|
15
|
+
|
|
16
|
+
@InputType()
|
|
17
|
+
export class <%= pascalCase(command.type) %>Input {
|
|
18
|
+
<% for (const field of command.fields) { -%>
|
|
19
|
+
@Field(() => <%= graphqlType(field.tsType) %><%= isNullable(field.tsType) ? ', { nullable: true }' : '' %>)
|
|
20
|
+
<%= field.name %><%= isNullable(field.tsType) ? '?' : '!' %>: <%= toTsFieldType(field.tsType) %>;
|
|
21
|
+
|
|
22
|
+
<% } -%>
|
|
23
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
<%
|
|
2
|
+
const command = commands[0];
|
|
3
|
+
if (!command) return '';
|
|
4
|
+
const mutationName = camelCase(sliceName);
|
|
5
|
+
%>import { Mutation, Resolver, Args } from '@nestjs/graphql';
|
|
6
|
+
import { Logger, Injectable } from '@nestjs/common';
|
|
7
|
+
import { CommandBus } from '@nestjs/cqrs';
|
|
8
|
+
import { <%= pascalCase(command.type) %>Command } from './<%= toKebabCase(sliceName) %>.command';
|
|
9
|
+
import { <%= pascalCase(command.type) %>Input } from './<%= toKebabCase(sliceName) %>.input';
|
|
10
|
+
import { MutationResponse } from '../../shared/graphql-types';
|
|
11
|
+
|
|
12
|
+
@Injectable()
|
|
13
|
+
@Resolver()
|
|
14
|
+
export class <%= pascalCase(command.type) %>Resolver {
|
|
15
|
+
private readonly logger = new Logger(<%= pascalCase(command.type) %>Resolver.name);
|
|
16
|
+
|
|
17
|
+
constructor(private readonly commandBus: CommandBus) {}
|
|
18
|
+
|
|
19
|
+
@Mutation(() => MutationResponse)
|
|
20
|
+
async <%= mutationName %>(
|
|
21
|
+
@Args({ name: 'input', type: () => <%= pascalCase(command.type) %>Input })
|
|
22
|
+
input: <%= pascalCase(command.type) %>Input
|
|
23
|
+
): Promise<MutationResponse> {
|
|
24
|
+
try {
|
|
25
|
+
await this.commandBus.execute(
|
|
26
|
+
new <%= pascalCase(command.type) %>Command(
|
|
27
|
+
<% for (let i = 0; i < command.fields.length; i++) { const field = command.fields[i]; -%>
|
|
28
|
+
input.<%= field.name %>,
|
|
29
|
+
<% } -%>
|
|
30
|
+
)
|
|
31
|
+
);
|
|
32
|
+
this.logger.log(`Successfully executed: <%= mutationName %>`);
|
|
33
|
+
return { success: true };
|
|
34
|
+
} catch (error: unknown) {
|
|
35
|
+
if (error instanceof Error) {
|
|
36
|
+
this.logger.error(`Failed to execute <%= mutationName %>: ${error.message}`, error.stack);
|
|
37
|
+
return {
|
|
38
|
+
success: false,
|
|
39
|
+
error: {
|
|
40
|
+
type: error.name,
|
|
41
|
+
message: error.message,
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
this.logger.error('Failed to execute <%= mutationName %>: Unknown error');
|
|
47
|
+
return {
|
|
48
|
+
success: false,
|
|
49
|
+
error: {
|
|
50
|
+
type: 'UnknownError',
|
|
51
|
+
message: 'An unexpected error occurred',
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
<%
|
|
2
|
+
function getOrmType(field) {
|
|
3
|
+
const cleanType = field.tsType.replace(/\s*\|\s*null\b/g, '').trim();
|
|
4
|
+
if (cleanType === 'string') return 'string';
|
|
5
|
+
if (cleanType === 'number') return 'number';
|
|
6
|
+
if (cleanType === 'boolean') return 'boolean';
|
|
7
|
+
if (cleanType === 'Date') return 'Date';
|
|
8
|
+
return 'string';
|
|
9
|
+
}
|
|
10
|
+
%>import { Entity, PrimaryKey, Property, Enum, Index } from '@mikro-orm/core';
|
|
11
|
+
<% if (entity.enumImports.length > 0) { -%>
|
|
12
|
+
import { <%= entity.enumImports.join(', ') %> } from '.';
|
|
13
|
+
<% } -%>
|
|
14
|
+
|
|
15
|
+
@Entity({ tableName: '<%= entity.tableName %>' })
|
|
16
|
+
export class <%= entity.entityName %> {
|
|
17
|
+
<% for (const field of entity.fields) { -%>
|
|
18
|
+
<% if (field.isPrimary) { -%>
|
|
19
|
+
@PrimaryKey({ type: '<%= getOrmType(field) %>' })
|
|
20
|
+
<%= field.name %>!: <%= toTsFieldType(field.tsType) %>;
|
|
21
|
+
|
|
22
|
+
<% } else if (field.isEnum && field.enumName) { -%>
|
|
23
|
+
@Enum(() => <%= field.enumName %>)
|
|
24
|
+
<% if (field.indexed) { -%>
|
|
25
|
+
@Index()
|
|
26
|
+
<% } -%>
|
|
27
|
+
<%= field.name %>!: <%= field.enumName %>;
|
|
28
|
+
|
|
29
|
+
<% } else { -%>
|
|
30
|
+
@Property({ type: '<%= getOrmType(field) %>'<%= field.nullable ? ', nullable: true' : '' %> })
|
|
31
|
+
<%= field.name %><%= field.nullable ? '?' : '!' %>: <%= toTsFieldType(field.tsType) %><%= field.nullable ? ' | null' : '' %>;
|
|
32
|
+
|
|
33
|
+
<% } -%>
|
|
34
|
+
<% } -%>
|
|
35
|
+
}
|