@postxl/generator 0.34.0 → 0.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/generator.js +40 -22
- package/dist/generators/indices/businesslogic-actiontypes.generator.d.ts +9 -0
- package/dist/generators/indices/businesslogic-actiontypes.generator.js +39 -0
- package/dist/generators/indices/businesslogic-update-index.generator.d.ts +9 -0
- package/dist/generators/indices/businesslogic-update-index.generator.js +20 -0
- package/dist/generators/indices/businesslogic-update-module.generator.d.ts +9 -0
- package/dist/generators/indices/businesslogic-update-module.generator.js +69 -0
- package/dist/generators/indices/businesslogic-update-service.generator.d.ts +9 -0
- package/dist/generators/indices/businesslogic-update-service.generator.js +34 -0
- package/dist/generators/indices/businesslogic-view-index.generator.d.ts +9 -0
- package/dist/generators/indices/businesslogic-view-index.generator.js +19 -0
- package/dist/generators/indices/{businesslogicindex.generator.d.ts → businesslogic-view-module.generator.d.ts} +2 -2
- package/dist/generators/indices/{businesslogicmodule.generator.js → businesslogic-view-module.generator.js} +22 -26
- package/dist/generators/indices/{businesslogicservice.generator.d.ts → businesslogic-view-service.generator.d.ts} +1 -1
- package/dist/generators/indices/{businesslogicservice.generator.js → businesslogic-view-service.generator.js} +9 -10
- package/dist/generators/indices/{datamockmodule.generator.js → datamock-module.generator.js} +8 -16
- package/dist/generators/indices/datamocker.generator.js +3 -7
- package/dist/generators/indices/datamodule.generator.js +7 -13
- package/dist/generators/indices/{businesslogicmodule.generator.d.ts → dispatcher-service.generator.d.ts} +2 -2
- package/dist/generators/indices/dispatcher-service.generator.js +81 -0
- package/dist/generators/indices/seed-migration.generator.d.ts +9 -0
- package/dist/generators/indices/seed-migration.generator.js +35 -0
- package/dist/generators/indices/seed-service.generator.d.ts +1 -1
- package/dist/generators/indices/seed-service.generator.js +327 -123
- package/dist/generators/indices/seed-template-decoder.generator.js +22 -6
- package/dist/generators/indices/{seed.generator.d.ts → seeddata-type.generator.d.ts} +2 -2
- package/dist/generators/indices/seeddata-type.generator.js +42 -0
- package/dist/generators/indices/types.generator.d.ts +1 -1
- package/dist/generators/indices/types.generator.js +8 -6
- package/dist/generators/models/businesslogic-update.generator.d.ts +10 -0
- package/dist/generators/models/businesslogic-update.generator.js +243 -0
- package/dist/generators/models/businesslogic-view.generator.d.ts +10 -0
- package/dist/generators/models/{businesslogic.generator.js → businesslogic-view.generator.js} +23 -72
- package/dist/generators/models/react.generator/modals.generator.js +2 -2
- package/dist/generators/models/repository.generator.d.ts +9 -0
- package/dist/generators/models/repository.generator.js +420 -131
- package/dist/generators/models/route.generator.js +45 -55
- package/dist/generators/models/seed.generator.js +6 -2
- package/dist/generators/models/types.generator.js +60 -13
- package/dist/lib/attributes.d.ts +5 -0
- package/dist/lib/imports.d.ts +23 -2
- package/dist/lib/imports.js +19 -1
- package/dist/lib/meta.d.ts +287 -34
- package/dist/lib/meta.js +87 -16
- package/dist/lib/schema/schema.d.ts +24 -6
- package/dist/lib/schema/types.d.ts +4 -0
- package/dist/lib/utils/jsdoc.d.ts +1 -1
- package/dist/lib/utils/jsdoc.js +8 -6
- package/dist/lib/utils/string.js +2 -1
- package/dist/prisma/attributes.js +7 -3
- package/dist/prisma/parse.js +25 -5
- package/package.json +1 -1
- package/dist/generators/indices/businesslogicindex.generator.js +0 -19
- package/dist/generators/indices/seed.generator.js +0 -17
- package/dist/generators/indices/testdataservice.generator.d.ts +0 -9
- package/dist/generators/indices/testdataservice.generator.js +0 -78
- package/dist/generators/models/businesslogic.generator.d.ts +0 -9
- /package/dist/generators/indices/{datamockmodule.generator.d.ts → datamock-module.generator.d.ts} +0 -0
|
@@ -5,20 +5,21 @@ const imports_1 = require("../../lib/imports");
|
|
|
5
5
|
const meta_1 = require("../../lib/meta");
|
|
6
6
|
const types_1 = require("../../lib/schema/types");
|
|
7
7
|
const types_2 = require("../../lib/types");
|
|
8
|
+
const string_1 = require("../../lib/utils/string");
|
|
8
9
|
// TODO: Remove hardcoded path that seems to be reused in multiple places!
|
|
9
10
|
const PXL_COMMON = (0, types_1.toPath)('@pxl/common');
|
|
10
11
|
/**
|
|
11
12
|
* Creates a decoder for the Seed Excel template.
|
|
12
13
|
*/
|
|
13
14
|
function generateSeedTemplateDecoder({ models, meta }) {
|
|
14
|
-
const imports = imports_1.ImportsGenerator.from(meta.
|
|
15
|
+
const imports = imports_1.ImportsGenerator.from(meta.seedData.templateDecoderFilePath);
|
|
15
16
|
const decoders = [];
|
|
16
17
|
const tableDecoders = [];
|
|
17
18
|
const renameTransforms = [];
|
|
18
19
|
for (const model of [...models].sort((a, b) => a.name.localeCompare(b.name))) {
|
|
19
20
|
const modelMeta = (0, meta_1.getModelMetadata)({ model });
|
|
20
21
|
decoders.push(generateTableDecoder({ model, meta: modelMeta, imports }));
|
|
21
|
-
tableDecoders.push(`${modelMeta.seed.excel.tableName}:
|
|
22
|
+
tableDecoders.push(`${modelMeta.seed.excel.tableName}: ${modelMeta.seed.decoder.decoderName}`);
|
|
22
23
|
renameTransforms.push(`${modelMeta.seed.decoder.dataName}: item['${modelMeta.seed.excel.tableName}']`);
|
|
23
24
|
}
|
|
24
25
|
return `
|
|
@@ -26,9 +27,14 @@ function generateSeedTemplateDecoder({ models, meta }) {
|
|
|
26
27
|
|
|
27
28
|
${imports.generate()}
|
|
28
29
|
|
|
30
|
+
/**
|
|
31
|
+
* Helper schema to identify blank Excel cells
|
|
32
|
+
*/
|
|
33
|
+
const nullOrBlankSchema = z.union([z.null(), z.literal('')])
|
|
34
|
+
|
|
29
35
|
${decoders.join('\n')}
|
|
30
36
|
|
|
31
|
-
export const ${meta.
|
|
37
|
+
export const ${meta.seedData.templateDecoderName} = z
|
|
32
38
|
.object({${tableDecoders.join(',\n')}})
|
|
33
39
|
.transform((item) => ({${renameTransforms.join(',\n')}}))
|
|
34
40
|
`;
|
|
@@ -36,10 +42,12 @@ function generateSeedTemplateDecoder({ models, meta }) {
|
|
|
36
42
|
exports.generateSeedTemplateDecoder = generateSeedTemplateDecoder;
|
|
37
43
|
function generateTableDecoder({ model, meta, imports, }) {
|
|
38
44
|
const fieldDecoders = [];
|
|
45
|
+
const blankFieldDecoders = [];
|
|
39
46
|
const renameTransforms = [];
|
|
40
47
|
for (const field of model.fields) {
|
|
41
48
|
const fieldMeta = (0, meta_1.getFieldMetadata)({ field });
|
|
42
49
|
renameTransforms.push(`${field.name}: item['${fieldMeta.excelColumnName}']`);
|
|
50
|
+
blankFieldDecoders.push(`${fieldMeta.excelColumnName}: nullOrBlankSchema`);
|
|
43
51
|
switch (field.kind) {
|
|
44
52
|
case 'id': {
|
|
45
53
|
imports.addImport({ items: [meta.types.toBrandedIdTypeFnName], from: meta.types.importPath });
|
|
@@ -81,6 +89,7 @@ function generateTableDecoder({ model, meta, imports, }) {
|
|
|
81
89
|
}
|
|
82
90
|
}
|
|
83
91
|
}
|
|
92
|
+
const blankSchemaName = `blank${(0, string_1.capitalize)(meta.seed.decoder.schemaName)}`;
|
|
84
93
|
return `
|
|
85
94
|
/**
|
|
86
95
|
* The schema for the ${model.name} table
|
|
@@ -88,13 +97,20 @@ function generateTableDecoder({ model, meta, imports, }) {
|
|
|
88
97
|
const ${meta.seed.decoder.schemaName} = z
|
|
89
98
|
.object({${fieldDecoders.join(',\n')}})
|
|
90
99
|
.transform((item) => ({${renameTransforms.join(',\n')}}))
|
|
91
|
-
|
|
92
|
-
/**
|
|
100
|
+
|
|
101
|
+
/** The schema to identify blank rows in the ${model.name} table */
|
|
102
|
+
const ${blankSchemaName} = z
|
|
103
|
+
.object({${blankFieldDecoders.join(',\n')}})
|
|
104
|
+
.transform(() => undefined)
|
|
105
|
+
|
|
106
|
+
/**
|
|
93
107
|
* The type of the ${model.name} table
|
|
94
108
|
*/
|
|
95
109
|
export type ${meta.seed.decoder.decoderTypeName} = z.infer<typeof ${meta.seed.decoder.schemaName}>
|
|
96
110
|
|
|
97
|
-
export const ${meta.seed.decoder.decoderName} = z
|
|
111
|
+
export const ${meta.seed.decoder.decoderName} = z
|
|
112
|
+
.array(${meta.seed.decoder.schemaName}.or(${blankSchemaName}))
|
|
113
|
+
.transform((items) => items.filter(Boolean) as ${meta.seed.decoder.decoderTypeName}[])
|
|
98
114
|
`;
|
|
99
115
|
}
|
|
100
116
|
function toExcelDecoder({ tsTypeName, dbTypeName: typeName, nullable, imports, }) {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { SchemaMetaData } from '../../lib/meta';
|
|
2
2
|
import { Model } from '../../lib/schema/schema';
|
|
3
3
|
/**
|
|
4
|
-
* Generates
|
|
4
|
+
* Generates a type for all SeedData.
|
|
5
5
|
*/
|
|
6
|
-
export declare function
|
|
6
|
+
export declare function generateSeedDataType({ models, meta }: {
|
|
7
7
|
models: Model[];
|
|
8
8
|
meta: SchemaMetaData;
|
|
9
9
|
}): string;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateSeedDataType = 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 a type for all SeedData.
|
|
9
|
+
*/
|
|
10
|
+
function generateSeedDataType({ models, meta }) {
|
|
11
|
+
const imports = imports_1.ImportsGenerator.from(meta.types.importPath);
|
|
12
|
+
imports.addImport({ from: meta.data.importPath, items: [(0, types_1.toClassName)('MockData')] });
|
|
13
|
+
const modelTypes = [];
|
|
14
|
+
const mockConverters = [];
|
|
15
|
+
for (const model of models) {
|
|
16
|
+
const modelMeta = (0, meta_1.getModelMetadata)({ model });
|
|
17
|
+
imports.addImport({
|
|
18
|
+
items: [modelMeta.types.dto.create, modelMeta.types.dto.update, modelMeta.types.dto.upsert],
|
|
19
|
+
from: modelMeta.types.importPath,
|
|
20
|
+
});
|
|
21
|
+
modelTypes.push(`${modelMeta.seed.constantName}?: {
|
|
22
|
+
create?: ${modelMeta.types.dto.create}[]
|
|
23
|
+
update?: ${modelMeta.types.dto.update}[]
|
|
24
|
+
upsert?: ${modelMeta.types.dto.upsert}[]
|
|
25
|
+
delete?: string[]
|
|
26
|
+
}`);
|
|
27
|
+
mockConverters.push(`${modelMeta.seed.constantName}: { create: data.${modelMeta.seed.constantName} }`);
|
|
28
|
+
}
|
|
29
|
+
return `
|
|
30
|
+
${imports.generate()}
|
|
31
|
+
|
|
32
|
+
export type SeedData = {
|
|
33
|
+
${modelTypes.join('\n')}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function mockDataToCreate(data: MockData): SeedData {
|
|
37
|
+
return {
|
|
38
|
+
${mockConverters.join(',\n')}
|
|
39
|
+
}
|
|
40
|
+
}`;
|
|
41
|
+
}
|
|
42
|
+
exports.generateSeedDataType = generateSeedDataType;
|
|
@@ -3,7 +3,7 @@ import { Enum, Model } from '../../lib/schema/schema';
|
|
|
3
3
|
/**
|
|
4
4
|
* Generates an index file that exports all types.
|
|
5
5
|
*/
|
|
6
|
-
export declare function generateTypesIndex({ models, enums, meta, }: {
|
|
6
|
+
export declare function generateTypesIndex({ models, enums, meta: schemaMeta, }: {
|
|
7
7
|
models: Model[];
|
|
8
8
|
enums: Enum[];
|
|
9
9
|
meta: SchemaMetaData;
|
|
@@ -6,16 +6,18 @@ const meta_1 = require("../../lib/meta");
|
|
|
6
6
|
/**
|
|
7
7
|
* Generates an index file that exports all types.
|
|
8
8
|
*/
|
|
9
|
-
function generateTypesIndex({ models, enums, meta, }) {
|
|
10
|
-
const exports = exports_1.ExportsGenerator.from(
|
|
9
|
+
function generateTypesIndex({ models, enums, meta: schemaMeta, }) {
|
|
10
|
+
const exports = exports_1.ExportsGenerator.from(schemaMeta.types.indexFilePath);
|
|
11
11
|
for (const model of models) {
|
|
12
|
-
const
|
|
13
|
-
exports.exportEverythingFromPath(
|
|
12
|
+
const modelMeta = (0, meta_1.getModelMetadata)({ model });
|
|
13
|
+
exports.exportEverythingFromPath(modelMeta.types.filePath);
|
|
14
14
|
}
|
|
15
15
|
for (const enumerator of enums) {
|
|
16
|
-
const
|
|
17
|
-
exports.exportEverythingFromPath(
|
|
16
|
+
const enumMeta = (0, meta_1.getEnumMetadata)({ enumerator });
|
|
17
|
+
exports.exportEverythingFromPath(enumMeta.types.filePath);
|
|
18
18
|
}
|
|
19
|
+
// dto.types contains generic types that are used by all models
|
|
20
|
+
exports.exportEverythingFromPath(schemaMeta.types.dto.path);
|
|
19
21
|
return exports.generate();
|
|
20
22
|
}
|
|
21
23
|
exports.generateTypesIndex = generateTypesIndex;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ModelMetaData } from '../../lib/meta';
|
|
2
|
+
import { Model } from '../../lib/schema/schema';
|
|
3
|
+
/**
|
|
4
|
+
* Generates update business logic for a given model.
|
|
5
|
+
* The update logic handles all Create/Update/Delete/Upsert operations. See template's readme for more info.
|
|
6
|
+
*/
|
|
7
|
+
export declare function generateModelBusinessLogicUpdate({ model, meta }: {
|
|
8
|
+
model: Model;
|
|
9
|
+
meta: ModelMetaData;
|
|
10
|
+
}): string;
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateModelBusinessLogicUpdate = void 0;
|
|
4
|
+
const imports_1 = require("../../lib/imports");
|
|
5
|
+
const meta_1 = require("../../lib/meta");
|
|
6
|
+
const jsdoc_1 = require("../../lib/utils/jsdoc");
|
|
7
|
+
const repository_generator_1 = require("./repository.generator");
|
|
8
|
+
/**
|
|
9
|
+
* Generates update business logic for a given model.
|
|
10
|
+
* The update logic handles all Create/Update/Delete/Upsert operations. See template's readme for more info.
|
|
11
|
+
*/
|
|
12
|
+
function generateModelBusinessLogicUpdate({ model, meta }) {
|
|
13
|
+
const schemaMeta = (0, meta_1.getSchemaMetadata)({ config: model.schemaConfig });
|
|
14
|
+
const imports = imports_1.ImportsGenerator.from(meta.businessLogic.update.serviceFilePath);
|
|
15
|
+
imports.addImports({
|
|
16
|
+
[meta.data.importPath]: meta.data.repositoryClassName,
|
|
17
|
+
[schemaMeta.actions.importPath]: schemaMeta.actions.actionExecutionInterface,
|
|
18
|
+
[meta.types.importPath]: [model.brandedIdType, meta.types.typeName],
|
|
19
|
+
[schemaMeta.businessLogic.update.serviceFilePath]: schemaMeta.businessLogic.update.serviceClassName,
|
|
20
|
+
[schemaMeta.businessLogic.view.serviceFilePath]: schemaMeta.businessLogic.view.serviceClassName,
|
|
21
|
+
[meta.data.importPath]: [meta.data.repositoryClassName],
|
|
22
|
+
});
|
|
23
|
+
/**
|
|
24
|
+
* The name of the variable that holds the repository instance for the current model
|
|
25
|
+
* (e.g. when we generate business logic service for Aggregation, the AggregationRepository
|
|
26
|
+
* would be referenced using `this.data` variable).
|
|
27
|
+
*/
|
|
28
|
+
const modelRepositoryVariableName = meta.businessLogic.dataRepositoryVariableName;
|
|
29
|
+
/**
|
|
30
|
+
* The name of the variable that holds the central business logic service instance.
|
|
31
|
+
* Instead of injecting a repository instance for each model, we inject this single instance
|
|
32
|
+
* which then provides access to all models' business logic.
|
|
33
|
+
*/
|
|
34
|
+
const updateServiceClassName = 'updateService';
|
|
35
|
+
const viewServiceClassName = 'viewService';
|
|
36
|
+
const actionBlocks = generateActionsBuildingBlocks({ model, meta });
|
|
37
|
+
imports.addImport({ from: meta.types.importPath, items: actionBlocks.importTypes });
|
|
38
|
+
const constructorParameters = [
|
|
39
|
+
`public readonly ${modelRepositoryVariableName}: ${meta.data.repositoryClassName}`,
|
|
40
|
+
`@Inject(forwardRef(() => ${schemaMeta.businessLogic.update.serviceClassName})) private readonly ${updateServiceClassName}: ${schemaMeta.businessLogic.update.serviceClassName}`,
|
|
41
|
+
`@Inject(forwardRef(() => ${schemaMeta.businessLogic.view.serviceClassName})) private readonly ${viewServiceClassName}: ${schemaMeta.businessLogic.view.serviceClassName}`,
|
|
42
|
+
];
|
|
43
|
+
const methodTypeSignatures = (0, repository_generator_1.getRepositoryMethodsTypeSignatures)({ model, meta });
|
|
44
|
+
return `
|
|
45
|
+
import { Inject, Injectable, forwardRef } from '@nestjs/common'
|
|
46
|
+
import { ExhaustiveSwitchCheck } from '@pxl/common'
|
|
47
|
+
|
|
48
|
+
${imports.generate()}
|
|
49
|
+
|
|
50
|
+
${actionBlocks.actionTypeDefinition}
|
|
51
|
+
|
|
52
|
+
${actionBlocks.resultMap}
|
|
53
|
+
|
|
54
|
+
${actionBlocks.typeDefinitionWithCreateFunction}
|
|
55
|
+
|
|
56
|
+
@Injectable()
|
|
57
|
+
export class ${meta.businessLogic.update.serviceClassName} {
|
|
58
|
+
constructor(${constructorParameters.join(',\n')}) {}
|
|
59
|
+
|
|
60
|
+
${actionBlocks.dispatcher}
|
|
61
|
+
|
|
62
|
+
${(0, jsdoc_1.toJsDocComment)(methodTypeSignatures.create.jsDoc)}
|
|
63
|
+
public async create(
|
|
64
|
+
{ item, execution }: ${methodTypeSignatures.create.parameters[0]}
|
|
65
|
+
): ${methodTypeSignatures.create.returnType} {
|
|
66
|
+
return this.${modelRepositoryVariableName}.create({ item, execution })
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
${(0, jsdoc_1.toJsDocComment)(methodTypeSignatures.createMany.jsDoc)}
|
|
71
|
+
public async createMany(
|
|
72
|
+
{ items, execution }: ${methodTypeSignatures.createMany.parameters[0]}
|
|
73
|
+
): ${methodTypeSignatures.createMany.returnType} {
|
|
74
|
+
return this.${modelRepositoryVariableName}.createMany({ items, execution })
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
${(0, jsdoc_1.toJsDocComment)(methodTypeSignatures.update.jsDoc)}
|
|
78
|
+
public async update(
|
|
79
|
+
{ item, execution }: ${methodTypeSignatures.update.parameters[0]}
|
|
80
|
+
): ${methodTypeSignatures.update.returnType} {
|
|
81
|
+
return this.${modelRepositoryVariableName}.update({ item, execution })
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
${(0, jsdoc_1.toJsDocComment)(methodTypeSignatures.updateMany.jsDoc)}
|
|
85
|
+
public async updateMany(
|
|
86
|
+
{ items, execution }: ${methodTypeSignatures.updateMany.parameters[0]}
|
|
87
|
+
): ${methodTypeSignatures.updateMany.returnType} {
|
|
88
|
+
return this.${modelRepositoryVariableName}.updateMany({ items, execution })
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
${(0, jsdoc_1.toJsDocComment)(methodTypeSignatures.upsert.jsDoc)}
|
|
92
|
+
public async upsert(
|
|
93
|
+
{ item, execution }: ${methodTypeSignatures.upsert.parameters[0]}
|
|
94
|
+
): ${methodTypeSignatures.upsert.returnType} {
|
|
95
|
+
return this.${modelRepositoryVariableName}.upsert({ item, execution })
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
${(0, jsdoc_1.toJsDocComment)(methodTypeSignatures.upsertMany.jsDoc)}
|
|
99
|
+
public async upsertMany(
|
|
100
|
+
{ items, execution }: ${methodTypeSignatures.upsertMany.parameters[0]}
|
|
101
|
+
): ${methodTypeSignatures.upsertMany.returnType} {
|
|
102
|
+
return this.${modelRepositoryVariableName}.upsertMany({ items, execution })
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
${(0, jsdoc_1.toJsDocComment)(methodTypeSignatures.delete.jsDoc)}
|
|
106
|
+
public async delete(
|
|
107
|
+
{ id, execution }: ${methodTypeSignatures.delete.parameters[0]}
|
|
108
|
+
): ${methodTypeSignatures.delete.returnType} {
|
|
109
|
+
return this.${modelRepositoryVariableName}.delete({ id, execution })
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
${(0, jsdoc_1.toJsDocComment)(methodTypeSignatures.deleteMany.jsDoc)}
|
|
113
|
+
public async deleteMany(
|
|
114
|
+
{ ids, execution }: ${methodTypeSignatures.deleteMany.parameters[0]}
|
|
115
|
+
): ${methodTypeSignatures.deleteMany.returnType} {
|
|
116
|
+
return this.${modelRepositoryVariableName}.deleteMany({ ids, execution })
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
}`;
|
|
120
|
+
}
|
|
121
|
+
exports.generateModelBusinessLogicUpdate = generateModelBusinessLogicUpdate;
|
|
122
|
+
function generateActionsBuildingBlocks({ model, meta }) {
|
|
123
|
+
const actionTypeDefinition = [];
|
|
124
|
+
const resultMap = [];
|
|
125
|
+
const typeDefinitionWithCreateFunction = [];
|
|
126
|
+
const importTypes = [];
|
|
127
|
+
const dispatcher = [];
|
|
128
|
+
const schemaMeta = (0, meta_1.getSchemaMetadata)({ config: model.schemaConfig });
|
|
129
|
+
const actionDefinitions = prepareActionDefinitions({ model, meta });
|
|
130
|
+
for (const [type, config] of Object.entries(actionDefinitions)) {
|
|
131
|
+
const def = generateAction({ model, meta, type: type, config });
|
|
132
|
+
actionTypeDefinition.push(def.actionName),
|
|
133
|
+
resultMap.push(def.resultMap),
|
|
134
|
+
typeDefinitionWithCreateFunction.push(def.typeDefinition, def.createFunction, ''),
|
|
135
|
+
importTypes.push(...def.importTypes),
|
|
136
|
+
dispatcher.push(def.dispatchCaseExpression);
|
|
137
|
+
}
|
|
138
|
+
return {
|
|
139
|
+
importTypes,
|
|
140
|
+
actionTypeDefinition: `export type Action_${meta.businessLogic.update.actionNameModelPart} = ${actionTypeDefinition.join(' | ')}`,
|
|
141
|
+
resultMap: `export type ActionResult_${meta.businessLogic.update.actionNameModelPart} = {
|
|
142
|
+
${resultMap.join('\n')}
|
|
143
|
+
}`,
|
|
144
|
+
typeDefinitionWithCreateFunction: `${typeDefinitionWithCreateFunction.join('\n')}`,
|
|
145
|
+
dispatcher: `
|
|
146
|
+
public async dispatch<A extends Action_${meta.businessLogic.update.actionNameModelPart}>({ action, execution }: {
|
|
147
|
+
action: A;
|
|
148
|
+
execution: ${schemaMeta.actions.actionExecutionInterface}
|
|
149
|
+
}) {
|
|
150
|
+
switch (action.type) {
|
|
151
|
+
${dispatcher.join('\n')}
|
|
152
|
+
default: {
|
|
153
|
+
throw new ExhaustiveSwitchCheck(action)
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}`,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
function prepareActionDefinitions({ model, meta, }) {
|
|
160
|
+
return {
|
|
161
|
+
create: {
|
|
162
|
+
actionName: `Action_${meta.businessLogic.update.actionNameModelPart}_Create`,
|
|
163
|
+
createFunctionName: meta.businessLogic.update.createActionFunctionNameCreate,
|
|
164
|
+
payload: meta.types.dto.create,
|
|
165
|
+
resultType: meta.types.typeName,
|
|
166
|
+
imports: [meta.types.dto.create],
|
|
167
|
+
dispatcherParameterName: 'item',
|
|
168
|
+
},
|
|
169
|
+
createMany: {
|
|
170
|
+
actionName: `Action_${meta.businessLogic.update.actionNameModelPart}_CreateMany`,
|
|
171
|
+
createFunctionName: meta.businessLogic.update.createActionFunctionNameCreateMany,
|
|
172
|
+
payload: `${meta.types.dto.create}[]`,
|
|
173
|
+
resultType: `${meta.types.typeName}[]`,
|
|
174
|
+
imports: [meta.types.dto.create],
|
|
175
|
+
dispatcherParameterName: 'items',
|
|
176
|
+
},
|
|
177
|
+
update: {
|
|
178
|
+
actionName: `Action_${meta.businessLogic.update.actionNameModelPart}_Update`,
|
|
179
|
+
createFunctionName: meta.businessLogic.update.createActionFunctionNameUpdate,
|
|
180
|
+
payload: meta.types.dto.update,
|
|
181
|
+
resultType: meta.types.typeName,
|
|
182
|
+
imports: [meta.types.dto.update],
|
|
183
|
+
dispatcherParameterName: 'item',
|
|
184
|
+
},
|
|
185
|
+
updateMany: {
|
|
186
|
+
actionName: `Action_${meta.businessLogic.update.actionNameModelPart}_UpdateMany`,
|
|
187
|
+
createFunctionName: meta.businessLogic.update.createActionFunctionNameUpdateMany,
|
|
188
|
+
payload: `${meta.types.dto.update}[]`,
|
|
189
|
+
resultType: `${meta.types.typeName}[]`,
|
|
190
|
+
imports: [meta.types.dto.update],
|
|
191
|
+
dispatcherParameterName: 'items',
|
|
192
|
+
},
|
|
193
|
+
upsert: {
|
|
194
|
+
actionName: `Action_${meta.businessLogic.update.actionNameModelPart}_Upsert`,
|
|
195
|
+
createFunctionName: meta.businessLogic.update.createActionFunctionNameUpsert,
|
|
196
|
+
payload: meta.types.dto.upsert,
|
|
197
|
+
resultType: meta.types.typeName,
|
|
198
|
+
imports: [meta.types.dto.upsert],
|
|
199
|
+
dispatcherParameterName: 'item',
|
|
200
|
+
},
|
|
201
|
+
upsertMany: {
|
|
202
|
+
actionName: `Action_${meta.businessLogic.update.actionNameModelPart}_UpsertMany`,
|
|
203
|
+
createFunctionName: meta.businessLogic.update.createActionFunctionNameUpsertMany,
|
|
204
|
+
payload: `${meta.types.dto.upsert}[]`,
|
|
205
|
+
resultType: `${meta.types.typeName}[]`,
|
|
206
|
+
imports: [meta.types.dto.upsert],
|
|
207
|
+
dispatcherParameterName: 'items',
|
|
208
|
+
},
|
|
209
|
+
delete: {
|
|
210
|
+
actionName: `Action_${meta.businessLogic.update.actionNameModelPart}_Delete`,
|
|
211
|
+
createFunctionName: meta.businessLogic.update.createActionFunctionNameDelete,
|
|
212
|
+
payload: model.brandedIdType,
|
|
213
|
+
resultType: model.brandedIdType,
|
|
214
|
+
imports: [model.brandedIdType],
|
|
215
|
+
dispatcherParameterName: 'id',
|
|
216
|
+
},
|
|
217
|
+
deleteMany: {
|
|
218
|
+
actionName: `Action_${meta.businessLogic.update.actionNameModelPart}_DeleteMany`,
|
|
219
|
+
createFunctionName: meta.businessLogic.update.createActionFunctionNameDeleteMany,
|
|
220
|
+
payload: `${model.brandedIdType}[]`,
|
|
221
|
+
resultType: `${model.brandedIdType}[]`,
|
|
222
|
+
imports: [model.brandedIdType],
|
|
223
|
+
dispatcherParameterName: 'ids',
|
|
224
|
+
},
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
function generateAction({ meta, type, config: { imports, actionName, payload, createFunctionName, resultType, dispatcherParameterName }, }) {
|
|
228
|
+
return {
|
|
229
|
+
actionName,
|
|
230
|
+
actionType: type,
|
|
231
|
+
importTypes: imports,
|
|
232
|
+
resultMap: `${type}: ${resultType}`,
|
|
233
|
+
typeDefinition: `
|
|
234
|
+
export type ${actionName} = { scope: '${meta.actions.actionScopeConstType}'; type: '${type}'; payload: ${payload} }`,
|
|
235
|
+
createFunction: `
|
|
236
|
+
export function ${createFunctionName}(payload: ${payload}): ${actionName} {
|
|
237
|
+
return { scope: '${meta.actions.actionScopeConstType}', type: '${type}', payload }
|
|
238
|
+
}`,
|
|
239
|
+
dispatchCaseExpression: `
|
|
240
|
+
case '${type}':
|
|
241
|
+
return this.${type}({ ${dispatcherParameterName}: action.payload, execution })`,
|
|
242
|
+
};
|
|
243
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ModelMetaData } from '../../lib/meta';
|
|
2
|
+
import { Model } from '../../lib/schema/schema';
|
|
3
|
+
/**
|
|
4
|
+
* Generates view business logic for a given model.
|
|
5
|
+
* The view logic exposes all information and links of a model. See template's readme for more info.
|
|
6
|
+
*/
|
|
7
|
+
export declare function generateModelBusinessLogicView({ model, meta }: {
|
|
8
|
+
model: Model;
|
|
9
|
+
meta: ModelMetaData;
|
|
10
|
+
}): string;
|
package/dist/generators/models/{businesslogic.generator.js → businesslogic-view.generator.js}
RENAMED
|
@@ -1,44 +1,23 @@
|
|
|
1
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
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
exports.
|
|
3
|
+
exports.generateModelBusinessLogicView = void 0;
|
|
27
4
|
const imports_1 = require("../../lib/imports");
|
|
28
5
|
const meta_1 = require("../../lib/meta");
|
|
29
6
|
const fields_1 = require("../../lib/schema/fields");
|
|
30
|
-
const Types = __importStar(require("../../lib/schema/types"));
|
|
31
7
|
const ast_1 = require("../../lib/utils/ast");
|
|
32
|
-
const repository_generator_1 = require("./repository.generator");
|
|
33
8
|
/**
|
|
34
|
-
* Generates business logic for a given model.
|
|
9
|
+
* Generates view business logic for a given model.
|
|
10
|
+
* The view logic exposes all information and links of a model. See template's readme for more info.
|
|
35
11
|
*/
|
|
36
|
-
|
|
37
|
-
function generateModelBusinessLogic({ model, meta }) {
|
|
12
|
+
function generateModelBusinessLogicView({ model, meta }) {
|
|
38
13
|
const schemaMeta = (0, meta_1.getSchemaMetadata)({ config: model.schemaConfig });
|
|
39
|
-
const imports = imports_1.ImportsGenerator.from(meta.businessLogic.serviceFilePath);
|
|
40
|
-
imports.
|
|
41
|
-
|
|
14
|
+
const imports = imports_1.ImportsGenerator.from(meta.businessLogic.view.serviceFilePath);
|
|
15
|
+
imports.addImports({
|
|
16
|
+
[meta.data.importPath]: meta.data.repositoryClassName,
|
|
17
|
+
[meta.types.importPath]: [model.brandedIdType, meta.types.typeName],
|
|
18
|
+
[schemaMeta.businessLogic.view.serviceFilePath]: schemaMeta.businessLogic.view.serviceClassName,
|
|
19
|
+
[meta.data.importPath]: [meta.data.repositoryClassName],
|
|
20
|
+
});
|
|
42
21
|
/**
|
|
43
22
|
* The name of the variable that holds the repository instance for the current model
|
|
44
23
|
* (e.g. when we generate business logic service for Aggregation, the AggregationRepository
|
|
@@ -50,16 +29,11 @@ function generateModelBusinessLogic({ model, meta }) {
|
|
|
50
29
|
* Instead of injecting a repository instance for each model, we inject this single instance
|
|
51
30
|
* which then provides access to all models' business logic.
|
|
52
31
|
*/
|
|
53
|
-
const
|
|
32
|
+
const viewServiceClassName = 'viewService';
|
|
54
33
|
const constructorParameters = [
|
|
55
34
|
`public readonly ${modelRepositoryVariableName}: ${meta.data.repositoryClassName}`,
|
|
56
|
-
`@Inject(forwardRef(() => ${schemaMeta.businessLogic.serviceClassName})) private readonly ${
|
|
35
|
+
`@Inject(forwardRef(() => ${schemaMeta.businessLogic.view.serviceClassName})) private readonly ${viewServiceClassName}: ${schemaMeta.businessLogic.view.serviceClassName}`,
|
|
57
36
|
];
|
|
58
|
-
imports.addImport({
|
|
59
|
-
from: schemaMeta.businessLogic.serviceFilePath,
|
|
60
|
-
items: [schemaMeta.businessLogic.serviceClassName],
|
|
61
|
-
});
|
|
62
|
-
imports.addImport({ from: meta.data.importPath, items: [meta.data.repositoryClassName] });
|
|
63
37
|
/**
|
|
64
38
|
* Variable names and their definitions indexed by the name of the relation they represent.
|
|
65
39
|
*/
|
|
@@ -67,9 +41,9 @@ function generateModelBusinessLogic({ model, meta }) {
|
|
|
67
41
|
for (const relation of (0, fields_1.getRelationFields)(model)) {
|
|
68
42
|
const refModel = relation.relationToModel;
|
|
69
43
|
const refMeta = (0, meta_1.getModelMetadata)({ model: refModel });
|
|
70
|
-
const variableGetter = `this.${
|
|
44
|
+
const variableGetter = `this.${viewServiceClassName}.${refMeta.businessLogic.view.serviceVariableName}.get(itemRaw.${relation.name})`;
|
|
71
45
|
const variablePresenceCheck = `
|
|
72
|
-
|
|
46
|
+
if (!${relation.relatedModelBacklinkFieldName}) {
|
|
73
47
|
throw new Error(\`Could not find ${refMeta.types.typeName} with id \${itemRaw.${relation.name}} for ${model.typeName}.${relation.name}!\`)
|
|
74
48
|
}
|
|
75
49
|
`;
|
|
@@ -114,11 +88,10 @@ function generateModelBusinessLogic({ model, meta }) {
|
|
|
114
88
|
})
|
|
115
89
|
.join(',\n')}
|
|
116
90
|
}
|
|
91
|
+
|
|
117
92
|
return item
|
|
118
93
|
}
|
|
119
94
|
`;
|
|
120
|
-
const methodTypeSignatures = (0, repository_generator_1.getRepositoryMethodsTypeSignatures)({ model, meta });
|
|
121
|
-
// prettier-ignore
|
|
122
95
|
return `
|
|
123
96
|
import { Inject, Injectable, forwardRef } from '@nestjs/common'
|
|
124
97
|
import { FilterOperator } from '@pxl/common'
|
|
@@ -126,7 +99,7 @@ import { FilterOperator } from '@pxl/common'
|
|
|
126
99
|
${imports.generate()}
|
|
127
100
|
|
|
128
101
|
@Injectable()
|
|
129
|
-
export class ${meta.businessLogic.serviceClassName} {
|
|
102
|
+
export class ${meta.businessLogic.view.serviceClassName} {
|
|
130
103
|
constructor(${constructorParameters.join(',\n')}) {}
|
|
131
104
|
|
|
132
105
|
/**
|
|
@@ -140,14 +113,14 @@ export class ${meta.businessLogic.serviceClassName} {
|
|
|
140
113
|
${hasLinkedItems ? linkedItemsGetterFn : ''}
|
|
141
114
|
|
|
142
115
|
/**
|
|
143
|
-
* Returns a map of all ${meta.
|
|
116
|
+
* Returns a map of all ${meta.userFriendlyNamePlural}.
|
|
144
117
|
*/
|
|
145
118
|
public getAll(): Map<${meta.types.brandedIdType}, ${model.typeName}> {
|
|
146
119
|
return this.${modelRepositoryVariableName}.getAll()
|
|
147
120
|
}
|
|
148
121
|
|
|
149
|
-
|
|
150
|
-
* Returns a list of filtered, sorted and paginated ${meta.
|
|
122
|
+
/**
|
|
123
|
+
* Returns a list of filtered, sorted and paginated ${meta.userFriendlyNamePlural}.
|
|
151
124
|
*/
|
|
152
125
|
public getList({
|
|
153
126
|
filter,
|
|
@@ -171,29 +144,6 @@ export class ${meta.businessLogic.serviceClassName} {
|
|
|
171
144
|
return { rows: paginated, count: items.length }
|
|
172
145
|
}
|
|
173
146
|
|
|
174
|
-
/**
|
|
175
|
-
* Creates a new ${meta.userFriendlyName}.
|
|
176
|
-
*/
|
|
177
|
-
public async create(item: ${methodTypeSignatures.create.parameters[0]}): ${methodTypeSignatures.create.returnType} {
|
|
178
|
-
return this.${modelRepositoryVariableName}.create(item)
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
/**
|
|
182
|
-
* Updates the given ${meta.userFriendlyName}.
|
|
183
|
-
*/
|
|
184
|
-
public async update(item: ${methodTypeSignatures.update.parameters[0]}): ${methodTypeSignatures.update.returnType} {
|
|
185
|
-
return this.${modelRepositoryVariableName}.update(item)
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
/**
|
|
189
|
-
* Deletes the ${meta.userFriendlyName} with the given id.
|
|
190
|
-
*
|
|
191
|
-
* Note: This does NOT delete any linked items.
|
|
192
|
-
* If the item is a dependency of another item, the deletion will fail!
|
|
193
|
-
*/
|
|
194
|
-
public async delete(id: ${methodTypeSignatures.delete.parameters[0]}): ${methodTypeSignatures.delete.returnType} {
|
|
195
|
-
return this.${modelRepositoryVariableName}.delete(id)
|
|
196
|
-
}
|
|
197
147
|
}
|
|
198
148
|
|
|
199
149
|
// Utility Functions
|
|
@@ -203,7 +153,7 @@ ${_createModelCompareFn({ model })}
|
|
|
203
153
|
${_createModelFilterFn({ model })}
|
|
204
154
|
`;
|
|
205
155
|
}
|
|
206
|
-
exports.
|
|
156
|
+
exports.generateModelBusinessLogicView = generateModelBusinessLogicView;
|
|
207
157
|
/**
|
|
208
158
|
* Generates a utility filter function for the given model that can be used to filter out instances
|
|
209
159
|
* of a model using a given operator on a given field.
|
|
@@ -221,8 +171,9 @@ function _createModelFilterFn({ model }) {
|
|
|
221
171
|
case 'contains': {
|
|
222
172
|
return (item[field] || '').toLowerCase().includes(value.toLowerCase())
|
|
223
173
|
}
|
|
224
|
-
default:
|
|
174
|
+
default: {
|
|
225
175
|
return false
|
|
176
|
+
}
|
|
226
177
|
}
|
|
227
178
|
`,
|
|
228
179
|
};
|
|
@@ -198,7 +198,7 @@ export const ${components.modals.editComponentName} = ({
|
|
|
198
198
|
<Typed.Formik
|
|
199
199
|
initialValues={{
|
|
200
200
|
${fields
|
|
201
|
-
.filter((f) => !f.attributes.isReadonly)
|
|
201
|
+
.filter((f) => !f.attributes.isReadonly || f.kind === 'id')
|
|
202
202
|
.map((field) => {
|
|
203
203
|
switch (field.kind) {
|
|
204
204
|
case 'enum':
|
|
@@ -500,7 +500,7 @@ function getEditFormInputFields({ model }) {
|
|
|
500
500
|
}
|
|
501
501
|
function getEditFormikMutationData({ model: { fields } }) {
|
|
502
502
|
return fields
|
|
503
|
-
.filter((f) => !f.attributes.isReadonly)
|
|
503
|
+
.filter((f) => !f.attributes.isReadonly || f.kind === 'id')
|
|
504
504
|
.map((field) => {
|
|
505
505
|
const formikFieldName = getFormikFieldName(field.name);
|
|
506
506
|
switch (field.kind) {
|
|
@@ -31,6 +31,10 @@ type FnSignature = {
|
|
|
31
31
|
* The return type of the function.
|
|
32
32
|
*/
|
|
33
33
|
returnType: string;
|
|
34
|
+
/**
|
|
35
|
+
* The JSDoc comment of the function.
|
|
36
|
+
*/
|
|
37
|
+
jsDoc?: string[];
|
|
34
38
|
};
|
|
35
39
|
/**
|
|
36
40
|
* Returns a collection of type signatures for the repository methods of a given model.
|
|
@@ -40,7 +44,12 @@ export declare function getRepositoryMethodsTypeSignatures({ model, meta }: {
|
|
|
40
44
|
meta: ModelMetaData;
|
|
41
45
|
}): {
|
|
42
46
|
create: FnSignature;
|
|
47
|
+
createMany: FnSignature;
|
|
43
48
|
update: FnSignature;
|
|
49
|
+
updateMany: FnSignature;
|
|
50
|
+
upsert: FnSignature;
|
|
51
|
+
upsertMany: FnSignature;
|
|
44
52
|
delete: FnSignature;
|
|
53
|
+
deleteMany: FnSignature;
|
|
45
54
|
};
|
|
46
55
|
export {};
|