@postxl/generator 0.56.3 → 0.56.5
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 +2 -1
- package/dist/generators/indices/dispatcher-service.generator.js +20 -6
- package/dist/generators/indices/importexport-exporter-class.generator.js +9 -22
- package/dist/generators/indices/routes-index.generator.d.ts +9 -0
- package/dist/generators/indices/routes-index.generator.js +26 -0
- package/dist/generators/models/businesslogic-update.generator.js +122 -98
- package/dist/generators/models/route.generator.d.ts +1 -8
- package/dist/generators/models/route.generator.js +1 -23
- package/dist/lib/meta.d.ts +7 -3
- package/dist/lib/meta.js +2 -1
- package/dist/lib/schema/schema.d.ts +10 -1
- package/dist/prisma/parse.js +24 -10
- package/package.json +1 -1
package/dist/generator.js
CHANGED
|
@@ -60,6 +60,7 @@ const importexport_exporter_class_generator_1 = require("./generators/indices/im
|
|
|
60
60
|
const importexport_import_service_generator_1 = require("./generators/indices/importexport-import-service.generator");
|
|
61
61
|
const importexport_types_generator_1 = require("./generators/indices/importexport-types.generator");
|
|
62
62
|
const repositories_generator_1 = require("./generators/indices/repositories.generator");
|
|
63
|
+
const routes_index_generator_1 = require("./generators/indices/routes-index.generator");
|
|
63
64
|
const seed_migration_generator_1 = require("./generators/indices/seed-migration.generator");
|
|
64
65
|
const seed_template_generator_1 = require("./generators/indices/seed-template.generator");
|
|
65
66
|
const selectors_generator_1 = require("./generators/indices/selectors.generator");
|
|
@@ -234,7 +235,7 @@ function generate({ models, enums, config, prismaClientPath, logger, }) {
|
|
|
234
235
|
generated.write(`/${meta.seedData.initialMigrationFilePath}.ts`, (0, seed_migration_generator_1.generateSeedMigration)({ models, meta }));
|
|
235
236
|
generated.write(`/${meta.seedData.templateExcelFilePath}`, yield (0, seed_template_generator_1.generateSeedExcelTemplate)({ models }));
|
|
236
237
|
// Routes
|
|
237
|
-
generated.write(`/${meta.trpc.routesFilePath}.ts`, (0,
|
|
238
|
+
generated.write(`/${meta.trpc.routesFilePath}.ts`, (0, routes_index_generator_1.generateRoutesIndex)({ models, meta }));
|
|
238
239
|
// Types
|
|
239
240
|
generated.write(`/${meta.types.indexFilePath}.ts`, (0, types_generator_2.generateTypesIndex)({ models, enums, meta }));
|
|
240
241
|
// -------------------------------------------------------------------------
|
|
@@ -54,7 +54,7 @@ export class ${meta.actions.dispatcher.class} {
|
|
|
54
54
|
const execution = await this.actionExecutionFactory.create({ action, dbService: this.dbService, user })
|
|
55
55
|
|
|
56
56
|
try {
|
|
57
|
-
const result = await
|
|
57
|
+
const result = await this.execute({ action, execution })
|
|
58
58
|
|
|
59
59
|
await execution.success(result)
|
|
60
60
|
|
|
@@ -65,22 +65,36 @@ export class ${meta.actions.dispatcher.class} {
|
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
private async execute
|
|
68
|
+
private async execute<A extends Action>({
|
|
69
|
+
action,
|
|
70
|
+
execution,
|
|
71
|
+
}: {
|
|
72
|
+
action: A
|
|
73
|
+
execution: IActionExecution
|
|
74
|
+
}): Promise<ResultOfAction<A>> {
|
|
69
75
|
switch (action.scope) {
|
|
70
76
|
${models
|
|
71
77
|
.map((model) => {
|
|
72
78
|
const modelMeta = (0, meta_1.getModelMetadata)({ model });
|
|
73
79
|
return `
|
|
74
|
-
case '${modelMeta.businessLogic.scopeName}':
|
|
75
|
-
|
|
80
|
+
case '${modelMeta.businessLogic.scopeName}': {
|
|
81
|
+
const method = this.updateService.${modelMeta.businessLogic.update.serviceVariableName}[action.type] as (params: {
|
|
82
|
+
data: A['payload']
|
|
83
|
+
execution: IActionExecution
|
|
84
|
+
}) => Promise<ResultOfAction<A>>
|
|
85
|
+
|
|
86
|
+
// NOTE: We need to bind the method to the service instance, as it is a method of the service and not a standalone function.
|
|
87
|
+
return method.bind(this.updateService.${modelMeta.businessLogic.update.serviceVariableName})({ data: action.payload, execution })
|
|
88
|
+
}
|
|
76
89
|
`;
|
|
77
90
|
})
|
|
78
91
|
.join('\n')}
|
|
92
|
+
|
|
79
93
|
case 'seed':
|
|
80
|
-
return this.seedService.dispatch({ action, execution })
|
|
94
|
+
return this.seedService.dispatch({ action, execution }) as Promise<ResultOfAction<A>>
|
|
81
95
|
|
|
82
96
|
case 'import':
|
|
83
|
-
return this.importService.dispatch({ action, execution })
|
|
97
|
+
return this.importService.dispatch({ action, execution }) as Promise<ResultOfAction<A>>
|
|
84
98
|
|
|
85
99
|
default:
|
|
86
100
|
throw new ExhaustiveSwitchCheck(action)
|
|
@@ -9,7 +9,6 @@ const types_1 = require("../../lib/schema/types");
|
|
|
9
9
|
*/
|
|
10
10
|
function generateImportExportExporterClass({ models, meta }) {
|
|
11
11
|
const imports = imports_1.ImportsGenerator.from(meta.importExport.exporterClass.filePath);
|
|
12
|
-
const modelsMap = new Map(models.map((model) => [model.name, model]));
|
|
13
12
|
imports.addImports({
|
|
14
13
|
[meta.businessLogic.view.importPath]: [meta.businessLogic.view.serviceClassName],
|
|
15
14
|
[meta.importExport.decoder.fullDecoderFilePath]: [
|
|
@@ -50,27 +49,15 @@ function generateImportExportExporterClass({ models, meta }) {
|
|
|
50
49
|
}
|
|
51
50
|
}
|
|
52
51
|
const childItemCalls = [];
|
|
53
|
-
for (const
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}
|
|
63
|
-
if (field.relationToModel.name !== model.name) {
|
|
64
|
-
continue;
|
|
65
|
-
}
|
|
66
|
-
const linkedModelMeta = (0, meta_1.getModelMetadata)({ model: relatedModel });
|
|
67
|
-
const linkedFieldMeta = (0, meta_1.getFieldMetadata)({ field: field });
|
|
68
|
-
childItemCalls.push(`
|
|
69
|
-
// Add all ${linkedModelMeta.userFriendlyNamePlural} that are related to the ${modelMeta.userFriendlyName} via ${field.name}
|
|
70
|
-
for (const ${field.name} of await this.viewService.${linkedModelMeta.businessLogic.view.serviceVariableName}.data.${linkedFieldMeta.getByForeignKeyIdsMethodFnName}(id)) {
|
|
71
|
-
await this.${linkedModelMeta.importExport.exportAddFunctionName}({id: ${field.name}, includeChildren})
|
|
72
|
-
}`);
|
|
73
|
-
}
|
|
52
|
+
for (const { referencingField, referencingModel } of model.references) {
|
|
53
|
+
const linkedModelMeta = (0, meta_1.getModelMetadata)({ model: referencingModel });
|
|
54
|
+
const linkedFieldMeta = (0, meta_1.getFieldMetadata)({ field: referencingField });
|
|
55
|
+
childItemCalls.push(`
|
|
56
|
+
// Add all ${linkedModelMeta.userFriendlyNamePlural} that are related to the ${modelMeta.userFriendlyName} via ${referencingField.name}
|
|
57
|
+
for (const ${referencingField.name} of await this.viewService.${linkedModelMeta.businessLogic.view.serviceVariableName}.data.${linkedFieldMeta.getByForeignKeyIdsMethodFnName}(id)) {
|
|
58
|
+
await this.${linkedModelMeta.importExport.exportAddFunctionName}({id: ${referencingField.name}, includeChildren})
|
|
59
|
+
}
|
|
60
|
+
`);
|
|
74
61
|
}
|
|
75
62
|
const childItems = childItemCalls.length > 0
|
|
76
63
|
? `
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { SchemaMetaData } from '../../lib/meta';
|
|
2
|
+
import { Model } from '../../lib/schema/schema';
|
|
3
|
+
/**
|
|
4
|
+
* Generates the index file for all the routes.
|
|
5
|
+
*/
|
|
6
|
+
export declare function generateRoutesIndex({ models, meta }: {
|
|
7
|
+
models: Model[];
|
|
8
|
+
meta: SchemaMetaData;
|
|
9
|
+
}): string;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateRoutesIndex = void 0;
|
|
4
|
+
const imports_1 = require("../../lib/imports");
|
|
5
|
+
const meta_1 = require("../../lib/meta");
|
|
6
|
+
/**
|
|
7
|
+
* Generates the index file for all the routes.
|
|
8
|
+
*/
|
|
9
|
+
function generateRoutesIndex({ models, meta }) {
|
|
10
|
+
const mm = models.map((model) => ({ model, meta: (0, meta_1.getModelMetadata)({ model }) }));
|
|
11
|
+
const imports = imports_1.ImportsGenerator.from(meta.trpc.routesFilePath);
|
|
12
|
+
for (const { meta } of mm) {
|
|
13
|
+
imports.addImport({ items: [meta.trpc.routerName], from: meta.trpc.routerFilePath });
|
|
14
|
+
}
|
|
15
|
+
return /* ts */ `
|
|
16
|
+
${imports.generate()}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Object with all generated routes.
|
|
20
|
+
*/
|
|
21
|
+
export const routes = {
|
|
22
|
+
${mm.map(({ meta }) => `${meta.trpc.routerName}`).join(',\n')}
|
|
23
|
+
}
|
|
24
|
+
`;
|
|
25
|
+
}
|
|
26
|
+
exports.generateRoutesIndex = generateRoutesIndex;
|
|
@@ -13,21 +13,45 @@ const jsdoc_1 = require("../../lib/utils/jsdoc");
|
|
|
13
13
|
*/
|
|
14
14
|
function generateModelBusinessLogicUpdate({ model, meta }) {
|
|
15
15
|
const schemaMeta = (0, meta_1.getSchemaMetadata)({ config: model.schemaConfig });
|
|
16
|
+
/**
|
|
17
|
+
* Shorthand variable for relevant metadata.
|
|
18
|
+
*/
|
|
19
|
+
const m = {
|
|
20
|
+
/**
|
|
21
|
+
* The name of the interface that handles the action execution.
|
|
22
|
+
*/
|
|
23
|
+
iExecution: schemaMeta.actions.execution.interface,
|
|
24
|
+
/**
|
|
25
|
+
* The name of the type that represents a fully typed, flat object, e.g. `Aggregation`
|
|
26
|
+
*/
|
|
27
|
+
typeName: meta.types.typeName,
|
|
28
|
+
/**
|
|
29
|
+
* Type of the ID field that is specific to this model, e.g. `AggregationId`
|
|
30
|
+
*/
|
|
31
|
+
brandedId: model.brandedIdType,
|
|
32
|
+
/**
|
|
33
|
+
* Internal type name for create payload, e.g. `CreateAggregation`
|
|
34
|
+
*/
|
|
35
|
+
createType: `Create${meta.internalSingularNameCapitalized}`,
|
|
36
|
+
/**
|
|
37
|
+
* Internal type name for update payload, e.g. `UpdateAggregation`
|
|
38
|
+
*/
|
|
39
|
+
updateType: `Update${meta.internalSingularNameCapitalized}`,
|
|
40
|
+
/**
|
|
41
|
+
* Internal type name for upsert payload, e.g. `UpsertAggregation`
|
|
42
|
+
*/
|
|
43
|
+
upsertType: `Upsert${meta.internalSingularNameCapitalized}`,
|
|
44
|
+
};
|
|
16
45
|
const imports = imports_1.ImportsGenerator.from(meta.businessLogic.update.serviceFilePath);
|
|
17
46
|
imports.addImports({
|
|
18
47
|
[meta.data.importPath]: meta.data.repository.className,
|
|
19
48
|
[meta.types.importPath]: [
|
|
20
|
-
(0, types_1.toAnnotatedTypeName)(
|
|
21
|
-
(0, types_1.toAnnotatedTypeName)(
|
|
49
|
+
(0, types_1.toAnnotatedTypeName)(m.brandedId),
|
|
50
|
+
(0, types_1.toAnnotatedTypeName)(m.typeName),
|
|
22
51
|
meta.types.toBrandedIdTypeFnName,
|
|
23
52
|
],
|
|
24
53
|
[meta.businessLogic.view.serviceFilePath]: [meta.businessLogic.view.serviceClassName],
|
|
25
|
-
[schemaMeta.actions.importPath]: [
|
|
26
|
-
schemaMeta.actions.execution.interface,
|
|
27
|
-
schemaMeta.actions.dispatcher.interface,
|
|
28
|
-
schemaMeta.actions.definition.payload,
|
|
29
|
-
schemaMeta.actions.definition.result,
|
|
30
|
-
],
|
|
54
|
+
[schemaMeta.actions.importPath]: [schemaMeta.actions.execution.interface, schemaMeta.actions.dispatcher.definition],
|
|
31
55
|
[schemaMeta.businessLogic.update.serviceFilePath]: schemaMeta.businessLogic.update.serviceClassName,
|
|
32
56
|
[schemaMeta.businessLogic.view.serviceFilePath]: schemaMeta.businessLogic.view.serviceClassName,
|
|
33
57
|
});
|
|
@@ -49,28 +73,70 @@ function generateModelBusinessLogicUpdate({ model, meta }) {
|
|
|
49
73
|
*/
|
|
50
74
|
const modelRepositoryVariableName = meta.businessLogic.dataRepositoryVariableName;
|
|
51
75
|
const constructorParameters = [
|
|
52
|
-
`
|
|
76
|
+
`private readonly ${modelRepositoryVariableName}: ${meta.data.repository.className}`,
|
|
53
77
|
`@Inject(forwardRef(() => ${schemaMeta.businessLogic.update.serviceClassName})) private readonly updateService: ${schemaMeta.businessLogic.update.serviceClassName}`,
|
|
54
78
|
`@Inject(forwardRef(() => ${schemaMeta.businessLogic.view.serviceClassName})) private readonly viewService: ${schemaMeta.businessLogic.view.serviceClassName}`,
|
|
55
79
|
];
|
|
56
80
|
const { zodCreateObject, zodUpdateObject, zodUpsertObject } = meta.businessLogic.update;
|
|
57
|
-
const {
|
|
58
|
-
|
|
59
|
-
* A return value of the dispatcher.
|
|
60
|
-
*
|
|
61
|
-
* NOTE: We need to cast to the return value every time so that the function correctly determines the return type.
|
|
62
|
-
*/
|
|
63
|
-
const dispatcherReturnValue = `Promise<${definition.result}<Actions, A>>`;
|
|
81
|
+
const { view, update } = meta.businessLogic;
|
|
82
|
+
/* prettier-ignore */
|
|
64
83
|
return /* ts */ `
|
|
65
84
|
import { Inject, Injectable, forwardRef } from '@nestjs/common'
|
|
66
|
-
import { ExhaustiveSwitchCheck } from '@backend/common'
|
|
67
85
|
import { z } from 'zod'
|
|
68
86
|
|
|
69
87
|
${imports.generate()}
|
|
70
88
|
|
|
71
89
|
export type Scope = "${meta.actions.actionScopeConstType}"
|
|
72
90
|
|
|
73
|
-
|
|
91
|
+
export type Actions = {
|
|
92
|
+
${(0, jsdoc_1.toJsDocComment)([`Creates a new ${meta.userFriendlyName} and returns it.`])}
|
|
93
|
+
create: {
|
|
94
|
+
payload: ${m.createType}
|
|
95
|
+
result: ${m.typeName}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
${(0, jsdoc_1.toJsDocComment)([`Creates multiple new ${meta.userFriendlyNamePlural} and returns them.`])}
|
|
99
|
+
createMany: {
|
|
100
|
+
payload: ${m.createType}[]
|
|
101
|
+
result: ${m.typeName}[]
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
${(0, jsdoc_1.toJsDocComment)([`Updates a ${meta.userFriendlyName} and returns it.`])}
|
|
105
|
+
update: {
|
|
106
|
+
payload: ${m.updateType}
|
|
107
|
+
result: ${m.typeName}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
${(0, jsdoc_1.toJsDocComment)([`Updates multiple ${meta.userFriendlyNamePlural} and returns them.`])}
|
|
111
|
+
updateMany: {
|
|
112
|
+
payload: ${m.updateType}[]
|
|
113
|
+
result: ${m.typeName}[]
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
${(0, jsdoc_1.toJsDocComment)([`Creates or updates a ${meta.userFriendlyName} and returns it.`])}
|
|
117
|
+
upsert: {
|
|
118
|
+
payload: ${m.upsertType}
|
|
119
|
+
result: ${m.typeName}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
${(0, jsdoc_1.toJsDocComment)([`Creates or updates multiple ${meta.userFriendlyNamePlural} and returns them.`])}
|
|
123
|
+
upsertMany: {
|
|
124
|
+
payload: ${m.upsertType}[]
|
|
125
|
+
result: ${m.typeName}[]
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
${(0, jsdoc_1.toJsDocComment)([`Deletes a ${meta.userFriendlyName} and returns its id.`])}
|
|
129
|
+
delete: {
|
|
130
|
+
payload: ${m.brandedId}
|
|
131
|
+
result: ${m.brandedId}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
${(0, jsdoc_1.toJsDocComment)([`Deletes multiple ${meta.userFriendlyNamePlural} and returns their ids.`])}
|
|
135
|
+
deleteMany: {
|
|
136
|
+
payload: ${m.brandedId}[]
|
|
137
|
+
result: ${m.brandedId}[]
|
|
138
|
+
}
|
|
139
|
+
}
|
|
74
140
|
|
|
75
141
|
/**
|
|
76
142
|
* Zod decoder for validating the create input of a ${meta.userFriendlyName}.
|
|
@@ -82,6 +148,8 @@ function generateModelBusinessLogicUpdate({ model, meta }) {
|
|
|
82
148
|
.join(',')}
|
|
83
149
|
})
|
|
84
150
|
|
|
151
|
+
type ${m.createType} = z.infer<typeof ${zodCreateObject}>
|
|
152
|
+
|
|
85
153
|
/**
|
|
86
154
|
* Zod decoder for validating the update input of a ${meta.userFriendlyName} .
|
|
87
155
|
*/
|
|
@@ -92,112 +160,68 @@ function generateModelBusinessLogicUpdate({ model, meta }) {
|
|
|
92
160
|
.join(',')}
|
|
93
161
|
})
|
|
94
162
|
|
|
163
|
+
type ${m.updateType} = z.infer<typeof ${zodUpdateObject}>
|
|
164
|
+
|
|
95
165
|
/**
|
|
96
166
|
* Zod decoder for validating the upsert input of a ${meta.userFriendlyName} .
|
|
97
167
|
*/
|
|
98
168
|
export const ${zodUpsertObject} = z.union([${zodUpdateObject}, ${zodCreateObject}])
|
|
169
|
+
|
|
170
|
+
type ${m.upsertType} = z.infer<typeof ${zodUpsertObject}>
|
|
171
|
+
|
|
172
|
+
export type ${update.serviceInterfaceName} = ${schemaMeta.actions.dispatcher.definition}<Actions>
|
|
173
|
+
|
|
174
|
+
@Injectable()
|
|
175
|
+
export class ${update.serviceClassName} implements ${update.serviceInterfaceName} {
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Instance of the ${meta.userFriendlyName} view service for convenience.
|
|
179
|
+
*/
|
|
180
|
+
private view: ${view.serviceClassName}
|
|
181
|
+
|
|
182
|
+
constructor(${constructorParameters.join(',\n')}) {
|
|
183
|
+
this.view = this.viewService.${view.serviceVariableName}
|
|
184
|
+
}
|
|
99
185
|
|
|
100
|
-
export type Actions = {
|
|
101
186
|
${(0, jsdoc_1.toJsDocComment)([`Creates a new ${meta.userFriendlyName} and returns it.`])}
|
|
102
|
-
create: {
|
|
103
|
-
|
|
104
|
-
result: ${meta.types.typeName}
|
|
187
|
+
public async create({ data, execution }: { data: ${m.createType}; execution: ${m.iExecution} }): Promise<${m.typeName}> {
|
|
188
|
+
return this.data.create({ item: data, execution })
|
|
105
189
|
}
|
|
106
190
|
|
|
107
191
|
${(0, jsdoc_1.toJsDocComment)([`Creates multiple new ${meta.userFriendlyNamePlural} and returns them.`])}
|
|
108
|
-
createMany: {
|
|
109
|
-
|
|
110
|
-
result: ${meta.types.typeName}[]
|
|
192
|
+
public async createMany({ data, execution }: { data: ${m.createType}[]; execution: ${m.iExecution} }): Promise<${m.typeName}[]> {
|
|
193
|
+
return this.data.createMany({ items: data, execution })
|
|
111
194
|
}
|
|
112
195
|
|
|
113
196
|
${(0, jsdoc_1.toJsDocComment)([`Updates a ${meta.userFriendlyName} and returns it.`])}
|
|
114
|
-
update: {
|
|
115
|
-
|
|
116
|
-
result: ${meta.types.typeName}
|
|
197
|
+
public async update({ data, execution }: { data: ${m.updateType}; execution: ${m.iExecution} }): Promise<${m.typeName}> {
|
|
198
|
+
return this.data.update({ item: data, execution })
|
|
117
199
|
}
|
|
118
200
|
|
|
119
201
|
${(0, jsdoc_1.toJsDocComment)([`Updates multiple ${meta.userFriendlyNamePlural} and returns them.`])}
|
|
120
|
-
updateMany: {
|
|
121
|
-
|
|
122
|
-
result: ${meta.types.typeName}[]
|
|
202
|
+
public async updateMany({ data, execution }: { data: ${m.updateType}[]; execution: ${m.iExecution} }): Promise<${m.typeName}[]> {
|
|
203
|
+
return this.data.updateMany({ items: data, execution })
|
|
123
204
|
}
|
|
124
205
|
|
|
125
206
|
${(0, jsdoc_1.toJsDocComment)([`Creates or updates a ${meta.userFriendlyName} and returns it.`])}
|
|
126
|
-
upsert: {
|
|
127
|
-
|
|
128
|
-
result: ${meta.types.typeName}
|
|
207
|
+
public async upsert({ data, execution }: { data: ${m.upsertType}; execution: ${m.iExecution} }): Promise<${m.typeName}> {
|
|
208
|
+
return this.data.upsert({ item: data, execution })
|
|
129
209
|
}
|
|
130
210
|
|
|
131
211
|
${(0, jsdoc_1.toJsDocComment)([`Creates or updates multiple ${meta.userFriendlyNamePlural} and returns them.`])}
|
|
132
|
-
upsertMany: {
|
|
133
|
-
|
|
134
|
-
result: ${meta.types.typeName}[]
|
|
212
|
+
public async upsertMany({ data, execution }: { data: ${m.upsertType}[]; execution: ${m.iExecution} }): Promise<${m.typeName}[]> {
|
|
213
|
+
return this.data.upsertMany({ items: data, execution })
|
|
135
214
|
}
|
|
136
|
-
|
|
215
|
+
|
|
137
216
|
${(0, jsdoc_1.toJsDocComment)([`Deletes a ${meta.userFriendlyName} and returns its id.`])}
|
|
138
|
-
delete: {
|
|
139
|
-
|
|
140
|
-
result: ${model.brandedIdType}
|
|
217
|
+
public async delete({ data, execution }: { data: ${m.brandedId}; execution: ${m.iExecution} }): Promise<${m.brandedId}> {
|
|
218
|
+
return this.data.delete({ id: data, execution })
|
|
141
219
|
}
|
|
142
220
|
|
|
143
221
|
${(0, jsdoc_1.toJsDocComment)([`Deletes multiple ${meta.userFriendlyNamePlural} and returns their ids.`])}
|
|
144
|
-
deleteMany: {
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
@Injectable()
|
|
151
|
-
export class ${meta.businessLogic.update.serviceClassName} implements ${dispatcher.interface}<Scope, Actions> {
|
|
152
|
-
/**
|
|
153
|
-
* Instance of the ${meta.userFriendlyName} view service for convenience.
|
|
154
|
-
*/
|
|
155
|
-
private view: ${meta.businessLogic.view.serviceClassName}
|
|
156
|
-
|
|
157
|
-
constructor(${constructorParameters.join(',\n')}) {
|
|
158
|
-
this.view = this.viewService.${meta.businessLogic.view.serviceVariableName}
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
* Dispatches an action to the appropriate method of the repository.
|
|
163
|
-
*/
|
|
164
|
-
public async dispatch<A extends ${definition.payload}<Scope, Actions>>({
|
|
165
|
-
action,
|
|
166
|
-
execution,
|
|
167
|
-
}: {
|
|
168
|
-
action: A
|
|
169
|
-
execution: ${schemaMeta.actions.execution.interface}
|
|
170
|
-
}): ${dispatcherReturnValue} {
|
|
171
|
-
switch (action.type) {
|
|
172
|
-
case 'create':
|
|
173
|
-
return this.data.create({ item: action.payload, execution }) as ${dispatcherReturnValue}
|
|
174
|
-
|
|
175
|
-
case 'createMany':
|
|
176
|
-
return this.data.createMany({ items: action.payload, execution }) as ${dispatcherReturnValue}
|
|
177
|
-
|
|
178
|
-
case 'update':
|
|
179
|
-
return this.data.update({ item: action.payload, execution }) as ${dispatcherReturnValue}
|
|
180
|
-
|
|
181
|
-
case 'updateMany':
|
|
182
|
-
return this.data.updateMany({ items: action.payload, execution }) as ${dispatcherReturnValue}
|
|
183
|
-
|
|
184
|
-
case 'upsert':
|
|
185
|
-
return this.data.upsert({ item: action.payload, execution }) as ${dispatcherReturnValue}
|
|
186
|
-
|
|
187
|
-
case 'upsertMany':
|
|
188
|
-
return this.data.upsertMany({ items: action.payload, execution }) as ${dispatcherReturnValue}
|
|
189
|
-
|
|
190
|
-
case 'delete':
|
|
191
|
-
return this.data.delete({ id: action.payload, execution }) as ${dispatcherReturnValue}
|
|
192
|
-
|
|
193
|
-
case 'deleteMany':
|
|
194
|
-
return this.data.deleteMany({ ids: action.payload, execution }) as ${dispatcherReturnValue}
|
|
195
|
-
|
|
196
|
-
default:
|
|
197
|
-
throw new ExhaustiveSwitchCheck(action)
|
|
198
|
-
|
|
199
|
-
}
|
|
200
|
-
}
|
|
222
|
+
public async deleteMany({ data, execution }: { data: ${m.brandedId}[]; execution: ${m.iExecution} }): Promise<${m.brandedId}[]> {
|
|
223
|
+
return this.data.deleteMany({ ids: data, execution })
|
|
224
|
+
}
|
|
201
225
|
}
|
|
202
226
|
`;
|
|
203
227
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ModelMetaData
|
|
1
|
+
import { ModelMetaData } from '../../lib/meta';
|
|
2
2
|
import { Model } from '../../lib/schema/schema';
|
|
3
3
|
/**
|
|
4
4
|
* Generates TRPC route for a given model.
|
|
@@ -7,10 +7,3 @@ export declare function generateRoute({ model, meta }: {
|
|
|
7
7
|
model: Model;
|
|
8
8
|
meta: ModelMetaData;
|
|
9
9
|
}): string;
|
|
10
|
-
/**
|
|
11
|
-
* Generates the index file for all the routes.
|
|
12
|
-
*/
|
|
13
|
-
export declare function generateRoutesIndex({ models, meta }: {
|
|
14
|
-
models: Model[];
|
|
15
|
-
meta: SchemaMetaData;
|
|
16
|
-
}): string;
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.generateRoute = void 0;
|
|
4
4
|
const imports_1 = require("../../lib/imports");
|
|
5
|
-
const meta_1 = require("../../lib/meta");
|
|
6
5
|
const types_1 = require("../../lib/schema/types");
|
|
7
6
|
/**
|
|
8
7
|
* Generates TRPC route for a given model.
|
|
@@ -96,24 +95,3 @@ export const ${meta.trpc.routerName} = router({
|
|
|
96
95
|
`;
|
|
97
96
|
}
|
|
98
97
|
exports.generateRoute = generateRoute;
|
|
99
|
-
/**
|
|
100
|
-
* Generates the index file for all the routes.
|
|
101
|
-
*/
|
|
102
|
-
function generateRoutesIndex({ models, meta }) {
|
|
103
|
-
const mm = models.map((model) => ({ model, meta: (0, meta_1.getModelMetadata)({ model }) }));
|
|
104
|
-
const imports = imports_1.ImportsGenerator.from(meta.trpc.routesFilePath);
|
|
105
|
-
for (const { meta } of mm) {
|
|
106
|
-
imports.addImport({ items: [meta.trpc.routerName], from: meta.trpc.routerFilePath });
|
|
107
|
-
}
|
|
108
|
-
return /* ts */ `
|
|
109
|
-
${imports.generate()}
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* Object with all generated routes.
|
|
113
|
-
*/
|
|
114
|
-
export const routes = {
|
|
115
|
-
${mm.map(({ meta }) => `${meta.trpc.routerName}`).join(',\n')}
|
|
116
|
-
}
|
|
117
|
-
`;
|
|
118
|
-
}
|
|
119
|
-
exports.generateRoutesIndex = generateRoutesIndex;
|
package/dist/lib/meta.d.ts
CHANGED
|
@@ -117,9 +117,9 @@ export type SchemaMetaData = {
|
|
|
117
117
|
*/
|
|
118
118
|
class: Types.ClassName;
|
|
119
119
|
/**
|
|
120
|
-
* The
|
|
120
|
+
* The definition type that may be used to create a dispatcher conforming class.
|
|
121
121
|
*/
|
|
122
|
-
|
|
122
|
+
definition: Types.TypeName;
|
|
123
123
|
};
|
|
124
124
|
definition: {
|
|
125
125
|
/**
|
|
@@ -919,9 +919,13 @@ export type ModelMetaData = {
|
|
|
919
919
|
*/
|
|
920
920
|
update: {
|
|
921
921
|
/**
|
|
922
|
-
* The name by which the model's update class is exposed in the updateService/context. (e.g.
|
|
922
|
+
* The name by which the model's update class is exposed in the updateService/context. (e.g. AggregationUpdateService)
|
|
923
923
|
*/
|
|
924
924
|
serviceClassName: Types.ClassName;
|
|
925
|
+
/**
|
|
926
|
+
* The name of the interface that represents the update service for this model. (e.g. IAggregationUpdateService)
|
|
927
|
+
*/
|
|
928
|
+
serviceInterfaceName: Types.TypeName;
|
|
925
929
|
/**
|
|
926
930
|
* The name by which the model's service is exposed in the updateService/context. (e.g. aggregations)
|
|
927
931
|
*/
|
package/dist/lib/meta.js
CHANGED
|
@@ -89,7 +89,7 @@ function getSchemaMetadata({ config }) {
|
|
|
89
89
|
dispatcher: {
|
|
90
90
|
filePath: Types.toPath(`${config.paths.actionsPath}dispatcher.service`),
|
|
91
91
|
class: Types.toClassName(`DispatcherService`),
|
|
92
|
-
|
|
92
|
+
definition: Types.toTypeName('IDispatcherDefinition'),
|
|
93
93
|
},
|
|
94
94
|
definition: {
|
|
95
95
|
schema: Types.toTypeName('ActionDef'),
|
|
@@ -338,6 +338,7 @@ function getModelMetadata({ model }) {
|
|
|
338
338
|
},
|
|
339
339
|
update: {
|
|
340
340
|
serviceClassName: Types.toClassName(`${PascalCase}UpdateService`),
|
|
341
|
+
serviceInterfaceName: Types.toTypeName(`I${PascalCase}UpdateService`),
|
|
341
342
|
serviceVariableName: Types.toVariableName(`${uncapitalizedPlural}`),
|
|
342
343
|
serviceFileName: Types.toFileName(`${camelCase}.update.service`),
|
|
343
344
|
serviceFilePath: Types.toPath(`${config.paths.businessLogicPath}update/${camelCase}.update.service`),
|
|
@@ -173,7 +173,16 @@ export type ModelFields = {
|
|
|
173
173
|
/**
|
|
174
174
|
* A list of models that reference this model in their relations.
|
|
175
175
|
*/
|
|
176
|
-
|
|
176
|
+
references: {
|
|
177
|
+
/**
|
|
178
|
+
* The name of the field in the referencing model that references this model.
|
|
179
|
+
*/
|
|
180
|
+
referencingField: FieldRelation;
|
|
181
|
+
/**
|
|
182
|
+
* The model that references this model.
|
|
183
|
+
*/
|
|
184
|
+
referencingModel: ModelCore;
|
|
185
|
+
}[];
|
|
177
186
|
};
|
|
178
187
|
/**
|
|
179
188
|
* A field of a model.
|
package/dist/prisma/parse.js
CHANGED
|
@@ -41,9 +41,27 @@ function parsePrismaSchema({ datamodel: { enums: enumsRaw, models: modelsRaw },
|
|
|
41
41
|
// NOTE: We preprocess models and enums so that we can populate relationships.
|
|
42
42
|
const models = modelsRaw.map((dmmfModel) => parseModelCore({ dmmfModel, config }));
|
|
43
43
|
const enums = enumsRaw.map((dmmfEnum) => parseEnum({ dmmfEnum, config }));
|
|
44
|
+
// NOTE: Then we parse the fields of the models.
|
|
44
45
|
const modelsWithFields = modelsRaw
|
|
45
46
|
.map((dmmfModel) => parseModel({ dmmfModel, models, enums, config }))
|
|
46
47
|
.filter(isModelNotIgnored);
|
|
48
|
+
// NOTE: Lastly we link back-relations to models.
|
|
49
|
+
for (const mwf of modelsWithFields) {
|
|
50
|
+
for (const field of mwf.fields) {
|
|
51
|
+
if (field.kind !== 'relation') {
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
const referencedModel = modelsWithFields.find((m) => m.sourceName === field.relationToModel.sourceName);
|
|
55
|
+
if (!referencedModel) {
|
|
56
|
+
// NOTE: This should never happen because Prisma should validate the validity of the relation.
|
|
57
|
+
(0, error_1.throwError)(`Model ${highlight(mwf.name)} not found!`);
|
|
58
|
+
}
|
|
59
|
+
referencedModel.references.push({
|
|
60
|
+
referencingModel: mwf,
|
|
61
|
+
referencingField: field,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
}
|
|
47
65
|
return { models: modelsWithFields, enums };
|
|
48
66
|
}
|
|
49
67
|
exports.parsePrismaSchema = parsePrismaSchema;
|
|
@@ -144,10 +162,6 @@ function parseModel({ dmmfModel, enums, models, config, }) {
|
|
|
144
162
|
// we need to preprocess relations and then figure out which scalar
|
|
145
163
|
// fields are actually foreign-keys.
|
|
146
164
|
const referencedModels = {};
|
|
147
|
-
/**
|
|
148
|
-
* A map of models that are referenced in any way in the relations.
|
|
149
|
-
*/
|
|
150
|
-
const relatedModels = {};
|
|
151
165
|
for (const dmmfField of dmmfModel.fields) {
|
|
152
166
|
if (dmmfField.kind !== 'object' || !dmmfField.relationName) {
|
|
153
167
|
continue;
|
|
@@ -158,7 +172,6 @@ function parseModel({ dmmfModel, enums, models, config, }) {
|
|
|
158
172
|
}
|
|
159
173
|
if (!dmmfField.relationFromFields || dmmfField.relationFromFields.length === 0) {
|
|
160
174
|
// NOTE: This field has no foreign-key values in this model so it must be a back-relation.
|
|
161
|
-
relatedModels[dmmfField.type] = referencedModel;
|
|
162
175
|
continue;
|
|
163
176
|
}
|
|
164
177
|
if (dmmfField.relationFromFields.length > 1) {
|
|
@@ -172,11 +185,10 @@ function parseModel({ dmmfModel, enums, models, config, }) {
|
|
|
172
185
|
referencedModels[dmmfField.relationFromFields[0]] = referencedModel;
|
|
173
186
|
}
|
|
174
187
|
const relationFields = dmmfModel.fields
|
|
175
|
-
.filter((f) => { var _a; return f.kind === 'object' && ((_a = f.relationToFields) === null || _a === void 0 ? void 0 : _a.length) === 1; })
|
|
188
|
+
.filter((f) => { var _a, _b; return f.kind === 'object' && ((_a = f.relationToFields) === null || _a === void 0 ? void 0 : _a.length) === 1 && ((_b = f.relationFromFields) === null || _b === void 0 ? void 0 : _b.length) === 1; })
|
|
176
189
|
.reduce((acc, f) => {
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
}
|
|
190
|
+
// NOTE: It's safe to assume that `relationFromFields` and `relationToFields` are defined because of the filter above.
|
|
191
|
+
acc[f.relationFromFields[0]] = f;
|
|
180
192
|
return acc;
|
|
181
193
|
}, {});
|
|
182
194
|
const fields = dmmfModel.fields
|
|
@@ -246,7 +258,9 @@ function parseModel({ dmmfModel, enums, models, config, }) {
|
|
|
246
258
|
nameField,
|
|
247
259
|
fields,
|
|
248
260
|
createdAtField,
|
|
249
|
-
updatedAtField,
|
|
261
|
+
updatedAtField,
|
|
262
|
+
// NOTE: This is only a stub because we link references after all models were parsed above.
|
|
263
|
+
references: [] });
|
|
250
264
|
}
|
|
251
265
|
/**
|
|
252
266
|
* Checks that there is exactly one id field and that there is at most one default field.
|