@postxl/generator 0.14.0 → 0.15.1
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 +16 -0
- package/dist/generators/indices/businesslogicindex.generator.d.ts +9 -0
- package/dist/generators/indices/businesslogicindex.generator.js +19 -0
- package/dist/generators/indices/businesslogicmodule.generator.d.ts +9 -0
- package/dist/generators/indices/businesslogicmodule.generator.js +43 -0
- package/dist/generators/indices/businesslogicservice.generator.d.ts +9 -0
- package/dist/generators/indices/businesslogicservice.generator.js +32 -0
- package/dist/generators/indices/datamockmodule.generator.js +1 -1
- package/dist/generators/indices/datamodule.generator.js +22 -21
- package/dist/generators/indices/dataservice.generator.js +1 -1
- package/dist/generators/indices/seed-template-decoder.generator.js +32 -11
- package/dist/generators/models/businesslogic.generator.d.ts +9 -0
- package/dist/generators/models/businesslogic.generator.js +172 -0
- package/dist/generators/models/react.generator/context.generator.js +5 -3
- package/dist/generators/models/react.generator/library.generator.js +1 -1
- package/dist/generators/models/react.generator/lookup.generator.js +1 -1
- package/dist/generators/models/react.generator/modals.generator.d.ts +1 -1
- package/dist/generators/models/react.generator/modals.generator.js +118 -60
- package/dist/generators/models/repository.generator.js +18 -2
- package/dist/generators/models/route.generator.js +6 -6
- package/dist/generators/models/seed.generator.js +5 -2
- package/dist/generators/models/stub.generator.js +11 -9
- package/dist/generators/models/types.generator.js +32 -2
- package/dist/lib/imports.js +12 -3
- package/dist/lib/meta.d.ts +101 -1
- package/dist/lib/meta.js +21 -0
- package/dist/lib/schema/fields.d.ts +5 -1
- package/dist/lib/schema/schema.d.ts +26 -1
- package/dist/lib/schema/schema.js +1 -1
- package/dist/prisma/parse.js +15 -3
- package/package.json +2 -2
package/dist/lib/meta.d.ts
CHANGED
|
@@ -5,6 +5,14 @@ import * as Types from './schema/types';
|
|
|
5
5
|
*/
|
|
6
6
|
export type SchemaMetaData = {
|
|
7
7
|
data: {
|
|
8
|
+
/**
|
|
9
|
+
* The name of the Module class
|
|
10
|
+
*/
|
|
11
|
+
moduleName: Types.ClassName;
|
|
12
|
+
/**
|
|
13
|
+
* Path that may be used to import from the data module.
|
|
14
|
+
*/
|
|
15
|
+
importPath: Types.Path;
|
|
8
16
|
/**
|
|
9
17
|
* Path to the file containing the data module class definition.
|
|
10
18
|
*/
|
|
@@ -34,6 +42,32 @@ export type SchemaMetaData = {
|
|
|
34
42
|
*/
|
|
35
43
|
stubIndexFilePath: Types.Path;
|
|
36
44
|
};
|
|
45
|
+
businessLogic: {
|
|
46
|
+
/**
|
|
47
|
+
* The name of the Module class
|
|
48
|
+
*/
|
|
49
|
+
moduleName: Types.ClassName;
|
|
50
|
+
/**
|
|
51
|
+
* Path that may be used to import from the business logic module.
|
|
52
|
+
*/
|
|
53
|
+
importPath: Types.Path;
|
|
54
|
+
/**
|
|
55
|
+
* Path to the file containing the business logic index.
|
|
56
|
+
*/
|
|
57
|
+
indexFilePath: Types.Path;
|
|
58
|
+
/**
|
|
59
|
+
* Path to the file containing the business logic module definition.
|
|
60
|
+
*/
|
|
61
|
+
moduleFilePath: Types.Path;
|
|
62
|
+
/**
|
|
63
|
+
* The name of the business logic service class.
|
|
64
|
+
*/
|
|
65
|
+
serviceClassName: Types.ClassName;
|
|
66
|
+
/**
|
|
67
|
+
* Path to the file containing the business logic service class definition.
|
|
68
|
+
*/
|
|
69
|
+
serviceFilePath: Types.Path;
|
|
70
|
+
};
|
|
37
71
|
seed: {
|
|
38
72
|
/**
|
|
39
73
|
* Path to the index file for the seed package.
|
|
@@ -104,6 +138,25 @@ export type ModelMetaData = {
|
|
|
104
138
|
* use a more specific name for your purposes (e.g. `reactCreateModalComponentName`).
|
|
105
139
|
*/
|
|
106
140
|
userFriendlyName: string;
|
|
141
|
+
/**
|
|
142
|
+
* The name of the model in singular form.
|
|
143
|
+
*
|
|
144
|
+
* NOTE: This name is meant to be used in internal variables only.
|
|
145
|
+
* For any variables, class names, etc. that are exposed, please use a more specific name.
|
|
146
|
+
* (e.g. `reactCreateModalComponentName`)
|
|
147
|
+
*/
|
|
148
|
+
internalSingularName: Types.VariableName;
|
|
149
|
+
/**
|
|
150
|
+
* The name of the model in plural form.
|
|
151
|
+
*
|
|
152
|
+
* NOTE: This name is meant to be used in internal variables only.
|
|
153
|
+
* For any variables, class names, etc. that are exposed, please use a more specific name.
|
|
154
|
+
* (e.g. `reactCreateModalComponentName`)
|
|
155
|
+
*/
|
|
156
|
+
internalPluralName: Types.VariableName;
|
|
157
|
+
/**
|
|
158
|
+
* Properties provided by the `data` generators.
|
|
159
|
+
*/
|
|
107
160
|
data: {
|
|
108
161
|
/**
|
|
109
162
|
* Path that may be used to import definitions of this model.
|
|
@@ -168,6 +221,34 @@ export type ModelMetaData = {
|
|
|
168
221
|
getMethodFnName: Types.Fnction;
|
|
169
222
|
};
|
|
170
223
|
};
|
|
224
|
+
/**
|
|
225
|
+
* Properties provided by the `business logic` generator.
|
|
226
|
+
*/
|
|
227
|
+
businessLogic: {
|
|
228
|
+
/**
|
|
229
|
+
* Path that may be used to import definitions of this model.
|
|
230
|
+
*/
|
|
231
|
+
importPath: Types.Path;
|
|
232
|
+
/**
|
|
233
|
+
* The name by which the model's class is exposed in the businessLogicService/context. (e.g. aggregations)
|
|
234
|
+
*/
|
|
235
|
+
serviceClassName: Types.ClassName;
|
|
236
|
+
/**
|
|
237
|
+
* The name by which the model's class is exposed in the businessLogicService/context. (e.g. aggregations)
|
|
238
|
+
*/
|
|
239
|
+
serviceVariableName: Types.VariableName;
|
|
240
|
+
/**
|
|
241
|
+
* Name of the file containing the service for this model.
|
|
242
|
+
*/
|
|
243
|
+
serviceFileName: Types.FileName;
|
|
244
|
+
/**
|
|
245
|
+
* Path to the file containing the service.
|
|
246
|
+
*/
|
|
247
|
+
serviceFilePath: Types.Path;
|
|
248
|
+
};
|
|
249
|
+
/**
|
|
250
|
+
* Properties provided by the `seed` generators.
|
|
251
|
+
*/
|
|
171
252
|
seed: {
|
|
172
253
|
/**
|
|
173
254
|
* The name of the constant containing seed data of this model (e.g. `aggregations`).
|
|
@@ -206,6 +287,9 @@ export type ModelMetaData = {
|
|
|
206
287
|
dataName: Types.VariableName;
|
|
207
288
|
};
|
|
208
289
|
};
|
|
290
|
+
/**
|
|
291
|
+
* Properties provided by the `react` generators.
|
|
292
|
+
*/
|
|
209
293
|
react: {
|
|
210
294
|
/**
|
|
211
295
|
* Name of the folder that contains React components for this model.
|
|
@@ -264,6 +348,9 @@ export type ModelMetaData = {
|
|
|
264
348
|
cardComponentName: Types.VariableName;
|
|
265
349
|
};
|
|
266
350
|
};
|
|
351
|
+
/**
|
|
352
|
+
* Properties provided by the `trpc` generators.
|
|
353
|
+
*/
|
|
267
354
|
trpc: {
|
|
268
355
|
/**
|
|
269
356
|
* The path to the file that contains the router definition for this model.
|
|
@@ -299,7 +386,7 @@ export type ModelMetaData = {
|
|
|
299
386
|
};
|
|
300
387
|
update: {
|
|
301
388
|
/**
|
|
302
|
-
* The name of the TRPC
|
|
389
|
+
* The name of the TRPC update method (e.g. `update` or `updateAggregation`).
|
|
303
390
|
*/
|
|
304
391
|
methodName: Types.VariableName;
|
|
305
392
|
/**
|
|
@@ -318,6 +405,9 @@ export type ModelMetaData = {
|
|
|
318
405
|
reactQueryMethod: Types.Fnction;
|
|
319
406
|
};
|
|
320
407
|
};
|
|
408
|
+
/**
|
|
409
|
+
* Properties provided by the `types` generators.
|
|
410
|
+
*/
|
|
321
411
|
types: {
|
|
322
412
|
/**
|
|
323
413
|
* The absolute path of the file that contains the type definition for this model.
|
|
@@ -344,6 +434,16 @@ export type ModelMetaData = {
|
|
|
344
434
|
* The name of the file containing type definitions (e.g. `aggregation.type`).
|
|
345
435
|
*/
|
|
346
436
|
typeDefFileName: Types.FileName;
|
|
437
|
+
/**
|
|
438
|
+
* The name of the type that represents a fully typed, flat object, e.g. `Aggregation`.
|
|
439
|
+
* This type only refers to related types by their branded ID.
|
|
440
|
+
*/
|
|
441
|
+
typeName: Types.TypeName;
|
|
442
|
+
/**
|
|
443
|
+
* The name of the type that represents a fully typed object, e.g. `AggregationFull`.
|
|
444
|
+
* This type refers to relations by linking to the (flat) types.
|
|
445
|
+
*/
|
|
446
|
+
linkedTypeName: Types.TypeName;
|
|
347
447
|
/**
|
|
348
448
|
* The name of the type that represents a source (i.e. database) object, e.g. `Aggregation`.
|
|
349
449
|
*/
|
package/dist/lib/meta.js
CHANGED
|
@@ -32,6 +32,8 @@ const string_1 = require("./utils/string");
|
|
|
32
32
|
function getSchemaMetadata({ config }) {
|
|
33
33
|
return {
|
|
34
34
|
data: {
|
|
35
|
+
moduleName: Types.toClassName(`DataModule`),
|
|
36
|
+
importPath: Types.toPath(`@${config.project}/data`),
|
|
35
37
|
dataModuleFilePath: Types.toPath(`${config.paths.dataLibPath}data.module`),
|
|
36
38
|
dataMockModuleFilePath: Types.toPath(`${config.paths.dataLibPath}data.mock.module`),
|
|
37
39
|
testDataServiceFilePath: Types.toPath(`${config.paths.dataLibPath}test-data.service`),
|
|
@@ -40,6 +42,14 @@ function getSchemaMetadata({ config }) {
|
|
|
40
42
|
repositoriesIndexFilePath: Types.toPath(`${config.paths.dataLibPath}repositories/index`),
|
|
41
43
|
stubIndexFilePath: Types.toPath(`${config.paths.dataLibPath}stubs/index`),
|
|
42
44
|
},
|
|
45
|
+
businessLogic: {
|
|
46
|
+
moduleName: Types.toClassName(`BusinessLogicModule`),
|
|
47
|
+
importPath: Types.toPath(`@${config.project}/business-logic`),
|
|
48
|
+
indexFilePath: Types.toPath(`${config.paths.businessLogicPath}index`),
|
|
49
|
+
moduleFilePath: Types.toPath(`${config.paths.businessLogicPath}business-logic.module`),
|
|
50
|
+
serviceClassName: Types.toClassName(`BusinessLogicService`),
|
|
51
|
+
serviceFilePath: Types.toPath(`${config.paths.businessLogicPath}business-logic.service`),
|
|
52
|
+
},
|
|
43
53
|
trpc: {
|
|
44
54
|
routesFilePath: Types.toPath(`${config.paths.trpcRoutesFolderPath}index`),
|
|
45
55
|
importPath: Types.toPath(`@${config.project}/trpc`),
|
|
@@ -68,6 +78,8 @@ function getModelMetadata({ model }) {
|
|
|
68
78
|
const { PascalCase, camelCase, pluralized, uncapitalizedPlural, capitalizedPlural } = (0, string_1.conjugateNames)(name);
|
|
69
79
|
return {
|
|
70
80
|
userFriendlyName: PascalCase,
|
|
81
|
+
internalSingularName: Types.toVariableName(camelCase),
|
|
82
|
+
internalPluralName: Types.toVariableName(uncapitalizedPlural),
|
|
71
83
|
data: {
|
|
72
84
|
mockDataPropertyName: Types.toVariableName(`${uncapitalizedPlural}`),
|
|
73
85
|
defaultStubConstantName: Types.toVariableName(`${camelCase}DefaultStub`),
|
|
@@ -87,6 +99,13 @@ function getModelMetadata({ model }) {
|
|
|
87
99
|
getMethodFnName: Types.toFunction(`${camelCase}`),
|
|
88
100
|
},
|
|
89
101
|
},
|
|
102
|
+
businessLogic: {
|
|
103
|
+
importPath: Types.toPath(`@${config.project}/businessLogic`),
|
|
104
|
+
serviceClassName: Types.toClassName(`${PascalCase}Service`),
|
|
105
|
+
serviceVariableName: Types.toVariableName(`${uncapitalizedPlural}`),
|
|
106
|
+
serviceFileName: Types.toFileName(`${camelCase}.service`),
|
|
107
|
+
serviceFilePath: Types.toPath(`${config.paths.businessLogicPath}${camelCase}.service`),
|
|
108
|
+
},
|
|
90
109
|
seed: {
|
|
91
110
|
filePath: Types.toPath(`${config.paths.seedPath}${uncapitalizedPlural}`),
|
|
92
111
|
constantName: Types.toVariableName(`${uncapitalizedPlural}`),
|
|
@@ -157,6 +176,8 @@ function getModelMetadata({ model }) {
|
|
|
157
176
|
brandedIdType: Types.toTypeName(`${PascalCase}Id`),
|
|
158
177
|
toBrandedIdTypeFnName: Types.toFunction(`to${PascalCase}Id`),
|
|
159
178
|
zodDecoderFnName: Types.toFunction(`${camelCase}Decoder`),
|
|
179
|
+
typeName: Types.toTypeName(`${PascalCase}`),
|
|
180
|
+
linkedTypeName: Types.toTypeName(`${PascalCase}Linked`),
|
|
160
181
|
typeDefFileName: Types.toFileName(`${camelCase}.type`),
|
|
161
182
|
sourceType: Types.toTypeName(`${PascalCase}`),
|
|
162
183
|
},
|
|
@@ -36,4 +36,8 @@ export declare const isUniqueStringField: (f: Field) => boolean;
|
|
|
36
36
|
/**
|
|
37
37
|
* Returns true if the given field has a maxLength attribute.
|
|
38
38
|
*/
|
|
39
|
-
export declare const isMaxLengthStringField: (f: Field) =>
|
|
39
|
+
export declare const isMaxLengthStringField: (f: Field) => f is Field & {
|
|
40
|
+
attributes: {
|
|
41
|
+
maxLength: number;
|
|
42
|
+
};
|
|
43
|
+
};
|
|
@@ -23,6 +23,10 @@ export type SchemaConfig = {
|
|
|
23
23
|
* If true, data module will not be generated.
|
|
24
24
|
*/
|
|
25
25
|
data: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* If true, business logic module will not be generated.
|
|
28
|
+
*/
|
|
29
|
+
businessLogic: boolean;
|
|
26
30
|
/**
|
|
27
31
|
* If true, seed data will not be generated.
|
|
28
32
|
*/
|
|
@@ -51,6 +55,13 @@ export type SchemaConfig = {
|
|
|
51
55
|
* may reference data library using `@project/data` import.
|
|
52
56
|
*/
|
|
53
57
|
dataLibPath: Types.Path;
|
|
58
|
+
/**
|
|
59
|
+
* Path to the directory containing business logic.
|
|
60
|
+
*
|
|
61
|
+
* NOTE: Metadata assumes that project is set up so that certain parts of the code
|
|
62
|
+
* may reference mock data using `@project/business-logic` import.
|
|
63
|
+
*/
|
|
64
|
+
businessLogicPath: Types.Path;
|
|
54
65
|
/**
|
|
55
66
|
* Path to the directory containing mock data samples.
|
|
56
67
|
*
|
|
@@ -285,6 +296,13 @@ export type FieldRelation = Prettify<Omit<FieldCore, 'name'> & {
|
|
|
285
296
|
* Name of the field and variable (e.g. aggregationId)
|
|
286
297
|
*/
|
|
287
298
|
name: string;
|
|
299
|
+
/**
|
|
300
|
+
* Name of the field in the related model that references this model (e.g. `aggregation`).
|
|
301
|
+
*
|
|
302
|
+
* NOTE: This does not reference the database column name, but the field name
|
|
303
|
+
* in the model (e.g. not `aggregationId`, but `aggregation`).
|
|
304
|
+
*/
|
|
305
|
+
relatedModelBacklinkFieldName: string;
|
|
288
306
|
/**
|
|
289
307
|
* Name of the unbranded TypeScript type of the field, e.g. string
|
|
290
308
|
*
|
|
@@ -308,6 +326,13 @@ export declare const isFieldRelation: (field: Field) => field is Prettify<Omit<F
|
|
|
308
326
|
* Name of the field and variable (e.g. aggregationId)
|
|
309
327
|
*/
|
|
310
328
|
name: string;
|
|
329
|
+
/**
|
|
330
|
+
* Name of the field in the related model that references this model (e.g. `aggregation`).
|
|
331
|
+
*
|
|
332
|
+
* NOTE: This does not reference the database column name, but the field name
|
|
333
|
+
* in the model (e.g. not `aggregationId`, but `aggregation`).
|
|
334
|
+
*/
|
|
335
|
+
relatedModelBacklinkFieldName: string;
|
|
311
336
|
/**
|
|
312
337
|
* Name of the unbranded TypeScript type of the field, e.g. string
|
|
313
338
|
*
|
|
@@ -341,7 +366,7 @@ export type FieldEnum = Prettify<Omit<FieldCore, 'name'> & {
|
|
|
341
366
|
enumerator: Enum;
|
|
342
367
|
}>;
|
|
343
368
|
/**
|
|
344
|
-
* Utility function to check if a field is an
|
|
369
|
+
* Utility function to check if a field is an enum field.
|
|
345
370
|
*/
|
|
346
371
|
export declare const isFieldEnum: (field: Field) => field is Prettify<Omit<FieldCore, "name"> & {
|
|
347
372
|
kind: 'enum';
|
|
@@ -12,7 +12,7 @@ exports.isFieldId = isFieldId;
|
|
|
12
12
|
const isFieldRelation = (field) => field.kind === 'relation';
|
|
13
13
|
exports.isFieldRelation = isFieldRelation;
|
|
14
14
|
/**
|
|
15
|
-
* Utility function to check if a field is an
|
|
15
|
+
* Utility function to check if a field is an enum field.
|
|
16
16
|
*/
|
|
17
17
|
const isFieldEnum = (field) => field.kind === 'enum';
|
|
18
18
|
exports.isFieldEnum = isFieldEnum;
|
package/dist/prisma/parse.js
CHANGED
|
@@ -84,9 +84,17 @@ function parseModel({ dmmfModel, enums, models, config, }) {
|
|
|
84
84
|
}
|
|
85
85
|
relations[dmmfField.relationFromFields[0]] = referencedModel;
|
|
86
86
|
}
|
|
87
|
+
const relationFields = dmmfModel.fields
|
|
88
|
+
.filter((f) => f.kind === 'object' && f.relationToFields && f.relationToFields.length === 1)
|
|
89
|
+
.reduce((acc, f) => {
|
|
90
|
+
if (f.relationFromFields && f.relationFromFields[0]) {
|
|
91
|
+
acc[f.relationFromFields[0]] = f;
|
|
92
|
+
}
|
|
93
|
+
return acc;
|
|
94
|
+
}, {});
|
|
87
95
|
const fields = dmmfModel.fields
|
|
88
96
|
.filter((dmmfField) =>
|
|
89
|
-
// if field is a "backlink", i.e. the
|
|
97
|
+
// if field is a "backlink", i.e. the receiver of a relation, we ignore it
|
|
90
98
|
dmmfField.kind !== 'object')
|
|
91
99
|
.map((dmmfField) => {
|
|
92
100
|
const attributes = (0, attributes_1.getFieldAttributes)(dmmfField);
|
|
@@ -101,7 +109,11 @@ function parseModel({ dmmfModel, enums, models, config, }) {
|
|
|
101
109
|
// NOTE: We mark scalar fields which are used in relations as relation fields by Purple Schema standards.
|
|
102
110
|
if (dmmfField.name in relations) {
|
|
103
111
|
const refModel = relations[dmmfField.name];
|
|
104
|
-
|
|
112
|
+
const refField = relationFields[dmmfField.name];
|
|
113
|
+
if (!refField) {
|
|
114
|
+
(0, error_1.throwError)(`Investigate: Relation field ${dmmfField.name} not found.`);
|
|
115
|
+
}
|
|
116
|
+
return Object.assign(Object.assign({ kind: 'relation' }, shared), { relatedModelBacklinkFieldName: refField.name, typeName: Types.toTypeName(dmmfField.type), unbrandedTypeName: getTsTypeForId(dmmfField), relationToModel: refModel });
|
|
105
117
|
}
|
|
106
118
|
if (dmmfField.isId) {
|
|
107
119
|
return Object.assign(Object.assign({ kind: 'id' }, shared), { isUnique: isUniqueField(dmmfField), isGenerated: isAutoIncrementField(dmmfField), unbrandedTypeName: getTsTypeForId(dmmfField), model: core });
|
|
@@ -117,7 +129,7 @@ function parseModel({ dmmfModel, enums, models, config, }) {
|
|
|
117
129
|
if (dmmfField.type === 'Float') {
|
|
118
130
|
validation = { type: 'float' };
|
|
119
131
|
}
|
|
120
|
-
return Object.assign(Object.assign({ kind: 'scalar' }, shared), { isUnique: isUniqueField(dmmfField), isGenerated: isAutoIncrementField(dmmfField), typeName: getTsTypeForScalar(dmmfField) });
|
|
132
|
+
return Object.assign(Object.assign({ kind: 'scalar', validation }, shared), { isUnique: isUniqueField(dmmfField), isGenerated: isAutoIncrementField(dmmfField), typeName: getTsTypeForScalar(dmmfField) });
|
|
121
133
|
}
|
|
122
134
|
if (dmmfField.kind === 'enum') {
|
|
123
135
|
const fieldEnumDef = enums.find((e) => e.sourceName === dmmfField.type);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@postxl/generator",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.1",
|
|
4
4
|
"main": "./dist/generator.js",
|
|
5
5
|
"typings": "./dist/generator.d.ts",
|
|
6
6
|
"bin": {
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"prettier": "^2.8.7",
|
|
23
23
|
"remeda": "1.9.4",
|
|
24
24
|
"zod": "3.21.4",
|
|
25
|
-
"@postxl/lock": "0.
|
|
25
|
+
"@postxl/lock": "0.4.1"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"@prisma/client": "4.12.0",
|