@postxl/generator 0.54.0 → 0.56.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.
@@ -3,9 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.generateModelBusinessLogicUpdate = void 0;
4
4
  const imports_1 = require("../../lib/imports");
5
5
  const meta_1 = require("../../lib/meta");
6
+ const fields_1 = require("../../lib/schema/fields");
6
7
  const types_1 = require("../../lib/schema/types");
8
+ const zod_1 = require("../../lib/schema/zod");
7
9
  const jsdoc_1 = require("../../lib/utils/jsdoc");
8
- const repository_generator_1 = require("./repository.generator");
9
10
  /**
10
11
  * Generates update business logic for a given model.
11
12
  * The update logic handles all Create/Update/Delete/Upsert operations. See template's readme for more info.
@@ -15,239 +16,182 @@ function generateModelBusinessLogicUpdate({ model, meta }) {
15
16
  const imports = imports_1.ImportsGenerator.from(meta.businessLogic.update.serviceFilePath);
16
17
  imports.addImports({
17
18
  [meta.data.importPath]: meta.data.repository.className,
18
- [schemaMeta.actions.importPath]: schemaMeta.actions.actionExecution.interface,
19
- [meta.types.importPath]: [(0, types_1.toAnnotatedTypeName)(model.brandedIdType), (0, types_1.toAnnotatedTypeName)(meta.types.typeName)],
19
+ [meta.types.importPath]: [
20
+ (0, types_1.toAnnotatedTypeName)(model.brandedIdType),
21
+ (0, types_1.toAnnotatedTypeName)(meta.types.typeName),
22
+ meta.types.toBrandedIdTypeFnName,
23
+ ],
20
24
  [meta.businessLogic.view.serviceFilePath]: [meta.businessLogic.view.serviceClassName],
25
+ [schemaMeta.actions.importPath]: [
26
+ schemaMeta.actions.actionExecution.interface,
27
+ schemaMeta.actions.dispatcher.interface,
28
+ schemaMeta.actions.dispatcher.actionMethod,
29
+ ],
21
30
  [schemaMeta.businessLogic.update.serviceFilePath]: schemaMeta.businessLogic.update.serviceClassName,
22
31
  [schemaMeta.businessLogic.view.serviceFilePath]: schemaMeta.businessLogic.view.serviceClassName,
23
- [meta.data.importPath]: [meta.data.repository.className],
24
32
  });
33
+ const { dispatcher } = schemaMeta.actions;
34
+ for (const relation of (0, fields_1.getRelationFields)(model)) {
35
+ // NOTE: We add branded id type and type name imports only for foreign models.
36
+ if (relation.relationToModel.typeName === model.typeName) {
37
+ continue;
38
+ }
39
+ const refMeta = (0, meta_1.getModelMetadata)({ model: relation.relationToModel });
40
+ imports.addImport({
41
+ items: [refMeta.types.toBrandedIdTypeFnName],
42
+ from: refMeta.types.filePath,
43
+ });
44
+ }
25
45
  /**
26
46
  * The name of the variable that holds the repository instance for the current model
27
47
  * (e.g. when we generate business logic service for Aggregation, the AggregationRepository
28
48
  * would be referenced using `this.data` variable).
29
49
  */
30
50
  const modelRepositoryVariableName = meta.businessLogic.dataRepositoryVariableName;
31
- /**
32
- * The name of the variable that holds the central business logic service instance.
33
- * Instead of injecting a repository instance for each model, we inject this single instance
34
- * which then provides access to all models' business logic.
35
- */
36
- const updateServiceClassName = 'updateService';
37
- const viewServiceClassName = 'viewService';
38
- const actionBlocks = generateActionsBuildingBlocks({ model, meta });
39
- imports.addImport({ from: meta.types.importPath, items: actionBlocks.importTypes });
40
51
  const constructorParameters = [
41
52
  `public readonly ${modelRepositoryVariableName}: ${meta.data.repository.className}`,
42
- `@Inject(forwardRef(() => ${schemaMeta.businessLogic.update.serviceClassName})) private readonly ${updateServiceClassName}: ${schemaMeta.businessLogic.update.serviceClassName}`,
43
- `@Inject(forwardRef(() => ${schemaMeta.businessLogic.view.serviceClassName})) private readonly ${viewServiceClassName}: ${schemaMeta.businessLogic.view.serviceClassName}`,
53
+ `@Inject(forwardRef(() => ${schemaMeta.businessLogic.update.serviceClassName})) private readonly updateService: ${schemaMeta.businessLogic.update.serviceClassName}`,
54
+ `@Inject(forwardRef(() => ${schemaMeta.businessLogic.view.serviceClassName})) private readonly viewService: ${schemaMeta.businessLogic.view.serviceClassName}`,
44
55
  ];
45
- const methodTypeSignatures = (0, repository_generator_1.getRepositoryMethodsTypeSignatures)({ model, meta });
56
+ const { zodCreateObject, zodUpdateObject, zodUpsertObject } = meta.businessLogic.update;
46
57
  return /* ts */ `
47
- import { Inject, Injectable, forwardRef } from '@nestjs/common'
48
- import { ExhaustiveSwitchCheck } from '@backend/common'
49
-
50
- ${imports.generate()}
51
-
52
- ${actionBlocks.actionTypeDefinition}
53
-
54
- ${actionBlocks.resultMap}
55
-
56
- ${actionBlocks.typeDefinitionWithCreateFunction}
57
-
58
- @Injectable()
59
- export class ${meta.businessLogic.update.serviceClassName} {
60
-
61
- /**
62
- * Instance of the ${meta.userFriendlyName} view service for convenience.
63
- */
64
- private view: ${meta.businessLogic.view.serviceClassName}
65
-
66
- constructor(${constructorParameters.join(',\n')}) {
67
- this.view = this.${viewServiceClassName}.${meta.businessLogic.view.serviceVariableName}
68
- }
69
-
70
- ${actionBlocks.dispatcher}
71
-
72
- ${(0, jsdoc_1.toJsDocComment)(methodTypeSignatures.create.jsDoc)}
73
- public async create(
74
- { item, execution }: ${methodTypeSignatures.create.parameters[0]}
75
- ): ${methodTypeSignatures.create.returnType} {
76
- return this.${modelRepositoryVariableName}.create({ item, execution })
77
- }
78
-
79
-
80
- ${(0, jsdoc_1.toJsDocComment)(methodTypeSignatures.createMany.jsDoc)}
81
- public async createMany(
82
- { items, execution }: ${methodTypeSignatures.createMany.parameters[0]}
83
- ): ${methodTypeSignatures.createMany.returnType} {
84
- return this.${modelRepositoryVariableName}.createMany({ items, execution })
85
- }
86
-
87
- ${(0, jsdoc_1.toJsDocComment)(methodTypeSignatures.update.jsDoc)}
88
- public async update(
89
- { item, execution }: ${methodTypeSignatures.update.parameters[0]}
90
- ): ${methodTypeSignatures.update.returnType} {
91
- return this.${modelRepositoryVariableName}.update({ item, execution })
92
- }
93
-
94
- ${(0, jsdoc_1.toJsDocComment)(methodTypeSignatures.updateMany.jsDoc)}
95
- public async updateMany(
96
- { items, execution }: ${methodTypeSignatures.updateMany.parameters[0]}
97
- ): ${methodTypeSignatures.updateMany.returnType} {
98
- return this.${modelRepositoryVariableName}.updateMany({ items, execution })
99
- }
100
-
101
- ${(0, jsdoc_1.toJsDocComment)(methodTypeSignatures.upsert.jsDoc)}
102
- public async upsert(
103
- { item, execution }: ${methodTypeSignatures.upsert.parameters[0]}
104
- ): ${methodTypeSignatures.upsert.returnType} {
105
- return this.${modelRepositoryVariableName}.upsert({ item, execution })
106
- }
107
-
108
- ${(0, jsdoc_1.toJsDocComment)(methodTypeSignatures.upsertMany.jsDoc)}
109
- public async upsertMany(
110
- { items, execution }: ${methodTypeSignatures.upsertMany.parameters[0]}
111
- ): ${methodTypeSignatures.upsertMany.returnType} {
112
- return this.${modelRepositoryVariableName}.upsertMany({ items, execution })
113
- }
114
-
115
- ${(0, jsdoc_1.toJsDocComment)(methodTypeSignatures.delete.jsDoc)}
116
- public async delete(
117
- { id, execution }: ${methodTypeSignatures.delete.parameters[0]}
118
- ): ${methodTypeSignatures.delete.returnType} {
119
- return this.${modelRepositoryVariableName}.delete({ id, execution })
120
- }
121
-
122
- ${(0, jsdoc_1.toJsDocComment)(methodTypeSignatures.deleteMany.jsDoc)}
123
- public async deleteMany(
124
- { ids, execution }: ${methodTypeSignatures.deleteMany.parameters[0]}
125
- ): ${methodTypeSignatures.deleteMany.returnType} {
126
- return this.${modelRepositoryVariableName}.deleteMany({ ids, execution })
127
- }
128
-
129
- }`;
130
- }
131
- exports.generateModelBusinessLogicUpdate = generateModelBusinessLogicUpdate;
132
- function generateActionsBuildingBlocks({ model, meta }) {
133
- const actionTypeDefinition = [];
134
- const resultMap = [];
135
- const typeDefinitionWithCreateFunction = [];
136
- const importTypes = [];
137
- const dispatcher = [];
138
- const schemaMeta = (0, meta_1.getSchemaMetadata)({ config: model.schemaConfig });
139
- const actionDefinitions = prepareActionDefinitions({ model, meta });
140
- for (const [type, config] of Object.entries(actionDefinitions)) {
141
- const def = generateAction({ model, meta, type: type, config });
142
- actionTypeDefinition.push(def.actionName),
143
- resultMap.push(def.resultMap),
144
- typeDefinitionWithCreateFunction.push(def.typeDefinition, def.createFunction, ''),
145
- importTypes.push(...def.importTypes),
146
- dispatcher.push(def.dispatchCaseExpression);
58
+ import { Inject, Injectable, forwardRef } from '@nestjs/common'
59
+ import { ExhaustiveSwitchCheck, UnionOmit } from '@backend/common'
60
+ import { z } from 'zod'
61
+
62
+ ${imports.generate()}
63
+
64
+ export type Scope = "${meta.actions.actionScopeConstType}"
65
+
66
+
67
+
68
+ /**
69
+ * Zod decoder for validating the create input of a ${meta.userFriendlyName}.
70
+ */
71
+ export const ${zodCreateObject} = z.object({
72
+ ${model.fields
73
+ .filter((f) => !f.attributes.isReadonly)
74
+ .map((f) => `${f.name}: z.${(0, zod_1.getZodDecoderDefinition)({ field: f })}`)
75
+ .join(',')}
76
+ })
77
+
78
+ /**
79
+ * Zod decoder for validating the update input of a ${meta.userFriendlyName} .
80
+ */
81
+ export const ${zodUpdateObject} = z.object({
82
+ ${model.fields
83
+ .filter((f) => !f.attributes.isReadonly || f.kind === 'id')
84
+ .map((f) => `${f.name}: z.${(0, zod_1.getZodDecoderDefinition)({ field: f, allowAnyOptionalField: f.kind !== 'id' })}`)
85
+ .join(',')}
86
+ })
87
+
88
+ /**
89
+ * Zod decoder for validating the upsert input of a ${meta.userFriendlyName} .
90
+ */
91
+ export const ${zodUpsertObject} = z.union([${zodUpdateObject}, ${zodCreateObject}])
92
+
93
+ export type Actions = {
94
+ ${(0, jsdoc_1.toJsDocComment)([`Creates a new ${meta.userFriendlyName} and returns it.`])}
95
+ create: {
96
+ payload: z.infer<typeof ${zodCreateObject}>
97
+ result: ${meta.types.typeName}
98
+ }
99
+
100
+ ${(0, jsdoc_1.toJsDocComment)([`Creates multiple new ${meta.userFriendlyNamePlural} and returns them.`])}
101
+ createMany: {
102
+ payload: z.infer<typeof ${zodCreateObject}>[]
103
+ result: ${meta.types.typeName}[]
104
+ }
105
+
106
+ ${(0, jsdoc_1.toJsDocComment)([`Updates a ${meta.userFriendlyName} and returns it.`])}
107
+ update: {
108
+ payload: z.infer<typeof ${zodUpdateObject}>
109
+ result: ${meta.types.typeName}
110
+ }
111
+
112
+ ${(0, jsdoc_1.toJsDocComment)([`Updates multiple ${meta.userFriendlyNamePlural} and returns them.`])}
113
+ updateMany: {
114
+ payload: z.infer<typeof ${zodUpdateObject}>[]
115
+ result: ${meta.types.typeName}[]
116
+ }
117
+
118
+ ${(0, jsdoc_1.toJsDocComment)([`Creates or updates a ${meta.userFriendlyName} and returns it.`])}
119
+ upsert: {
120
+ payload: z.infer<typeof ${zodUpsertObject}>
121
+ result: ${meta.types.typeName}
122
+ }
123
+
124
+ ${(0, jsdoc_1.toJsDocComment)([`Creates or updates multiple ${meta.userFriendlyNamePlural} and returns them.`])}
125
+ upsertMany: {
126
+ payload: z.infer<typeof ${zodUpsertObject}>[]
127
+ result: ${meta.types.typeName}[]
128
+ }
129
+
130
+ ${(0, jsdoc_1.toJsDocComment)([`Deletes a ${meta.userFriendlyName} and returns its id.`])}
131
+ delete: {
132
+ payload: ${model.brandedIdType}
133
+ result: ${model.brandedIdType}
134
+ }
135
+
136
+ ${(0, jsdoc_1.toJsDocComment)([`Deletes multiple ${meta.userFriendlyNamePlural} and returns their ids.`])}
137
+ deleteMany: {
138
+ payload: ${model.brandedIdType}[]
139
+ result: ${model.brandedIdType}[]
140
+ }
147
141
  }
148
- return {
149
- importTypes,
150
- actionTypeDefinition: `export type Action_${meta.businessLogic.update.actionNameModelPart} = ${actionTypeDefinition.join(' | ')}`,
151
- resultMap: `export type ActionResult_${meta.businessLogic.update.actionNameModelPart} = {
152
- ${resultMap.join('\n')}
153
- }`,
154
- typeDefinitionWithCreateFunction: `${typeDefinitionWithCreateFunction.join('\n')}`,
155
- dispatcher: `
156
- public async dispatch<A extends Action_${meta.businessLogic.update.actionNameModelPart}>({ action, execution }: {
157
- action: A;
158
- execution: ${schemaMeta.actions.actionExecution.interface}
159
- }) {
142
+
143
+ @Injectable()
144
+ export class ${meta.businessLogic.update.serviceClassName} implements ${dispatcher.interface}<Scope, Actions> {
145
+ /**
146
+ * Instance of the ${meta.userFriendlyName} view service for convenience.
147
+ */
148
+ private view: ${meta.businessLogic.view.serviceClassName}
149
+
150
+ constructor(${constructorParameters.join(',\n')}) {
151
+ this.view = this.viewService.${meta.businessLogic.view.serviceVariableName}
152
+ }
153
+
154
+ /**
155
+ * Dispatches an action to the appropriate method of the repository.
156
+ */
157
+ public async dispatch<A extends ${dispatcher.actionMethod}<Scope, Actions>>({
158
+ action,
159
+ execution,
160
+ }: {
161
+ action: UnionOmit<A, 'result'>
162
+ execution: ${schemaMeta.actions.actionExecution.interface}
163
+ }): Promise<A['result']> {
160
164
  switch (action.type) {
161
- ${dispatcher.join('\n')}
162
- default: {
165
+ case 'create':
166
+ return this.data.create({ item: action.payload, execution })
167
+
168
+ case 'createMany':
169
+ return this.data.createMany({ items: action.payload, execution })
170
+
171
+ case 'update':
172
+ return this.data.update({ item: action.payload, execution })
173
+
174
+ case 'updateMany':
175
+ return this.data.updateMany({ items: action.payload, execution })
176
+
177
+ case 'upsert':
178
+ return this.data.upsert({ item: action.payload, execution })
179
+
180
+ case 'upsertMany':
181
+ return this.data.upsertMany({ items: action.payload, execution })
182
+
183
+ case 'delete':
184
+ return this.data.delete({ id: action.payload, execution })
185
+
186
+ case 'deleteMany':
187
+ return this.data.deleteMany({ ids: action.payload, execution })
188
+
189
+ default:
163
190
  throw new ExhaustiveSwitchCheck(action)
164
- }
191
+
165
192
  }
166
- }`,
167
- };
168
- }
169
- function prepareActionDefinitions({ model, meta, }) {
170
- return {
171
- create: {
172
- actionName: `Action_${meta.businessLogic.update.actionNameModelPart}_Create`,
173
- createFunctionName: meta.businessLogic.update.createActionFunctionNameCreate,
174
- payload: meta.types.dto.create,
175
- resultType: meta.types.typeName,
176
- imports: [(0, types_1.toAnnotatedTypeName)(meta.types.dto.create)],
177
- dispatcherParameterName: 'item',
178
- },
179
- createMany: {
180
- actionName: `Action_${meta.businessLogic.update.actionNameModelPart}_CreateMany`,
181
- createFunctionName: meta.businessLogic.update.createActionFunctionNameCreateMany,
182
- payload: `${meta.types.dto.create}[]`,
183
- resultType: `${meta.types.typeName}[]`,
184
- imports: [(0, types_1.toAnnotatedTypeName)(meta.types.dto.create)],
185
- dispatcherParameterName: 'items',
186
- },
187
- update: {
188
- actionName: `Action_${meta.businessLogic.update.actionNameModelPart}_Update`,
189
- createFunctionName: meta.businessLogic.update.createActionFunctionNameUpdate,
190
- payload: meta.types.dto.update,
191
- resultType: meta.types.typeName,
192
- imports: [(0, types_1.toAnnotatedTypeName)(meta.types.dto.update)],
193
- dispatcherParameterName: 'item',
194
- },
195
- updateMany: {
196
- actionName: `Action_${meta.businessLogic.update.actionNameModelPart}_UpdateMany`,
197
- createFunctionName: meta.businessLogic.update.createActionFunctionNameUpdateMany,
198
- payload: `${meta.types.dto.update}[]`,
199
- resultType: `${meta.types.typeName}[]`,
200
- imports: [(0, types_1.toAnnotatedTypeName)(meta.types.dto.update)],
201
- dispatcherParameterName: 'items',
202
- },
203
- upsert: {
204
- actionName: `Action_${meta.businessLogic.update.actionNameModelPart}_Upsert`,
205
- createFunctionName: meta.businessLogic.update.createActionFunctionNameUpsert,
206
- payload: meta.types.dto.upsert,
207
- resultType: meta.types.typeName,
208
- imports: [(0, types_1.toAnnotatedTypeName)(meta.types.dto.upsert)],
209
- dispatcherParameterName: 'item',
210
- },
211
- upsertMany: {
212
- actionName: `Action_${meta.businessLogic.update.actionNameModelPart}_UpsertMany`,
213
- createFunctionName: meta.businessLogic.update.createActionFunctionNameUpsertMany,
214
- payload: `${meta.types.dto.upsert}[]`,
215
- resultType: `${meta.types.typeName}[]`,
216
- imports: [(0, types_1.toAnnotatedTypeName)(meta.types.dto.upsert)],
217
- dispatcherParameterName: 'items',
218
- },
219
- delete: {
220
- actionName: `Action_${meta.businessLogic.update.actionNameModelPart}_Delete`,
221
- createFunctionName: meta.businessLogic.update.createActionFunctionNameDelete,
222
- payload: model.brandedIdType,
223
- resultType: model.brandedIdType,
224
- imports: [(0, types_1.toAnnotatedTypeName)(model.brandedIdType)],
225
- dispatcherParameterName: 'id',
226
- },
227
- deleteMany: {
228
- actionName: `Action_${meta.businessLogic.update.actionNameModelPart}_DeleteMany`,
229
- createFunctionName: meta.businessLogic.update.createActionFunctionNameDeleteMany,
230
- payload: `${model.brandedIdType}[]`,
231
- resultType: `${model.brandedIdType}[]`,
232
- imports: [(0, types_1.toAnnotatedTypeName)(model.brandedIdType)],
233
- dispatcherParameterName: 'ids',
234
- },
235
- };
236
- }
237
- function generateAction({ meta, type, config: { imports, actionName, payload, createFunctionName, resultType, dispatcherParameterName }, }) {
238
- return {
239
- actionName,
240
- actionType: type,
241
- importTypes: imports,
242
- resultMap: `${type}: ${resultType}`,
243
- typeDefinition: `
244
- export type ${actionName} = { scope: '${meta.actions.actionScopeConstType}'; type: '${type}'; payload: ${payload} }`,
245
- createFunction: `
246
- export function ${createFunctionName}(payload: ${payload}): ${actionName} {
247
- return { scope: '${meta.actions.actionScopeConstType}', type: '${type}', payload }
248
- }`,
249
- dispatchCaseExpression: `
250
- case '${type}':
251
- return this.${type}({ ${dispatcherParameterName}: action.payload, execution })`,
252
- };
193
+ }
194
+ }
195
+ `;
253
196
  }
197
+ exports.generateModelBusinessLogicUpdate = generateModelBusinessLogicUpdate;
@@ -5,7 +5,9 @@ const imports_1 = require("../../lib/imports");
5
5
  const meta_1 = require("../../lib/meta");
6
6
  const fields_1 = require("../../lib/schema/fields");
7
7
  const types_1 = require("../../lib/schema/types");
8
+ const types_2 = require("../../lib/types");
8
9
  const ast_1 = require("../../lib/utils/ast");
10
+ const jsdoc_1 = require("../../lib/utils/jsdoc");
9
11
  /**
10
12
  * Generates view business logic for a given model.
11
13
  * The view logic exposes all information and links of a model. See template's readme for more info.
@@ -44,24 +46,30 @@ function generateModelBusinessLogicView({ model, meta }) {
44
46
  const refMeta = (0, meta_1.getModelMetadata)({ model: refModel });
45
47
  const variableGetter = `await this.${viewServiceClassName}.${refMeta.businessLogic.view.serviceVariableName}.get(itemRaw.${relation.name})`;
46
48
  const variablePresenceCheck = `
47
- if (!${relation.relatedModelBacklinkFieldName}) {
49
+ if (!${relation.relationFieldName}) {
48
50
  throw new Error(\`Could not find ${refMeta.types.typeName} with id \${itemRaw.${relation.name}} for ${model.typeName}.${relation.name}!\`)
49
51
  }
50
52
  `;
51
- const relationVariableName = relation.relatedModelBacklinkFieldName;
53
+ const relationVariableName = relation.relationFieldName;
54
+ const relationVariableDefinition = relation.isRequired
55
+ ? `${variableGetter};${variablePresenceCheck}`
56
+ : `itemRaw.${relation.name} !== null ? ${variableGetter} : null`;
52
57
  variables.set(relation.name, {
53
58
  variableName: relationVariableName,
54
- variableDefinition: `
55
- const ${relationVariableName} = ${relation.isRequired
56
- ? `${variableGetter};${variablePresenceCheck}`
57
- : `itemRaw.${relation.name} !== null ? ${variableGetter} : null`}
58
- `,
59
+ variableDefinition: `const ${relationVariableName} = ${relationVariableDefinition}`,
59
60
  });
61
+ if (relation.relationToModel.typeName !== model.typeName) {
62
+ imports.addImport({
63
+ items: [refMeta.types.toBrandedIdTypeFnName],
64
+ from: refMeta.types.filePath,
65
+ });
66
+ imports.addTypeImport({
67
+ items: [refModel.brandedIdType, refMeta.types.typeName],
68
+ from: refMeta.types.filePath,
69
+ });
70
+ }
60
71
  }
61
72
  const hasLinkedItems = variables.size > 0;
62
- if (hasLinkedItems) {
63
- imports.addTypeImport({ from: meta.types.importPath, items: [meta.types.linkedTypeName] });
64
- }
65
73
  const linkedItemsGetterFn = `
66
74
  /**
67
75
  * Returns the linked ${meta.userFriendlyName} with the given id or null if it does not exist.
@@ -92,6 +100,16 @@ function generateModelBusinessLogicView({ model, meta }) {
92
100
 
93
101
  return item
94
102
  }
103
+ `;
104
+ const linkedTypeDefinition = `
105
+ export type ${meta.types.linkedTypeName} = {
106
+ ${model.fields
107
+ .map((f) => `
108
+ ${(0, jsdoc_1.getFieldComment)(f)}
109
+ ${getLinkedFieldType(f)}${f.isRequired ? '' : ' | null'}
110
+ `)
111
+ .join('\n')}
112
+ }
95
113
  `;
96
114
  return /* ts */ `
97
115
  /* eslint-disable @typescript-eslint/no-unused-vars */
@@ -100,6 +118,8 @@ import { FilterOperator } from '@backend/common'
100
118
 
101
119
  ${imports.generate()}
102
120
 
121
+ ${hasLinkedItems ? linkedTypeDefinition : ''}
122
+
103
123
  @Injectable()
104
124
  export class ${meta.businessLogic.view.serviceClassName} {
105
125
  constructor(${constructorParameters.join(',\n')}) {}
@@ -253,3 +273,20 @@ function compare(a: ${model.typeName}, b: ${model.typeName}, field: keyof ${mode
253
273
 
254
274
  `;
255
275
  }
276
+ /**
277
+ * Converts a field to a TypeScript type definition with linked fields.
278
+ */
279
+ function getLinkedFieldType(f) {
280
+ switch (f.kind) {
281
+ case 'enum':
282
+ return `${f.name}: ${f.typeName}`;
283
+ case 'relation':
284
+ return `${f.relationFieldName}: ${f.relationToModel.typeName}`;
285
+ case 'id':
286
+ return `${f.name}: ${f.model.brandedIdType}`;
287
+ case 'scalar':
288
+ return `${f.name}: ${f.tsTypeName}`;
289
+ default:
290
+ throw new types_2.ExhaustiveSwitchCheck(f);
291
+ }
292
+ }
@@ -9,28 +9,18 @@ const types_1 = require("../../lib/schema/types");
9
9
  */
10
10
  function generateRoute({ model, meta }) {
11
11
  const { idField, defaultField } = model;
12
+ const { scopeName, dataRepositoryVariableName } = meta.businessLogic;
12
13
  const defaultValueMethod = `
13
- getDefault: procedure.query(({ ctx }) => ctx.view.${meta.data.dataServiceName}.${meta.businessLogic.dataRepositoryVariableName}.defaultValue),
14
+ getDefault: procedure.query(({ ctx }) => ctx.view.${meta.data.dataServiceName}.${dataRepositoryVariableName}.defaultValue),
14
15
  `;
16
+ const { zodCreateObject, zodUpdateObject, zodUpsertObject } = meta.businessLogic.update;
15
17
  const imports = imports_1.ImportsGenerator.from(meta.trpc.routerFilePath).addImports({
16
18
  [meta.types.importPath]: [
17
19
  (0, types_1.toAnnotatedTypeName)(model.typeName),
18
20
  meta.types.toBrandedIdTypeFnName,
19
- meta.types.zodDecoderFnNames.createObject,
20
- meta.types.zodDecoderFnNames.updateObject,
21
- meta.types.zodDecoderFnNames.upsertObject,
22
21
  meta.types.zodDecoderFnNames.id,
23
22
  ],
24
- [meta.businessLogic.importPath]: [
25
- meta.businessLogic.update.createActionFunctionNameCreate,
26
- meta.businessLogic.update.createActionFunctionNameCreateMany,
27
- meta.businessLogic.update.createActionFunctionNameUpdate,
28
- meta.businessLogic.update.createActionFunctionNameUpdateMany,
29
- meta.businessLogic.update.createActionFunctionNameUpsert,
30
- meta.businessLogic.update.createActionFunctionNameUpsertMany,
31
- meta.businessLogic.update.createActionFunctionNameDelete,
32
- meta.businessLogic.update.createActionFunctionNameDeleteMany,
33
- ],
23
+ [meta.businessLogic.update.serviceFilePath]: [zodCreateObject, zodUpdateObject, zodUpsertObject],
34
24
  });
35
25
  return /* ts */ `
36
26
  import { z } from 'zod'
@@ -71,30 +61,37 @@ export const ${meta.trpc.routerName} = router({
71
61
  return ctx.view.${meta.data.dataServiceName}.getList(input)
72
62
  }),
73
63
 
74
- create: procedure.input(${meta.types.zodDecoderFnNames.createObject})
75
- .mutation(({ input, ctx }) => ctx.dispatch(${meta.businessLogic.update.createActionFunctionNameCreate}(input))),
64
+ create: procedure
65
+ .input(${zodCreateObject})
66
+ .mutation(({ input, ctx }) => ctx.dispatch({scope: "${scopeName}", type: "create", payload: input})),
76
67
 
77
- createMany: procedure.input(z.array(${meta.types.zodDecoderFnNames.createObject}))
78
- .mutation(({ input, ctx }) => ctx.dispatch(${meta.businessLogic.update.createActionFunctionNameCreateMany}(input))),
68
+ createMany: procedure
69
+ .input(z.array(${zodCreateObject}))
70
+ .mutation(({ input, ctx }) => ctx.dispatch({scope: "${scopeName}", type: "createMany", payload: input})),
79
71
 
80
- update: procedure.input(${meta.types.zodDecoderFnNames.updateObject})
81
- .mutation(({ input, ctx }) => ctx.dispatch(${meta.businessLogic.update.createActionFunctionNameUpdate}(input))),
72
+ update: procedure
73
+ .input(${zodUpdateObject})
74
+ .mutation(({ input, ctx }) => ctx.dispatch({scope: "${scopeName}", type: "update", payload: input})),
82
75
 
83
- updateMany: procedure.input(z.array(${meta.types.zodDecoderFnNames.updateObject}))
84
- .mutation(({ input, ctx }) => ctx.dispatch(${meta.businessLogic.update.createActionFunctionNameUpdateMany}(input))),
76
+ updateMany: procedure
77
+ .input(z.array(${zodUpdateObject}))
78
+ .mutation(({ input, ctx }) => ctx.dispatch({scope: "${scopeName}", type: "updateMany", payload: input})),
85
79
 
86
- upsert: procedure.input(${meta.types.zodDecoderFnNames.upsertObject})
87
- .mutation(({ input, ctx }) => ctx.dispatch(${meta.businessLogic.update.createActionFunctionNameUpsert}(input))),
80
+ upsert: procedure
81
+ .input(${zodUpsertObject})
82
+ .mutation(({ input, ctx }) => ctx.dispatch({scope: "${scopeName}", type: "upsert", payload: input})),
88
83
 
89
- upsertMany: procedure.input(z.array(${meta.types.zodDecoderFnNames.upsertObject}))
90
- .mutation(({ input, ctx }) => ctx.dispatch(${meta.businessLogic.update.createActionFunctionNameUpsertMany}(input))),
84
+ upsertMany: procedure
85
+ .input(z.array(${zodUpsertObject}))
86
+ .mutation(({ input, ctx }) => ctx.dispatch({scope: "${scopeName}", type: "upsertMany", payload: input})),
91
87
 
92
- delete: procedure.input(${meta.types.zodDecoderFnNames.id})
93
- .mutation(({ input, ctx }) => ctx.dispatch(${meta.businessLogic.update.createActionFunctionNameDelete}(input))),
88
+ delete: procedure
89
+ .input(${meta.types.zodDecoderFnNames.id})
90
+ .mutation(({ input, ctx }) => ctx.dispatch({scope: "${scopeName}", type: "delete", payload: input})),
94
91
 
95
- deleteMany: procedure.input(z.array(${meta.types.zodDecoderFnNames.id}))
96
- .mutation(({ input, ctx }) => ctx.dispatch(${meta.businessLogic.update.createActionFunctionNameDeleteMany}(input))),
97
-
92
+ deleteMany: procedure
93
+ .input(z.array(${meta.types.zodDecoderFnNames.id}))
94
+ .mutation(({ input, ctx }) => ctx.dispatch({scope: "${scopeName}", type: "deleteMany", payload: input})),
98
95
  })
99
96
  `;
100
97
  }