@postxl/generator 0.65.2 → 0.67.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/dist/generator.js +0 -2
- package/dist/generators/models/businesslogic-update.generator.js +53 -77
- package/dist/generators/models/route.generator.js +0 -4
- package/dist/generators/models/types.generator.js +3 -20
- package/dist/lib/attributes.d.ts +0 -5
- package/dist/lib/meta.d.ts +0 -20
- package/dist/lib/meta.js +0 -23
- package/dist/lib/schema/schema.d.ts +5 -1
- package/dist/lib/typescript.d.ts +5 -0
- package/dist/lib/typescript.js +22 -0
- package/dist/lib/{schema/zod.d.ts → zod.d.ts} +1 -1
- package/dist/lib/{schema/zod.js → zod.js} +5 -2
- package/dist/prisma/attributes.js +1 -3
- package/dist/prisma/parse.js +8 -7
- package/package.json +1 -1
- package/dist/generators/indices/businesslogic-update-clonecontext.generator.d.ts +0 -9
- package/dist/generators/indices/businesslogic-update-clonecontext.generator.js +0 -39
package/dist/generator.js
CHANGED
|
@@ -42,7 +42,6 @@ const prettier = __importStar(require("@postxl/prettier"));
|
|
|
42
42
|
const react_generator_1 = require("./generators/enums/react.generator");
|
|
43
43
|
const types_generator_1 = require("./generators/enums/types.generator");
|
|
44
44
|
const businesslogic_actiontypes_generator_1 = require("./generators/indices/businesslogic-actiontypes.generator");
|
|
45
|
-
const businesslogic_update_clonecontext_generator_1 = require("./generators/indices/businesslogic-update-clonecontext.generator");
|
|
46
45
|
const businesslogic_update_module_generator_1 = require("./generators/indices/businesslogic-update-module.generator");
|
|
47
46
|
const businesslogic_update_service_generator_1 = require("./generators/indices/businesslogic-update-service.generator");
|
|
48
47
|
const businesslogic_view_module_generator_1 = require("./generators/indices/businesslogic-view-module.generator");
|
|
@@ -220,7 +219,6 @@ function generate({ models, enums, config, prismaClientPath, logger, }) {
|
|
|
220
219
|
// Business Logic
|
|
221
220
|
generated.write(`/${meta.view.moduleLocation.path}.ts`, (0, businesslogic_view_module_generator_1.generateBusinessLogicViewModule)({ models, meta }));
|
|
222
221
|
generated.write(`/${meta.view.serviceLocation.path}.ts`, (0, businesslogic_view_service_generator_1.generateBusinessLogicViewService)({ models, meta }));
|
|
223
|
-
generated.write(`/${meta.update.cloneContextFilePath}.ts`, (0, businesslogic_update_clonecontext_generator_1.generateBusinessLogicCloneContext)({ models, meta }));
|
|
224
222
|
generated.write(`/${meta.update.moduleLocation.path}.ts`, (0, businesslogic_update_module_generator_1.generateBusinessLogicUpdateModule)({ models, meta }));
|
|
225
223
|
generated.write(`/${meta.update.serviceLocation.path}.ts`, (0, businesslogic_update_service_generator_1.generateBusinessLogicUpdateService)({ models, meta }));
|
|
226
224
|
generated.write(`/${meta.update.actionTypesFilePath}.ts`, (0, businesslogic_actiontypes_generator_1.generateBusinessLogicActionTypes)({ models, meta }));
|
|
@@ -28,9 +28,10 @@ const imports_1 = require("../../lib/imports");
|
|
|
28
28
|
const meta_1 = require("../../lib/meta");
|
|
29
29
|
const fields_1 = require("../../lib/schema/fields");
|
|
30
30
|
const Types = __importStar(require("../../lib/schema/types"));
|
|
31
|
-
const
|
|
31
|
+
const typescript_1 = require("../../lib/typescript");
|
|
32
32
|
const jsdoc_1 = require("../../lib/utils/jsdoc");
|
|
33
33
|
const string_1 = require("../../lib/utils/string");
|
|
34
|
+
const zod_1 = require("../../lib/zod");
|
|
34
35
|
/**
|
|
35
36
|
* Generates update business logic for a given model.
|
|
36
37
|
* The update logic handles all Create/Update/Delete/Upsert operations. See template's readme for more info.
|
|
@@ -46,12 +47,6 @@ function generateModelBusinessLogicUpdate({ model, meta }) {
|
|
|
46
47
|
createType: `Create${meta.internalSingularNameCapitalized}`,
|
|
47
48
|
updateType: `Update${meta.internalSingularNameCapitalized}`,
|
|
48
49
|
upsertType: `Upsert${meta.internalSingularNameCapitalized}`,
|
|
49
|
-
cloneType: `Clone${meta.internalSingularNameCapitalized}`,
|
|
50
|
-
},
|
|
51
|
-
cloneContext: {
|
|
52
|
-
type: schemaMeta.update.cloneContextType,
|
|
53
|
-
createMethod: schemaMeta.update.cloneContextCreateMethod,
|
|
54
|
-
map: meta.update.cloneContextMap,
|
|
55
50
|
},
|
|
56
51
|
};
|
|
57
52
|
const imports = imports_1.ImportsGenerator.from(meta.update.serviceClassLocation.path);
|
|
@@ -61,27 +56,33 @@ function generateModelBusinessLogicUpdate({ model, meta }) {
|
|
|
61
56
|
Types.toAnnotatedTypeName(m.brandedId),
|
|
62
57
|
Types.toAnnotatedTypeName(m.typeName),
|
|
63
58
|
meta.types.toBrandedIdTypeFnName,
|
|
64
|
-
Types.toFunctionName(`omitId`),
|
|
65
59
|
],
|
|
66
60
|
[meta.view.serviceLocation.import]: [meta.view.serviceClassName],
|
|
67
61
|
[schemaMeta.actions.execution.interfaceLocation.import]: [schemaMeta.actions.execution.interface],
|
|
68
62
|
[schemaMeta.actions.dispatcher.definitionLocation.import]: [schemaMeta.actions.dispatcher.definition],
|
|
69
63
|
[schemaMeta.update.serviceLocation.path]: schemaMeta.update.serviceClassName,
|
|
70
|
-
[schemaMeta.update.cloneContextFilePath]: [
|
|
71
|
-
schemaMeta.update.cloneContextType,
|
|
72
|
-
schemaMeta.update.cloneContextCreateMethod,
|
|
73
|
-
],
|
|
74
64
|
[schemaMeta.view.serviceLocation.import]: schemaMeta.view.serviceClassName,
|
|
75
65
|
});
|
|
76
|
-
for (const
|
|
66
|
+
for (const field of (0, fields_1.getRelationFields)(model)) {
|
|
77
67
|
// NOTE: We add `toBrandedType` functions for foreign models for decoders.
|
|
78
|
-
if (
|
|
68
|
+
if (field.relationToModel.typeName === model.typeName) {
|
|
79
69
|
continue;
|
|
80
70
|
}
|
|
81
|
-
const
|
|
71
|
+
const refModelMeta = (0, meta_1.getModelMetadata)({ model: field.relationToModel });
|
|
82
72
|
imports.addImport({
|
|
83
|
-
|
|
84
|
-
|
|
73
|
+
from: refModelMeta.types.importPath,
|
|
74
|
+
items: [refModelMeta.types.toBrandedIdTypeFnName],
|
|
75
|
+
});
|
|
76
|
+
imports.addTypeImport({
|
|
77
|
+
from: refModelMeta.types.importPath,
|
|
78
|
+
items: [refModelMeta.types.brandedIdType],
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
for (const { enumerator } of (0, fields_1.getEnumFields)(model)) {
|
|
82
|
+
const enumMeta = (0, meta_1.getEnumMetadata)({ enumerator });
|
|
83
|
+
imports.addTypeImport({
|
|
84
|
+
from: enumMeta.types.importPath,
|
|
85
|
+
items: [enumerator.tsTypeName],
|
|
85
86
|
});
|
|
86
87
|
}
|
|
87
88
|
/**
|
|
@@ -97,8 +98,9 @@ function generateModelBusinessLogicUpdate({ model, meta }) {
|
|
|
97
98
|
];
|
|
98
99
|
const decoders = meta.update.decoders;
|
|
99
100
|
const { view, update } = meta;
|
|
100
|
-
const deleteFn =
|
|
101
|
-
const deleteManyFn =
|
|
101
|
+
const deleteFn = generateDeleteFn({ model, meta, m });
|
|
102
|
+
const deleteManyFn = generateDeleteManyFn({ imports, model, meta, m });
|
|
103
|
+
const cloneFn = generateCloneFn({ model, meta, m });
|
|
102
104
|
/* prettier-ignore */
|
|
103
105
|
return /* ts */ `
|
|
104
106
|
import { Inject, Injectable, forwardRef } from '@nestjs/common'
|
|
@@ -132,12 +134,6 @@ function generateModelBusinessLogicUpdate({ model, meta }) {
|
|
|
132
134
|
payload: ${m.brandedId}
|
|
133
135
|
result: ${m.brandedId}
|
|
134
136
|
}
|
|
135
|
-
|
|
136
|
-
${(0, jsdoc_1.toJsDocComment)([`Clones a ${meta.userFriendlyName} and returns the clone.`])}
|
|
137
|
-
clone: {
|
|
138
|
-
payload: ${m.decoders.cloneType}
|
|
139
|
-
result: ${m.typeName}
|
|
140
|
-
}
|
|
141
137
|
}
|
|
142
138
|
|
|
143
139
|
/**
|
|
@@ -171,23 +167,10 @@ function generateModelBusinessLogicUpdate({ model, meta }) {
|
|
|
171
167
|
|
|
172
168
|
type ${m.decoders.upsertType} = z.infer<typeof ${decoders.upsert}>
|
|
173
169
|
|
|
174
|
-
/**
|
|
175
|
-
* Zod decoder for validating the clone input of a ${meta.userFriendlyName} .
|
|
176
|
-
*/
|
|
177
|
-
export const ${decoders.clone} = z.object({
|
|
178
|
-
${model.fields
|
|
179
|
-
.filter((f) => !f.attributes.isReadonly || f.kind === "id")
|
|
180
|
-
.map((f) => `${f.name}: z.${(0, zod_1.getZodDecoderDefinition)({ field: f, allowAnyOptionalField: f.kind !== 'id' })}`)
|
|
181
|
-
.join(',')}
|
|
182
|
-
})
|
|
183
|
-
|
|
184
|
-
type ${m.decoders.cloneType} = z.infer<typeof ${decoders.clone}>
|
|
185
|
-
|
|
186
170
|
export const ${decoders.name} = {
|
|
187
171
|
create: ${decoders.create},
|
|
188
172
|
update: ${decoders.update},
|
|
189
173
|
upsert: ${decoders.upsert},
|
|
190
|
-
clone: ${decoders.clone},
|
|
191
174
|
}
|
|
192
175
|
|
|
193
176
|
export type ${update.serviceInterfaceName} = ${schemaMeta.actions.dispatcher.definition}<Actions>
|
|
@@ -223,7 +206,7 @@ function generateModelBusinessLogicUpdate({ model, meta }) {
|
|
|
223
206
|
|
|
224
207
|
${deleteManyFn}
|
|
225
208
|
|
|
226
|
-
${
|
|
209
|
+
${cloneFn}
|
|
227
210
|
}
|
|
228
211
|
`;
|
|
229
212
|
}
|
|
@@ -231,11 +214,12 @@ exports.generateModelBusinessLogicUpdate = generateModelBusinessLogicUpdate;
|
|
|
231
214
|
/**
|
|
232
215
|
* Returns a function implementation that deletes a single entity and all its related entities.
|
|
233
216
|
*/
|
|
234
|
-
function
|
|
217
|
+
function generateDeleteFn({ model, meta, m }) {
|
|
235
218
|
const backReferenceDelete = [];
|
|
236
219
|
const backReferenceNames = [];
|
|
237
220
|
for (const { referencingField, referencingModel } of model.references) {
|
|
238
|
-
// NOTE: We only delete back references that are required references
|
|
221
|
+
// NOTE: We only delete back references that are required references so that delete method
|
|
222
|
+
// doesn't fail on non-null constraints.
|
|
239
223
|
if (!referencingField.isRequired) {
|
|
240
224
|
continue;
|
|
241
225
|
}
|
|
@@ -262,7 +246,7 @@ function generateDeleteFunction({ model, meta, m }) {
|
|
|
262
246
|
/**
|
|
263
247
|
* Returns a function that deletes multiple entities and all their related entities.
|
|
264
248
|
*/
|
|
265
|
-
function
|
|
249
|
+
function generateDeleteManyFn({ imports, model, meta, m, }) {
|
|
266
250
|
const idArrays = [];
|
|
267
251
|
const idAssignments = [];
|
|
268
252
|
const deleteCalls = [];
|
|
@@ -312,50 +296,42 @@ function generateDeleteManyMethod({ imports, model, meta, m, }) {
|
|
|
312
296
|
}`;
|
|
313
297
|
}
|
|
314
298
|
/**
|
|
315
|
-
* Returns a function that
|
|
299
|
+
* Returns a function that shallow clones a given entity. Unique fields are required
|
|
300
|
+
* to generate a unique clone as skipping them would result in a non-unique clone.
|
|
316
301
|
*/
|
|
317
|
-
function
|
|
318
|
-
const
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
continue;
|
|
302
|
+
function generateCloneFn({ model, meta, m }) {
|
|
303
|
+
const inputFields = model.fields.map((f) => {
|
|
304
|
+
const type = (0, typescript_1.getFieldType)(f);
|
|
305
|
+
// NOTE: ID field is always required to resolve the source.
|
|
306
|
+
if (f.kind === 'id') {
|
|
307
|
+
return `${f.name}: ${type}`;
|
|
324
308
|
}
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
309
|
+
if (f.isUnique) {
|
|
310
|
+
// NOTE: `unique` fields require a new value.
|
|
311
|
+
if (f.isRequired) {
|
|
312
|
+
return `${f.name}: ${type}`;
|
|
313
|
+
}
|
|
314
|
+
return `${f.name}: ${type} | null`;
|
|
315
|
+
}
|
|
316
|
+
// NOTE: Non-unique fields can be copied from the source.
|
|
317
|
+
if (f.isRequired) {
|
|
318
|
+
return `${f.name}?: ${type}`;
|
|
319
|
+
}
|
|
320
|
+
return `${f.name}?: ${type} | null`;
|
|
321
|
+
});
|
|
336
322
|
return `
|
|
337
323
|
${(0, jsdoc_1.toJsDocComment)([`Creates a new ${meta.userFriendlyName} deep clone and returns it.`])}
|
|
338
324
|
public async clone(
|
|
339
|
-
{ data: {
|
|
340
|
-
{ data: ${m.decoders.cloneType}; execution: ${m.iExecution}; context?: ${m.cloneContext.type} }
|
|
325
|
+
{ data, execution }: { data: { ${inputFields.join(', ')} }; execution: ${m.iExecution} }
|
|
341
326
|
): Promise<${m.typeName}> {
|
|
342
|
-
const
|
|
343
|
-
if (alreadyCloned) {
|
|
344
|
-
// We already cloned this item before, so we return the cloned item.
|
|
345
|
-
return alreadyCloned
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
const source = await this.view.get(id)
|
|
327
|
+
const source = await this.view.get(data.id)
|
|
349
328
|
if (!source) {
|
|
350
|
-
throw new Error(\`${meta.userFriendlyName} with id \${id} not found\`)
|
|
329
|
+
throw new Error(\`${meta.userFriendlyName} with id \${data.id} not found\`)
|
|
351
330
|
}
|
|
352
331
|
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
context.${m.cloneContext.map}.set(id, clone)
|
|
356
|
-
|
|
357
|
-
${backReferenceCloning.join('\n')}
|
|
332
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
333
|
+
const { id, ...duplicate } = { ...source, ...data } satisfies Actions['create']['payload']
|
|
358
334
|
|
|
359
|
-
return
|
|
335
|
+
return await this.create({ data: duplicate, execution })
|
|
360
336
|
}`;
|
|
361
337
|
}
|
|
@@ -75,10 +75,6 @@ export const ${meta.trpc.routerName} = router({
|
|
|
75
75
|
delete: procedure
|
|
76
76
|
.input(${meta.types.zodDecoderFnNames.id})
|
|
77
77
|
.mutation(({ input, ctx }) => ctx.dispatch({scope: "${scopeName}", type: "delete", payload: input})),
|
|
78
|
-
|
|
79
|
-
clone: procedure
|
|
80
|
-
.input(${decoders.name}.clone)
|
|
81
|
-
.mutation(({ input, ctx }) => ctx.dispatch({scope: "${scopeName}", type: "clone", payload: input})),
|
|
82
78
|
})
|
|
83
79
|
`;
|
|
84
80
|
}
|
|
@@ -4,9 +4,9 @@ exports.generateModelTypes = void 0;
|
|
|
4
4
|
const imports_1 = require("../../lib/imports");
|
|
5
5
|
const meta_1 = require("../../lib/meta");
|
|
6
6
|
const fields_1 = require("../../lib/schema/fields");
|
|
7
|
-
const
|
|
8
|
-
const types_1 = require("../../lib/types");
|
|
7
|
+
const typescript_1 = require("../../lib/typescript");
|
|
9
8
|
const jsdoc_1 = require("../../lib/utils/jsdoc");
|
|
9
|
+
const zod_1 = require("../../lib/zod");
|
|
10
10
|
/**
|
|
11
11
|
* Generates types for a given model.
|
|
12
12
|
*/
|
|
@@ -47,7 +47,7 @@ export type ${meta.types.typeName} = {
|
|
|
47
47
|
.map((f) => {
|
|
48
48
|
return `
|
|
49
49
|
${(0, jsdoc_1.getFieldComment)(f)}
|
|
50
|
-
${f.name}: ${getFieldType(f)}${f.isRequired ? '' : ' | null'}
|
|
50
|
+
${f.name}: ${(0, typescript_1.getFieldType)(f)}${f.isRequired ? '' : ' | null'}
|
|
51
51
|
`;
|
|
52
52
|
})
|
|
53
53
|
.join('\n')}
|
|
@@ -98,20 +98,3 @@ export type ${meta.types.dto.upsert} = ${schemaMeta.types.dto.upsert}<${meta.typ
|
|
|
98
98
|
`;
|
|
99
99
|
}
|
|
100
100
|
exports.generateModelTypes = generateModelTypes;
|
|
101
|
-
/**
|
|
102
|
-
* Converts a field to a TypeScript type definition.
|
|
103
|
-
*/
|
|
104
|
-
function getFieldType(f) {
|
|
105
|
-
switch (f.kind) {
|
|
106
|
-
case 'enum':
|
|
107
|
-
return f.typeName;
|
|
108
|
-
case 'relation':
|
|
109
|
-
return f.relationToModel.brandedIdType;
|
|
110
|
-
case 'id':
|
|
111
|
-
return f.model.brandedIdType;
|
|
112
|
-
case 'scalar':
|
|
113
|
-
return f.tsTypeName;
|
|
114
|
-
default:
|
|
115
|
-
throw new types_1.ExhaustiveSwitchCheck(f);
|
|
116
|
-
}
|
|
117
|
-
}
|
package/dist/lib/attributes.d.ts
CHANGED
|
@@ -90,11 +90,6 @@ export type FieldAttributes = {
|
|
|
90
90
|
* The field that should be used as the default label for the model.
|
|
91
91
|
*/
|
|
92
92
|
isLabel?: boolean;
|
|
93
|
-
/**
|
|
94
|
-
* Schema tag: `@@CloneWithParent()`
|
|
95
|
-
* If set, the all models that reference the parent that was cloned should also be cloned.
|
|
96
|
-
*/
|
|
97
|
-
cloneWithParent?: boolean;
|
|
98
93
|
};
|
|
99
94
|
export type EnumAttributes = {
|
|
100
95
|
/**
|
package/dist/lib/meta.d.ts
CHANGED
|
@@ -560,18 +560,6 @@ export type SchemaMetaData = {
|
|
|
560
560
|
* Path to the file containing the overall action types
|
|
561
561
|
*/
|
|
562
562
|
actionTypesFilePath: Types.FilePath;
|
|
563
|
-
/**
|
|
564
|
-
* Path to the file containing the clone context
|
|
565
|
-
*/
|
|
566
|
-
cloneContextFilePath: Types.FilePath;
|
|
567
|
-
/**
|
|
568
|
-
* The name of the clone context type
|
|
569
|
-
*/
|
|
570
|
-
cloneContextType: Types.TypeName;
|
|
571
|
-
/**
|
|
572
|
-
* The name of the function that creates a clone context
|
|
573
|
-
*/
|
|
574
|
-
cloneContextCreateMethod: Types.FunctionName;
|
|
575
563
|
};
|
|
576
564
|
seedData: {
|
|
577
565
|
/**
|
|
@@ -942,15 +930,7 @@ export type ModelMetaData = {
|
|
|
942
930
|
* The name of the function that decodes an Upsert object to a fully typed object (e.g. `aggregationUpsertDecoder`.)
|
|
943
931
|
*/
|
|
944
932
|
upsert: Types.FunctionName;
|
|
945
|
-
/**
|
|
946
|
-
* The name of the function that clones an object (e.g. `aggregationCloneDecoder`.)
|
|
947
|
-
*/
|
|
948
|
-
clone: Types.FunctionName;
|
|
949
933
|
};
|
|
950
|
-
/**
|
|
951
|
-
* The name of the map variable in the clone context that holds the cloned items of this model (e.g. `aggregation`)
|
|
952
|
-
*/
|
|
953
|
-
cloneContextMap: Types.VariableName;
|
|
954
934
|
/**
|
|
955
935
|
* Name by which the business logic service exposes the data service.
|
|
956
936
|
*/
|
package/dist/lib/meta.js
CHANGED
|
@@ -118,9 +118,6 @@ function getSchemaMetadata({ config }) {
|
|
|
118
118
|
serviceClassName: Types.toClassName(`UpdateService`),
|
|
119
119
|
serviceLocation: Types.toModuleLocation(`update`, `${config.paths.businessUpdateLogicPath}update.service`),
|
|
120
120
|
actionTypesFilePath: Types.toPath(`${config.paths.businessUpdateLogicPath}actions`),
|
|
121
|
-
cloneContextFilePath: Types.toPath(`${config.paths.businessUpdateLogicPath}clone.context`),
|
|
122
|
-
cloneContextType: Types.toTypeName(`CloneContext`),
|
|
123
|
-
cloneContextCreateMethod: Types.toFunctionName(`createCloneContext`),
|
|
124
121
|
},
|
|
125
122
|
data: {
|
|
126
123
|
moduleName: Types.toClassName(`DataModule`),
|
|
@@ -342,9 +339,7 @@ function getModelMetadata({ model }) {
|
|
|
342
339
|
create: Types.toFunctionName(`${camelCase}CreateDecoder`),
|
|
343
340
|
update: Types.toFunctionName(`${camelCase}UpdateDecoder`),
|
|
344
341
|
upsert: Types.toFunctionName(`${camelCase}UpsertDecoder`),
|
|
345
|
-
clone: Types.toFunctionName(`${camelCase}CloneDecoder`),
|
|
346
342
|
},
|
|
347
|
-
cloneContextMap: Types.toVariableName(`${camelCase}`),
|
|
348
343
|
dataRepositoryVariableName: Types.toVariableName(`data`),
|
|
349
344
|
},
|
|
350
345
|
seed: {
|
|
@@ -435,24 +430,6 @@ function getFieldMetadata({ field }) {
|
|
|
435
430
|
getByForeignKeyIdsMethodFnName: Types.toFunctionName(`getIdsFor${PascalCase}`),
|
|
436
431
|
excelColumnName: (0, string_1.toPascalCase)(field.name),
|
|
437
432
|
};
|
|
438
|
-
// switch (field.kind) {
|
|
439
|
-
// case 'id':
|
|
440
|
-
// return {
|
|
441
|
-
// tsFieldName: Types.toVariableName(toCamelCase(field.name)),
|
|
442
|
-
// }
|
|
443
|
-
// case 'enum':
|
|
444
|
-
// return {
|
|
445
|
-
// tsFieldName: Types.toVariableName(toCamelCase(field.name)),
|
|
446
|
-
// }
|
|
447
|
-
// case 'relation':
|
|
448
|
-
// return {
|
|
449
|
-
// tsFieldName: Types.toVariableName(toCamelCase(field.name)),
|
|
450
|
-
// }
|
|
451
|
-
// case 'scalar':
|
|
452
|
-
// return {
|
|
453
|
-
// tsFieldName: Types.toVariableName(toCamelCase(field.name)),
|
|
454
|
-
// }
|
|
455
|
-
// }
|
|
456
433
|
}
|
|
457
434
|
exports.getFieldMetadata = getFieldMetadata;
|
|
458
435
|
/**
|
|
@@ -215,9 +215,13 @@ export type FieldCore = {
|
|
|
215
215
|
*/
|
|
216
216
|
description?: string;
|
|
217
217
|
/**
|
|
218
|
-
*
|
|
218
|
+
* Tells whether there's a NOT NULL constraint on the field.
|
|
219
219
|
*/
|
|
220
220
|
isRequired: boolean;
|
|
221
|
+
/**
|
|
222
|
+
* Tells whether there's a unique constraint on the field.
|
|
223
|
+
*/
|
|
224
|
+
isUnique: boolean;
|
|
221
225
|
/**
|
|
222
226
|
* A dictionary of potential attributes the field can have.
|
|
223
227
|
*/
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getFieldType = void 0;
|
|
4
|
+
const types_1 = require("./types");
|
|
5
|
+
/**
|
|
6
|
+
* Converts a field to a TypeScript type definition.
|
|
7
|
+
*/
|
|
8
|
+
function getFieldType(f) {
|
|
9
|
+
switch (f.kind) {
|
|
10
|
+
case 'enum':
|
|
11
|
+
return f.typeName;
|
|
12
|
+
case 'relation':
|
|
13
|
+
return f.relationToModel.brandedIdType;
|
|
14
|
+
case 'id':
|
|
15
|
+
return f.model.brandedIdType;
|
|
16
|
+
case 'scalar':
|
|
17
|
+
return f.tsTypeName;
|
|
18
|
+
default:
|
|
19
|
+
throw new types_1.ExhaustiveSwitchCheck(f);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
exports.getFieldType = getFieldType;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getZodDecoderDefinition = void 0;
|
|
4
|
-
const meta_1 = require("
|
|
5
|
-
const types_1 = require("
|
|
4
|
+
const meta_1 = require("./meta");
|
|
5
|
+
const types_1 = require("./types");
|
|
6
6
|
/**
|
|
7
7
|
* Returns the string defining the zod decoder for a given field.
|
|
8
8
|
*/
|
|
@@ -25,6 +25,9 @@ const getZodDecoderDefinition = ({ field, allowAnyOptionalField, }) => {
|
|
|
25
25
|
return definition;
|
|
26
26
|
};
|
|
27
27
|
exports.getZodDecoderDefinition = getZodDecoderDefinition;
|
|
28
|
+
/**
|
|
29
|
+
* Returns the string defining the type of the Zod decoder for a given field.
|
|
30
|
+
*/
|
|
28
31
|
function getZodTypeDefinition(field) {
|
|
29
32
|
switch (field.kind) {
|
|
30
33
|
case 'scalar':
|
|
@@ -148,10 +148,9 @@ function getFieldAttributes(field) {
|
|
|
148
148
|
.or(zod_1.default.string().transform((s) => parseInt(s, 10)))
|
|
149
149
|
.optional(),
|
|
150
150
|
readonly: blankStringBooleanDecoder,
|
|
151
|
-
cloneWithParent: blankStringBooleanDecoder,
|
|
152
151
|
})
|
|
153
152
|
.transform((obj) => {
|
|
154
|
-
var _a
|
|
153
|
+
var _a;
|
|
155
154
|
if (isPrismaIgnored && !obj.ignore) {
|
|
156
155
|
throw new Error(`Field ${field.name} is ignored by Prisma, but is missing the "ignore" PostXL attribute!`);
|
|
157
156
|
}
|
|
@@ -165,7 +164,6 @@ function getFieldAttributes(field) {
|
|
|
165
164
|
isReadonly: obj.readonly || field.isGenerated || field.isUpdatedAt || field.name === 'createdAt' || field.isId,
|
|
166
165
|
isUpdatedAt: (_a = field.isUpdatedAt) !== null && _a !== void 0 ? _a : false,
|
|
167
166
|
isCreatedAt: field.name === 'createdAt',
|
|
168
|
-
cloneWithParent: (_b = obj.cloneWithParent) !== null && _b !== void 0 ? _b : false,
|
|
169
167
|
};
|
|
170
168
|
});
|
|
171
169
|
const result = decoder.safeParse(attributes);
|
package/dist/prisma/parse.js
CHANGED
|
@@ -29,15 +29,11 @@ const error_1 = require("../lib/utils/error");
|
|
|
29
29
|
const logger_1 = require("../lib/utils/logger");
|
|
30
30
|
const string_1 = require("../lib/utils/string");
|
|
31
31
|
const attributes_1 = require("./attributes");
|
|
32
|
-
/**
|
|
33
|
-
* These models are required for the generators/backend to work.
|
|
34
|
-
*/
|
|
35
|
-
const REQUIRED_MODELS = ['User', 'Config', 'File', 'Action', 'Mutation'];
|
|
36
32
|
/**
|
|
37
33
|
* Converts a Prisma schema (DMMF) document to a Schema that's passed around generators.
|
|
38
34
|
*/
|
|
39
35
|
function parsePrismaSchema({ datamodel: { enums: enumsRaw, models: modelsRaw }, config, }) {
|
|
40
|
-
|
|
36
|
+
ensurePXLSystemModelsExist(modelsRaw);
|
|
41
37
|
ensureConsistency({ models: modelsRaw, enums: enumsRaw });
|
|
42
38
|
// NOTE: We preprocess models and enums so that we can populate relationships.
|
|
43
39
|
const models = modelsRaw.map((dmmfModel) => parseModelCore({ dmmfModel, config }));
|
|
@@ -66,8 +62,12 @@ function parsePrismaSchema({ datamodel: { enums: enumsRaw, models: modelsRaw },
|
|
|
66
62
|
return { models: modelsWithFields, enums };
|
|
67
63
|
}
|
|
68
64
|
exports.parsePrismaSchema = parsePrismaSchema;
|
|
69
|
-
|
|
70
|
-
|
|
65
|
+
/**
|
|
66
|
+
* These models are required for the generators/backend to work.
|
|
67
|
+
*/
|
|
68
|
+
const SYSTEM_MODELS = ['User', 'Config', 'File', 'Action', 'Mutation'];
|
|
69
|
+
function ensurePXLSystemModelsExist(models) {
|
|
70
|
+
for (const requiredModel of SYSTEM_MODELS) {
|
|
71
71
|
if (!models.find((m) => m.name === requiredModel)) {
|
|
72
72
|
(0, error_1.throwError)(`Required model ${(0, logger_1.highlight)(requiredModel)} not found in schema!`);
|
|
73
73
|
}
|
|
@@ -209,6 +209,7 @@ function parseModel({ dmmfModel, enums, models, config, }) {
|
|
|
209
209
|
description: attributes.description,
|
|
210
210
|
sourceName: dmmfField.name,
|
|
211
211
|
isRequired: dmmfField.isRequired,
|
|
212
|
+
isUnique: dmmfField.isUnique,
|
|
212
213
|
attributes,
|
|
213
214
|
schemaConfig: config,
|
|
214
215
|
schemaType: dmmfField.type,
|
package/package.json
CHANGED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { SchemaMetaData } from '../../lib/meta';
|
|
2
|
-
import { Model } from '../../lib/schema/schema';
|
|
3
|
-
/**
|
|
4
|
-
* Generates the clone context for the business logic update service.
|
|
5
|
-
*/
|
|
6
|
-
export declare function generateBusinessLogicCloneContext({ models, meta: schemaMeta, }: {
|
|
7
|
-
models: Model[];
|
|
8
|
-
meta: SchemaMetaData;
|
|
9
|
-
}): string;
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.generateBusinessLogicCloneContext = void 0;
|
|
4
|
-
const imports_1 = require("../../lib/imports");
|
|
5
|
-
const meta_1 = require("../../lib/meta");
|
|
6
|
-
/**
|
|
7
|
-
* Generates the clone context for the business logic update service.
|
|
8
|
-
*/
|
|
9
|
-
function generateBusinessLogicCloneContext({ models, meta: schemaMeta, }) {
|
|
10
|
-
const imports = imports_1.ImportsGenerator.from(schemaMeta.update.cloneContextFilePath);
|
|
11
|
-
const typeDefinitions = [];
|
|
12
|
-
const mapAssignments = [];
|
|
13
|
-
for (const model of models) {
|
|
14
|
-
const modelMeta = (0, meta_1.getModelMetadata)({ model });
|
|
15
|
-
imports.addImports({
|
|
16
|
-
[schemaMeta.types.importPath]: [modelMeta.types.brandedIdType, modelMeta.types.typeName],
|
|
17
|
-
});
|
|
18
|
-
typeDefinitions.push(`${modelMeta.update.cloneContextMap}: Map<${modelMeta.types.brandedIdType}, ${modelMeta.types.typeName}>`);
|
|
19
|
-
mapAssignments.push(`${modelMeta.update.cloneContextMap}: new Map()`);
|
|
20
|
-
}
|
|
21
|
-
return /* ts */ `
|
|
22
|
-
${imports.generate()}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* The context that is passed in a clone action.
|
|
26
|
-
*
|
|
27
|
-
* This context is used to track which items have already been cloned and link them to the cloned item.
|
|
28
|
-
*/
|
|
29
|
-
export type CloneContext = {
|
|
30
|
-
${typeDefinitions.join('\n')}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export function createCloneContext(): CloneContext {
|
|
34
|
-
return {
|
|
35
|
-
${mapAssignments.join(',\n')}
|
|
36
|
-
}
|
|
37
|
-
}`;
|
|
38
|
-
}
|
|
39
|
-
exports.generateBusinessLogicCloneContext = generateBusinessLogicCloneContext;
|