@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,64 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.generateDataMockModule = void 0;
|
|
4
|
-
const imports_1 = require("../../lib/imports");
|
|
5
|
-
const meta_1 = require("../../lib/meta");
|
|
6
|
-
/**
|
|
7
|
-
* Generates a mocking class
|
|
8
|
-
*/
|
|
9
|
-
function generateDataMockModule({ models, meta }) {
|
|
10
|
-
const mm = models.map((model) => ({ model, meta: (0, meta_1.getModelMetadata)({ model }) }));
|
|
11
|
-
const imports = imports_1.ImportsGenerator.from(meta.data.mockModule.location.path).addImports({
|
|
12
|
-
[meta.data.moduleLocation.path]: [meta.data.moduleName],
|
|
13
|
-
[meta.data.dataService.location.path]: [meta.data.dataService.class],
|
|
14
|
-
[meta.backendModules.db.moduleLocation.import]: [meta.backendModules.db.moduleName],
|
|
15
|
-
// we need to import the file directly instead via the normal index file as this would cause a circular dependency else
|
|
16
|
-
[meta.actions.execution.mockLocation.import]: [meta.actions.execution.mock],
|
|
17
|
-
});
|
|
18
|
-
for (const { model, meta } of mm) {
|
|
19
|
-
imports.addTypeImport({ items: [model.typeName], from: meta.types.importPath });
|
|
20
|
-
imports.addImport({ items: [meta.data.repository.className], from: meta.data.repository.location.path });
|
|
21
|
-
imports.addImport({ items: [meta.data.mockRepository.className], from: meta.data.mockRepository.location.path });
|
|
22
|
-
}
|
|
23
|
-
const providers = mm
|
|
24
|
-
.map(({ meta }) => `{
|
|
25
|
-
provide: ${meta.data.repository.className},
|
|
26
|
-
useFactory: async () => {
|
|
27
|
-
const repository = new ${meta.data.mockRepository.className}()
|
|
28
|
-
if (!!seed && !!seed.${meta.seed.constantName}) {
|
|
29
|
-
await repository.reInit({items: seed.${meta.seed.constantName}, execution })
|
|
30
|
-
}
|
|
31
|
-
return repository
|
|
32
|
-
}
|
|
33
|
-
}`)
|
|
34
|
-
.join(', ');
|
|
35
|
-
return /* ts */ `
|
|
36
|
-
import { DynamicModule } from '@nestjs/common'
|
|
37
|
-
|
|
38
|
-
${imports.generate()}
|
|
39
|
-
|
|
40
|
-
export class ${meta.data.mockModule.name} {
|
|
41
|
-
static mock(seed?: MockData): DynamicModule {
|
|
42
|
-
const execution = new MockActionExecution()
|
|
43
|
-
|
|
44
|
-
const providers = [
|
|
45
|
-
DataService,
|
|
46
|
-
${providers}
|
|
47
|
-
]
|
|
48
|
-
|
|
49
|
-
return {
|
|
50
|
-
module: ${meta.data.moduleName},
|
|
51
|
-
imports: [DatabaseModule.provideMock()],
|
|
52
|
-
providers,
|
|
53
|
-
exports: providers,
|
|
54
|
-
global: true,
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export interface ${meta.data.dataMockDataType} {
|
|
60
|
-
${mm.map(({ model, meta }) => `${meta.data.mockDataPropertyName}?: ${model.typeName}[]`).join('\n')}
|
|
61
|
-
}
|
|
62
|
-
`;
|
|
63
|
-
}
|
|
64
|
-
exports.generateDataMockModule = generateDataMockModule;
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { SchemaMetaData } from '../../lib/meta';
|
|
2
|
-
import { Model } from '../../lib/schema/schema';
|
|
3
|
-
/**
|
|
4
|
-
* Generates a generic data mocker class.
|
|
5
|
-
*/
|
|
6
|
-
export declare function generateDataMocker({ models, meta: schemaMeta }: {
|
|
7
|
-
models: Model[];
|
|
8
|
-
meta: SchemaMetaData;
|
|
9
|
-
}): string;
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.generateDataMocker = void 0;
|
|
4
|
-
const imports_1 = require("../../lib/imports");
|
|
5
|
-
const meta_1 = require("../../lib/meta");
|
|
6
|
-
const schema_1 = require("../../lib/schema/schema");
|
|
7
|
-
const types_1 = require("../../lib/schema/types");
|
|
8
|
-
/**
|
|
9
|
-
* Generates a generic data mocker class.
|
|
10
|
-
*/
|
|
11
|
-
function generateDataMocker({ models, meta: schemaMeta }) {
|
|
12
|
-
const modelMetas = models.map((model) => ({ model, meta: (0, meta_1.getModelMetadata)({ model }) }));
|
|
13
|
-
const imports = imports_1.ImportsGenerator.from(schemaMeta.e2e.dataMockerLocation.path);
|
|
14
|
-
for (const { model, meta } of modelMetas) {
|
|
15
|
-
imports.addImports({
|
|
16
|
-
[meta.types.importPath]: [(0, types_1.toAnnotatedTypeName)(model.typeName)],
|
|
17
|
-
[meta.e2e.stubLocation.path]: [meta.e2e.stubGenerationFnName],
|
|
18
|
-
});
|
|
19
|
-
}
|
|
20
|
-
const publicVariables = modelMetas
|
|
21
|
-
.map(({ model, meta }) => `public ${meta.data.dataServiceName}: ${model.typeName}[] = []`)
|
|
22
|
-
.join('\n');
|
|
23
|
-
const privateIds = modelMetas
|
|
24
|
-
.map(({ model, meta }) => `private ${meta.data.dataServiceIdName}Ids = new IdTracker<${model.typeName}>()`)
|
|
25
|
-
.join('\n');
|
|
26
|
-
const addDataFunctions = modelMetas.map(({ model, meta }) => generateAddDataFunction(model, meta)).join('\n');
|
|
27
|
-
return `
|
|
28
|
-
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
29
|
-
import type { MockData } from '@backend/data/data.mock.module'
|
|
30
|
-
|
|
31
|
-
${imports.generate()}
|
|
32
|
-
|
|
33
|
-
import { IdTracker } from './id-tracker.class'
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
export class DataMocker implements MockData {
|
|
37
|
-
${publicVariables}
|
|
38
|
-
|
|
39
|
-
${privateIds}
|
|
40
|
-
|
|
41
|
-
${addDataFunctions}
|
|
42
|
-
}
|
|
43
|
-
`;
|
|
44
|
-
}
|
|
45
|
-
exports.generateDataMocker = generateDataMocker;
|
|
46
|
-
function generateAddDataFunction(model, meta) {
|
|
47
|
-
const { fields, idField } = model;
|
|
48
|
-
const relations = fields
|
|
49
|
-
.filter(schema_1.isFieldRelation)
|
|
50
|
-
.map((field) => (Object.assign(Object.assign({}, field), { meta: (0, meta_1.getModelMetadata)({ model: field.relationToModel }), fieldMeta: (0, meta_1.getFieldMetadata)({ field }), model: field.relationToModel })))
|
|
51
|
-
.map((r) => {
|
|
52
|
-
if (r.isRequired) {
|
|
53
|
-
return `
|
|
54
|
-
if (_item.${r.name}) {
|
|
55
|
-
if (this.${r.meta.data.dataServiceName}.findIndex((x) => x.id === _item.${r.name}) === -1) {
|
|
56
|
-
this.add${r.model.typeName}({ id: _item.${r.name} })
|
|
57
|
-
}
|
|
58
|
-
} else {
|
|
59
|
-
if (this.${r.meta.data.dataServiceName}.length === 0) {
|
|
60
|
-
this.add${r.model.typeName}()
|
|
61
|
-
}
|
|
62
|
-
_item.${r.name} = this.${r.meta.data.dataServiceName}[0].id
|
|
63
|
-
}
|
|
64
|
-
`;
|
|
65
|
-
}
|
|
66
|
-
return `
|
|
67
|
-
if (_item.${r.name}) {
|
|
68
|
-
if (this.${r.meta.data.dataServiceName}.findIndex((x) => x.id === _item.${r.name}) === -1) {
|
|
69
|
-
this.add${r.model.typeName}({ id: _item.${r.name} })
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
`;
|
|
73
|
-
});
|
|
74
|
-
// TODO: Move the publicly accessible function's name to the metadata definition!
|
|
75
|
-
return /* ts */ `
|
|
76
|
-
public add${model.typeName}(
|
|
77
|
-
item?: Partial<Omit<${model.typeName}, '${idField.name}'> & { ${idField.name}: ${idField.unbrandedTypeName} }>
|
|
78
|
-
): DataMocker {
|
|
79
|
-
const _stub = stub${model.typeName}(item ?? {})
|
|
80
|
-
const _item = this.${meta.data.dataServiceIdName}Ids.ensureId(_stub)
|
|
81
|
-
|
|
82
|
-
this.${meta.data.dataServiceName}.push(_item)
|
|
83
|
-
|
|
84
|
-
${relations.join('\n')}
|
|
85
|
-
|
|
86
|
-
return this
|
|
87
|
-
}`;
|
|
88
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { SchemaMetaData } from '../../lib/meta';
|
|
2
|
-
import { Model } from '../../lib/schema/schema';
|
|
3
|
-
/**
|
|
4
|
-
* Generates a const that contains the SQL to delete all data from the E2E database.
|
|
5
|
-
*
|
|
6
|
-
* This is used in e2e tests to empty the database before each test.
|
|
7
|
-
*/
|
|
8
|
-
export declare function generateEmptyDatabaseCommand({ models }: {
|
|
9
|
-
models: Model[];
|
|
10
|
-
meta: SchemaMetaData;
|
|
11
|
-
}): string;
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.generateEmptyDatabaseCommand = void 0;
|
|
4
|
-
/**
|
|
5
|
-
* Generates a const that contains the SQL to delete all data from the E2E database.
|
|
6
|
-
*
|
|
7
|
-
* This is used in e2e tests to empty the database before each test.
|
|
8
|
-
*/
|
|
9
|
-
function generateEmptyDatabaseCommand({ models }) {
|
|
10
|
-
const modelTables = models.map((model) => `${model.sourceSchemaName !== undefined ? `"${model.sourceSchemaName}".` : ''}"${model.sourceName}"`);
|
|
11
|
-
// We determine the schema used for all system tables by looking at the User model's schema.
|
|
12
|
-
const userModel = models.find((model) => model.name === 'User');
|
|
13
|
-
if (!userModel) {
|
|
14
|
-
throw new Error('Model definition for "User" could not be found - hence schema for system table cannot be derived!');
|
|
15
|
-
}
|
|
16
|
-
const configSchema = userModel.sourceSchemaName !== undefined ? `"${userModel.sourceSchemaName}".` : '';
|
|
17
|
-
const systemTables = ['Action', 'Mutation'].map((table) => `${configSchema}"${table}"`);
|
|
18
|
-
const configTableName = `${configSchema}"Config"`;
|
|
19
|
-
return /** ts */ `
|
|
20
|
-
/**
|
|
21
|
-
* SQL instruction to delete all data from the E2E database. Should only be used internally by the DbService!
|
|
22
|
-
*/
|
|
23
|
-
export const wipeDatabaseCommand = \`
|
|
24
|
-
DO $$
|
|
25
|
-
BEGIN
|
|
26
|
-
IF EXISTS (SELECT 1 FROM ${configTableName} WHERE "isTest" = TRUE) THEN
|
|
27
|
-
TRUNCATE TABLE
|
|
28
|
-
${[...systemTables, ...modelTables].join(',\n ')};
|
|
29
|
-
END IF;
|
|
30
|
-
END
|
|
31
|
-
$$;\`
|
|
32
|
-
`;
|
|
33
|
-
}
|
|
34
|
-
exports.generateEmptyDatabaseCommand = generateEmptyDatabaseCommand;
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { SchemaMetaData } from '../../lib/meta';
|
|
2
|
-
import { Model } from '../../lib/schema/schema';
|
|
3
|
-
/**
|
|
4
|
-
* Generates the TestDataService class.
|
|
5
|
-
*/
|
|
6
|
-
export declare function generateTestDataService({ models, meta: schemaMeta, }: {
|
|
7
|
-
models: Model[];
|
|
8
|
-
meta: SchemaMetaData;
|
|
9
|
-
}): string;
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.generateTestDataService = void 0;
|
|
4
|
-
const imports_1 = require("../../lib/imports");
|
|
5
|
-
const meta_1 = require("../../lib/meta");
|
|
6
|
-
const types_1 = require("../../lib/schema/types");
|
|
7
|
-
/**
|
|
8
|
-
* Generates the TestDataService class.
|
|
9
|
-
*/
|
|
10
|
-
function generateTestDataService({ models, meta: schemaMeta, }) {
|
|
11
|
-
const imports = imports_1.ImportsGenerator.from(schemaMeta.data.testDataServiceFilePath);
|
|
12
|
-
imports.addImports({
|
|
13
|
-
[schemaMeta.actions.execution.classLocation.import]: [(0, types_1.toClassName)('ActionExecutionFactory')],
|
|
14
|
-
[schemaMeta.data.dataService.location.import]: [schemaMeta.data.dataService.class],
|
|
15
|
-
[schemaMeta.backendModules.db.databaseService.location.import]: [schemaMeta.backendModules.db.databaseService.name],
|
|
16
|
-
[schemaMeta.data.mockModule.location.import]: [(0, types_1.toAnnotatedTypeName)(schemaMeta.data.dataMockDataType)],
|
|
17
|
-
[schemaMeta.importExport.converterFunctions.location.import]: [
|
|
18
|
-
schemaMeta.importExport.converterFunctions.mockDataToBulkMutations,
|
|
19
|
-
],
|
|
20
|
-
});
|
|
21
|
-
const reInitCalls = [];
|
|
22
|
-
const modelMetas = models.map((model) => ({ model, meta: (0, meta_1.getModelMetadata)({ model }) }));
|
|
23
|
-
for (const { model, meta } of modelMetas) {
|
|
24
|
-
if (model.defaultField) {
|
|
25
|
-
imports.addImport({ items: [meta.data.stubGenerationFnName], from: meta.data.stubLocation.import });
|
|
26
|
-
const stubDefault = `${meta.data.stubGenerationFnName}({ ${model.defaultField.name}: true })`;
|
|
27
|
-
reInitCalls.push(`await this.dataService.${meta.data.dataServiceName}.reInit({ items: mockData.${meta.seed.constantName}?.create ?? [${stubDefault}], execution: actionExecution })`);
|
|
28
|
-
}
|
|
29
|
-
else {
|
|
30
|
-
reInitCalls.push(`await this.dataService.${meta.data.dataServiceName}.reInit({ items: mockData.${meta.seed.constantName}?.create ?? [], execution: actionExecution })`);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
return /* ts */ `
|
|
34
|
-
import { Injectable, Logger } from '@nestjs/common'
|
|
35
|
-
|
|
36
|
-
${imports.generate()}
|
|
37
|
-
|
|
38
|
-
@Injectable()
|
|
39
|
-
export class TestDataService {
|
|
40
|
-
private logger = new Logger(TestDataService.name)
|
|
41
|
-
|
|
42
|
-
constructor(
|
|
43
|
-
private readonly databaseService: DatabaseService,
|
|
44
|
-
private readonly dataService: ${schemaMeta.data.dataService.class},
|
|
45
|
-
private readonly actionExecutionFactory: ActionExecutionFactory,
|
|
46
|
-
) {}
|
|
47
|
-
|
|
48
|
-
public async resetTestData(data: MockData) {
|
|
49
|
-
this.logger.log('💥 Emptying test data')
|
|
50
|
-
await this.databaseService.WIPE_ENTIRE_DATABASE()
|
|
51
|
-
|
|
52
|
-
// We need to init the user repository first so the root user is created
|
|
53
|
-
this.logger.log('✍ Setting test data')
|
|
54
|
-
await this.dataService.users.init()
|
|
55
|
-
|
|
56
|
-
this.logger.log('✍ Setting test data')
|
|
57
|
-
|
|
58
|
-
const mockData = ${schemaMeta.importExport.converterFunctions.mockDataToBulkMutations}(data)
|
|
59
|
-
|
|
60
|
-
const actionExecution = await this.actionExecutionFactory.create({
|
|
61
|
-
action: {
|
|
62
|
-
scope: 'seed',
|
|
63
|
-
type: 'data',
|
|
64
|
-
name: 'E2E',
|
|
65
|
-
order: 0,
|
|
66
|
-
payload: []
|
|
67
|
-
},
|
|
68
|
-
databaseService: this.databaseService,
|
|
69
|
-
user: this.dataService.users.rootUser,
|
|
70
|
-
})
|
|
71
|
-
|
|
72
|
-
try {
|
|
73
|
-
${reInitCalls.join('\n')}
|
|
74
|
-
|
|
75
|
-
await actionExecution.success()
|
|
76
|
-
this.logger.log('✅ Reset test data')
|
|
77
|
-
} catch (e) {
|
|
78
|
-
await actionExecution.error(e)
|
|
79
|
-
throw e
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
}`;
|
|
83
|
-
}
|
|
84
|
-
exports.generateTestDataService = generateTestDataService;
|
|
@@ -1,324 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
-
if (mod && mod.__esModule) return mod;
|
|
20
|
-
var result = {};
|
|
21
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
-
__setModuleDefault(result, mod);
|
|
23
|
-
return result;
|
|
24
|
-
};
|
|
25
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
exports.generateModelBusinessLogicUpdate = void 0;
|
|
27
|
-
const imports_1 = require("../../lib/imports");
|
|
28
|
-
const meta_1 = require("../../lib/meta");
|
|
29
|
-
const fields_1 = require("../../lib/schema/fields");
|
|
30
|
-
const Types = __importStar(require("../../lib/schema/types"));
|
|
31
|
-
const typescript_1 = require("../../lib/typescript");
|
|
32
|
-
const jsdoc_1 = require("../../lib/utils/jsdoc");
|
|
33
|
-
const string_1 = require("../../lib/utils/string");
|
|
34
|
-
const zod_1 = require("../../lib/zod");
|
|
35
|
-
/**
|
|
36
|
-
* Generates update business logic for a given model.
|
|
37
|
-
* The update logic handles all Create/Update/Delete/Upsert operations. See template's readme for more info.
|
|
38
|
-
*/
|
|
39
|
-
function generateModelBusinessLogicUpdate({ model, meta }) {
|
|
40
|
-
const schemaMeta = (0, meta_1.getSchemaMetadata)({ config: model.schemaConfig });
|
|
41
|
-
const m = {
|
|
42
|
-
iExecution: schemaMeta.actions.execution.interface,
|
|
43
|
-
typeName: meta.types.typeName,
|
|
44
|
-
brandedId: model.brandedIdType,
|
|
45
|
-
};
|
|
46
|
-
const imports = imports_1.ImportsGenerator.from(meta.update.serviceClassLocation.path);
|
|
47
|
-
imports.addImports({
|
|
48
|
-
[meta.data.repository.location.import]: meta.data.repository.className,
|
|
49
|
-
[meta.types.importPath]: [
|
|
50
|
-
Types.toAnnotatedTypeName(m.brandedId),
|
|
51
|
-
Types.toAnnotatedTypeName(m.typeName),
|
|
52
|
-
meta.types.toBrandedIdTypeFnName,
|
|
53
|
-
],
|
|
54
|
-
[meta.view.serviceLocation.import]: [meta.view.serviceClassName],
|
|
55
|
-
[schemaMeta.actions.execution.interfaceLocation.import]: [schemaMeta.actions.execution.interface],
|
|
56
|
-
[schemaMeta.actions.dispatcher.definitionLocation.import]: [schemaMeta.actions.dispatcher.definition],
|
|
57
|
-
[schemaMeta.update.serviceLocation.path]: schemaMeta.update.serviceClassName,
|
|
58
|
-
[schemaMeta.view.serviceLocation.import]: schemaMeta.view.serviceClassName,
|
|
59
|
-
});
|
|
60
|
-
for (const field of (0, fields_1.getRelationFields)(model)) {
|
|
61
|
-
// NOTE: We add `toBrandedType` functions for foreign models for decoders.
|
|
62
|
-
if (field.relationToModel.typeName === model.typeName) {
|
|
63
|
-
continue;
|
|
64
|
-
}
|
|
65
|
-
const refModelMeta = (0, meta_1.getModelMetadata)({ model: field.relationToModel });
|
|
66
|
-
imports.addImport({
|
|
67
|
-
from: refModelMeta.types.importPath,
|
|
68
|
-
items: [refModelMeta.types.toBrandedIdTypeFnName],
|
|
69
|
-
});
|
|
70
|
-
imports.addTypeImport({
|
|
71
|
-
from: refModelMeta.types.importPath,
|
|
72
|
-
items: [refModelMeta.types.brandedIdType],
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
for (const { enumerator } of (0, fields_1.getEnumFields)(model)) {
|
|
76
|
-
const enumMeta = (0, meta_1.getEnumMetadata)({ enumerator });
|
|
77
|
-
imports.addTypeImport({
|
|
78
|
-
from: enumMeta.types.importPath,
|
|
79
|
-
items: [enumerator.tsTypeName],
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
/**
|
|
83
|
-
* The name of the variable that holds the repository instance for the current model
|
|
84
|
-
* (e.g. when we generate business logic service for Aggregation, the AggregationRepository
|
|
85
|
-
* would be referenced using `this.data` variable).
|
|
86
|
-
*/
|
|
87
|
-
const modelRepositoryVariableName = meta.view.dataRepositoryVariableName;
|
|
88
|
-
const constructorParameters = [
|
|
89
|
-
`private readonly ${modelRepositoryVariableName}: ${meta.data.repository.className}`,
|
|
90
|
-
`@Inject(forwardRef(() => ${schemaMeta.update.serviceClassName})) private readonly updateService: ${schemaMeta.update.serviceClassName}`,
|
|
91
|
-
`@Inject(forwardRef(() => ${schemaMeta.view.serviceClassName})) private readonly viewService: ${schemaMeta.view.serviceClassName}`,
|
|
92
|
-
];
|
|
93
|
-
const { view, update } = meta;
|
|
94
|
-
const deleteFn = generateDeleteFn({ model, meta, m });
|
|
95
|
-
const deleteManyFn = generateDeleteManyFn({ imports, model, meta, m });
|
|
96
|
-
const cloneFn = generateCloneFn({ model, meta, m });
|
|
97
|
-
/* prettier-ignore */
|
|
98
|
-
return /* ts */ `
|
|
99
|
-
import { Inject, Injectable, forwardRef } from '@nestjs/common'
|
|
100
|
-
import { z } from 'zod'
|
|
101
|
-
|
|
102
|
-
${imports.generate()}
|
|
103
|
-
|
|
104
|
-
export type Scope = "${meta.actions.actionScopeConstType}"
|
|
105
|
-
|
|
106
|
-
export type Actions = {
|
|
107
|
-
${(0, jsdoc_1.toJsDocComment)([`Creates a new ${meta.userFriendlyName} and returns it.`])}
|
|
108
|
-
create: {
|
|
109
|
-
payload: CreatePayload
|
|
110
|
-
result: ${m.typeName}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
${(0, jsdoc_1.toJsDocComment)([`Updates a ${meta.userFriendlyName} and returns it.`])}
|
|
114
|
-
update: {
|
|
115
|
-
payload: UpdatePayload
|
|
116
|
-
result: ${m.typeName}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
${(0, jsdoc_1.toJsDocComment)([`Creates or updates a ${meta.userFriendlyName} and returns it.`])}
|
|
120
|
-
upsert: {
|
|
121
|
-
payload: UpsertPayload
|
|
122
|
-
result: ${m.typeName}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
${(0, jsdoc_1.toJsDocComment)([`Deletes a ${meta.userFriendlyName} and returns its id.`])}
|
|
126
|
-
delete: {
|
|
127
|
-
payload: ${m.brandedId}
|
|
128
|
-
result: ${m.brandedId}
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* Zod decoder for validating the create input of a ${meta.userFriendlyName}.
|
|
134
|
-
*/
|
|
135
|
-
export const ${meta.update.createInputDecoder} = z.object({
|
|
136
|
-
${model.fields
|
|
137
|
-
.filter((f) => !f.attributes.isReadonly)
|
|
138
|
-
.map((f) => `${f.name}: z.${(0, zod_1.getZodDecoderDefinition)({ field: f })}`)
|
|
139
|
-
.join(',')}
|
|
140
|
-
})
|
|
141
|
-
|
|
142
|
-
type CreatePayload = z.infer<typeof ${meta.update.createInputDecoder}>
|
|
143
|
-
|
|
144
|
-
/**
|
|
145
|
-
* Zod decoder for validating the update input of a ${meta.userFriendlyName} .
|
|
146
|
-
*/
|
|
147
|
-
export const ${meta.update.updateInputDecoder} = z.object({
|
|
148
|
-
${model.fields
|
|
149
|
-
.filter((f) => !f.attributes.isReadonly || f.kind === 'id')
|
|
150
|
-
.map((f) => `${f.name}: z.${(0, zod_1.getZodDecoderDefinition)({ field: f, allowAnyOptionalField: f.kind !== 'id' })}`)
|
|
151
|
-
.join(',')}
|
|
152
|
-
})
|
|
153
|
-
|
|
154
|
-
type UpdatePayload = z.infer<typeof ${meta.update.updateInputDecoder}>
|
|
155
|
-
|
|
156
|
-
/**
|
|
157
|
-
* Zod decoder for validating the upsert input of a ${meta.userFriendlyName} .
|
|
158
|
-
*/
|
|
159
|
-
export const ${meta.update.upsertInputDecoder} = z.union([${meta.update.updateInputDecoder}, ${meta.update.createInputDecoder}])
|
|
160
|
-
|
|
161
|
-
type UpsertPayload = z.infer<typeof ${meta.update.upsertInputDecoder}>
|
|
162
|
-
|
|
163
|
-
export type ${update.serviceInterfaceName} = ${schemaMeta.actions.dispatcher.definition}<Actions>
|
|
164
|
-
|
|
165
|
-
@Injectable()
|
|
166
|
-
export class ${update.serviceClassName} implements ${update.serviceInterfaceName} {
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
* Instance of the ${meta.userFriendlyName} view service for convenience.
|
|
170
|
-
*/
|
|
171
|
-
private view: ${view.serviceClassName}
|
|
172
|
-
|
|
173
|
-
constructor(${constructorParameters.join(',\n')}) {
|
|
174
|
-
this.view = this.viewService.${view.serviceVariableName}
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
${(0, jsdoc_1.toJsDocComment)([`Creates a new ${meta.userFriendlyName} and returns it.`])}
|
|
178
|
-
public async create({ data, execution }: { data: CreatePayload; execution: ${m.iExecution} }): Promise<${m.typeName}> {
|
|
179
|
-
return this.data.create({ item: data, execution })
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
${(0, jsdoc_1.toJsDocComment)([`Updates a ${meta.userFriendlyName} and returns it.`])}
|
|
183
|
-
public async update({ data, execution }: { data: UpdatePayload; execution: ${m.iExecution} }): Promise<${m.typeName}> {
|
|
184
|
-
return this.data.update({ item: data, execution })
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
${(0, jsdoc_1.toJsDocComment)([`Creates or updates a ${meta.userFriendlyName} and returns it.`])}
|
|
188
|
-
public async upsert({ data, execution }: { data: UpsertPayload; execution: ${m.iExecution} }): Promise<${m.typeName}> {
|
|
189
|
-
return this.data.upsert({ item: data, execution })
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
${deleteFn}
|
|
193
|
-
|
|
194
|
-
${deleteManyFn}
|
|
195
|
-
|
|
196
|
-
${cloneFn}
|
|
197
|
-
}
|
|
198
|
-
`;
|
|
199
|
-
}
|
|
200
|
-
exports.generateModelBusinessLogicUpdate = generateModelBusinessLogicUpdate;
|
|
201
|
-
/**
|
|
202
|
-
* Returns a function implementation that deletes a single entity and all its related entities.
|
|
203
|
-
*/
|
|
204
|
-
function generateDeleteFn({ model, meta, m }) {
|
|
205
|
-
const backReferenceDelete = [];
|
|
206
|
-
const backReferenceNames = [];
|
|
207
|
-
for (const { referencingField, referencingModel } of model.references) {
|
|
208
|
-
// NOTE: We only delete back references that are required references so that delete method
|
|
209
|
-
// doesn't fail on non-null constraints.
|
|
210
|
-
if (!referencingField.isRequired) {
|
|
211
|
-
continue;
|
|
212
|
-
}
|
|
213
|
-
const refModelMeta = (0, meta_1.getModelMetadata)({ model: referencingModel });
|
|
214
|
-
const refFieldMeta = (0, meta_1.getFieldMetadata)({ field: referencingField });
|
|
215
|
-
const ids = `${refModelMeta.internalSingularName}${(0, string_1.capitalize)(referencingField.name)}s`;
|
|
216
|
-
backReferenceNames.push(`${refModelMeta.userFriendlyNamePlural}.${referencingField.name}`);
|
|
217
|
-
backReferenceDelete.push(`
|
|
218
|
-
// ${referencingModel.name}.${referencingField.name}
|
|
219
|
-
const ${ids} = await this.viewService.${refModelMeta.view.serviceVariableName}.data.${refFieldMeta.getByForeignKeyIdsMethodFnName}(data)
|
|
220
|
-
await this.updateService.${refModelMeta.update.serviceVariableName}.deleteMany({ data: ${ids}, execution })
|
|
221
|
-
`);
|
|
222
|
-
}
|
|
223
|
-
return `
|
|
224
|
-
${(0, jsdoc_1.toJsDocComment)([`Deletes a ${meta.userFriendlyName} instance and returns its id.`])}
|
|
225
|
-
public async delete(
|
|
226
|
-
{ data, execution }: { data: ${m.brandedId}; execution: ${m.iExecution} }
|
|
227
|
-
): Promise<${m.brandedId}> {
|
|
228
|
-
${backReferenceDelete.join('\n')}
|
|
229
|
-
return this.data.delete({ id: data, execution })
|
|
230
|
-
}
|
|
231
|
-
`;
|
|
232
|
-
}
|
|
233
|
-
/**
|
|
234
|
-
* Returns a function that deletes multiple entities and all their related entities.
|
|
235
|
-
*/
|
|
236
|
-
function generateDeleteManyFn({ imports, model, meta, m, }) {
|
|
237
|
-
const idArrays = [];
|
|
238
|
-
const idAssignments = [];
|
|
239
|
-
const deleteCalls = [];
|
|
240
|
-
for (const { referencingField, referencingModel } of model.references) {
|
|
241
|
-
// NOTE: We only delete back references that are required references.
|
|
242
|
-
if (!referencingField.isRequired) {
|
|
243
|
-
continue;
|
|
244
|
-
}
|
|
245
|
-
imports.addTypeImport({ items: [referencingModel.brandedIdType], from: meta.types.importPath });
|
|
246
|
-
const refModelMeta = (0, meta_1.getModelMetadata)({ model: referencingModel });
|
|
247
|
-
const refFieldMeta = (0, meta_1.getFieldMetadata)({ field: referencingField });
|
|
248
|
-
const idArray = `${refModelMeta.internalSingularName}${(0, string_1.capitalize)(referencingField.name)}s`;
|
|
249
|
-
idArrays.push(`const ${idArray}: ${referencingModel.brandedIdType}[] = []`);
|
|
250
|
-
idAssignments.push(`
|
|
251
|
-
{
|
|
252
|
-
// ${referencingModel.name}.${referencingField.name}
|
|
253
|
-
const _ids = await this.viewService.${refModelMeta.view.serviceVariableName}.data.${refFieldMeta.getByForeignKeyIdsMethodFnName}(id)
|
|
254
|
-
${idArray}.push(..._ids)
|
|
255
|
-
}
|
|
256
|
-
`);
|
|
257
|
-
deleteCalls.push(`await this.updateService.${refModelMeta.update.serviceVariableName}.deleteMany({ data: ${idArray}, execution })`);
|
|
258
|
-
}
|
|
259
|
-
let relatedEntities = '';
|
|
260
|
-
if (idArrays.length > 0) {
|
|
261
|
-
relatedEntities = `
|
|
262
|
-
${idArrays.join('\n')}
|
|
263
|
-
|
|
264
|
-
for (const id of ids) {
|
|
265
|
-
${idAssignments.join('\n')}
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
${deleteCalls.join('\n')}
|
|
269
|
-
`;
|
|
270
|
-
}
|
|
271
|
-
return `
|
|
272
|
-
${(0, jsdoc_1.toJsDocComment)([`Deletes multiple ${meta.userFriendlyNamePlural} and returns their ids.`])}
|
|
273
|
-
public async deleteMany(
|
|
274
|
-
{ data: ids, execution }: { data: ${m.brandedId}[]; execution: ${m.iExecution} }
|
|
275
|
-
): Promise<${m.brandedId}[]> {
|
|
276
|
-
if (ids.length === 0) {
|
|
277
|
-
return []
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
${relatedEntities}
|
|
281
|
-
|
|
282
|
-
return this.data.deleteMany({ ids, execution })
|
|
283
|
-
}`;
|
|
284
|
-
}
|
|
285
|
-
/**
|
|
286
|
-
* Returns a function that shallow clones a given entity. Unique fields are required
|
|
287
|
-
* to generate a unique clone as skipping them would result in a non-unique clone.
|
|
288
|
-
*/
|
|
289
|
-
function generateCloneFn({ model, meta, m }) {
|
|
290
|
-
const inputFields = model.fields.map((f) => {
|
|
291
|
-
const type = (0, typescript_1.getFieldType)(f);
|
|
292
|
-
// NOTE: ID field is always required to resolve the source.
|
|
293
|
-
if (f.kind === 'id') {
|
|
294
|
-
return `${f.name}: ${type}`;
|
|
295
|
-
}
|
|
296
|
-
if (f.isUnique) {
|
|
297
|
-
// NOTE: `unique` fields require a new value.
|
|
298
|
-
if (f.isRequired) {
|
|
299
|
-
return `${f.name}: ${type}`;
|
|
300
|
-
}
|
|
301
|
-
return `${f.name}: ${type} | null`;
|
|
302
|
-
}
|
|
303
|
-
// NOTE: Non-unique fields can be copied from the source.
|
|
304
|
-
if (f.isRequired) {
|
|
305
|
-
return `${f.name}?: ${type}`;
|
|
306
|
-
}
|
|
307
|
-
return `${f.name}?: ${type} | null`;
|
|
308
|
-
});
|
|
309
|
-
return `
|
|
310
|
-
${(0, jsdoc_1.toJsDocComment)([`Creates a new ${meta.userFriendlyName} deep clone and returns it.`])}
|
|
311
|
-
public async clone(
|
|
312
|
-
{ data, execution }: { data: { ${inputFields.join(', ')} }; execution: ${m.iExecution} }
|
|
313
|
-
): Promise<${m.typeName}> {
|
|
314
|
-
const source = await this.view.get(data.id)
|
|
315
|
-
if (!source) {
|
|
316
|
-
throw new Error(\`${meta.userFriendlyName} with id \${data.id} not found\`)
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
320
|
-
const { id, ...duplicate } = { ...source, ...data } satisfies Actions['create']['payload']
|
|
321
|
-
|
|
322
|
-
return await this.create({ data: duplicate, execution })
|
|
323
|
-
}`;
|
|
324
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|