@postxl/generator 0.68.0 → 0.69.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 +34 -43
- package/dist/generators/indices/{datamodule.generator.d.ts → data/module.generator.d.ts} +2 -2
- package/dist/generators/indices/{datamodule.generator.js → data/module.generator.js} +4 -5
- package/dist/generators/indices/{dataservice.generator.d.ts → data/service.generator.d.ts} +2 -2
- package/dist/generators/indices/{dataservice.generator.js → data/service.generator.js} +5 -5
- package/dist/generators/indices/{data-types.generator.d.ts → data/types.generator.d.ts} +2 -2
- package/dist/generators/indices/{data-types.generator.js → data/types.generator.js} +2 -2
- package/dist/generators/indices/{importexport-convert-import-functions.generator.d.ts → import-export/importexport-convert-import-functions.generator.d.ts} +2 -2
- package/dist/generators/indices/{importexport-convert-import-functions.generator.js → import-export/importexport-convert-import-functions.generator.js} +4 -26
- package/dist/generators/indices/{importexport-exporter-class.generator.d.ts → import-export/importexport-exporter-class.generator.d.ts} +2 -2
- package/dist/generators/indices/{importexport-exporter-class.generator.js → import-export/importexport-exporter-class.generator.js} +4 -5
- package/dist/generators/indices/{importexport-import-service.generator.d.ts → import-export/importexport-import-service.generator.d.ts} +2 -2
- package/dist/generators/indices/{importexport-import-service.generator.js → import-export/importexport-import-service.generator.js} +4 -4
- package/dist/generators/indices/{importexport-types.generator.d.ts → import-export/importexport-types.generator.d.ts} +2 -2
- package/dist/generators/indices/{importexport-types.generator.js → import-export/importexport-types.generator.js} +2 -2
- package/dist/generators/indices/types.generator.js +13 -1
- package/dist/generators/indices/{businesslogic-actiontypes.generator.d.ts → update/actiontypes.generator.d.ts} +2 -2
- package/dist/generators/indices/{businesslogic-actiontypes.generator.js → update/actiontypes.generator.js} +3 -3
- package/dist/generators/indices/{businesslogic-update-module.generator.d.ts → update/module.generator.d.ts} +2 -2
- package/dist/generators/indices/{businesslogic-update-module.generator.js → update/module.generator.js} +2 -2
- package/dist/generators/indices/{businesslogic-update-service.generator.d.ts → update/service.generator.d.ts} +2 -2
- package/dist/generators/indices/{businesslogic-update-service.generator.js → update/service.generator.js} +2 -2
- package/dist/generators/indices/{businesslogic-view-module.generator.d.ts → view/module.generator.d.ts} +2 -2
- package/dist/generators/indices/{businesslogic-view-module.generator.js → view/module.generator.js} +2 -2
- package/dist/generators/indices/{businesslogic-view-service.generator.d.ts → view/service.generator.d.ts} +2 -2
- package/dist/generators/indices/{businesslogic-view-service.generator.js → view/service.generator.js} +2 -2
- package/dist/generators/models/repository.generator.d.ts +0 -46
- package/dist/generators/models/repository.generator.js +348 -796
- package/dist/generators/models/route.generator.js +2 -2
- package/dist/generators/models/types.generator.js +27 -2
- package/dist/generators/models/{businesslogic-update.generator.d.ts → update/service.generator.d.ts} +2 -2
- package/dist/generators/models/update/service.generator.js +252 -0
- package/dist/generators/models/{businesslogic-view.generator.d.ts → view/service.generator.d.ts} +2 -2
- package/dist/generators/models/{businesslogic-view.generator.js → view/service.generator.js} +12 -18
- package/dist/lib/attributes.d.ts +0 -5
- package/dist/lib/meta.d.ts +16 -54
- package/dist/lib/meta.js +2 -18
- package/dist/prisma/attributes.js +0 -2
- package/package.json +1 -1
- package/dist/generators/indices/datamock-module.generator.d.ts +0 -9
- package/dist/generators/indices/datamock-module.generator.js +0 -64
- package/dist/generators/indices/datamocker.generator.d.ts +0 -9
- package/dist/generators/indices/datamocker.generator.js +0 -88
- package/dist/generators/indices/emptydatabasemigration.generator.d.ts +0 -11
- package/dist/generators/indices/emptydatabasemigration.generator.js +0 -34
- package/dist/generators/indices/testdata-service.generator.d.ts +0 -9
- package/dist/generators/indices/testdata-service.generator.js +0 -84
- package/dist/generators/models/businesslogic-update.generator.js +0 -324
- /package/dist/generators/models/{react.generator → react}/context.generator.d.ts +0 -0
- /package/dist/generators/models/{react.generator → react}/context.generator.js +0 -0
- /package/dist/generators/models/{react.generator → react}/index.d.ts +0 -0
- /package/dist/generators/models/{react.generator → react}/index.js +0 -0
- /package/dist/generators/models/{react.generator → react}/library.generator.d.ts +0 -0
- /package/dist/generators/models/{react.generator → react}/library.generator.js +0 -0
- /package/dist/generators/models/{react.generator → react}/lookup.generator.d.ts +0 -0
- /package/dist/generators/models/{react.generator → react}/lookup.generator.js +0 -0
- /package/dist/generators/models/{react.generator → react}/modals.generator.d.ts +0 -0
- /package/dist/generators/models/{react.generator → react}/modals.generator.js +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.generateRepository = 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");
|
|
@@ -21,29 +21,13 @@ function generateRepository({ model, meta }) {
|
|
|
21
21
|
(0, types_1.toAnnotatedTypeName)(model.typeName),
|
|
22
22
|
(0, types_1.toAnnotatedTypeName)(model.brandedIdType),
|
|
23
23
|
meta.types.toBrandedIdTypeFnName,
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
meta.types.dto.create,
|
|
25
|
+
meta.types.dto.update,
|
|
26
|
+
meta.types.dto.upsert,
|
|
27
|
+
meta.types.dto.clone,
|
|
27
28
|
],
|
|
28
29
|
[schemaMeta.actions.execution.interfaceLocation.import]: [schemaMeta.actions.execution.interface],
|
|
29
30
|
});
|
|
30
|
-
// NOTE: We first generate different parts of the code responsible for a particular task
|
|
31
|
-
// and then we combine them into the final code block.
|
|
32
|
-
//
|
|
33
|
-
// Based on the model, the repository is generated slightly differently:
|
|
34
|
-
// 1.) if the model has a default field, the repository will have a public variable "defaultValue"
|
|
35
|
-
// that is set and verified during init,
|
|
36
|
-
// 2.) if the model has a generated id, the repository will have a function "generateNextId" that
|
|
37
|
-
// is used to generate the next id. The `create` and `createMany` functions will use this function
|
|
38
|
-
// and allow being called with an id,
|
|
39
|
-
// 3.) unique string fields are ensured to be unique,
|
|
40
|
-
// 4.) max length string fields are ensured to not exceed their max length,
|
|
41
|
-
// 5.) index for fields marked with index or unique attribute,
|
|
42
|
-
// 6.) relations are indexed by the foreign key.
|
|
43
|
-
//
|
|
44
|
-
// The repository is generated differently based on whether the model is stored in the database or in memory.
|
|
45
|
-
// If the model is stored in the database, all CUD operations will result in a database call. If the model is
|
|
46
|
-
// stored in memory, all CUD operations will be performed in memory without any database calls.
|
|
47
31
|
const idBlocks = generateIdBlocks({ model, meta });
|
|
48
32
|
const defaultValueBlocks = generateDefaultBlocks({ model, meta });
|
|
49
33
|
const uniqueStringFieldsBlocks = generateUniqueFieldsBlocks({ model, meta });
|
|
@@ -51,43 +35,15 @@ function generateRepository({ model, meta }) {
|
|
|
51
35
|
const validationBlocks = generateValidationBlocks({ model, meta });
|
|
52
36
|
const indexBlocks = generateIndexBlocks({ model, schemaMeta, meta, imports });
|
|
53
37
|
const relationsBlocks = generateRelationsBlocks({ model, meta, imports });
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
uniqueStringFieldsBlocks,
|
|
62
|
-
relationsBlocks,
|
|
63
|
-
defaultValueBlocks,
|
|
64
|
-
idBlocks,
|
|
65
|
-
indexBlocks,
|
|
66
|
-
maxLengthBlocks,
|
|
67
|
-
validationBlocks,
|
|
68
|
-
},
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
else {
|
|
72
|
-
mainBlocks = generateMainBuildingBlocks_InDatabase({
|
|
73
|
-
model,
|
|
74
|
-
meta,
|
|
75
|
-
schemaMeta,
|
|
76
|
-
imports,
|
|
77
|
-
blocks: {
|
|
78
|
-
uniqueStringFieldsBlocks,
|
|
79
|
-
relationsBlocks,
|
|
80
|
-
defaultValueBlocks,
|
|
81
|
-
idBlocks,
|
|
82
|
-
indexBlocks,
|
|
83
|
-
maxLengthBlocks,
|
|
84
|
-
validationBlocks,
|
|
85
|
-
},
|
|
86
|
-
});
|
|
87
|
-
}
|
|
38
|
+
imports.addImports({
|
|
39
|
+
[meta.types.importPath]: [meta.types.zodDecoderFnNames.fromDatabase],
|
|
40
|
+
[schemaMeta.backendModules.db.databaseService.location.import]: [schemaMeta.backendModules.db.databaseService.name],
|
|
41
|
+
[schemaMeta.backendModules.db.typesImportPath]: [(0, types_1.toAnnotatedTypeName)((0, types_1.toTypeName)(`${model.sourceName} as DbType`))],
|
|
42
|
+
[(0, types_1.toPackageName)('@postxl/runtime')]: [(0, types_1.toFunctionName)('format'), (0, types_1.toFunctionName)('pluralize')],
|
|
43
|
+
});
|
|
44
|
+
const userRepositorySpecificBlocks = generateUserRepositorySpecificBlocks_InDatabase({ model, meta, imports });
|
|
88
45
|
return `
|
|
89
46
|
import { Injectable, Logger } from '@nestjs/common'
|
|
90
|
-
|
|
91
47
|
${idBlocks.libraryImports}
|
|
92
48
|
${imports.generate()}
|
|
93
49
|
|
|
@@ -108,19 +64,43 @@ export class ${meta.data.repository.className} implements Repository<${model.typ
|
|
|
108
64
|
|
|
109
65
|
${indexBlocks.nestedMapDeclarations.join('\n')}
|
|
110
66
|
|
|
111
|
-
${
|
|
67
|
+
${userRepositorySpecificBlocks.rootUserNameConst}
|
|
112
68
|
|
|
113
|
-
${
|
|
69
|
+
${userRepositorySpecificBlocks.getterBlock}
|
|
114
70
|
|
|
115
|
-
${
|
|
71
|
+
constructor(protected db: ${schemaMeta.backendModules.db.databaseService.name}) {}
|
|
116
72
|
|
|
117
|
-
|
|
73
|
+
public async init() {
|
|
74
|
+
this.data.clear()
|
|
75
|
+
|
|
76
|
+
${relationsBlocks.clearCode.join('\n')}
|
|
77
|
+
|
|
78
|
+
${uniqueStringFieldsBlocks.clearCode.join('\n')}
|
|
79
|
+
|
|
80
|
+
${defaultValueBlocks.init.resetCode}
|
|
81
|
+
|
|
82
|
+
${indexBlocks.initCode.join('\n')}
|
|
83
|
+
|
|
84
|
+
const data = await this.db.${meta.data.repository.getMethodFnName}.findMany({})
|
|
118
85
|
|
|
119
|
-
|
|
86
|
+
for (const rawItem of data) {
|
|
87
|
+
const item = this.${meta.data.repository.decoderFnName}(rawItem)
|
|
88
|
+
this.set(item)
|
|
120
89
|
|
|
121
|
-
|
|
90
|
+
${defaultValueBlocks.init.setCode}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
${idBlocks.initCode}
|
|
94
|
+
|
|
95
|
+
${defaultValueBlocks.init.checkCode}
|
|
96
|
+
|
|
97
|
+
${userRepositorySpecificBlocks.initCall}
|
|
98
|
+
|
|
99
|
+
this.logger.log(\`\${format(this.data.size)} \${pluralize('${model.typeName}', this.data.size)} loaded\`)
|
|
100
|
+
${indexBlocks.initLogCode.join('\n')}
|
|
101
|
+
}
|
|
122
102
|
|
|
123
|
-
${
|
|
103
|
+
${userRepositorySpecificBlocks.rootUserInitializeBlock}
|
|
124
104
|
|
|
125
105
|
// NOTE: The current implementation is synchronous, but it needs to be async to conform to the interface.
|
|
126
106
|
// eslint-disable-next-line @typescript-eslint/require-await
|
|
@@ -161,21 +141,254 @@ export class ${meta.data.repository.className} implements Repository<${model.typ
|
|
|
161
141
|
return this.data.size
|
|
162
142
|
}
|
|
163
143
|
|
|
164
|
-
${
|
|
144
|
+
${(0, jsdoc_1.toJsDocComment)([
|
|
145
|
+
`Checks that item has the ${idField.name} field.`,
|
|
146
|
+
`In case none exists, ${idBlocks.verifyFunctionComment}`,
|
|
147
|
+
uniqueStringFieldsBlocks.verifyFunctionComment,
|
|
148
|
+
maxLengthBlocks.verifyFunctionComment,
|
|
149
|
+
])}
|
|
150
|
+
private verifyItem(
|
|
151
|
+
item: ${idBlocks.verifyFunctionParameterType}
|
|
152
|
+
): ${idBlocks.createFunctionParameterType} {
|
|
153
|
+
${idBlocks.verifyCode}
|
|
154
|
+
|
|
155
|
+
${maxLengthBlocks.verifyCode.join('\n')}
|
|
156
|
+
|
|
157
|
+
${uniqueStringFieldsBlocks.verifyCode.join('\n')}
|
|
158
|
+
|
|
159
|
+
${validationBlocks.verifyCode.join('\n')}
|
|
160
|
+
|
|
161
|
+
return {
|
|
162
|
+
${idField.name},
|
|
163
|
+
${model.fields
|
|
164
|
+
.filter((f) => f.kind !== 'id' && !f.attributes.isReadonly)
|
|
165
|
+
.map((f) => `${f.name}: item.${f.name}`)
|
|
166
|
+
.join(',\n')}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
private toCreateItem(item: ${idBlocks.createFunctionParameterType}) {
|
|
171
|
+
return {
|
|
172
|
+
${model.fields
|
|
173
|
+
.filter((f) => !f.attributes.isReadonly || f.kind === 'id')
|
|
174
|
+
.map((f) => `${f.sourceName}: item.${f.name}`)
|
|
175
|
+
.join(',\n')},
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
${(0, jsdoc_1.toJsDocComment)([`Creates a new ${meta.userFriendlyName} and returns it.`])}
|
|
180
|
+
public async create(
|
|
181
|
+
{ item, execution }: { item: ${meta.types.dto.create}, execution: ${schemaMeta.actions.execution.interface} }
|
|
182
|
+
): Promise<${model.typeName}> {
|
|
183
|
+
const mutationId = await execution.startCreateMutation({
|
|
184
|
+
model: '${meta.actions.actionScopeConstType}',
|
|
185
|
+
createObject: item
|
|
186
|
+
})
|
|
187
|
+
|
|
188
|
+
try {
|
|
189
|
+
const newItem = this.${meta.data.repository.decoderFnName}(
|
|
190
|
+
await this.db.${meta.data.repository.getMethodFnName}.create({
|
|
191
|
+
data: this.toCreateItem(this.verifyItem(item)),
|
|
192
|
+
}),
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
this.set(newItem)
|
|
196
|
+
await execution.finishCreateMutation({ mutationId, createdObject: newItem, entityId: newItem.id })
|
|
197
|
+
return newItem
|
|
198
|
+
} catch (error) {
|
|
199
|
+
await execution.errorMutation({ mutationId, error })
|
|
200
|
+
throw error
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
${(0, jsdoc_1.toJsDocComment)([`Creates multiple new ${meta.userFriendlyNamePlural} and returns them.`])}
|
|
205
|
+
public async createMany(
|
|
206
|
+
{items, execution}: { items: ${meta.types.dto.create}[], execution: ${schemaMeta.actions.execution.interface} }
|
|
207
|
+
): Promise<${model.typeName}[]> {
|
|
208
|
+
const mutationId = await execution.startCreateManyMutation({
|
|
209
|
+
model: '${meta.actions.actionScopeConstType}',
|
|
210
|
+
createObjects: items
|
|
211
|
+
})
|
|
212
|
+
|
|
213
|
+
try {
|
|
214
|
+
const newItems = items.map((item) => this.verifyItem(item))
|
|
215
|
+
|
|
216
|
+
await this.db.${meta.data.repository.getMethodFnName}.createMany({ data: newItems.map(i => this.toCreateItem(i)) })
|
|
217
|
+
|
|
218
|
+
const dbItems = await this.db.${meta.data.repository.getMethodFnName}.findMany({
|
|
219
|
+
where: {
|
|
220
|
+
${model.idField.sourceName}: { in: newItems.map(i => i.${model.idField.name}) }
|
|
221
|
+
}
|
|
222
|
+
})
|
|
223
|
+
|
|
224
|
+
const result = dbItems.map((item) => this.${meta.data.repository.decoderFnName}(item))
|
|
225
|
+
|
|
226
|
+
for (const item of result) {
|
|
227
|
+
this.set(item)
|
|
228
|
+
}
|
|
165
229
|
|
|
166
|
-
|
|
230
|
+
await execution.finishCreateManyMutation({
|
|
231
|
+
mutationId,
|
|
232
|
+
createdObjects: result,
|
|
233
|
+
entityIds: newItems.map((i) => i.id),
|
|
234
|
+
})
|
|
235
|
+
return result
|
|
236
|
+
} catch (error) {
|
|
237
|
+
await execution.errorMutation({ mutationId, error })
|
|
238
|
+
throw error
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
${(0, jsdoc_1.toJsDocComment)([`Updates a ${meta.userFriendlyName} and returns it.`])}
|
|
243
|
+
public async update(
|
|
244
|
+
{ item, execution }: { item: ${meta.types.dto.update}, execution: ${schemaMeta.actions.execution.interface} }
|
|
245
|
+
): Promise<${model.typeName}> {
|
|
246
|
+
const existingItem = await this.get(item.${idField.name})
|
|
247
|
+
if (!existingItem) {
|
|
248
|
+
throw new Error(\`Could not update ${meta.userFriendlyName} with id \${item.id}. Not found!\`)
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
const mutationId = await execution.startUpdateMutation({
|
|
252
|
+
model: '${meta.actions.actionScopeConstType}',
|
|
253
|
+
entityId: item.id,
|
|
254
|
+
sourceObject: existingItem,
|
|
255
|
+
updateObject: item,
|
|
256
|
+
})
|
|
257
|
+
try {
|
|
258
|
+
${maxLengthBlocks.updateCode.join('\n')}
|
|
167
259
|
|
|
168
|
-
|
|
260
|
+
${uniqueStringFieldsBlocks.updateCode.join('\n')}
|
|
261
|
+
|
|
262
|
+
const newItem = this.${meta.data.repository.decoderFnName}(
|
|
263
|
+
await this.db.${meta.data.repository.getMethodFnName}.update({
|
|
264
|
+
where: {
|
|
265
|
+
${idField.sourceName}: item.${idField.name},
|
|
266
|
+
},
|
|
267
|
+
data: {
|
|
268
|
+
${[...model.fields.values()]
|
|
269
|
+
.filter((f) => f.kind !== 'id' && !f.attributes.isReadonly)
|
|
270
|
+
.map((f) => f.isRequired
|
|
271
|
+
? `${f.sourceName}: item.${f.name} ?? existingItem.${f.name}`
|
|
272
|
+
: `${f.sourceName}: item.${f.name}`)
|
|
273
|
+
.join(',\n')}
|
|
274
|
+
},
|
|
275
|
+
}),
|
|
276
|
+
)
|
|
277
|
+
|
|
278
|
+
this.remove(existingItem)
|
|
279
|
+
this.set(newItem)
|
|
280
|
+
|
|
281
|
+
await execution.finishUpdateMutation({ mutationId, updatedObject: newItem })
|
|
282
|
+
return newItem
|
|
283
|
+
} catch (error) {
|
|
284
|
+
await execution.errorMutation({ mutationId, error })
|
|
285
|
+
throw error
|
|
286
|
+
}
|
|
287
|
+
}
|
|
169
288
|
|
|
170
|
-
${
|
|
289
|
+
${(0, jsdoc_1.toJsDocComment)([`Updates multiple ${meta.userFriendlyNamePlural} and returns them.`])}
|
|
290
|
+
public async updateMany(
|
|
291
|
+
{ items, execution }: { items: ${meta.types.dto.update}[], execution: ${schemaMeta.actions.execution.interface} }
|
|
292
|
+
): Promise<${model.typeName}[]> {
|
|
293
|
+
const result: ${model.typeName}[] = []
|
|
294
|
+
for (const item of items) {
|
|
295
|
+
try {
|
|
296
|
+
const updated = await this.update({ item, execution })
|
|
297
|
+
result.push(updated)
|
|
298
|
+
} catch {
|
|
299
|
+
/* empty */
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
return result
|
|
303
|
+
}
|
|
171
304
|
|
|
172
|
-
${
|
|
305
|
+
${(0, jsdoc_1.toJsDocComment)([`Creates or updates a ${meta.userFriendlyName} and returns it.`])}
|
|
306
|
+
public async upsert(
|
|
307
|
+
{ item, execution }: { item: ${meta.types.dto.upsert}, execution: ${schemaMeta.actions.execution.interface} }
|
|
308
|
+
): Promise<${model.typeName}> {
|
|
309
|
+
const existingItem = item.${model.idField.name} ? (await this.get(item.${model.idField.name})) : null
|
|
310
|
+
if (existingItem) {
|
|
311
|
+
return this.update({ item: item as ${meta.types.dto.update}, execution })
|
|
312
|
+
} else {
|
|
313
|
+
return this.create({ item: item as ${meta.types.dto.create}, execution })
|
|
314
|
+
}
|
|
315
|
+
}
|
|
173
316
|
|
|
174
|
-
${
|
|
317
|
+
${(0, jsdoc_1.toJsDocComment)([`Creates or updates multiple ${meta.userFriendlyNamePlural} and returns them.`])}
|
|
318
|
+
public async upsertMany(
|
|
319
|
+
{ items, execution }: { items: ${meta.types.dto.upsert}[], execution: ${schemaMeta.actions.execution.interface} }
|
|
320
|
+
): Promise<${model.typeName}[]> {
|
|
321
|
+
const result: ${model.typeName}[] = []
|
|
322
|
+
for (const item of items) {
|
|
323
|
+
try {
|
|
324
|
+
const updated = await this.upsert({ item, execution })
|
|
325
|
+
result.push(updated)
|
|
326
|
+
} catch {
|
|
327
|
+
/* empty */
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
return result
|
|
331
|
+
}
|
|
175
332
|
|
|
176
|
-
${
|
|
333
|
+
${(0, jsdoc_1.toJsDocComment)([`Deletes a ${meta.userFriendlyName} and returns its id.`])}
|
|
334
|
+
public async delete(
|
|
335
|
+
{ id, execution }: { id: ${model.brandedIdType}, execution: ${schemaMeta.actions.execution.interface} }
|
|
336
|
+
): Promise<${model.brandedIdType}> {
|
|
337
|
+
const existingItem = await this.get(id)
|
|
338
|
+
if (!existingItem) {
|
|
339
|
+
throw new Error(\`Could not delete ${model.typeName} with id \${id}. Not found!\`)
|
|
340
|
+
}
|
|
177
341
|
|
|
178
|
-
|
|
342
|
+
const mutationId = await execution.startDeleteMutation({
|
|
343
|
+
model: '${meta.actions.actionScopeConstType}',
|
|
344
|
+
entityId: id,
|
|
345
|
+
sourceObject: existingItem,
|
|
346
|
+
})
|
|
347
|
+
try {
|
|
348
|
+
|
|
349
|
+
await this.db.${meta.data.repository.getMethodFnName}.delete({ where: { ${idField.sourceName}:id } })
|
|
350
|
+
|
|
351
|
+
this.remove(existingItem)
|
|
352
|
+
await execution.finishDeleteMutation({ mutationId })
|
|
353
|
+
return id
|
|
354
|
+
} catch (error) {
|
|
355
|
+
await execution.errorMutation({ mutationId, error })
|
|
356
|
+
throw error
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
${(0, jsdoc_1.toJsDocComment)([`Deletes multiple ${meta.userFriendlyNamePlural} and returns their ids.`])}
|
|
361
|
+
public async deleteMany(
|
|
362
|
+
{ ids, execution }: { ids: ${model.brandedIdType}[], execution: ${schemaMeta.actions.execution.interface} }
|
|
363
|
+
): Promise<${model.brandedIdType}[]> {
|
|
364
|
+
const deletedIds: ${model.brandedIdType}[] = []
|
|
365
|
+
for (const id of ids) {
|
|
366
|
+
try {
|
|
367
|
+
await this.delete({ id, execution })
|
|
368
|
+
deletedIds.push(id)
|
|
369
|
+
} catch {
|
|
370
|
+
/* empty */
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
return deletedIds
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
${(0, jsdoc_1.toJsDocComment)([`Creates a new ${meta.userFriendlyName} shallow clone and returns it.`])}
|
|
377
|
+
public async clone({ id, item, execution }: {
|
|
378
|
+
id: ${model.brandedIdType}
|
|
379
|
+
item: (item: ${model.typeName}) => ${meta.types.dto.clone},
|
|
380
|
+
execution: ${schemaMeta.actions.execution.interface}
|
|
381
|
+
}): Promise<${model.typeName}> {
|
|
382
|
+
const source = await this.get(id)
|
|
383
|
+
if (!source) {
|
|
384
|
+
throw new Error(\`${meta.userFriendlyName} with id \${id} not found\`)
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
388
|
+
const { id: _, ...data } = { ...source, ...item(source) }
|
|
389
|
+
|
|
390
|
+
return await this.create({ item: data, execution })
|
|
391
|
+
}
|
|
179
392
|
|
|
180
393
|
${relationsBlocks.getterFunctions.join('\n')}
|
|
181
394
|
|
|
@@ -210,575 +423,20 @@ export class ${meta.data.repository.className} implements Repository<${model.typ
|
|
|
210
423
|
${indexBlocks.removeCode.join('\n')}
|
|
211
424
|
}
|
|
212
425
|
|
|
213
|
-
|
|
426
|
+
/**
|
|
427
|
+
* Utility function that converts a given Database object to a TypeScript model instance
|
|
428
|
+
*/
|
|
429
|
+
private ${meta.data.repository.decoderFnName}(
|
|
430
|
+
item: Pick<DbType, ${model.fields.map((f) => `'${f.sourceName}'`).join(' | ')}>
|
|
431
|
+
): ${model.typeName} {
|
|
432
|
+
return ${meta.types.zodDecoderFnNames.fromDatabase}.parse({
|
|
433
|
+
${model.fields.map((f) => `${f.name}: item.${f.sourceName}`).join(',\n')}
|
|
434
|
+
})
|
|
435
|
+
}
|
|
214
436
|
}
|
|
215
437
|
`;
|
|
216
438
|
}
|
|
217
439
|
exports.generateRepository = generateRepository;
|
|
218
|
-
/**
|
|
219
|
-
* Generates a mock repository data structure for a given model: same a repository, but in memory only.
|
|
220
|
-
*/
|
|
221
|
-
function generateMockRepository({ model: modelSource, meta: metaSource, }) {
|
|
222
|
-
// We re-use the repository block, but we change the meta data to use the mock repository name and the model to be in memory only
|
|
223
|
-
const meta = Object.assign(Object.assign({}, metaSource), { data: Object.assign(Object.assign({}, metaSource.data), { repository: Object.assign(Object.assign({}, metaSource.data.repository), { className: metaSource.data.mockRepository.className, location: metaSource.data.mockRepository.location }) }) });
|
|
224
|
-
const model = Object.assign(Object.assign({}, modelSource), { attributes: Object.assign(Object.assign({}, modelSource.attributes), { inMemoryOnly: true }) });
|
|
225
|
-
return generateRepository({ model, meta });
|
|
226
|
-
}
|
|
227
|
-
exports.generateMockRepository = generateMockRepository;
|
|
228
|
-
/**
|
|
229
|
-
* Generates the main building blocks of the repository for in-memory model.
|
|
230
|
-
*/
|
|
231
|
-
function _generateMainBuildingBlocks_InMemoryOnly({ model, meta, imports, blocks, }) {
|
|
232
|
-
const methodTypeSignatures = getRepositoryMethodsTypeSignatures({ model, meta });
|
|
233
|
-
const userRepositorySpecificBlocks = generateUserRepositorySpecificBlocks_InMemoryOnly({ model, meta, imports });
|
|
234
|
-
imports.addImport({ from: (0, types_1.toPackageName)('@postxl/runtime'), items: [(0, types_1.toFunctionName)('removeUndefinedProperties')] });
|
|
235
|
-
return {
|
|
236
|
-
constructorCode: '',
|
|
237
|
-
userRepositorySpecificBlocks,
|
|
238
|
-
initCode: `
|
|
239
|
-
// NOTE: The current implementation is synchronous, but it needs to be async to conform to the interface.
|
|
240
|
-
// eslint-disable-next-line @typescript-eslint/require-await
|
|
241
|
-
public async init() {
|
|
242
|
-
this.data.clear()
|
|
243
|
-
|
|
244
|
-
${blocks.relationsBlocks.clearCode.join('\n')}
|
|
245
|
-
|
|
246
|
-
${blocks.uniqueStringFieldsBlocks.clearCode.join('\n')}
|
|
247
|
-
|
|
248
|
-
${blocks.defaultValueBlocks.init.resetCode}
|
|
249
|
-
|
|
250
|
-
${blocks.indexBlocks.initCode.join('\n')}
|
|
251
|
-
|
|
252
|
-
${userRepositorySpecificBlocks.initCall}
|
|
253
|
-
}`,
|
|
254
|
-
reInitCode: `
|
|
255
|
-
public async reInit({items, execution}: ${methodTypeSignatures.createMany.parameters[0]}): Promise<void> {
|
|
256
|
-
await this.init()
|
|
257
|
-
await this.createMany({items, execution})
|
|
258
|
-
}`,
|
|
259
|
-
deleteAllCode: `
|
|
260
|
-
public async deleteAll(): Promise<void> {
|
|
261
|
-
return this.init()
|
|
262
|
-
}`,
|
|
263
|
-
createCode: `
|
|
264
|
-
${(0, jsdoc_1.toJsDocComment)([
|
|
265
|
-
`Checks that item has the ${model.idField.name} field.`,
|
|
266
|
-
`In case none exists, ${blocks.idBlocks.verifyFunctionComment}`,
|
|
267
|
-
blocks.uniqueStringFieldsBlocks.verifyFunctionComment,
|
|
268
|
-
blocks.maxLengthBlocks.verifyFunctionComment,
|
|
269
|
-
])}
|
|
270
|
-
private verifyItem(
|
|
271
|
-
item: ${blocks.idBlocks.verifyFunctionParameterType}
|
|
272
|
-
): ${model.name} {
|
|
273
|
-
${blocks.idBlocks.verifyCode}
|
|
274
|
-
|
|
275
|
-
${blocks.maxLengthBlocks.verifyCode.join('\n')}
|
|
276
|
-
|
|
277
|
-
${blocks.uniqueStringFieldsBlocks.verifyCode.join('\n')}
|
|
278
|
-
|
|
279
|
-
${blocks.validationBlocks.verifyCode.join('\n')}
|
|
280
|
-
|
|
281
|
-
return {
|
|
282
|
-
${model.idField.name},
|
|
283
|
-
${model.fields
|
|
284
|
-
.filter((f) => f.kind !== 'id' && !f.attributes.isReadonly)
|
|
285
|
-
.map((f) => `${f.name}: item.${f.name}`)
|
|
286
|
-
.join(',\n')},
|
|
287
|
-
${model.createdAtField ? `${model.createdAtField.sourceName}: new Date(),` : ''}
|
|
288
|
-
${model.updatedAtField ? `${model.updatedAtField.sourceName}: new Date(),` : ''}
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
${(0, jsdoc_1.toJsDocComment)(methodTypeSignatures.create.jsDoc)}
|
|
293
|
-
// Non-mocked version is async - so we keep type-compatible signatures for create() and createWithId()
|
|
294
|
-
// eslint-disable-next-line @typescript-eslint/require-await, @typescript-eslint/no-unused-vars
|
|
295
|
-
public async create(
|
|
296
|
-
{ item, execution }: ${methodTypeSignatures.create.parameters[0]}
|
|
297
|
-
): ${methodTypeSignatures.create.returnType} {
|
|
298
|
-
const mutationId = await execution.startCreateMutation({
|
|
299
|
-
model: '${meta.actions.actionScopeConstType}',
|
|
300
|
-
createObject: item
|
|
301
|
-
})
|
|
302
|
-
|
|
303
|
-
try {
|
|
304
|
-
const newItem = this.verifyItem(item)
|
|
305
|
-
|
|
306
|
-
this.set(newItem)
|
|
307
|
-
await execution.finishCreateMutation({ mutationId, createdObject: newItem, entityId: newItem.id })
|
|
308
|
-
return newItem
|
|
309
|
-
} catch (error) {
|
|
310
|
-
await execution.errorMutation({ mutationId, error })
|
|
311
|
-
throw error
|
|
312
|
-
}
|
|
313
|
-
}`,
|
|
314
|
-
createManyCode: `
|
|
315
|
-
${(0, jsdoc_1.toJsDocComment)(methodTypeSignatures.createMany.jsDoc)}
|
|
316
|
-
public async createMany(
|
|
317
|
-
{ items, execution }: ${methodTypeSignatures.createMany.parameters[0]}
|
|
318
|
-
): ${methodTypeSignatures.createMany.returnType} {
|
|
319
|
-
const mutationId = await execution.startCreateManyMutation({
|
|
320
|
-
model: '${meta.actions.actionScopeConstType}',
|
|
321
|
-
createObjects: items
|
|
322
|
-
})
|
|
323
|
-
|
|
324
|
-
try {
|
|
325
|
-
const newItems = items.map((item) => this.verifyItem(item))
|
|
326
|
-
|
|
327
|
-
for (const item of newItems) {
|
|
328
|
-
this.set(item)
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
await execution.finishCreateManyMutation({
|
|
332
|
-
mutationId,
|
|
333
|
-
createdObjects: newItems,
|
|
334
|
-
entityIds: newItems.map((i) => i.id),
|
|
335
|
-
})
|
|
336
|
-
return newItems
|
|
337
|
-
} catch (error) {
|
|
338
|
-
await execution.errorMutation({ mutationId, error })
|
|
339
|
-
throw error
|
|
340
|
-
}
|
|
341
|
-
}`,
|
|
342
|
-
updateCode: `
|
|
343
|
-
${(0, jsdoc_1.toJsDocComment)(methodTypeSignatures.update.jsDoc)}
|
|
344
|
-
public async update(
|
|
345
|
-
{ item, execution }: ${methodTypeSignatures.update.parameters[0]}
|
|
346
|
-
): ${methodTypeSignatures.update.returnType} {
|
|
347
|
-
const existingItem = await this.get(item.id)
|
|
348
|
-
|
|
349
|
-
if (!existingItem) {
|
|
350
|
-
throw new Error(\`Could not update ${meta.userFriendlyName} with id \${item.id}. Not found!\`)
|
|
351
|
-
}
|
|
352
|
-
const mutationId = await execution.startUpdateMutation({
|
|
353
|
-
model: '${meta.actions.actionScopeConstType}',
|
|
354
|
-
entityId: item.id,
|
|
355
|
-
sourceObject: existingItem,
|
|
356
|
-
updateObject: item,
|
|
357
|
-
})
|
|
358
|
-
try {
|
|
359
|
-
${blocks.maxLengthBlocks.updateCode.join('\n')}
|
|
360
|
-
|
|
361
|
-
${blocks.uniqueStringFieldsBlocks.updateCode.join('\n')}
|
|
362
|
-
|
|
363
|
-
const newItem = { ...existingItem, ...removeUndefinedProperties(item) }
|
|
364
|
-
${model.updatedAtField ? `newItem.${model.updatedAtField.name} = new Date()` : ''}
|
|
365
|
-
|
|
366
|
-
this.remove(existingItem)
|
|
367
|
-
this.set(newItem)
|
|
368
|
-
|
|
369
|
-
await execution.finishUpdateMutation({ mutationId, updatedObject: newItem })
|
|
370
|
-
return newItem
|
|
371
|
-
} catch (error) {
|
|
372
|
-
await execution.errorMutation({ mutationId, error })
|
|
373
|
-
throw error
|
|
374
|
-
}
|
|
375
|
-
}`,
|
|
376
|
-
updateManyCode: `
|
|
377
|
-
${(0, jsdoc_1.toJsDocComment)(methodTypeSignatures.updateMany.jsDoc)}
|
|
378
|
-
public async updateMany(
|
|
379
|
-
{ items, execution }: ${methodTypeSignatures.updateMany.parameters[0]}
|
|
380
|
-
): ${methodTypeSignatures.updateMany.returnType} {
|
|
381
|
-
const result: ${model.typeName}[] = []
|
|
382
|
-
for (const item of items) {
|
|
383
|
-
try {
|
|
384
|
-
const updated = await this.update({ item, execution })
|
|
385
|
-
result.push(updated)
|
|
386
|
-
} catch {
|
|
387
|
-
/* empty */
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
return result
|
|
391
|
-
}`,
|
|
392
|
-
upsertCode: `
|
|
393
|
-
${(0, jsdoc_1.toJsDocComment)(methodTypeSignatures.upsert.jsDoc)}
|
|
394
|
-
public async upsert(
|
|
395
|
-
{ item, execution }: ${methodTypeSignatures.upsert.parameters[0]}
|
|
396
|
-
): ${methodTypeSignatures.upsert.returnType} {
|
|
397
|
-
const existingItem = item.${model.idField.name} ? (await this.get(item.${model.idField.name})) : null
|
|
398
|
-
if (existingItem) {
|
|
399
|
-
return this.update({ item: item as ${meta.types.dto.update}, execution })
|
|
400
|
-
} else {
|
|
401
|
-
return this.create({ item: item as ${meta.types.dto.create}, execution })
|
|
402
|
-
}
|
|
403
|
-
}`,
|
|
404
|
-
upsertManyCode: `
|
|
405
|
-
${(0, jsdoc_1.toJsDocComment)(methodTypeSignatures.upsertMany.jsDoc)}
|
|
406
|
-
public async upsertMany(
|
|
407
|
-
{ items, execution }: ${methodTypeSignatures.upsertMany.parameters[0]}
|
|
408
|
-
): ${methodTypeSignatures.upsertMany.returnType} {
|
|
409
|
-
const result: ${model.typeName}[] = []
|
|
410
|
-
for (const item of items) {
|
|
411
|
-
try {
|
|
412
|
-
const updated = await this.upsert({ item, execution })
|
|
413
|
-
result.push(updated)
|
|
414
|
-
} catch {
|
|
415
|
-
/* empty */
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
return result
|
|
419
|
-
}`,
|
|
420
|
-
deleteCode: `
|
|
421
|
-
${(0, jsdoc_1.toJsDocComment)(methodTypeSignatures.delete.jsDoc)}
|
|
422
|
-
public async delete(
|
|
423
|
-
{ id, execution }: ${methodTypeSignatures.delete.parameters[0]}
|
|
424
|
-
): ${methodTypeSignatures.delete.returnType} {
|
|
425
|
-
const existingItem = await this.get(id)
|
|
426
|
-
if (!existingItem) {
|
|
427
|
-
throw new Error(\`Could not delete ${model.typeName} with id \${id}. Not found!\`)
|
|
428
|
-
}
|
|
429
|
-
const mutationId = await execution.startDeleteMutation({
|
|
430
|
-
model: '${meta.actions.actionScopeConstType}',
|
|
431
|
-
entityId: id,
|
|
432
|
-
sourceObject: existingItem,
|
|
433
|
-
})
|
|
434
|
-
try {
|
|
435
|
-
this.remove(existingItem)
|
|
436
|
-
await execution.finishDeleteMutation({ mutationId })
|
|
437
|
-
return id
|
|
438
|
-
} catch (error) {
|
|
439
|
-
await execution.errorMutation({ mutationId, error })
|
|
440
|
-
throw error
|
|
441
|
-
}
|
|
442
|
-
}`,
|
|
443
|
-
deleteManyCode: `
|
|
444
|
-
${(0, jsdoc_1.toJsDocComment)(methodTypeSignatures.deleteMany.jsDoc)}
|
|
445
|
-
public async deleteMany(
|
|
446
|
-
{ ids, execution }: ${methodTypeSignatures.deleteMany.parameters[0]}
|
|
447
|
-
): ${methodTypeSignatures.deleteMany.returnType} {
|
|
448
|
-
const deletedIds: ${model.brandedIdType}[] = []
|
|
449
|
-
for (const id of ids) {
|
|
450
|
-
try {
|
|
451
|
-
await this.delete({ id, execution })
|
|
452
|
-
deletedIds.push(id)
|
|
453
|
-
} catch {
|
|
454
|
-
/* empty */
|
|
455
|
-
}
|
|
456
|
-
}
|
|
457
|
-
return deletedIds
|
|
458
|
-
}`,
|
|
459
|
-
databaseDecoderCode: ``,
|
|
460
|
-
};
|
|
461
|
-
}
|
|
462
|
-
/**
|
|
463
|
-
* Generates the methods of the repository for a model that is stored in the database.
|
|
464
|
-
*/
|
|
465
|
-
function generateMainBuildingBlocks_InDatabase({ model, meta, schemaMeta, imports, blocks, }) {
|
|
466
|
-
const decoderFunctionName = meta.data.repository.decoderFnName;
|
|
467
|
-
const { idField } = model;
|
|
468
|
-
imports.addImports({
|
|
469
|
-
[meta.types.importPath]: [meta.types.zodDecoderFnNames.fromDatabase],
|
|
470
|
-
[schemaMeta.backendModules.db.databaseService.location.import]: [schemaMeta.backendModules.db.databaseService.name],
|
|
471
|
-
[schemaMeta.backendModules.db.typesImportPath]: [(0, types_1.toAnnotatedTypeName)((0, types_1.toTypeName)(`${model.sourceName} as DbType`))],
|
|
472
|
-
[(0, types_1.toPackageName)('@postxl/runtime')]: [(0, types_1.toFunctionName)('format'), (0, types_1.toFunctionName)('pluralize')],
|
|
473
|
-
});
|
|
474
|
-
const dbTableName = [model.sourceSchemaName, model.sourceName]
|
|
475
|
-
.filter((s) => s != null)
|
|
476
|
-
.map((part) => `"${part}"`)
|
|
477
|
-
.join('.');
|
|
478
|
-
const methodTypeSignatures = getRepositoryMethodsTypeSignatures({ model, meta });
|
|
479
|
-
const userRepositorySpecificBlocks = generateUserRepositorySpecificBlocks_InDatabase({ model, meta, imports });
|
|
480
|
-
return {
|
|
481
|
-
constructorCode: `constructor(protected db: ${schemaMeta.backendModules.db.databaseService.name}) {}`,
|
|
482
|
-
userRepositorySpecificBlocks,
|
|
483
|
-
initCode: `
|
|
484
|
-
public async init() {
|
|
485
|
-
this.data.clear()
|
|
486
|
-
|
|
487
|
-
${blocks.relationsBlocks.clearCode.join('\n')}
|
|
488
|
-
|
|
489
|
-
${blocks.uniqueStringFieldsBlocks.clearCode.join('\n')}
|
|
490
|
-
|
|
491
|
-
${blocks.defaultValueBlocks.init.resetCode}
|
|
492
|
-
|
|
493
|
-
${blocks.indexBlocks.initCode.join('\n')}
|
|
494
|
-
|
|
495
|
-
const data = await this.db.${meta.data.repository.getMethodFnName}.findMany({})
|
|
496
|
-
|
|
497
|
-
for (const rawItem of data) {
|
|
498
|
-
const item = this.${decoderFunctionName}(rawItem)
|
|
499
|
-
this.set(item)
|
|
500
|
-
|
|
501
|
-
${blocks.defaultValueBlocks.init.setCode}
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
${blocks.idBlocks.initCode}
|
|
505
|
-
|
|
506
|
-
${blocks.defaultValueBlocks.init.checkCode}
|
|
507
|
-
|
|
508
|
-
${userRepositorySpecificBlocks.initCall}
|
|
509
|
-
|
|
510
|
-
this.logger.log(\`\${format(this.data.size)} \${pluralize('${model.typeName}', this.data.size)} loaded\`)
|
|
511
|
-
${blocks.indexBlocks.initLogCode.join('\n')}
|
|
512
|
-
}`,
|
|
513
|
-
reInitCode: `
|
|
514
|
-
public async reInit(
|
|
515
|
-
{ items, execution }: ${methodTypeSignatures.createMany.parameters[0]}
|
|
516
|
-
): Promise<void> {
|
|
517
|
-
if (!this.db.isTestDB) {
|
|
518
|
-
const errorMsg =
|
|
519
|
-
'ReInit() shall only be called in tests using MockRepositories or in DB configured for E2E tests!'
|
|
520
|
-
this.logger.error(errorMsg)
|
|
521
|
-
throw new Error(errorMsg)
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
await this.db.runOnlyOnTestDb(() => this.createMany({ items, execution }))
|
|
525
|
-
|
|
526
|
-
return this.init()
|
|
527
|
-
}`,
|
|
528
|
-
deleteAllCode: `
|
|
529
|
-
public async deleteAll(): Promise<void> {
|
|
530
|
-
await this.db.runOnlyOnTestDb(() => this.db.$executeRaw\`DELETE FROM ${dbTableName}\`)
|
|
531
|
-
|
|
532
|
-
return this.init()
|
|
533
|
-
}
|
|
534
|
-
`,
|
|
535
|
-
// prettier-ignore
|
|
536
|
-
createCode: `
|
|
537
|
-
${(0, jsdoc_1.toJsDocComment)([
|
|
538
|
-
`Checks that item has the ${idField.name} field.`,
|
|
539
|
-
`In case none exists, ${blocks.idBlocks.verifyFunctionComment}`,
|
|
540
|
-
blocks.uniqueStringFieldsBlocks.verifyFunctionComment,
|
|
541
|
-
blocks.maxLengthBlocks.verifyFunctionComment,
|
|
542
|
-
])}
|
|
543
|
-
private verifyItem(
|
|
544
|
-
item: ${blocks.idBlocks.verifyFunctionParameterType}
|
|
545
|
-
): ${blocks.idBlocks.createFunctionParameterType} {
|
|
546
|
-
${blocks.idBlocks.verifyCode}
|
|
547
|
-
|
|
548
|
-
${blocks.maxLengthBlocks.verifyCode.join('\n')}
|
|
549
|
-
|
|
550
|
-
${blocks.uniqueStringFieldsBlocks.verifyCode.join('\n')}
|
|
551
|
-
|
|
552
|
-
${blocks.validationBlocks.verifyCode.join('\n')}
|
|
553
|
-
|
|
554
|
-
return {
|
|
555
|
-
${idField.name},
|
|
556
|
-
${model.fields
|
|
557
|
-
.filter((f) => f.kind !== 'id' && !f.attributes.isReadonly)
|
|
558
|
-
.map((f) => `${f.name}: item.${f.name}`)
|
|
559
|
-
.join(',\n')}
|
|
560
|
-
}
|
|
561
|
-
}
|
|
562
|
-
|
|
563
|
-
private toCreateItem(item: ${blocks.idBlocks.createFunctionParameterType}) {
|
|
564
|
-
return {
|
|
565
|
-
${model.fields
|
|
566
|
-
.filter((f) => !f.attributes.isReadonly || f.kind === 'id')
|
|
567
|
-
.map((f) => `${f.sourceName}: item.${f.name}`)
|
|
568
|
-
.join(',\n')},
|
|
569
|
-
}
|
|
570
|
-
}
|
|
571
|
-
|
|
572
|
-
${(0, jsdoc_1.toJsDocComment)(methodTypeSignatures.create.jsDoc)}
|
|
573
|
-
public async create(
|
|
574
|
-
{ item, execution }: ${methodTypeSignatures.create.parameters[0]}
|
|
575
|
-
): ${methodTypeSignatures.create.returnType} {
|
|
576
|
-
const mutationId = await execution.startCreateMutation({
|
|
577
|
-
model: '${meta.actions.actionScopeConstType}',
|
|
578
|
-
createObject: item
|
|
579
|
-
})
|
|
580
|
-
|
|
581
|
-
try {
|
|
582
|
-
const newItem = this.${decoderFunctionName}(
|
|
583
|
-
await this.db.${meta.data.repository.getMethodFnName}.create({
|
|
584
|
-
data: this.toCreateItem(this.verifyItem(item)),
|
|
585
|
-
}),
|
|
586
|
-
)
|
|
587
|
-
|
|
588
|
-
this.set(newItem)
|
|
589
|
-
await execution.finishCreateMutation({ mutationId, createdObject: newItem, entityId: newItem.id })
|
|
590
|
-
return newItem
|
|
591
|
-
} catch (error) {
|
|
592
|
-
await execution.errorMutation({ mutationId, error })
|
|
593
|
-
throw error
|
|
594
|
-
}
|
|
595
|
-
}`,
|
|
596
|
-
// prettier-ignore
|
|
597
|
-
createManyCode: `
|
|
598
|
-
${(0, jsdoc_1.toJsDocComment)(methodTypeSignatures.createMany.jsDoc)}
|
|
599
|
-
public async createMany(
|
|
600
|
-
{items, execution}: ${methodTypeSignatures.createMany.parameters[0]}
|
|
601
|
-
): ${methodTypeSignatures.createMany.returnType} {
|
|
602
|
-
const mutationId = await execution.startCreateManyMutation({
|
|
603
|
-
model: '${meta.actions.actionScopeConstType}',
|
|
604
|
-
createObjects: items
|
|
605
|
-
})
|
|
606
|
-
|
|
607
|
-
try {
|
|
608
|
-
const newItems = items.map((item) => this.verifyItem(item))
|
|
609
|
-
|
|
610
|
-
await this.db.${meta.data.repository.getMethodFnName}.createMany({ data: newItems.map(i => this.toCreateItem(i)) })
|
|
611
|
-
|
|
612
|
-
const dbItems = await this.db.${meta.data.repository.getMethodFnName}.findMany({
|
|
613
|
-
where: {
|
|
614
|
-
${model.idField.sourceName}: { in: newItems.map(i => i.${model.idField.name}) }
|
|
615
|
-
}
|
|
616
|
-
})
|
|
617
|
-
|
|
618
|
-
const result = dbItems.map((item) => this.${decoderFunctionName}(item))
|
|
619
|
-
|
|
620
|
-
for (const item of result) {
|
|
621
|
-
this.set(item)
|
|
622
|
-
}
|
|
623
|
-
|
|
624
|
-
await execution.finishCreateManyMutation({
|
|
625
|
-
mutationId,
|
|
626
|
-
createdObjects: result,
|
|
627
|
-
entityIds: newItems.map((i) => i.id),
|
|
628
|
-
})
|
|
629
|
-
return result
|
|
630
|
-
} catch (error) {
|
|
631
|
-
await execution.errorMutation({ mutationId, error })
|
|
632
|
-
throw error
|
|
633
|
-
}
|
|
634
|
-
}`,
|
|
635
|
-
updateCode: `
|
|
636
|
-
${(0, jsdoc_1.toJsDocComment)(methodTypeSignatures.update.jsDoc)}
|
|
637
|
-
public async update(
|
|
638
|
-
{ item, execution }: ${methodTypeSignatures.update.parameters[0]}
|
|
639
|
-
): ${methodTypeSignatures.update.returnType} {
|
|
640
|
-
const existingItem = await this.get(item.${idField.name})
|
|
641
|
-
if (!existingItem) {
|
|
642
|
-
throw new Error(\`Could not update ${meta.userFriendlyName} with id \${item.id}. Not found!\`)
|
|
643
|
-
}
|
|
644
|
-
|
|
645
|
-
const mutationId = await execution.startUpdateMutation({
|
|
646
|
-
model: '${meta.actions.actionScopeConstType}',
|
|
647
|
-
entityId: item.id,
|
|
648
|
-
sourceObject: existingItem,
|
|
649
|
-
updateObject: item,
|
|
650
|
-
})
|
|
651
|
-
try {
|
|
652
|
-
${blocks.maxLengthBlocks.updateCode.join('\n')}
|
|
653
|
-
|
|
654
|
-
${blocks.uniqueStringFieldsBlocks.updateCode.join('\n')}
|
|
655
|
-
|
|
656
|
-
const newItem = this.${decoderFunctionName}(
|
|
657
|
-
await this.db.${meta.data.repository.getMethodFnName}.update({
|
|
658
|
-
where: {
|
|
659
|
-
${idField.sourceName}: item.${idField.name},
|
|
660
|
-
},
|
|
661
|
-
data: {
|
|
662
|
-
${[...model.fields.values()]
|
|
663
|
-
.filter((f) => f.kind !== 'id' && !f.attributes.isReadonly)
|
|
664
|
-
.map((f) => f.isRequired
|
|
665
|
-
? `${f.sourceName}: item.${f.name} ?? existingItem.${f.name}`
|
|
666
|
-
: `${f.sourceName}: item.${f.name}`)
|
|
667
|
-
.join(',\n')}
|
|
668
|
-
},
|
|
669
|
-
}),
|
|
670
|
-
)
|
|
671
|
-
|
|
672
|
-
this.remove(existingItem)
|
|
673
|
-
this.set(newItem)
|
|
674
|
-
|
|
675
|
-
await execution.finishUpdateMutation({ mutationId, updatedObject: newItem })
|
|
676
|
-
return newItem
|
|
677
|
-
} catch (error) {
|
|
678
|
-
await execution.errorMutation({ mutationId, error })
|
|
679
|
-
throw error
|
|
680
|
-
}
|
|
681
|
-
}`,
|
|
682
|
-
updateManyCode: `
|
|
683
|
-
${(0, jsdoc_1.toJsDocComment)(methodTypeSignatures.updateMany.jsDoc)}
|
|
684
|
-
public async updateMany(
|
|
685
|
-
{ items, execution }: ${methodTypeSignatures.updateMany.parameters[0]}
|
|
686
|
-
): ${methodTypeSignatures.updateMany.returnType} {
|
|
687
|
-
const result: ${model.typeName}[] = []
|
|
688
|
-
for (const item of items) {
|
|
689
|
-
try {
|
|
690
|
-
const updated = await this.update({ item, execution })
|
|
691
|
-
result.push(updated)
|
|
692
|
-
} catch {
|
|
693
|
-
/* empty */
|
|
694
|
-
}
|
|
695
|
-
}
|
|
696
|
-
return result
|
|
697
|
-
}`,
|
|
698
|
-
upsertCode: `
|
|
699
|
-
${(0, jsdoc_1.toJsDocComment)(methodTypeSignatures.upsert.jsDoc)}
|
|
700
|
-
public async upsert(
|
|
701
|
-
{ item, execution }: ${methodTypeSignatures.upsert.parameters[0]}
|
|
702
|
-
): ${methodTypeSignatures.upsert.returnType} {
|
|
703
|
-
const existingItem = item.${model.idField.name} ? (await this.get(item.${model.idField.name})) : null
|
|
704
|
-
if (existingItem) {
|
|
705
|
-
return this.update({ item: item as ${meta.types.dto.update}, execution })
|
|
706
|
-
} else {
|
|
707
|
-
return this.create({ item: item as ${meta.types.dto.create}, execution })
|
|
708
|
-
}
|
|
709
|
-
}`,
|
|
710
|
-
upsertManyCode: `
|
|
711
|
-
${(0, jsdoc_1.toJsDocComment)(methodTypeSignatures.upsertMany.jsDoc)}
|
|
712
|
-
public async upsertMany(
|
|
713
|
-
{ items, execution }: ${methodTypeSignatures.upsertMany.parameters[0]}
|
|
714
|
-
): ${methodTypeSignatures.upsertMany.returnType} {
|
|
715
|
-
const result: ${model.typeName}[] = []
|
|
716
|
-
for (const item of items) {
|
|
717
|
-
try {
|
|
718
|
-
const updated = await this.upsert({ item, execution })
|
|
719
|
-
result.push(updated)
|
|
720
|
-
} catch {
|
|
721
|
-
/* empty */
|
|
722
|
-
}
|
|
723
|
-
}
|
|
724
|
-
return result
|
|
725
|
-
}`,
|
|
726
|
-
deleteCode: `
|
|
727
|
-
${(0, jsdoc_1.toJsDocComment)(methodTypeSignatures.delete.jsDoc)}
|
|
728
|
-
public async delete(
|
|
729
|
-
{ id, execution }: ${methodTypeSignatures.delete.parameters[0]}
|
|
730
|
-
): ${methodTypeSignatures.delete.returnType} {
|
|
731
|
-
const existingItem = await this.get(id)
|
|
732
|
-
if (!existingItem) {
|
|
733
|
-
throw new Error(\`Could not delete ${model.typeName} with id \${id}. Not found!\`)
|
|
734
|
-
}
|
|
735
|
-
|
|
736
|
-
const mutationId = await execution.startDeleteMutation({
|
|
737
|
-
model: '${meta.actions.actionScopeConstType}',
|
|
738
|
-
entityId: id,
|
|
739
|
-
sourceObject: existingItem,
|
|
740
|
-
})
|
|
741
|
-
try {
|
|
742
|
-
|
|
743
|
-
await this.db.${meta.data.repository.getMethodFnName}.delete({ where: { ${idField.sourceName}:id } })
|
|
744
|
-
|
|
745
|
-
this.remove(existingItem)
|
|
746
|
-
await execution.finishDeleteMutation({ mutationId })
|
|
747
|
-
return id
|
|
748
|
-
} catch (error) {
|
|
749
|
-
await execution.errorMutation({ mutationId, error })
|
|
750
|
-
throw error
|
|
751
|
-
}
|
|
752
|
-
}`,
|
|
753
|
-
deleteManyCode: `
|
|
754
|
-
${(0, jsdoc_1.toJsDocComment)(methodTypeSignatures.deleteMany.jsDoc)}
|
|
755
|
-
public async deleteMany(
|
|
756
|
-
{ ids, execution }: ${methodTypeSignatures.deleteMany.parameters[0]}
|
|
757
|
-
): ${methodTypeSignatures.deleteMany.returnType} {
|
|
758
|
-
const deletedIds: ${model.brandedIdType}[] = []
|
|
759
|
-
for (const id of ids) {
|
|
760
|
-
try {
|
|
761
|
-
await this.delete({ id, execution })
|
|
762
|
-
deletedIds.push(id)
|
|
763
|
-
} catch {
|
|
764
|
-
/* empty */
|
|
765
|
-
}
|
|
766
|
-
}
|
|
767
|
-
return deletedIds
|
|
768
|
-
}`,
|
|
769
|
-
databaseDecoderCode: `
|
|
770
|
-
/**
|
|
771
|
-
* Utility function that converts a given Database object to a TypeScript model instance
|
|
772
|
-
*/
|
|
773
|
-
private ${decoderFunctionName}(
|
|
774
|
-
item: Pick<DbType, ${model.fields.map((f) => `'${f.sourceName}'`).join(' | ')}>
|
|
775
|
-
): ${model.typeName} {
|
|
776
|
-
return ${meta.types.zodDecoderFnNames.fromDatabase}.parse({
|
|
777
|
-
${model.fields.map((f) => `${f.name}: item.${f.sourceName}`).join(',\n')}
|
|
778
|
-
})
|
|
779
|
-
}`,
|
|
780
|
-
};
|
|
781
|
-
}
|
|
782
440
|
function generateUserRepositorySpecificBlocks_InDatabase({ model, meta, imports, }) {
|
|
783
441
|
if (model.name !== 'User') {
|
|
784
442
|
return {
|
|
@@ -815,40 +473,6 @@ function generateUserRepositorySpecificBlocks_InDatabase({ model, meta, imports,
|
|
|
815
473
|
}`,
|
|
816
474
|
};
|
|
817
475
|
}
|
|
818
|
-
function generateUserRepositorySpecificBlocks_InMemoryOnly({ model, meta, imports, }) {
|
|
819
|
-
if (model.name !== 'User') {
|
|
820
|
-
return {
|
|
821
|
-
rootUserNameConst: '',
|
|
822
|
-
getterBlock: '',
|
|
823
|
-
initCall: '',
|
|
824
|
-
rootUserInitializeBlock: '',
|
|
825
|
-
};
|
|
826
|
-
}
|
|
827
|
-
const { rootUserId, rootUserValue } = generateSharedRootUserBlocks({ model, meta, imports });
|
|
828
|
-
return {
|
|
829
|
-
rootUserNameConst: `public static ROOT_USER_ID = ${meta.types.toBrandedIdTypeFnName}(${rootUserId})`,
|
|
830
|
-
getterBlock: `
|
|
831
|
-
// We initialize the root user in the init() function
|
|
832
|
-
private _rootUser!: ${meta.types.typeName}
|
|
833
|
-
public get rootUser(): ${meta.types.typeName} {
|
|
834
|
-
return this._rootUser
|
|
835
|
-
}`,
|
|
836
|
-
initCall: `await this.initializeRootUser()`,
|
|
837
|
-
rootUserInitializeBlock: `
|
|
838
|
-
private async initializeRootUser(): Promise<void> {
|
|
839
|
-
const existingRootUser = await this.get(${meta.data.repository.className}.ROOT_USER_ID)
|
|
840
|
-
if (existingRootUser) {
|
|
841
|
-
this._rootUser = existingRootUser
|
|
842
|
-
return
|
|
843
|
-
}
|
|
844
|
-
|
|
845
|
-
const rawUser = { ${rootUserValue} }
|
|
846
|
-
const newRootUser = this.verifyItem (rawUser)
|
|
847
|
-
this.set(newRootUser)
|
|
848
|
-
this._rootUser = newRootUser
|
|
849
|
-
}`,
|
|
850
|
-
};
|
|
851
|
-
}
|
|
852
476
|
function generateSharedRootUserBlocks({ model, meta, imports, }) {
|
|
853
477
|
var _a;
|
|
854
478
|
const providedDefault = model.attributes.systemUser;
|
|
@@ -969,139 +593,67 @@ function generateSharedRootUserBlocks({ model, meta, imports, }) {
|
|
|
969
593
|
function generateIdBlocks({ model, meta }) {
|
|
970
594
|
const idField = model.idField;
|
|
971
595
|
if (!idField.isGenerated) {
|
|
972
|
-
return
|
|
596
|
+
return {
|
|
597
|
+
libraryImports: '',
|
|
598
|
+
generateNextIdFunctionName: '',
|
|
599
|
+
initCode: '',
|
|
600
|
+
verifyFunctionComment: `an error is thrown as field has no default setting in schema.`,
|
|
601
|
+
verifyFunctionParameterType: meta.types.dto.create,
|
|
602
|
+
verifyCode: `
|
|
603
|
+
if (item.${idField.name} === undefined) {
|
|
604
|
+
throw new Error('Id field ${idField.name} is required!')
|
|
605
|
+
}
|
|
606
|
+
const ${idField.name} = ${meta.types.toBrandedIdTypeFnName}(item.${idField.name})`,
|
|
607
|
+
setCode: '',
|
|
608
|
+
createFunctionParameterType: model.typeName,
|
|
609
|
+
};
|
|
973
610
|
}
|
|
974
611
|
if (idField.schemaType === 'Int') {
|
|
975
|
-
|
|
612
|
+
const generatedFields = model.fields.filter((f) => f.kind === 'id' || f.attributes.isReadonly);
|
|
613
|
+
const readonlyFields = model.fields.filter((f) => f.attributes.isReadonly && f.kind !== 'id');
|
|
614
|
+
return {
|
|
615
|
+
libraryImports: '',
|
|
616
|
+
generateNextIdFunctionName: `
|
|
617
|
+
protected currentMaxId = 0
|
|
618
|
+
public generateNextId(): ${model.brandedIdType} {
|
|
619
|
+
return ${meta.types.toBrandedIdTypeFnName}(++this.currentMaxId)
|
|
620
|
+
}`,
|
|
621
|
+
initCode: `this.currentMaxId = (await this.db.${meta.data.repository.getMethodFnName}.aggregate({ _max: { ${idField.sourceName}: true } }))._max.${idField.sourceName} ?? 0`,
|
|
622
|
+
verifyFunctionComment: 'the id is generated by increasing the highest former id and assigned to the item.',
|
|
623
|
+
// prettier-ignore
|
|
624
|
+
verifyFunctionParameterType: `(Omit<${model.typeName}, ${generatedFields.map((f) => `'${f.name}'`).join(' | ')}> & Partial<{${idField.name}: ${idField.unbrandedTypeName}}>)`,
|
|
625
|
+
verifyCode: `const ${idField.name} = (item.${idField.name} !== undefined) ? ${meta.types.toBrandedIdTypeFnName}(item.${idField.name}) : this.generateNextId()`,
|
|
626
|
+
createFunctionParameterType:
|
|
627
|
+
// NOTE: In case we have readonly fields, we need to omit them from the create function.
|
|
628
|
+
readonlyFields.length === 0
|
|
629
|
+
? model.typeName
|
|
630
|
+
: `Omit<${model.typeName}, ${readonlyFields.map((f) => `'${f.name}'`).join(' |')}>`,
|
|
631
|
+
setCode: `if (item.id > this.currentMaxId) { this.currentMaxId = item.id }`,
|
|
632
|
+
};
|
|
976
633
|
}
|
|
977
634
|
if (idField.schemaType === 'String') {
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
}
|
|
982
|
-
|
|
983
|
-
* Returns a collection of type signatures for the repository methods of a given model.
|
|
984
|
-
*/
|
|
985
|
-
// NOTE: We export this function as an interface simplification to the repository generator. Internally, we
|
|
986
|
-
// use the same functions as the ones used in this function which we don't want to expose.
|
|
987
|
-
function getRepositoryMethodsTypeSignatures({ model, meta }) {
|
|
988
|
-
const schemaMeta = (0, meta_1.getSchemaMetadata)({ config: model.schemaConfig });
|
|
989
|
-
return {
|
|
990
|
-
create: {
|
|
991
|
-
jsDoc: [`Creates a new ${meta.userFriendlyName} and returns it.`],
|
|
992
|
-
parameters: [`{item: ${meta.types.dto.create}, execution: ${schemaMeta.actions.execution.interface}}`],
|
|
993
|
-
returnType: `Promise<${model.typeName}>`,
|
|
994
|
-
},
|
|
995
|
-
createMany: {
|
|
996
|
-
jsDoc: [`Creates multiple new ${meta.userFriendlyNamePlural} and returns them.`],
|
|
997
|
-
parameters: [`{items: ${meta.types.dto.create}[], execution: ${schemaMeta.actions.execution.interface}}`],
|
|
998
|
-
returnType: `Promise<${model.typeName}[]>`,
|
|
999
|
-
},
|
|
1000
|
-
update: {
|
|
1001
|
-
jsDoc: [`Updates a ${meta.userFriendlyName} and returns it.`],
|
|
1002
|
-
parameters: [`{item: ${meta.types.dto.update}, execution: ${schemaMeta.actions.execution.interface}}`],
|
|
1003
|
-
returnType: `Promise<${model.typeName}>`,
|
|
1004
|
-
},
|
|
1005
|
-
updateMany: {
|
|
1006
|
-
jsDoc: [`Updates multiple ${meta.userFriendlyNamePlural} and returns them.`],
|
|
1007
|
-
parameters: [`{items: ${meta.types.dto.update}[], execution: ${schemaMeta.actions.execution.interface}}`],
|
|
1008
|
-
returnType: `Promise<${model.typeName}[]>`,
|
|
1009
|
-
},
|
|
1010
|
-
upsert: {
|
|
1011
|
-
jsDoc: [`Creates or updates a ${meta.userFriendlyName} and returns it.`],
|
|
1012
|
-
parameters: [`{item: ${meta.types.dto.upsert}, execution: ${schemaMeta.actions.execution.interface}}`],
|
|
1013
|
-
returnType: `Promise<${model.typeName}>`,
|
|
1014
|
-
},
|
|
1015
|
-
upsertMany: {
|
|
1016
|
-
jsDoc: [`Creates or updates multiple ${meta.userFriendlyNamePlural} and returns them.`],
|
|
1017
|
-
parameters: [`{items: ${meta.types.dto.upsert}[], execution: ${schemaMeta.actions.execution.interface}}`],
|
|
1018
|
-
returnType: `Promise<${model.typeName}[]>`,
|
|
1019
|
-
},
|
|
1020
|
-
delete: {
|
|
1021
|
-
jsDoc: [`Deletes a ${meta.userFriendlyName} and returns its id.`],
|
|
1022
|
-
parameters: [`{id: ${model.brandedIdType}, execution: ${schemaMeta.actions.execution.interface}}`],
|
|
1023
|
-
returnType: `Promise<${model.brandedIdType}>`,
|
|
1024
|
-
},
|
|
1025
|
-
deleteMany: {
|
|
1026
|
-
jsDoc: [`Deletes multiple ${meta.userFriendlyNamePlural} and returns their ids.`],
|
|
1027
|
-
parameters: [`{ids: ${model.brandedIdType}[], execution: ${schemaMeta.actions.execution.interface}}`],
|
|
1028
|
-
returnType: `Promise<${model.brandedIdType}[]>`,
|
|
1029
|
-
},
|
|
1030
|
-
};
|
|
1031
|
-
}
|
|
1032
|
-
exports.getRepositoryMethodsTypeSignatures = getRepositoryMethodsTypeSignatures;
|
|
1033
|
-
/**
|
|
1034
|
-
* Generates the id block code chunks for a model that requires an ID field to be manually
|
|
1035
|
-
* supplied to the create function.
|
|
1036
|
-
*/
|
|
1037
|
-
function _generateIdBlocks_NoGeneration({ idField, model, meta, }) {
|
|
1038
|
-
return {
|
|
1039
|
-
libraryImports: '',
|
|
1040
|
-
generateNextIdFunctionName: '',
|
|
1041
|
-
initCode: '',
|
|
1042
|
-
verifyFunctionComment: `an error is thrown as field has no default setting in schema.`,
|
|
1043
|
-
verifyFunctionParameterType: meta.types.dto.create,
|
|
1044
|
-
verifyCode: `
|
|
1045
|
-
if (item.${idField.name} === undefined) {
|
|
1046
|
-
throw new Error('Id field ${idField.name} is required!')
|
|
1047
|
-
}
|
|
1048
|
-
const ${idField.name} = ${meta.types.toBrandedIdTypeFnName}(item.${idField.name})`,
|
|
1049
|
-
setCode: '',
|
|
1050
|
-
createFunctionParameterType: model.typeName,
|
|
1051
|
-
};
|
|
1052
|
-
}
|
|
1053
|
-
/**
|
|
1054
|
-
* Generates the id block code chunks for a model that has an integer id field.
|
|
1055
|
-
* Given chunks make sure that the id is unique if provided or generate a new one if not.
|
|
1056
|
-
*/
|
|
1057
|
-
function _generateIdBlock_Int({ idField, model, meta, }) {
|
|
1058
|
-
const generatedFields = model.fields.filter((f) => f.kind === 'id' || f.attributes.isReadonly);
|
|
1059
|
-
const readonlyFields = model.fields.filter((f) => f.attributes.isReadonly && f.kind !== 'id');
|
|
1060
|
-
return {
|
|
1061
|
-
libraryImports: '',
|
|
1062
|
-
generateNextIdFunctionName: `
|
|
1063
|
-
protected currentMaxId = 0
|
|
1064
|
-
public generateNextId(): ${model.brandedIdType} {
|
|
1065
|
-
return ${meta.types.toBrandedIdTypeFnName}(++this.currentMaxId)
|
|
1066
|
-
}`,
|
|
1067
|
-
initCode: `this.currentMaxId = (await this.db.${meta.data.repository.getMethodFnName}.aggregate({ _max: { ${idField.sourceName}: true } }))._max.${idField.sourceName} ?? 0`,
|
|
1068
|
-
verifyFunctionComment: 'the id is generated by increasing the highest former id and assigned to the item.',
|
|
1069
|
-
// prettier-ignore
|
|
1070
|
-
verifyFunctionParameterType: `(Omit<${model.typeName}, ${generatedFields.map((f) => `'${f.name}'`).join(' | ')}> & Partial<{${idField.name}: ${idField.unbrandedTypeName}}>)`,
|
|
1071
|
-
verifyCode: `const ${idField.name} = (item.${idField.name} !== undefined) ? ${meta.types.toBrandedIdTypeFnName}(item.${idField.name}) : this.generateNextId()`,
|
|
1072
|
-
createFunctionParameterType:
|
|
1073
|
-
// NOTE: In case we have readonly fields, we need to omit them from the create function.
|
|
1074
|
-
readonlyFields.length === 0
|
|
1075
|
-
? model.typeName
|
|
1076
|
-
: `Omit<${model.typeName}, ${readonlyFields.map((f) => `'${f.name}'`).join(' |')}>`,
|
|
1077
|
-
setCode: `if (item.id > this.currentMaxId) { this.currentMaxId = item.id }`,
|
|
1078
|
-
};
|
|
1079
|
-
}
|
|
1080
|
-
/**
|
|
1081
|
-
* Generates the id block code chunks for a model that has a UUID id field.
|
|
1082
|
-
* It allows you to provide a custom id or generates a new one if not.
|
|
1083
|
-
*/
|
|
1084
|
-
function _generateIdBlock_UUID({ idField, model, meta, }) {
|
|
1085
|
-
const dbGeneratedFields = model.fields.filter((f) => f.kind === 'id' || f.attributes.isReadonly);
|
|
1086
|
-
const readonlyFields = model.fields.filter((f) => f.attributes.isReadonly && f.kind !== 'id');
|
|
1087
|
-
return {
|
|
1088
|
-
libraryImports: `import { randomUUID } from 'crypto'`,
|
|
1089
|
-
generateNextIdFunctionName: `
|
|
635
|
+
const dbGeneratedFields = model.fields.filter((f) => f.kind === 'id' || f.attributes.isReadonly);
|
|
636
|
+
const readonlyFields = model.fields.filter((f) => f.attributes.isReadonly && f.kind !== 'id');
|
|
637
|
+
return {
|
|
638
|
+
libraryImports: `import { randomUUID } from 'crypto'`,
|
|
639
|
+
generateNextIdFunctionName: `
|
|
1090
640
|
public generateNextId(): ${model.brandedIdType} {
|
|
1091
641
|
return ${meta.types.toBrandedIdTypeFnName}(randomUUID())
|
|
1092
642
|
}`,
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
643
|
+
initCode: '',
|
|
644
|
+
verifyFunctionComment: 'a new UUID is generated and assigned to the item.',
|
|
645
|
+
// prettier-ignore
|
|
646
|
+
verifyFunctionParameterType: `(Omit<${model.typeName}, ${dbGeneratedFields.map((f) => `'${f.name}'`).join(' | ')}> & Partial<{${idField.name}: ${idField.unbrandedTypeName}}>)`,
|
|
647
|
+
verifyCode: `const ${idField.name} = (item.${idField.name} !== undefined) ? ${meta.types.toBrandedIdTypeFnName}(item.${idField.name}) : this.generateNextId()`,
|
|
648
|
+
createFunctionParameterType:
|
|
649
|
+
// NOTE: In case we have readonly fields, we need to omit them from the create function.
|
|
650
|
+
readonlyFields.length === 0
|
|
651
|
+
? model.typeName
|
|
652
|
+
: `Omit<${model.typeName}, ${readonlyFields.map((f) => `'${f.name}'`).join(' |')}>`,
|
|
653
|
+
setCode: '',
|
|
654
|
+
};
|
|
655
|
+
}
|
|
656
|
+
throw new Error(`Repository block only supports Id generation for number and strings! Found ${idField.schemaType} for model ${model.name} instead!`);
|
|
1105
657
|
}
|
|
1106
658
|
/**
|
|
1107
659
|
* Returns the code chunks that define the default value property and its initialization.
|