@postxl/generator 0.69.0 → 0.70.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.
Files changed (57) hide show
  1. package/README.md +1 -20
  2. package/dist/generator.js +41 -40
  3. package/dist/generators/indices/{datamodule.generator.d.ts → data/module.generator.d.ts} +2 -2
  4. package/dist/generators/indices/{datamodule.generator.js → data/module.generator.js} +4 -5
  5. package/dist/generators/indices/{dataservice.generator.d.ts → data/service.generator.d.ts} +2 -2
  6. package/dist/generators/indices/{dataservice.generator.js → data/service.generator.js} +5 -5
  7. package/dist/generators/indices/{data-types.generator.d.ts → data/types.generator.d.ts} +2 -2
  8. package/dist/generators/indices/{data-types.generator.js → data/types.generator.js} +2 -2
  9. package/dist/generators/indices/{importexport-convert-import-functions.generator.d.ts → import-export/importexport-convert-import-functions.generator.d.ts} +2 -2
  10. package/dist/generators/indices/{importexport-convert-import-functions.generator.js → import-export/importexport-convert-import-functions.generator.js} +4 -4
  11. package/dist/generators/indices/{importexport-exporter-class.generator.d.ts → import-export/importexport-exporter-class.generator.d.ts} +2 -2
  12. package/dist/generators/indices/{importexport-exporter-class.generator.js → import-export/importexport-exporter-class.generator.js} +4 -5
  13. package/dist/generators/indices/{importexport-import-service.generator.d.ts → import-export/importexport-import-service.generator.d.ts} +2 -2
  14. package/dist/generators/indices/{importexport-import-service.generator.js → import-export/importexport-import-service.generator.js} +4 -4
  15. package/dist/generators/indices/{importexport-types.generator.d.ts → import-export/importexport-types.generator.d.ts} +2 -2
  16. package/dist/generators/indices/{importexport-types.generator.js → import-export/importexport-types.generator.js} +2 -2
  17. package/dist/generators/indices/{routes-index.generator.js → routes.generator.js} +3 -0
  18. package/dist/generators/indices/seed-template.generator.js +2 -2
  19. package/dist/generators/indices/types.generator.js +13 -1
  20. package/dist/generators/indices/{businesslogic-actiontypes.generator.d.ts → update/actiontypes.generator.d.ts} +2 -2
  21. package/dist/generators/indices/{businesslogic-actiontypes.generator.js → update/actiontypes.generator.js} +3 -3
  22. package/dist/generators/indices/{businesslogic-update-module.generator.d.ts → update/module.generator.d.ts} +2 -2
  23. package/dist/generators/indices/{businesslogic-update-module.generator.js → update/module.generator.js} +2 -2
  24. package/dist/generators/indices/{businesslogic-update-service.generator.d.ts → update/service.generator.d.ts} +2 -2
  25. package/dist/generators/indices/{businesslogic-update-service.generator.js → update/service.generator.js} +2 -2
  26. package/dist/generators/indices/{businesslogic-view-module.generator.d.ts → view/module.generator.d.ts} +2 -2
  27. package/dist/generators/indices/{businesslogic-view-module.generator.js → view/module.generator.js} +2 -2
  28. package/dist/generators/indices/{businesslogic-view-service.generator.d.ts → view/service.generator.d.ts} +2 -2
  29. package/dist/generators/indices/{businesslogic-view-service.generator.js → view/service.generator.js} +2 -2
  30. package/dist/generators/models/importexport-decoder.generator.d.ts +1 -2
  31. package/dist/generators/models/importexport-decoder.generator.js +17 -46
  32. package/dist/generators/models/repository.generator.d.ts +0 -39
  33. package/dist/generators/models/repository.generator.js +103 -175
  34. package/dist/generators/models/route.generator.js +7 -3
  35. package/dist/generators/models/types.generator.js +27 -2
  36. package/dist/generators/models/{businesslogic-update.generator.d.ts → update/service.generator.d.ts} +2 -2
  37. package/dist/generators/models/update/service.generator.js +252 -0
  38. package/dist/generators/models/{businesslogic-view.generator.d.ts → view/service.generator.d.ts} +2 -2
  39. package/dist/generators/models/{businesslogic-view.generator.js → view/service.generator.js} +12 -18
  40. package/dist/lib/meta.d.ts +16 -31
  41. package/dist/lib/meta.js +2 -19
  42. package/dist/lib/schema/fields.d.ts +1 -1
  43. package/dist/lib/zod.d.ts +1 -1
  44. package/dist/prisma/parse.js +1 -1
  45. package/package.json +5 -8
  46. package/dist/generators/models/businesslogic-update.generator.js +0 -324
  47. /package/dist/generators/indices/{routes-index.generator.d.ts → routes.generator.d.ts} +0 -0
  48. /package/dist/generators/models/{react.generator → react}/context.generator.d.ts +0 -0
  49. /package/dist/generators/models/{react.generator → react}/context.generator.js +0 -0
  50. /package/dist/generators/models/{react.generator → react}/index.d.ts +0 -0
  51. /package/dist/generators/models/{react.generator → react}/index.js +0 -0
  52. /package/dist/generators/models/{react.generator → react}/library.generator.d.ts +0 -0
  53. /package/dist/generators/models/{react.generator → react}/library.generator.js +0 -0
  54. /package/dist/generators/models/{react.generator → react}/lookup.generator.d.ts +0 -0
  55. /package/dist/generators/models/{react.generator → react}/lookup.generator.js +0 -0
  56. /package/dist/generators/models/{react.generator → react}/modals.generator.d.ts +0 -0
  57. /package/dist/generators/models/{react.generator → react}/modals.generator.js +0 -0
@@ -1,324 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
- Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.generateModelBusinessLogicUpdate = void 0;
27
- const imports_1 = require("../../lib/imports");
28
- const meta_1 = require("../../lib/meta");
29
- const fields_1 = require("../../lib/schema/fields");
30
- const Types = __importStar(require("../../lib/schema/types"));
31
- const typescript_1 = require("../../lib/typescript");
32
- const jsdoc_1 = require("../../lib/utils/jsdoc");
33
- const string_1 = require("../../lib/utils/string");
34
- const zod_1 = require("../../lib/zod");
35
- /**
36
- * Generates update business logic for a given model.
37
- * The update logic handles all Create/Update/Delete/Upsert operations. See template's readme for more info.
38
- */
39
- function generateModelBusinessLogicUpdate({ model, meta }) {
40
- const schemaMeta = (0, meta_1.getSchemaMetadata)({ config: model.schemaConfig });
41
- const m = {
42
- iExecution: schemaMeta.actions.execution.interface,
43
- typeName: meta.types.typeName,
44
- brandedId: model.brandedIdType,
45
- };
46
- const imports = imports_1.ImportsGenerator.from(meta.update.serviceClassLocation.path);
47
- imports.addImports({
48
- [meta.data.repository.location.import]: meta.data.repository.className,
49
- [meta.types.importPath]: [
50
- Types.toAnnotatedTypeName(m.brandedId),
51
- Types.toAnnotatedTypeName(m.typeName),
52
- meta.types.toBrandedIdTypeFnName,
53
- ],
54
- [meta.view.serviceLocation.import]: [meta.view.serviceClassName],
55
- [schemaMeta.actions.execution.interfaceLocation.import]: [schemaMeta.actions.execution.interface],
56
- [schemaMeta.actions.dispatcher.definitionLocation.import]: [schemaMeta.actions.dispatcher.definition],
57
- [schemaMeta.update.serviceLocation.path]: schemaMeta.update.serviceClassName,
58
- [schemaMeta.view.serviceLocation.import]: schemaMeta.view.serviceClassName,
59
- });
60
- for (const field of (0, fields_1.getRelationFields)(model)) {
61
- // NOTE: We add `toBrandedType` functions for foreign models for decoders.
62
- if (field.relationToModel.typeName === model.typeName) {
63
- continue;
64
- }
65
- const refModelMeta = (0, meta_1.getModelMetadata)({ model: field.relationToModel });
66
- imports.addImport({
67
- from: refModelMeta.types.importPath,
68
- items: [refModelMeta.types.toBrandedIdTypeFnName],
69
- });
70
- imports.addTypeImport({
71
- from: refModelMeta.types.importPath,
72
- items: [refModelMeta.types.brandedIdType],
73
- });
74
- }
75
- for (const { enumerator } of (0, fields_1.getEnumFields)(model)) {
76
- const enumMeta = (0, meta_1.getEnumMetadata)({ enumerator });
77
- imports.addTypeImport({
78
- from: enumMeta.types.importPath,
79
- items: [enumerator.tsTypeName],
80
- });
81
- }
82
- /**
83
- * The name of the variable that holds the repository instance for the current model
84
- * (e.g. when we generate business logic service for Aggregation, the AggregationRepository
85
- * would be referenced using `this.data` variable).
86
- */
87
- const modelRepositoryVariableName = meta.view.dataRepositoryVariableName;
88
- const constructorParameters = [
89
- `private readonly ${modelRepositoryVariableName}: ${meta.data.repository.className}`,
90
- `@Inject(forwardRef(() => ${schemaMeta.update.serviceClassName})) private readonly updateService: ${schemaMeta.update.serviceClassName}`,
91
- `@Inject(forwardRef(() => ${schemaMeta.view.serviceClassName})) private readonly viewService: ${schemaMeta.view.serviceClassName}`,
92
- ];
93
- const { view, update } = meta;
94
- const deleteFn = generateDeleteFn({ model, meta, m });
95
- const deleteManyFn = generateDeleteManyFn({ imports, model, meta, m });
96
- const cloneFn = generateCloneFn({ model, meta, m });
97
- /* prettier-ignore */
98
- return /* ts */ `
99
- import { Inject, Injectable, forwardRef } from '@nestjs/common'
100
- import { z } from 'zod'
101
-
102
- ${imports.generate()}
103
-
104
- export type Scope = "${meta.actions.actionScopeConstType}"
105
-
106
- export type Actions = {
107
- ${(0, jsdoc_1.toJsDocComment)([`Creates a new ${meta.userFriendlyName} and returns it.`])}
108
- create: {
109
- payload: CreatePayload
110
- result: ${m.typeName}
111
- }
112
-
113
- ${(0, jsdoc_1.toJsDocComment)([`Updates a ${meta.userFriendlyName} and returns it.`])}
114
- update: {
115
- payload: UpdatePayload
116
- result: ${m.typeName}
117
- }
118
-
119
- ${(0, jsdoc_1.toJsDocComment)([`Creates or updates a ${meta.userFriendlyName} and returns it.`])}
120
- upsert: {
121
- payload: UpsertPayload
122
- result: ${m.typeName}
123
- }
124
-
125
- ${(0, jsdoc_1.toJsDocComment)([`Deletes a ${meta.userFriendlyName} and returns its id.`])}
126
- delete: {
127
- payload: ${m.brandedId}
128
- result: ${m.brandedId}
129
- }
130
- }
131
-
132
- /**
133
- * Zod decoder for validating the create input of a ${meta.userFriendlyName}.
134
- */
135
- export const ${meta.update.createInputDecoder} = z.object({
136
- ${model.fields
137
- .filter((f) => !f.attributes.isReadonly)
138
- .map((f) => `${f.name}: z.${(0, zod_1.getZodDecoderDefinition)({ field: f })}`)
139
- .join(',')}
140
- })
141
-
142
- type CreatePayload = z.infer<typeof ${meta.update.createInputDecoder}>
143
-
144
- /**
145
- * Zod decoder for validating the update input of a ${meta.userFriendlyName} .
146
- */
147
- export const ${meta.update.updateInputDecoder} = z.object({
148
- ${model.fields
149
- .filter((f) => !f.attributes.isReadonly || f.kind === 'id')
150
- .map((f) => `${f.name}: z.${(0, zod_1.getZodDecoderDefinition)({ field: f, allowAnyOptionalField: f.kind !== 'id' })}`)
151
- .join(',')}
152
- })
153
-
154
- type UpdatePayload = z.infer<typeof ${meta.update.updateInputDecoder}>
155
-
156
- /**
157
- * Zod decoder for validating the upsert input of a ${meta.userFriendlyName} .
158
- */
159
- export const ${meta.update.upsertInputDecoder} = z.union([${meta.update.updateInputDecoder}, ${meta.update.createInputDecoder}])
160
-
161
- type UpsertPayload = z.infer<typeof ${meta.update.upsertInputDecoder}>
162
-
163
- export type ${update.serviceInterfaceName} = ${schemaMeta.actions.dispatcher.definition}<Actions>
164
-
165
- @Injectable()
166
- export class ${update.serviceClassName} implements ${update.serviceInterfaceName} {
167
-
168
- /**
169
- * Instance of the ${meta.userFriendlyName} view service for convenience.
170
- */
171
- private view: ${view.serviceClassName}
172
-
173
- constructor(${constructorParameters.join(',\n')}) {
174
- this.view = this.viewService.${view.serviceVariableName}
175
- }
176
-
177
- ${(0, jsdoc_1.toJsDocComment)([`Creates a new ${meta.userFriendlyName} and returns it.`])}
178
- public async create({ data, execution }: { data: CreatePayload; execution: ${m.iExecution} }): Promise<${m.typeName}> {
179
- return this.data.create({ item: data, execution })
180
- }
181
-
182
- ${(0, jsdoc_1.toJsDocComment)([`Updates a ${meta.userFriendlyName} and returns it.`])}
183
- public async update({ data, execution }: { data: UpdatePayload; execution: ${m.iExecution} }): Promise<${m.typeName}> {
184
- return this.data.update({ item: data, execution })
185
- }
186
-
187
- ${(0, jsdoc_1.toJsDocComment)([`Creates or updates a ${meta.userFriendlyName} and returns it.`])}
188
- public async upsert({ data, execution }: { data: UpsertPayload; execution: ${m.iExecution} }): Promise<${m.typeName}> {
189
- return this.data.upsert({ item: data, execution })
190
- }
191
-
192
- ${deleteFn}
193
-
194
- ${deleteManyFn}
195
-
196
- ${cloneFn}
197
- }
198
- `;
199
- }
200
- exports.generateModelBusinessLogicUpdate = generateModelBusinessLogicUpdate;
201
- /**
202
- * Returns a function implementation that deletes a single entity and all its related entities.
203
- */
204
- function generateDeleteFn({ model, meta, m }) {
205
- const backReferenceDelete = [];
206
- const backReferenceNames = [];
207
- for (const { referencingField, referencingModel } of model.references) {
208
- // NOTE: We only delete back references that are required references so that delete method
209
- // doesn't fail on non-null constraints.
210
- if (!referencingField.isRequired) {
211
- continue;
212
- }
213
- const refModelMeta = (0, meta_1.getModelMetadata)({ model: referencingModel });
214
- const refFieldMeta = (0, meta_1.getFieldMetadata)({ field: referencingField });
215
- const ids = `${refModelMeta.internalSingularName}${(0, string_1.capitalize)(referencingField.name)}s`;
216
- backReferenceNames.push(`${refModelMeta.userFriendlyNamePlural}.${referencingField.name}`);
217
- backReferenceDelete.push(`
218
- // ${referencingModel.name}.${referencingField.name}
219
- const ${ids} = await this.viewService.${refModelMeta.view.serviceVariableName}.data.${refFieldMeta.getByForeignKeyIdsMethodFnName}(data)
220
- await this.updateService.${refModelMeta.update.serviceVariableName}.deleteMany({ data: ${ids}, execution })
221
- `);
222
- }
223
- return `
224
- ${(0, jsdoc_1.toJsDocComment)([`Deletes a ${meta.userFriendlyName} instance and returns its id.`])}
225
- public async delete(
226
- { data, execution }: { data: ${m.brandedId}; execution: ${m.iExecution} }
227
- ): Promise<${m.brandedId}> {
228
- ${backReferenceDelete.join('\n')}
229
- return this.data.delete({ id: data, execution })
230
- }
231
- `;
232
- }
233
- /**
234
- * Returns a function that deletes multiple entities and all their related entities.
235
- */
236
- function generateDeleteManyFn({ imports, model, meta, m, }) {
237
- const idArrays = [];
238
- const idAssignments = [];
239
- const deleteCalls = [];
240
- for (const { referencingField, referencingModel } of model.references) {
241
- // NOTE: We only delete back references that are required references.
242
- if (!referencingField.isRequired) {
243
- continue;
244
- }
245
- imports.addTypeImport({ items: [referencingModel.brandedIdType], from: meta.types.importPath });
246
- const refModelMeta = (0, meta_1.getModelMetadata)({ model: referencingModel });
247
- const refFieldMeta = (0, meta_1.getFieldMetadata)({ field: referencingField });
248
- const idArray = `${refModelMeta.internalSingularName}${(0, string_1.capitalize)(referencingField.name)}s`;
249
- idArrays.push(`const ${idArray}: ${referencingModel.brandedIdType}[] = []`);
250
- idAssignments.push(`
251
- {
252
- // ${referencingModel.name}.${referencingField.name}
253
- const _ids = await this.viewService.${refModelMeta.view.serviceVariableName}.data.${refFieldMeta.getByForeignKeyIdsMethodFnName}(id)
254
- ${idArray}.push(..._ids)
255
- }
256
- `);
257
- deleteCalls.push(`await this.updateService.${refModelMeta.update.serviceVariableName}.deleteMany({ data: ${idArray}, execution })`);
258
- }
259
- let relatedEntities = '';
260
- if (idArrays.length > 0) {
261
- relatedEntities = `
262
- ${idArrays.join('\n')}
263
-
264
- for (const id of ids) {
265
- ${idAssignments.join('\n')}
266
- }
267
-
268
- ${deleteCalls.join('\n')}
269
- `;
270
- }
271
- return `
272
- ${(0, jsdoc_1.toJsDocComment)([`Deletes multiple ${meta.userFriendlyNamePlural} and returns their ids.`])}
273
- public async deleteMany(
274
- { data: ids, execution }: { data: ${m.brandedId}[]; execution: ${m.iExecution} }
275
- ): Promise<${m.brandedId}[]> {
276
- if (ids.length === 0) {
277
- return []
278
- }
279
-
280
- ${relatedEntities}
281
-
282
- return this.data.deleteMany({ ids, execution })
283
- }`;
284
- }
285
- /**
286
- * Returns a function that shallow clones a given entity. Unique fields are required
287
- * to generate a unique clone as skipping them would result in a non-unique clone.
288
- */
289
- function generateCloneFn({ model, meta, m }) {
290
- const inputFields = model.fields.map((f) => {
291
- const type = (0, typescript_1.getFieldType)(f);
292
- // NOTE: ID field is always required to resolve the source.
293
- if (f.kind === 'id') {
294
- return `${f.name}: ${type}`;
295
- }
296
- if (f.isUnique) {
297
- // NOTE: `unique` fields require a new value.
298
- if (f.isRequired) {
299
- return `${f.name}: ${type}`;
300
- }
301
- return `${f.name}: ${type} | null`;
302
- }
303
- // NOTE: Non-unique fields can be copied from the source.
304
- if (f.isRequired) {
305
- return `${f.name}?: ${type}`;
306
- }
307
- return `${f.name}?: ${type} | null`;
308
- });
309
- return `
310
- ${(0, jsdoc_1.toJsDocComment)([`Creates a new ${meta.userFriendlyName} deep clone and returns it.`])}
311
- public async clone(
312
- { data, execution }: { data: { ${inputFields.join(', ')} }; execution: ${m.iExecution} }
313
- ): Promise<${m.typeName}> {
314
- const source = await this.view.get(data.id)
315
- if (!source) {
316
- throw new Error(\`${meta.userFriendlyName} with id \${data.id} not found\`)
317
- }
318
-
319
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
320
- const { id, ...duplicate } = { ...source, ...data } satisfies Actions['create']['payload']
321
-
322
- return await this.create({ data: duplicate, execution })
323
- }`;
324
- }