@postxl/generator 0.56.6 → 0.56.7
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.
|
@@ -1,54 +1,59 @@
|
|
|
1
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
|
+
};
|
|
2
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
26
|
exports.generateModelBusinessLogicUpdate = void 0;
|
|
4
27
|
const imports_1 = require("../../lib/imports");
|
|
5
28
|
const meta_1 = require("../../lib/meta");
|
|
6
29
|
const fields_1 = require("../../lib/schema/fields");
|
|
7
|
-
const
|
|
30
|
+
const Types = __importStar(require("../../lib/schema/types"));
|
|
8
31
|
const zod_1 = require("../../lib/schema/zod");
|
|
9
32
|
const jsdoc_1 = require("../../lib/utils/jsdoc");
|
|
33
|
+
const string_1 = require("../../lib/utils/string");
|
|
10
34
|
/**
|
|
11
35
|
* Generates update business logic for a given model.
|
|
12
36
|
* The update logic handles all Create/Update/Delete/Upsert operations. See template's readme for more info.
|
|
13
37
|
*/
|
|
14
38
|
function generateModelBusinessLogicUpdate({ model, meta }) {
|
|
15
39
|
const schemaMeta = (0, meta_1.getSchemaMetadata)({ config: model.schemaConfig });
|
|
16
|
-
/**
|
|
17
|
-
* Shorthand variable for relevant metadata.
|
|
18
|
-
*/
|
|
19
40
|
const m = {
|
|
20
|
-
/**
|
|
21
|
-
* The name of the interface that handles the action execution.
|
|
22
|
-
*/
|
|
23
41
|
iExecution: schemaMeta.actions.execution.interface,
|
|
24
|
-
/**
|
|
25
|
-
* The name of the type that represents a fully typed, flat object, e.g. `Aggregation`
|
|
26
|
-
*/
|
|
27
42
|
typeName: meta.types.typeName,
|
|
28
|
-
/**
|
|
29
|
-
* Type of the ID field that is specific to this model, e.g. `AggregationId`
|
|
30
|
-
*/
|
|
31
43
|
brandedId: model.brandedIdType,
|
|
32
|
-
/**
|
|
33
|
-
* Internal type name for create payload, e.g. `CreateAggregation`
|
|
34
|
-
*/
|
|
35
44
|
createType: `Create${meta.internalSingularNameCapitalized}`,
|
|
36
|
-
/**
|
|
37
|
-
* Internal type name for update payload, e.g. `UpdateAggregation`
|
|
38
|
-
*/
|
|
39
45
|
updateType: `Update${meta.internalSingularNameCapitalized}`,
|
|
40
|
-
/**
|
|
41
|
-
* Internal type name for upsert payload, e.g. `UpsertAggregation`
|
|
42
|
-
*/
|
|
43
46
|
upsertType: `Upsert${meta.internalSingularNameCapitalized}`,
|
|
47
|
+
cloneType: `Clone${meta.internalSingularNameCapitalized}`,
|
|
44
48
|
};
|
|
45
49
|
const imports = imports_1.ImportsGenerator.from(meta.businessLogic.update.serviceFilePath);
|
|
46
50
|
imports.addImports({
|
|
47
51
|
[meta.data.importPath]: meta.data.repository.className,
|
|
48
52
|
[meta.types.importPath]: [
|
|
49
|
-
|
|
50
|
-
|
|
53
|
+
Types.toAnnotatedTypeName(m.brandedId),
|
|
54
|
+
Types.toAnnotatedTypeName(m.typeName),
|
|
51
55
|
meta.types.toBrandedIdTypeFnName,
|
|
56
|
+
Types.toFunctionName(`omitId`),
|
|
52
57
|
],
|
|
53
58
|
[meta.businessLogic.view.serviceFilePath]: [meta.businessLogic.view.serviceClassName],
|
|
54
59
|
[schemaMeta.actions.importPath]: [schemaMeta.actions.execution.interface, schemaMeta.actions.dispatcher.definition],
|
|
@@ -66,6 +71,9 @@ function generateModelBusinessLogicUpdate({ model, meta }) {
|
|
|
66
71
|
from: refMeta.types.importPath,
|
|
67
72
|
});
|
|
68
73
|
}
|
|
74
|
+
for (const { referencingModel } of model.references) {
|
|
75
|
+
imports.addTypeImport({ items: [referencingModel.brandedIdType], from: meta.types.importPath });
|
|
76
|
+
}
|
|
69
77
|
/**
|
|
70
78
|
* The name of the variable that holds the repository instance for the current model
|
|
71
79
|
* (e.g. when we generate business logic service for Aggregation, the AggregationRepository
|
|
@@ -77,7 +85,7 @@ function generateModelBusinessLogicUpdate({ model, meta }) {
|
|
|
77
85
|
`@Inject(forwardRef(() => ${schemaMeta.businessLogic.update.serviceClassName})) private readonly updateService: ${schemaMeta.businessLogic.update.serviceClassName}`,
|
|
78
86
|
`@Inject(forwardRef(() => ${schemaMeta.businessLogic.view.serviceClassName})) private readonly viewService: ${schemaMeta.businessLogic.view.serviceClassName}`,
|
|
79
87
|
];
|
|
80
|
-
const { zodCreateObject, zodUpdateObject, zodUpsertObject } = meta.businessLogic.update;
|
|
88
|
+
const { zodCreateObject, zodUpdateObject, zodUpsertObject, zodCloneObject } = meta.businessLogic.update;
|
|
81
89
|
const { view, update } = meta.businessLogic;
|
|
82
90
|
/* prettier-ignore */
|
|
83
91
|
return /* ts */ `
|
|
@@ -136,6 +144,12 @@ function generateModelBusinessLogicUpdate({ model, meta }) {
|
|
|
136
144
|
payload: ${m.brandedId}[]
|
|
137
145
|
result: ${m.brandedId}[]
|
|
138
146
|
}
|
|
147
|
+
|
|
148
|
+
${(0, jsdoc_1.toJsDocComment)([`Clones a ${meta.userFriendlyName} and returns the clone.`])}
|
|
149
|
+
clone: {
|
|
150
|
+
payload: ${m.cloneType}
|
|
151
|
+
result: ${m.typeName}
|
|
152
|
+
}
|
|
139
153
|
}
|
|
140
154
|
|
|
141
155
|
/**
|
|
@@ -169,6 +183,18 @@ function generateModelBusinessLogicUpdate({ model, meta }) {
|
|
|
169
183
|
|
|
170
184
|
type ${m.upsertType} = z.infer<typeof ${zodUpsertObject}>
|
|
171
185
|
|
|
186
|
+
/**
|
|
187
|
+
* Zod decoder for validating the clone input of a ${meta.userFriendlyName} .
|
|
188
|
+
*/
|
|
189
|
+
export const ${zodCloneObject} = z.object({
|
|
190
|
+
${model.fields
|
|
191
|
+
.filter((f) => !f.attributes.isReadonly && f.kind !== "relation" || f.kind === 'id')
|
|
192
|
+
.map((f) => `${f.name}: z.${(0, zod_1.getZodDecoderDefinition)({ field: f, allowAnyOptionalField: f.kind !== 'id' })}`)
|
|
193
|
+
.join(',')}
|
|
194
|
+
})
|
|
195
|
+
|
|
196
|
+
type ${m.cloneType} = z.infer<typeof ${zodCloneObject}>
|
|
197
|
+
|
|
172
198
|
export type ${update.serviceInterfaceName} = ${schemaMeta.actions.dispatcher.definition}<Actions>
|
|
173
199
|
|
|
174
200
|
@Injectable()
|
|
@@ -213,16 +239,122 @@ function generateModelBusinessLogicUpdate({ model, meta }) {
|
|
|
213
239
|
return this.data.upsertMany({ items: data, execution })
|
|
214
240
|
}
|
|
215
241
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
return this.data.delete({ id: data, execution })
|
|
219
|
-
}
|
|
242
|
+
|
|
243
|
+
${generateDeleteFunction({ model, meta, m })}
|
|
220
244
|
|
|
221
|
-
${(
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
}
|
|
245
|
+
${generateDeleteManyMethod({ model, meta, m })}
|
|
246
|
+
|
|
247
|
+
${generateCloneMethod({ model, meta, m })}
|
|
225
248
|
}
|
|
226
249
|
`;
|
|
227
250
|
}
|
|
228
251
|
exports.generateModelBusinessLogicUpdate = generateModelBusinessLogicUpdate;
|
|
252
|
+
/**
|
|
253
|
+
* Returns a function implementation that deletes a single entity and all its related entities.
|
|
254
|
+
*/
|
|
255
|
+
function generateDeleteFunction({ model, meta, m }) {
|
|
256
|
+
const backReferenceDelete = [];
|
|
257
|
+
const backReferenceNames = [];
|
|
258
|
+
for (const { referencingField, referencingModel } of model.references) {
|
|
259
|
+
const refModelMeta = (0, meta_1.getModelMetadata)({ model: referencingModel });
|
|
260
|
+
const refFieldMeta = (0, meta_1.getFieldMetadata)({ field: referencingField });
|
|
261
|
+
const ids = `${refModelMeta.internalSingularName}${(0, string_1.capitalize)(referencingField.name)}s`;
|
|
262
|
+
backReferenceNames.push(`${refModelMeta.userFriendlyNamePlural}.${referencingField.name}`);
|
|
263
|
+
backReferenceDelete.push(`
|
|
264
|
+
// ${referencingModel.name}.${referencingField.name}
|
|
265
|
+
const ${ids} = await this.viewService.${refModelMeta.businessLogic.view.serviceVariableName}.data.${refFieldMeta.getByForeignKeyIdsMethodFnName}(data)
|
|
266
|
+
await this.updateService.${refModelMeta.businessLogic.update.serviceVariableName}.deleteMany({ data: ${ids}, execution })
|
|
267
|
+
`);
|
|
268
|
+
}
|
|
269
|
+
return `
|
|
270
|
+
${(0, jsdoc_1.toJsDocComment)([`Deletes a ${meta.userFriendlyName} instance and returns its id.`])}
|
|
271
|
+
public async delete(
|
|
272
|
+
{ data, execution }: { data: ${m.brandedId}; execution: ${m.iExecution} }
|
|
273
|
+
): Promise<${m.brandedId}> {
|
|
274
|
+
${backReferenceDelete.join('\n')}
|
|
275
|
+
return this.data.delete({ id: data, execution })
|
|
276
|
+
}
|
|
277
|
+
`;
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Returns a function that deletes multiple entities and all their related entities.
|
|
281
|
+
*/
|
|
282
|
+
function generateDeleteManyMethod({ model, meta, m }) {
|
|
283
|
+
const idArrays = [];
|
|
284
|
+
const idAssignments = [];
|
|
285
|
+
const deleteCalls = [];
|
|
286
|
+
for (const { referencingField, referencingModel } of model.references) {
|
|
287
|
+
const refModelMeta = (0, meta_1.getModelMetadata)({ model: referencingModel });
|
|
288
|
+
const refFieldMeta = (0, meta_1.getFieldMetadata)({ field: referencingField });
|
|
289
|
+
const idArray = `${refModelMeta.internalSingularName}${(0, string_1.capitalize)(referencingField.name)}s`;
|
|
290
|
+
idArrays.push(`const ${idArray}: ${referencingModel.brandedIdType}[] = []`);
|
|
291
|
+
idAssignments.push(`
|
|
292
|
+
{
|
|
293
|
+
// ${referencingModel.name}.${referencingField.name}
|
|
294
|
+
const _ids = await this.viewService.${refModelMeta.businessLogic.view.serviceVariableName}.data.${refFieldMeta.getByForeignKeyIdsMethodFnName}(id)
|
|
295
|
+
${idArray}.push(..._ids)
|
|
296
|
+
}
|
|
297
|
+
`);
|
|
298
|
+
deleteCalls.push(`await this.updateService.${refModelMeta.businessLogic.update.serviceVariableName}.deleteMany({ data: ${idArray}, execution })`);
|
|
299
|
+
}
|
|
300
|
+
let relatedEntities = '';
|
|
301
|
+
if (model.references.length > 0) {
|
|
302
|
+
relatedEntities = `
|
|
303
|
+
${idArrays.join('\n')}
|
|
304
|
+
|
|
305
|
+
for (const id of ids) {
|
|
306
|
+
${idAssignments.join('\n')}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
${deleteCalls.join('\n')}
|
|
310
|
+
`;
|
|
311
|
+
}
|
|
312
|
+
return `
|
|
313
|
+
${(0, jsdoc_1.toJsDocComment)([`Deletes multiple ${meta.userFriendlyNamePlural} and returns their ids.`])}
|
|
314
|
+
public async deleteMany(
|
|
315
|
+
{ data: ids, execution }: { data: ${m.brandedId}[]; execution: ${m.iExecution} }
|
|
316
|
+
): Promise<${m.brandedId}[]> {
|
|
317
|
+
if (ids.length === 0) {
|
|
318
|
+
return []
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
${relatedEntities}
|
|
322
|
+
|
|
323
|
+
return this.data.deleteMany({ ids, execution })
|
|
324
|
+
}`;
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Returns a function that deep clones a given entity and all its related entities.
|
|
328
|
+
*/
|
|
329
|
+
function generateCloneMethod({ model, meta, m }) {
|
|
330
|
+
const backReferenceCloning = [];
|
|
331
|
+
const backReferenceNames = [];
|
|
332
|
+
for (const { referencingField, referencingModel } of model.references) {
|
|
333
|
+
const refModelMeta = (0, meta_1.getModelMetadata)({ model: referencingModel });
|
|
334
|
+
const refFieldMeta = (0, meta_1.getFieldMetadata)({ field: referencingField });
|
|
335
|
+
backReferenceNames.push(`${refModelMeta.userFriendlyNamePlural}.${referencingField.name}`);
|
|
336
|
+
backReferenceCloning.push(`
|
|
337
|
+
// ${referencingModel.name}.${referencingField.name}
|
|
338
|
+
for (const childId of await this.viewService.${refModelMeta.businessLogic.view.serviceVariableName}.data.${refFieldMeta.getByForeignKeyIdsMethodFnName}(id)) {
|
|
339
|
+
const clonedChild = await this.updateService.${refModelMeta.businessLogic.update.serviceVariableName}.clone({ data: { id: childId }, execution})
|
|
340
|
+
await this.updateService.${refModelMeta.businessLogic.update.serviceVariableName}.update({ data: { id: clonedChild.id, ${referencingField.name}: clone.id }, execution })
|
|
341
|
+
}
|
|
342
|
+
`);
|
|
343
|
+
}
|
|
344
|
+
return `
|
|
345
|
+
${(0, jsdoc_1.toJsDocComment)([`Creates a new ${meta.userFriendlyName} deep clone and returns it.`])}
|
|
346
|
+
public async clone(
|
|
347
|
+
{ data: { id, ...data }, execution }: { data: ${m.cloneType}; execution: ${m.iExecution} }
|
|
348
|
+
): Promise<${m.typeName}> {
|
|
349
|
+
const source = await this.view.get(id)
|
|
350
|
+
if (!source) {
|
|
351
|
+
throw new Error(\`${meta.userFriendlyName} with id \${id} not found\`)
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
const clone = await this.create({ data: { ...omitId(source), ...data }, execution })
|
|
355
|
+
|
|
356
|
+
${backReferenceCloning.join('\n')}
|
|
357
|
+
|
|
358
|
+
return clone
|
|
359
|
+
}`;
|
|
360
|
+
}
|
|
@@ -12,14 +12,14 @@ function generateRoute({ model, meta }) {
|
|
|
12
12
|
const defaultValueMethod = `
|
|
13
13
|
getDefault: procedure.query(({ ctx }) => ctx.view.${meta.data.dataServiceName}.${dataRepositoryVariableName}.defaultValue),
|
|
14
14
|
`;
|
|
15
|
-
const { zodCreateObject, zodUpdateObject, zodUpsertObject } = meta.businessLogic.update;
|
|
15
|
+
const { zodCreateObject, zodUpdateObject, zodUpsertObject, zodCloneObject } = meta.businessLogic.update;
|
|
16
16
|
const imports = imports_1.ImportsGenerator.from(meta.trpc.routerFilePath).addImports({
|
|
17
17
|
[meta.types.importPath]: [
|
|
18
18
|
(0, types_1.toAnnotatedTypeName)(model.typeName),
|
|
19
19
|
meta.types.toBrandedIdTypeFnName,
|
|
20
20
|
meta.types.zodDecoderFnNames.id,
|
|
21
21
|
],
|
|
22
|
-
[meta.businessLogic.update.serviceFilePath]: [zodCreateObject, zodUpdateObject, zodUpsertObject],
|
|
22
|
+
[meta.businessLogic.update.serviceFilePath]: [zodCreateObject, zodUpdateObject, zodUpsertObject, zodCloneObject],
|
|
23
23
|
});
|
|
24
24
|
return /* ts */ `
|
|
25
25
|
import { z } from 'zod'
|
|
@@ -91,6 +91,10 @@ export const ${meta.trpc.routerName} = router({
|
|
|
91
91
|
deleteMany: procedure
|
|
92
92
|
.input(z.array(${meta.types.zodDecoderFnNames.id}))
|
|
93
93
|
.mutation(({ input, ctx }) => ctx.dispatch({scope: "${scopeName}", type: "deleteMany", payload: input})),
|
|
94
|
+
|
|
95
|
+
clone: procedure
|
|
96
|
+
.input(${zodCloneObject})
|
|
97
|
+
.mutation(({ input, ctx }) => ctx.dispatch({scope: "${scopeName}", type: "clone", payload: input})),
|
|
94
98
|
})
|
|
95
99
|
`;
|
|
96
100
|
}
|
package/dist/lib/meta.d.ts
CHANGED
|
@@ -954,6 +954,10 @@ export type ModelMetaData = {
|
|
|
954
954
|
* The name of the function that decodes an Upsert object to a fully typed object, e.g. `aggregationUpsertDecoder`.
|
|
955
955
|
*/
|
|
956
956
|
zodUpsertObject: Types.FunctionName;
|
|
957
|
+
/**
|
|
958
|
+
* The name of the function that clones an object, e.g. `aggregationCloneDecoder`.
|
|
959
|
+
*/
|
|
960
|
+
zodCloneObject: Types.FunctionName;
|
|
957
961
|
};
|
|
958
962
|
/**
|
|
959
963
|
* Name by which the business logic service exposes the data service.
|
package/dist/lib/meta.js
CHANGED
|
@@ -346,6 +346,7 @@ function getModelMetadata({ model }) {
|
|
|
346
346
|
zodCreateObject: Types.toFunctionName(`${camelCase}CreateDecoder`),
|
|
347
347
|
zodUpdateObject: Types.toFunctionName(`${camelCase}UpdateDecoder`),
|
|
348
348
|
zodUpsertObject: Types.toFunctionName(`${camelCase}UpsertDecoder`),
|
|
349
|
+
zodCloneObject: Types.toFunctionName(`${camelCase}CloneDecoder`),
|
|
349
350
|
},
|
|
350
351
|
dataRepositoryVariableName: Types.toVariableName(`data`),
|
|
351
352
|
},
|