@postxl/generator 0.34.0 → 0.35.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 (58) hide show
  1. package/dist/generator.js +40 -22
  2. package/dist/generators/indices/businesslogic-actiontypes.generator.d.ts +9 -0
  3. package/dist/generators/indices/businesslogic-actiontypes.generator.js +39 -0
  4. package/dist/generators/indices/businesslogic-update-index.generator.d.ts +9 -0
  5. package/dist/generators/indices/businesslogic-update-index.generator.js +20 -0
  6. package/dist/generators/indices/businesslogic-update-module.generator.d.ts +9 -0
  7. package/dist/generators/indices/businesslogic-update-module.generator.js +69 -0
  8. package/dist/generators/indices/businesslogic-update-service.generator.d.ts +9 -0
  9. package/dist/generators/indices/businesslogic-update-service.generator.js +34 -0
  10. package/dist/generators/indices/businesslogic-view-index.generator.d.ts +9 -0
  11. package/dist/generators/indices/businesslogic-view-index.generator.js +19 -0
  12. package/dist/generators/indices/{businesslogicindex.generator.d.ts → businesslogic-view-module.generator.d.ts} +2 -2
  13. package/dist/generators/indices/{businesslogicmodule.generator.js → businesslogic-view-module.generator.js} +22 -26
  14. package/dist/generators/indices/{businesslogicservice.generator.d.ts → businesslogic-view-service.generator.d.ts} +1 -1
  15. package/dist/generators/indices/{businesslogicservice.generator.js → businesslogic-view-service.generator.js} +9 -10
  16. package/dist/generators/indices/{datamockmodule.generator.js → datamock-module.generator.js} +8 -16
  17. package/dist/generators/indices/datamocker.generator.js +3 -7
  18. package/dist/generators/indices/datamodule.generator.js +7 -13
  19. package/dist/generators/indices/{businesslogicmodule.generator.d.ts → dispatcher-service.generator.d.ts} +2 -2
  20. package/dist/generators/indices/dispatcher-service.generator.js +81 -0
  21. package/dist/generators/indices/seed-migration.generator.d.ts +9 -0
  22. package/dist/generators/indices/seed-migration.generator.js +35 -0
  23. package/dist/generators/indices/seed-service.generator.d.ts +1 -1
  24. package/dist/generators/indices/seed-service.generator.js +327 -123
  25. package/dist/generators/indices/seed-template-decoder.generator.js +22 -6
  26. package/dist/generators/indices/{seed.generator.d.ts → seeddata-type.generator.d.ts} +2 -2
  27. package/dist/generators/indices/seeddata-type.generator.js +42 -0
  28. package/dist/generators/indices/types.generator.d.ts +1 -1
  29. package/dist/generators/indices/types.generator.js +8 -6
  30. package/dist/generators/models/businesslogic-update.generator.d.ts +10 -0
  31. package/dist/generators/models/businesslogic-update.generator.js +243 -0
  32. package/dist/generators/models/businesslogic-view.generator.d.ts +10 -0
  33. package/dist/generators/models/{businesslogic.generator.js → businesslogic-view.generator.js} +23 -72
  34. package/dist/generators/models/react.generator/modals.generator.js +2 -2
  35. package/dist/generators/models/repository.generator.d.ts +9 -0
  36. package/dist/generators/models/repository.generator.js +420 -131
  37. package/dist/generators/models/route.generator.js +45 -55
  38. package/dist/generators/models/seed.generator.js +6 -2
  39. package/dist/generators/models/types.generator.js +60 -13
  40. package/dist/lib/attributes.d.ts +5 -0
  41. package/dist/lib/imports.d.ts +23 -2
  42. package/dist/lib/imports.js +19 -1
  43. package/dist/lib/meta.d.ts +287 -34
  44. package/dist/lib/meta.js +87 -16
  45. package/dist/lib/schema/schema.d.ts +24 -6
  46. package/dist/lib/schema/types.d.ts +4 -0
  47. package/dist/lib/utils/jsdoc.d.ts +1 -1
  48. package/dist/lib/utils/jsdoc.js +8 -6
  49. package/dist/lib/utils/string.js +2 -1
  50. package/dist/prisma/attributes.js +7 -3
  51. package/dist/prisma/parse.js +25 -5
  52. package/package.json +1 -1
  53. package/dist/generators/indices/businesslogicindex.generator.js +0 -19
  54. package/dist/generators/indices/seed.generator.js +0 -17
  55. package/dist/generators/indices/testdataservice.generator.d.ts +0 -9
  56. package/dist/generators/indices/testdataservice.generator.js +0 -78
  57. package/dist/generators/models/businesslogic.generator.d.ts +0 -9
  58. /package/dist/generators/indices/{datamockmodule.generator.d.ts → datamock-module.generator.d.ts} +0 -0
@@ -2,8 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.generateRoutesIndex = exports.generateRoute = void 0;
4
4
  const meta_1 = require("../../lib/meta");
5
- const fields_1 = require("../../lib/schema/fields");
6
- const zod_1 = require("../../lib/schema/zod");
7
5
  const imports_1 = require("../../lib/imports");
8
6
  /**
9
7
  * Generates TRPC route for a given model.
@@ -11,22 +9,28 @@ const imports_1 = require("../../lib/imports");
11
9
  function generateRoute({ model, meta }) {
12
10
  const { idField, defaultField } = model;
13
11
  const defaultValueMethod = `
14
- getDefault: procedure.query(({ ctx }) => ctx.data.${meta.data.dataServiceName}.${meta.businessLogic.dataRepositoryVariableName}.defaultValue),
12
+ getDefault: procedure.query(({ ctx }) => ctx.view.${meta.data.dataServiceName}.${meta.businessLogic.dataRepositoryVariableName}.defaultValue),
15
13
  `;
16
- const createMethod = getCreateMethod({ model, meta });
17
- const updateMethod = getUpdateMethod({ model, meta });
18
- const deleteMethod = getDeleteMethod({ idField, meta });
19
- const imports = imports_1.ImportsGenerator.from(meta.trpc.routerFilePath).addImport({
20
- items: [model.typeName, meta.types.toBrandedIdTypeFnName],
21
- from: meta.types.importPath,
14
+ const imports = imports_1.ImportsGenerator.from(meta.trpc.routerFilePath).addImports({
15
+ [meta.types.importPath]: [
16
+ model.typeName,
17
+ meta.types.toBrandedIdTypeFnName,
18
+ meta.types.zodDecoderFnNames.createObject,
19
+ meta.types.zodDecoderFnNames.updateObject,
20
+ meta.types.zodDecoderFnNames.upsertObject,
21
+ meta.types.zodDecoderFnNames.id,
22
+ ],
23
+ [meta.businessLogic.importPath]: [
24
+ meta.businessLogic.update.createActionFunctionNameCreate,
25
+ meta.businessLogic.update.createActionFunctionNameCreateMany,
26
+ meta.businessLogic.update.createActionFunctionNameUpdate,
27
+ meta.businessLogic.update.createActionFunctionNameUpdateMany,
28
+ meta.businessLogic.update.createActionFunctionNameUpsert,
29
+ meta.businessLogic.update.createActionFunctionNameUpsertMany,
30
+ meta.businessLogic.update.createActionFunctionNameDelete,
31
+ meta.businessLogic.update.createActionFunctionNameDeleteMany,
32
+ ],
22
33
  });
23
- for (const relation of (0, fields_1.getRelationFields)(model)) {
24
- const depMeta = (0, meta_1.getModelMetadata)({ model: relation.relationToModel });
25
- imports.addImport({
26
- items: [depMeta.types.toBrandedIdTypeFnName],
27
- from: depMeta.types.importPath,
28
- });
29
- }
30
34
  return `
31
35
  import { z } from 'zod'
32
36
  import { procedure, router } from '../trpc'
@@ -39,8 +43,8 @@ export const ${meta.trpc.routerName} = router({
39
43
 
40
44
  get: procedure
41
45
  .input(z.${idField.unbrandedTypeName}().transform(${meta.types.toBrandedIdTypeFnName}))
42
- .query(({ input, ctx }) => ctx.data.${meta.data.dataServiceName}.get(input)),
43
- getMap: procedure.query(({ ctx }) => ctx.data.${meta.data.dataServiceName}.getAll()),
46
+ .query(({ input, ctx }) => ctx.view.${meta.data.dataServiceName}.get(input)),
47
+ getMap: procedure.query(({ ctx }) => ctx.view.${meta.data.dataServiceName}.getAll()),
44
48
  getList: procedure
45
49
  .input(z.object({
46
50
  cursor: CURSOR_DECODER,
@@ -63,51 +67,37 @@ export const ${meta.trpc.routerName} = router({
63
67
  .optional(),
64
68
  }))
65
69
  .query(({ input, ctx }) => {
66
- return ctx.data.${meta.data.dataServiceName}.getList(input)
70
+ return ctx.view.${meta.data.dataServiceName}.getList(input)
67
71
  }),
68
72
 
69
- ${createMethod}
73
+ create: procedure.input(${meta.types.zodDecoderFnNames.createObject})
74
+ .mutation(({ input, ctx }) => ctx.dispatch(${meta.businessLogic.update.createActionFunctionNameCreate}(input))),
75
+
76
+ createMany: procedure.input(z.array(${meta.types.zodDecoderFnNames.createObject}))
77
+ .mutation(({ input, ctx }) => ctx.dispatch(${meta.businessLogic.update.createActionFunctionNameCreateMany}(input))),
78
+
79
+ update: procedure.input(${meta.types.zodDecoderFnNames.updateObject})
80
+ .mutation(({ input, ctx }) => ctx.dispatch(${meta.businessLogic.update.createActionFunctionNameUpdate}(input))),
81
+
82
+ updateMany: procedure.input(z.array(${meta.types.zodDecoderFnNames.updateObject}))
83
+ .mutation(({ input, ctx }) => ctx.dispatch(${meta.businessLogic.update.createActionFunctionNameUpdateMany}(input))),
84
+
85
+ upsert: procedure.input(${meta.types.zodDecoderFnNames.upsertObject})
86
+ .mutation(({ input, ctx }) => ctx.dispatch(${meta.businessLogic.update.createActionFunctionNameUpsert}(input))),
70
87
 
71
- ${updateMethod}
88
+ upsertMany: procedure.input(z.array(${meta.types.zodDecoderFnNames.upsertObject}))
89
+ .mutation(({ input, ctx }) => ctx.dispatch(${meta.businessLogic.update.createActionFunctionNameUpsertMany}(input))),
90
+
91
+ delete: procedure.input(${meta.types.zodDecoderFnNames.id})
92
+ .mutation(({ input, ctx }) => ctx.dispatch(${meta.businessLogic.update.createActionFunctionNameDelete}(input))),
93
+
94
+ deleteMany: procedure.input(z.array(${meta.types.zodDecoderFnNames.id}))
95
+ .mutation(({ input, ctx }) => ctx.dispatch(${meta.businessLogic.update.createActionFunctionNameDeleteMany}(input))),
72
96
 
73
- ${deleteMethod}
74
97
  })
75
98
  `;
76
99
  }
77
100
  exports.generateRoute = generateRoute;
78
- function getCreateMethod({ model: { fields }, meta }) {
79
- const parameters = fields
80
- .filter((f) => f.kind !== 'id' && !f.attributes.isReadonly)
81
- .map((field) => `${field.name}: z.${(0, zod_1.getZodDecoderDefinition)({ field })}`)
82
- .join(',');
83
- return `
84
- create: procedure.input(z.object({
85
- ${parameters}
86
- }))
87
- .mutation(({ input, ctx }) => ctx.data.${meta.data.dataServiceName}.create(input)),
88
- `;
89
- }
90
- function getUpdateMethod({ model: { fields }, meta }) {
91
- const parameters = fields
92
- .filter((f) => !f.attributes.isReadonly)
93
- .map((field) => `${field.name}: z.${(0, zod_1.getZodDecoderDefinition)({ field, allowAnyOptionalField: field.kind !== 'id' })}`)
94
- .join(',');
95
- return `update: procedure
96
- .input(
97
- z.object({
98
- ${parameters}
99
- })
100
- )
101
- .mutation(({ input, ctx }) => ctx.data.${meta.data.dataServiceName}.update(input)),
102
- `;
103
- }
104
- function getDeleteMethod({ idField, meta }) {
105
- return `
106
- delete: procedure
107
- .input(z.${idField.unbrandedTypeName}().transform(${meta.types.toBrandedIdTypeFnName}))
108
- .mutation(({ input, ctx }) => ctx.data.${meta.data.dataServiceName}.delete(input)),
109
- `;
110
- }
111
101
  /**
112
102
  * Generates the index file for all the routes.
113
103
  */
@@ -12,6 +12,10 @@ const string_1 = require("../../lib/utils/string");
12
12
  * Creates a seed file for a given model.
13
13
  */
14
14
  function generateSeedModel({ model, itemCount, meta, }) {
15
+ var _a;
16
+ // NOTE: We seed `faker` independently for each model.
17
+ // This way changes to another model or to the ordering of models in the schema doesn't impact the generated values.
18
+ faker_1.faker.seed((_a = model.attributes.randomSeed) !== null && _a !== void 0 ? _a : 0);
15
19
  const imports = imports_1.ImportsGenerator.from(meta.seed.filePath).addImport({
16
20
  items: [model.typeName, meta.types.toBrandedIdTypeFnName],
17
21
  from: meta.types.importPath,
@@ -245,7 +249,7 @@ function generateEnumFieldExample({ field, mode, index, }) {
245
249
  * Creates the seed file that exposes all seed data as single object.
246
250
  */
247
251
  function generateSeeds({ models, config, }) {
248
- const imports = imports_1.ImportsGenerator.from(config.paths.seedPath);
252
+ const imports = imports_1.ImportsGenerator.from(config.paths.seedLibPath);
249
253
  for (const { meta } of models) {
250
254
  imports.addImport({
251
255
  items: [meta.seed.constantName],
@@ -254,7 +258,7 @@ function generateSeeds({ models, config, }) {
254
258
  }
255
259
  const seeds = models.map(({ meta }) => `${meta.seed.constantName}`).join(',\n');
256
260
  return `
257
- import { MockData } from '${config.paths.seedPath}'
261
+ import { MockData } from '${config.paths.seedLibPath}'
258
262
 
259
263
  ${imports.generate()}
260
264
 
@@ -6,10 +6,12 @@ const meta_1 = require("../../lib/meta");
6
6
  const fields_1 = require("../../lib/schema/fields");
7
7
  const zod_1 = require("../../lib/schema/zod");
8
8
  const types_1 = require("../../lib/types");
9
+ const jsdoc_1 = require("../../lib/utils/jsdoc");
9
10
  /**
10
11
  * Generates types for a given model.
11
12
  */
12
13
  function generateModelTypes({ model, meta }) {
14
+ var _a, _b;
13
15
  const idField = model.idField;
14
16
  const imports = imports_1.ImportsGenerator.from(meta.types.filePath);
15
17
  let hasLinkedItems = false;
@@ -32,23 +34,23 @@ function generateModelTypes({ model, meta }) {
32
34
  from: refEnumMeta.types.filePath,
33
35
  });
34
36
  }
37
+ const schemaMeta = (0, meta_1.getSchemaMetadata)({ config: model.schemaConfig });
38
+ imports.addImport({
39
+ items: [schemaMeta.types.dto.create, schemaMeta.types.dto.update, schemaMeta.types.dto.upsert],
40
+ from: schemaMeta.types.dto.path,
41
+ });
42
+ const decoderNames = meta.types.zodDecoderFnNames;
35
43
  return `
36
44
  import { z } from 'zod'
37
45
 
38
46
  ${imports.generate()}
39
47
 
40
-
41
- ${model.description
42
- ? `
43
- /**
44
- * ${model.description.split('\n').join('\n * ')}
45
- */`
46
- : ''}
48
+ ${(0, jsdoc_1.toJsDocComment)((_b = (_a = model.description) === null || _a === void 0 ? void 0 : _a.split('\n')) !== null && _b !== void 0 ? _b : [])}
47
49
  export type ${meta.types.typeName} = {
48
50
  ${model.fields
49
51
  .map((f) => `
50
- ${getFieldComment(f)}
51
- ${f.name}: ${getFieldType(f)}${f.isRequired ? '' : ' | null'}`)
52
+ ${getFieldComment(f)}
53
+ ${f.name}: ${getFieldType(f)}${f.isRequired ? '' : ' | null'}`)
52
54
  .join('\n')}
53
55
  }
54
56
 
@@ -64,7 +66,7 @@ ${getLinkedFieldType(f)}${f.isRequired ? '' : ' | null'}`)
64
66
  }`}
65
67
 
66
68
  /**
67
- * Branded Id type that should be used to identify an instance of this model.
69
+ * Branded Id type that should be used to identify an instance of a ${meta.userFriendlyName}.
68
70
  */
69
71
  export type ${model.brandedIdType} = ${idField.unbrandedTypeName} & {
70
72
  readonly ___type: '${model.typeName}'
@@ -78,12 +80,56 @@ export function ${meta.types.toBrandedIdTypeFnName}(id: ${idField.unbrandedTypeN
78
80
  }
79
81
 
80
82
  /**
81
- * Zod decoder for validating a Participant object.
83
+ * Zod decoder for validating a ${meta.userFriendlyName} id.
82
84
  */
83
- export const ${meta.types.zodDecoderFnName} = z.object({
85
+ export const ${decoderNames.id} = z.${(0, zod_1.getZodDecoderDefinition)({ field: idField })}
86
+
87
+ /**
88
+ * Zod decoder for validating a ${meta.userFriendlyName} from the database.
89
+ */
90
+ export const ${decoderNames.fromDatabase} = z.object({
84
91
  ${model.fields.map((field) => `${field.name}: z.${(0, zod_1.getZodDecoderDefinition)({ field })}`).join(',')}
85
92
  })
86
93
 
94
+ /**
95
+ * Zod decoder for validating the create input of a ${meta.userFriendlyName}.
96
+ */
97
+ export const ${decoderNames.createObject} = z.object({
98
+ ${model.fields
99
+ .filter((f) => !f.attributes.isReadonly)
100
+ .map((field) => `${field.name}: z.${(0, zod_1.getZodDecoderDefinition)({ field })}`)
101
+ .join(',')}
102
+ })
103
+
104
+ /**
105
+ * Zod decoder for validating the update input of a ${meta.userFriendlyName} .
106
+ */
107
+ export const ${decoderNames.updateObject} = z.object({
108
+ ${model.fields
109
+ .filter((f) => !f.attributes.isReadonly || f.kind === 'id')
110
+ .map((field) => `${field.name}: z.${(0, zod_1.getZodDecoderDefinition)({ field, allowAnyOptionalField: field.kind !== 'id' })}`)
111
+ .join(',')}
112
+ })
113
+
114
+ /**
115
+ * Zod decoder for validating the upsert input of a ${meta.userFriendlyName} .
116
+ */
117
+ export const ${decoderNames.upsertObject} = z.union([${decoderNames.updateObject}, ${decoderNames.createObject}])
118
+
119
+ /**
120
+ * Data transfer object for creating a new ${meta.userFriendlyName} instance.
121
+ */
122
+ export type ${meta.types.dto.create} = ${schemaMeta.types.dto.create}<${meta.types.typeName}, ${model.brandedIdType}>
123
+
124
+ /**
125
+ * Data transfer object for updating an existing ${meta.userFriendlyName} instance.
126
+ */
127
+ export type ${meta.types.dto.update} = ${schemaMeta.types.dto.update}<${meta.types.typeName}, ${model.brandedIdType}>
128
+
129
+ /**
130
+ * Data transfer object for upserting an existing ${meta.userFriendlyName} instance.
131
+ */
132
+ export type ${meta.types.dto.upsert} = ${schemaMeta.types.dto.upsert}<${meta.types.typeName}, ${model.brandedIdType}>
87
133
  `;
88
134
  }
89
135
  exports.generateModelTypes = generateModelTypes;
@@ -99,8 +145,9 @@ function getFieldComment(f) {
99
145
  if (examples) {
100
146
  comment += ` * ${examples}\n`;
101
147
  }
102
- if (comment === '')
148
+ if (comment === '') {
103
149
  return '';
150
+ }
104
151
  return `
105
152
  /**
106
153
  ${comment}*/`;
@@ -26,6 +26,11 @@ export type ModelAttributes = {
26
26
  * Creates an index on the given fields.
27
27
  */
28
28
  index?: string[];
29
+ /**
30
+ * Schema tag: ´@@Seed()`
31
+ * Seed to use for random generation.
32
+ */
33
+ randomSeed?: number;
29
34
  };
30
35
  export type FieldAttributes = {
31
36
  /**
@@ -1,4 +1,17 @@
1
1
  import * as Types from './schema/types';
2
+ /**
3
+ * A structured definition of multiple imports: The key of the object is the "from" path,
4
+ * the value is a list (or single item) of items to import.
5
+ *
6
+ * Example:
7
+ * ```
8
+ * {
9
+ * [meta.data.importPath]: meta.data.repositoryClassName,
10
+ * [meta.types.importPath]: [model.brandedIdType, meta.types.typeName],
11
+ * }
12
+ * ```
13
+ */
14
+ export type BulkImportDefinition = Record<Types.Path, Types.ImportableTypes[] | Types.ImportableTypes>;
2
15
  /**
3
16
  * A utility component that lets you generate TypeScript import statements
4
17
  * and makes sure every import is only added once.
@@ -24,10 +37,18 @@ export declare class ImportsGenerator {
24
37
  *
25
38
  * NOTE: You should never add no items from a given path.
26
39
  */
27
- addImport({ items, from, }: {
28
- items: (Types.Fnction | Types.ClassName | Types.TypeName | Types.VariableName)[];
40
+ addImport({ items, from }: {
41
+ items: Types.ImportableTypes[];
29
42
  from: Types.Path;
30
43
  }): ImportsGenerator;
44
+ /**
45
+ * Adds a multiple import statements to the imports list.
46
+ *
47
+ * @param entries - A record of items to import indexed by the path.
48
+ *
49
+ * NOTE: You should never add no items from a given path.
50
+ */
51
+ addImports(entries: BulkImportDefinition): ImportsGenerator;
31
52
  /**
32
53
  * Returns the TypeScript import statement.
33
54
  */
@@ -25,7 +25,7 @@ class ImportsGenerator {
25
25
  *
26
26
  * NOTE: You should never add no items from a given path.
27
27
  */
28
- addImport({ items, from, }) {
28
+ addImport({ items, from }) {
29
29
  // NOTE: Generator relies that there's at least one import statement from a given path.
30
30
  if (items.length === 0) {
31
31
  throw new Error(`You cannot add an import statement without any items from ${from}.`);
@@ -37,6 +37,24 @@ class ImportsGenerator {
37
37
  items.forEach((item) => this._imports[resolvedPath].add(item));
38
38
  return this;
39
39
  }
40
+ /**
41
+ * Adds a multiple import statements to the imports list.
42
+ *
43
+ * @param entries - A record of items to import indexed by the path.
44
+ *
45
+ * NOTE: You should never add no items from a given path.
46
+ */
47
+ addImports(entries) {
48
+ for (const [key, items] of Object.entries(entries)) {
49
+ if (Array.isArray(items)) {
50
+ this.addImport({ items, from: key });
51
+ }
52
+ else {
53
+ this.addImport({ items: [items], from: key });
54
+ }
55
+ }
56
+ return this;
57
+ }
40
58
  /**
41
59
  * Returns the TypeScript import statement.
42
60
  */