@postxl/generator 0.56.2 → 0.56.4
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/businesslogic-actiontypes.generator.js +3 -4
- package/dist/generators/indices/datamock-module.generator.js +1 -1
- package/dist/generators/indices/dataservice.generator.js +7 -7
- package/dist/generators/indices/dispatcher-service.generator.js +19 -6
- package/dist/generators/indices/importexport-exporter-class.generator.js +9 -22
- package/dist/generators/indices/importexport-import-service.generator.js +4 -4
- 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 +123 -99
- package/dist/generators/models/businesslogic-view.generator.js +3 -3
- package/dist/generators/models/repository.generator.js +9 -9
- 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 +21 -7
- package/dist/lib/meta.js +9 -4
- 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
|
// -------------------------------------------------------------------------
|
|
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.generateBusinessLogicActionTypes = void 0;
|
|
4
4
|
const imports_1 = require("../../lib/imports");
|
|
5
5
|
const meta_1 = require("../../lib/meta");
|
|
6
|
-
const types_1 = require("../../lib/schema/types");
|
|
7
6
|
const file_1 = require("../../lib/utils/file");
|
|
8
7
|
/**
|
|
9
8
|
* Generates the action types for the BusinessLogicModule.
|
|
@@ -11,7 +10,7 @@ const file_1 = require("../../lib/utils/file");
|
|
|
11
10
|
function generateBusinessLogicActionTypes({ models, meta }) {
|
|
12
11
|
const imports = imports_1.ImportsGenerator.from(meta.businessLogic.update.actionTypesFilePath).addImport({
|
|
13
12
|
from: meta.actions.importPath,
|
|
14
|
-
items: [
|
|
13
|
+
items: [meta.actions.definition.payload, meta.actions.definition.resultDict],
|
|
15
14
|
});
|
|
16
15
|
const updateServiceImports = [];
|
|
17
16
|
const modelNameTypeElements = [];
|
|
@@ -27,8 +26,8 @@ function generateBusinessLogicActionTypes({ models, meta }) {
|
|
|
27
26
|
to: modelMeta.businessLogic.update.serviceFilePath,
|
|
28
27
|
});
|
|
29
28
|
updateServiceImports.push(`import type * as ${className} from '${relativeImportPath}'`);
|
|
30
|
-
actionsTypeElements.push(
|
|
31
|
-
actionResultTypeElements.push(`${scope}:
|
|
29
|
+
actionsTypeElements.push(`${meta.actions.definition.payload}<${className}.Scope, ${className}.Actions>`);
|
|
30
|
+
actionResultTypeElements.push(`${scope}: ${meta.actions.definition.resultDict}<${className}.Actions>`);
|
|
32
31
|
}
|
|
33
32
|
return /* ts */ `
|
|
34
33
|
${imports.generate()}
|
|
@@ -36,7 +36,7 @@ function generateDataMockModule({ models, meta }) {
|
|
|
36
36
|
[meta.data.dataModuleFilePath]: [Types.toVariableName('DataModule')],
|
|
37
37
|
[meta.data.dataService.filePath]: [meta.data.dataService.class],
|
|
38
38
|
// we need to import the file directly instead via the normal index file as this would cause a circular dependency else
|
|
39
|
-
[meta.actions.importPath]: [meta.actions.
|
|
39
|
+
[meta.actions.importPath]: [meta.actions.execution.mock],
|
|
40
40
|
});
|
|
41
41
|
for (const { model, meta } of mm) {
|
|
42
42
|
imports.addTypeImport({ items: [model.typeName], from: meta.types.importPath });
|
|
@@ -29,7 +29,7 @@ function generateDataService({ models, meta }) {
|
|
|
29
29
|
[meta.types.importPath]: [(0, types_1.toAnnotatedTypeName)(meta.types.dto.create), (0, types_1.toAnnotatedTypeName)(meta.types.dto.update)],
|
|
30
30
|
[meta.data.repository.typeFilePath]: [(0, types_1.toAnnotatedTypeName)(meta.data.repository.typeName)],
|
|
31
31
|
[meta.data.types.filePath]: [(0, types_1.toAnnotatedTypeName)(meta.data.types.bulkMutation)],
|
|
32
|
-
[meta.actions.importPath]: [meta.actions.
|
|
32
|
+
[meta.actions.importPath]: [meta.actions.execution.interface],
|
|
33
33
|
});
|
|
34
34
|
const creates = [];
|
|
35
35
|
const updates = [];
|
|
@@ -77,7 +77,7 @@ export class ${meta.data.dataService.class} {
|
|
|
77
77
|
}
|
|
78
78
|
public async ${meta.data.dataService.executeBulkMutations}(
|
|
79
79
|
{ steps, execution }:
|
|
80
|
-
{ steps: ${meta.data.types.bulkMutation}[]; execution: ${meta.actions.
|
|
80
|
+
{ steps: ${meta.data.types.bulkMutation}[]; execution: ${meta.actions.execution.interface} }
|
|
81
81
|
) {
|
|
82
82
|
let index = 0
|
|
83
83
|
for (const step of steps) {
|
|
@@ -88,7 +88,7 @@ export class ${meta.data.dataService.class} {
|
|
|
88
88
|
|
|
89
89
|
public async ${meta.data.dataService.executeBulkMutation}(
|
|
90
90
|
{ data, execution }:
|
|
91
|
-
{ data: ${meta.data.types.bulkMutation}, execution: ${meta.actions.
|
|
91
|
+
{ data: ${meta.data.types.bulkMutation}, execution: ${meta.actions.execution.interface}}
|
|
92
92
|
) {
|
|
93
93
|
// NOTE: the order of these calls is important, because of foreign key constraints
|
|
94
94
|
// The current order is based on the order of the models in the schema
|
|
@@ -114,7 +114,7 @@ export class ${meta.data.dataService.class} {
|
|
|
114
114
|
name: string
|
|
115
115
|
data: ${meta.types.dto.create}<T, ID>[] | undefined
|
|
116
116
|
repo: ${meta.data.repository.typeName}<T, ID>
|
|
117
|
-
execution: ${meta.actions.
|
|
117
|
+
execution: ${meta.actions.execution.interface}
|
|
118
118
|
}): Promise<void> {
|
|
119
119
|
if (!data) {
|
|
120
120
|
return
|
|
@@ -146,7 +146,7 @@ export class ${meta.data.dataService.class} {
|
|
|
146
146
|
name: string
|
|
147
147
|
data: ${meta.types.dto.update}<T, ID>[] | undefined
|
|
148
148
|
repo: ${meta.data.repository.typeName}<T, ID>
|
|
149
|
-
execution: ${meta.actions.
|
|
149
|
+
execution: ${meta.actions.execution.interface}
|
|
150
150
|
}): Promise<void> {
|
|
151
151
|
if (!data) {
|
|
152
152
|
return
|
|
@@ -178,7 +178,7 @@ export class ${meta.data.dataService.class} {
|
|
|
178
178
|
name: string
|
|
179
179
|
data: (${meta.types.dto.create}<T, ID> | ${meta.types.dto.update}<T, ID>)[] | undefined
|
|
180
180
|
repo: ${meta.data.repository.typeName}<T, ID>
|
|
181
|
-
execution: ${meta.actions.
|
|
181
|
+
execution: ${meta.actions.execution.interface}
|
|
182
182
|
}): Promise<void> {
|
|
183
183
|
if (!data) {
|
|
184
184
|
return
|
|
@@ -210,7 +210,7 @@ export class ${meta.data.dataService.class} {
|
|
|
210
210
|
name: string
|
|
211
211
|
data: ID[] | undefined
|
|
212
212
|
repo: ${meta.data.repository.typeName}<T, ID>
|
|
213
|
-
execution: ${meta.actions.
|
|
213
|
+
execution: ${meta.actions.execution.interface}
|
|
214
214
|
}): Promise<void> {
|
|
215
215
|
if (!data) {
|
|
216
216
|
return
|
|
@@ -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,35 @@ 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
|
+
return method({ data: action.payload, execution })
|
|
87
|
+
}
|
|
76
88
|
`;
|
|
77
89
|
})
|
|
78
90
|
.join('\n')}
|
|
91
|
+
|
|
79
92
|
case 'seed':
|
|
80
|
-
return this.seedService.dispatch({ action, execution })
|
|
93
|
+
return this.seedService.dispatch({ action, execution }) as Promise<ResultOfAction<A>>
|
|
81
94
|
|
|
82
95
|
case 'import':
|
|
83
|
-
return this.importService.dispatch({ action, execution })
|
|
96
|
+
return this.importService.dispatch({ action, execution }) as Promise<ResultOfAction<A>>
|
|
84
97
|
|
|
85
98
|
default:
|
|
86
99
|
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
|
? `
|
|
@@ -22,7 +22,7 @@ function generateImportExportImportService({ models, meta }) {
|
|
|
22
22
|
(0, types_1.toAnnotatedTypeName)(dto.idType),
|
|
23
23
|
(0, types_1.toAnnotatedTypeName)(dto.update),
|
|
24
24
|
],
|
|
25
|
-
[meta.actions.importPath]: [meta.actions.
|
|
25
|
+
[meta.actions.importPath]: [meta.actions.execution.interface, meta.actions.dispatcher.class],
|
|
26
26
|
[types.filePath]: [
|
|
27
27
|
(0, types_1.toAnnotatedTypeName)(delta_Fields),
|
|
28
28
|
(0, types_1.toAnnotatedTypeName)(delta_Model.type),
|
|
@@ -78,7 +78,7 @@ export class ${meta.importExport.importService.name} {
|
|
|
78
78
|
execution
|
|
79
79
|
}: {
|
|
80
80
|
action: Action_Import;
|
|
81
|
-
execution: ${meta.actions.
|
|
81
|
+
execution: ${meta.actions.execution.interface}
|
|
82
82
|
}) {
|
|
83
83
|
switch (action.type) {
|
|
84
84
|
case 'detect-delta':
|
|
@@ -110,7 +110,7 @@ export class ${meta.importExport.importService.name} {
|
|
|
110
110
|
execution
|
|
111
111
|
}: {
|
|
112
112
|
delta: Delta;
|
|
113
|
-
execution: ${meta.actions.
|
|
113
|
+
execution: ${meta.actions.execution.interface}
|
|
114
114
|
}) {
|
|
115
115
|
const bulkMutations = ${converterFunctions.deltaToBulkMutations}(delta)
|
|
116
116
|
return this.data.${meta.data.dataService.executeBulkMutations}({ steps: bulkMutations, execution })
|
|
@@ -121,7 +121,7 @@ export class ${meta.importExport.importService.name} {
|
|
|
121
121
|
execution
|
|
122
122
|
}: {
|
|
123
123
|
data: ${meta.importExport.decoder.decodedPXLModelDataTypeName};
|
|
124
|
-
execution: ${meta.actions.
|
|
124
|
+
execution: ${meta.actions.execution.interface}
|
|
125
125
|
}) {
|
|
126
126
|
const { bulkMutations } = await this.detectDelta(data)
|
|
127
127
|
return this.data.${meta.data.dataService.executeBulkMutations}({ steps: bulkMutations, execution })
|
|
@@ -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,25 +13,48 @@ 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.actionExecution.interface,
|
|
27
|
-
schemaMeta.actions.dispatcher.result,
|
|
28
|
-
schemaMeta.actions.dispatcher.interface,
|
|
29
|
-
schemaMeta.actions.dispatcher.actionMethod,
|
|
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
|
});
|
|
34
|
-
const { dispatcher } = schemaMeta.actions;
|
|
35
58
|
for (const relation of (0, fields_1.getRelationFields)(model)) {
|
|
36
59
|
// NOTE: We add branded id type and type name imports only for foreign models.
|
|
37
60
|
if (relation.relationToModel.typeName === model.typeName) {
|
|
@@ -40,7 +63,7 @@ function generateModelBusinessLogicUpdate({ model, meta }) {
|
|
|
40
63
|
const refMeta = (0, meta_1.getModelMetadata)({ model: relation.relationToModel });
|
|
41
64
|
imports.addImport({
|
|
42
65
|
items: [refMeta.types.toBrandedIdTypeFnName],
|
|
43
|
-
from: refMeta.types.
|
|
66
|
+
from: refMeta.types.importPath,
|
|
44
67
|
});
|
|
45
68
|
}
|
|
46
69
|
/**
|
|
@@ -50,27 +73,70 @@ function generateModelBusinessLogicUpdate({ model, meta }) {
|
|
|
50
73
|
*/
|
|
51
74
|
const modelRepositoryVariableName = meta.businessLogic.dataRepositoryVariableName;
|
|
52
75
|
const constructorParameters = [
|
|
53
|
-
`
|
|
76
|
+
`private readonly ${modelRepositoryVariableName}: ${meta.data.repository.className}`,
|
|
54
77
|
`@Inject(forwardRef(() => ${schemaMeta.businessLogic.update.serviceClassName})) private readonly updateService: ${schemaMeta.businessLogic.update.serviceClassName}`,
|
|
55
78
|
`@Inject(forwardRef(() => ${schemaMeta.businessLogic.view.serviceClassName})) private readonly viewService: ${schemaMeta.businessLogic.view.serviceClassName}`,
|
|
56
79
|
];
|
|
57
80
|
const { zodCreateObject, zodUpdateObject, zodUpsertObject } = meta.businessLogic.update;
|
|
58
|
-
|
|
59
|
-
|
|
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<${schemaMeta.actions.dispatcher.result}<Actions, AM>>`;
|
|
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, UnionOmit } 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<AM extends ${dispatcher.actionMethod}<Scope, Actions>>({
|
|
165
|
-
action,
|
|
166
|
-
execution,
|
|
167
|
-
}: {
|
|
168
|
-
action: UnionOmit<AM, 'result'>
|
|
169
|
-
execution: ${schemaMeta.actions.actionExecution.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
|
}
|
|
@@ -59,8 +59,8 @@ function generateModelBusinessLogicView({ model, meta }) {
|
|
|
59
59
|
variableDefinition: `const ${relationVariableName} = ${relationVariableDefinition}`,
|
|
60
60
|
});
|
|
61
61
|
if (relation.relationToModel.typeName !== model.typeName) {
|
|
62
|
-
imports.addImport({ from: refMeta.types.
|
|
63
|
-
imports.addTypeImport({ from: refMeta.types.
|
|
62
|
+
imports.addImport({ from: refMeta.types.importPath, items: [refMeta.types.toBrandedIdTypeFnName] });
|
|
63
|
+
imports.addTypeImport({ from: refMeta.types.importPath, items: [refModel.brandedIdType, refMeta.types.typeName] });
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
66
|
const hasLinkedItems = variables.size > 0;
|
|
@@ -68,7 +68,7 @@ function generateModelBusinessLogicView({ model, meta }) {
|
|
|
68
68
|
// NOTE: If we need to generate the linked item type, we need to import the enum types.
|
|
69
69
|
for (const enumField of (0, fields_1.getEnumFields)(model)) {
|
|
70
70
|
const enumMeta = (0, meta_1.getEnumMetadata)(enumField);
|
|
71
|
-
imports.addTypeImport({ from: enumMeta.types.
|
|
71
|
+
imports.addTypeImport({ from: enumMeta.types.importPath, items: [enumField.typeName] });
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
74
|
const linkedItemsGetterFn = `
|
|
@@ -25,7 +25,7 @@ function generateRepository({ model, meta }) {
|
|
|
25
25
|
(0, types_1.toAnnotatedTypeName)(meta.types.dto.update),
|
|
26
26
|
(0, types_1.toAnnotatedTypeName)(meta.types.dto.upsert),
|
|
27
27
|
],
|
|
28
|
-
[schemaMeta.actions.importPath]: [schemaMeta.actions.
|
|
28
|
+
[schemaMeta.actions.importPath]: [schemaMeta.actions.execution.interface],
|
|
29
29
|
});
|
|
30
30
|
// NOTE: We first generate different parts of the code responsible for a particular task
|
|
31
31
|
// and then we combine them into the final code block.
|
|
@@ -990,42 +990,42 @@ function getRepositoryMethodsTypeSignatures({ model, meta }) {
|
|
|
990
990
|
return {
|
|
991
991
|
create: {
|
|
992
992
|
jsDoc: [`Creates a new ${meta.userFriendlyName} and returns it.`],
|
|
993
|
-
parameters: [`{item: ${meta.types.dto.create}, execution: ${schemaMeta.actions.
|
|
993
|
+
parameters: [`{item: ${meta.types.dto.create}, execution: ${schemaMeta.actions.execution.interface}}`],
|
|
994
994
|
returnType: `Promise<${model.typeName}>`,
|
|
995
995
|
},
|
|
996
996
|
createMany: {
|
|
997
997
|
jsDoc: [`Creates multiple new ${meta.userFriendlyNamePlural} and returns them.`],
|
|
998
|
-
parameters: [`{items: ${meta.types.dto.create}[], execution: ${schemaMeta.actions.
|
|
998
|
+
parameters: [`{items: ${meta.types.dto.create}[], execution: ${schemaMeta.actions.execution.interface}}`],
|
|
999
999
|
returnType: `Promise<${model.typeName}[]>`,
|
|
1000
1000
|
},
|
|
1001
1001
|
update: {
|
|
1002
1002
|
jsDoc: [`Updates a ${meta.userFriendlyName} and returns it.`],
|
|
1003
|
-
parameters: [`{item: ${meta.types.dto.update}, execution: ${schemaMeta.actions.
|
|
1003
|
+
parameters: [`{item: ${meta.types.dto.update}, execution: ${schemaMeta.actions.execution.interface}}`],
|
|
1004
1004
|
returnType: `Promise<${model.typeName}>`,
|
|
1005
1005
|
},
|
|
1006
1006
|
updateMany: {
|
|
1007
1007
|
jsDoc: [`Updates multiple ${meta.userFriendlyNamePlural} and returns them.`],
|
|
1008
|
-
parameters: [`{items: ${meta.types.dto.update}[], execution: ${schemaMeta.actions.
|
|
1008
|
+
parameters: [`{items: ${meta.types.dto.update}[], execution: ${schemaMeta.actions.execution.interface}}`],
|
|
1009
1009
|
returnType: `Promise<${model.typeName}[]>`,
|
|
1010
1010
|
},
|
|
1011
1011
|
upsert: {
|
|
1012
1012
|
jsDoc: [`Creates or updates a ${meta.userFriendlyName} and returns it.`],
|
|
1013
|
-
parameters: [`{item: ${meta.types.dto.upsert}, execution: ${schemaMeta.actions.
|
|
1013
|
+
parameters: [`{item: ${meta.types.dto.upsert}, execution: ${schemaMeta.actions.execution.interface}}`],
|
|
1014
1014
|
returnType: `Promise<${model.typeName}>`,
|
|
1015
1015
|
},
|
|
1016
1016
|
upsertMany: {
|
|
1017
1017
|
jsDoc: [`Creates or updates multiple ${meta.userFriendlyNamePlural} and returns them.`],
|
|
1018
|
-
parameters: [`{items: ${meta.types.dto.upsert}[], execution: ${schemaMeta.actions.
|
|
1018
|
+
parameters: [`{items: ${meta.types.dto.upsert}[], execution: ${schemaMeta.actions.execution.interface}}`],
|
|
1019
1019
|
returnType: `Promise<${model.typeName}[]>`,
|
|
1020
1020
|
},
|
|
1021
1021
|
delete: {
|
|
1022
1022
|
jsDoc: [`Deletes a ${meta.userFriendlyName} and returns its id.`],
|
|
1023
|
-
parameters: [`{id: ${model.brandedIdType}, execution: ${schemaMeta.actions.
|
|
1023
|
+
parameters: [`{id: ${model.brandedIdType}, execution: ${schemaMeta.actions.execution.interface}}`],
|
|
1024
1024
|
returnType: `Promise<${model.brandedIdType}>`,
|
|
1025
1025
|
},
|
|
1026
1026
|
deleteMany: {
|
|
1027
1027
|
jsDoc: [`Deletes multiple ${meta.userFriendlyNamePlural} and returns their ids.`],
|
|
1028
|
-
parameters: [`{ids: ${model.brandedIdType}[], execution: ${schemaMeta.actions.
|
|
1028
|
+
parameters: [`{ids: ${model.brandedIdType}[], execution: ${schemaMeta.actions.execution.interface}}`],
|
|
1029
1029
|
returnType: `Promise<${model.brandedIdType}[]>`,
|
|
1030
1030
|
},
|
|
1031
1031
|
};
|
|
@@ -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
|
@@ -93,7 +93,7 @@ export type SchemaMetaData = {
|
|
|
93
93
|
* Path that may be used to import from the action module.
|
|
94
94
|
*/
|
|
95
95
|
importPath: Types.BackendModulePath;
|
|
96
|
-
|
|
96
|
+
execution: {
|
|
97
97
|
/**
|
|
98
98
|
* The name of the interface that handles the action execution.
|
|
99
99
|
*/
|
|
@@ -117,17 +117,27 @@ 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
|
+
};
|
|
124
|
+
definition: {
|
|
125
|
+
/**
|
|
126
|
+
* The schema type to define action definitions.
|
|
127
|
+
*/
|
|
128
|
+
schema: Types.TypeName;
|
|
123
129
|
/**
|
|
124
|
-
* The
|
|
130
|
+
* The generated payload of the defined actions.
|
|
125
131
|
*/
|
|
126
|
-
|
|
132
|
+
payload: Types.TypeName;
|
|
127
133
|
/**
|
|
128
|
-
* The
|
|
134
|
+
* The generated result of the defined actions.
|
|
129
135
|
*/
|
|
130
136
|
result: Types.TypeName;
|
|
137
|
+
/**
|
|
138
|
+
* The transformer type that converts action definitions into results dictionary.
|
|
139
|
+
*/
|
|
140
|
+
resultDict: Types.TypeName;
|
|
131
141
|
};
|
|
132
142
|
};
|
|
133
143
|
/**
|
|
@@ -909,9 +919,13 @@ export type ModelMetaData = {
|
|
|
909
919
|
*/
|
|
910
920
|
update: {
|
|
911
921
|
/**
|
|
912
|
-
* 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)
|
|
913
923
|
*/
|
|
914
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;
|
|
915
929
|
/**
|
|
916
930
|
* The name by which the model's service is exposed in the updateService/context. (e.g. aggregations)
|
|
917
931
|
*/
|
package/dist/lib/meta.js
CHANGED
|
@@ -81,7 +81,7 @@ function getSchemaMetadata({ config }) {
|
|
|
81
81
|
actions: {
|
|
82
82
|
moduleName: Types.toClassName(`ActionModule`),
|
|
83
83
|
importPath: Types.toBackendModulePath(`@backend/actions`),
|
|
84
|
-
|
|
84
|
+
execution: {
|
|
85
85
|
interface: Types.toClassName(`IActionExecution`),
|
|
86
86
|
class: Types.toClassName(`ActionExecution`),
|
|
87
87
|
mock: Types.toClassName(`MockActionExecution`),
|
|
@@ -89,9 +89,13 @@ function getSchemaMetadata({ config }) {
|
|
|
89
89
|
dispatcher: {
|
|
90
90
|
filePath: Types.toPath(`${config.paths.actionsPath}dispatcher.service`),
|
|
91
91
|
class: Types.toClassName(`DispatcherService`),
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
92
|
+
definition: Types.toTypeName('IDispatcherDefinition'),
|
|
93
|
+
},
|
|
94
|
+
definition: {
|
|
95
|
+
schema: Types.toTypeName('ActionDef'),
|
|
96
|
+
payload: Types.toTypeName('ActionDefPayload'),
|
|
97
|
+
result: Types.toTypeName('ActionDefResult'),
|
|
98
|
+
resultDict: Types.toTypeName('ActionDefResultDict'),
|
|
95
99
|
},
|
|
96
100
|
},
|
|
97
101
|
businessLogic: {
|
|
@@ -334,6 +338,7 @@ function getModelMetadata({ model }) {
|
|
|
334
338
|
},
|
|
335
339
|
update: {
|
|
336
340
|
serviceClassName: Types.toClassName(`${PascalCase}UpdateService`),
|
|
341
|
+
serviceInterfaceName: Types.toTypeName(`I${PascalCase}UpdateService`),
|
|
337
342
|
serviceVariableName: Types.toVariableName(`${uncapitalizedPlural}`),
|
|
338
343
|
serviceFileName: Types.toFileName(`${camelCase}.update.service`),
|
|
339
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.
|