@postxl/generator 0.39.0 → 0.40.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 +37 -21
- package/dist/generators/indices/businesslogic-update-module.generator.js +1 -1
- package/dist/generators/indices/businesslogic-view-module.generator.js +1 -1
- package/dist/generators/indices/{seed-service.generator.d.ts → data-types.generator.d.ts} +2 -2
- package/dist/generators/indices/data-types.generator.js +48 -0
- package/dist/generators/indices/datamock-module.generator.js +7 -7
- package/dist/generators/indices/datamodule.generator.js +13 -34
- package/dist/generators/indices/dataservice.generator.js +201 -8
- package/dist/generators/indices/dispatcher-service.generator.js +14 -5
- package/dist/generators/indices/importexport-convert-import-functions.generator.d.ts +9 -0
- package/dist/generators/indices/importexport-convert-import-functions.generator.js +528 -0
- package/dist/generators/indices/{seed-template-decoder.generator.d.ts → importexport-exporter-class.generator.d.ts} +2 -2
- package/dist/generators/indices/importexport-exporter-class.generator.js +116 -0
- package/dist/generators/indices/importexport-import-service.generator.d.ts +9 -0
- package/dist/generators/indices/importexport-import-service.generator.js +563 -0
- package/dist/generators/indices/{seeddata-type.generator.d.ts → importexport-types.generator.d.ts} +2 -2
- package/dist/generators/indices/importexport-types.generator.js +234 -0
- package/dist/generators/indices/repositories.generator.js +7 -7
- package/dist/generators/indices/seed-template.generator.js +1 -1
- package/dist/generators/indices/testdata-service.generator.js +5 -4
- package/dist/generators/models/businesslogic-update.generator.js +5 -5
- package/dist/generators/models/businesslogic-view.generator.js +3 -3
- package/dist/generators/models/importexport-decoder.generator.d.ts +23 -0
- package/dist/generators/models/importexport-decoder.generator.js +234 -0
- package/dist/generators/models/repository.generator.js +50 -21
- package/dist/lib/imports.d.ts +1 -1
- package/dist/lib/meta.d.ts +468 -134
- package/dist/lib/meta.js +187 -80
- package/dist/lib/schema/schema.d.ts +54 -43
- package/dist/lib/schema/types.d.ts +63 -12
- package/dist/lib/schema/types.js +27 -7
- package/dist/lib/utils/string.d.ts +1 -0
- package/dist/lib/utils/string.js +4 -0
- package/dist/prisma/parse.js +4 -4
- package/package.json +1 -1
- package/dist/generators/indices/seed-service.generator.js +0 -354
- package/dist/generators/indices/seed-template-decoder.generator.js +0 -151
- package/dist/generators/indices/seeddata-type.generator.js +0 -42
package/dist/generator.js
CHANGED
|
@@ -48,24 +48,27 @@ const businesslogic_update_service_generator_1 = require("./generators/indices/b
|
|
|
48
48
|
const businesslogic_view_index_generator_1 = require("./generators/indices/businesslogic-view-index.generator");
|
|
49
49
|
const businesslogic_view_module_generator_1 = require("./generators/indices/businesslogic-view-module.generator");
|
|
50
50
|
const businesslogic_view_service_generator_1 = require("./generators/indices/businesslogic-view-service.generator");
|
|
51
|
+
const data_types_generator_1 = require("./generators/indices/data-types.generator");
|
|
51
52
|
const datamock_module_generator_1 = require("./generators/indices/datamock-module.generator");
|
|
52
53
|
const datamocker_generator_1 = require("./generators/indices/datamocker.generator");
|
|
53
54
|
const datamodule_generator_1 = require("./generators/indices/datamodule.generator");
|
|
54
55
|
const dataservice_generator_1 = require("./generators/indices/dataservice.generator");
|
|
55
56
|
const dispatcher_service_generator_1 = require("./generators/indices/dispatcher-service.generator");
|
|
56
57
|
const emptydatabasemigration_generator_1 = require("./generators/indices/emptydatabasemigration.generator");
|
|
58
|
+
const importexport_convert_import_functions_generator_1 = require("./generators/indices/importexport-convert-import-functions.generator");
|
|
59
|
+
const importexport_exporter_class_generator_1 = require("./generators/indices/importexport-exporter-class.generator");
|
|
60
|
+
const importexport_import_service_generator_1 = require("./generators/indices/importexport-import-service.generator");
|
|
61
|
+
const importexport_types_generator_1 = require("./generators/indices/importexport-types.generator");
|
|
57
62
|
const repositories_generator_1 = require("./generators/indices/repositories.generator");
|
|
58
63
|
const seed_migration_generator_1 = require("./generators/indices/seed-migration.generator");
|
|
59
|
-
const seed_service_generator_1 = require("./generators/indices/seed-service.generator");
|
|
60
64
|
const seed_template_generator_1 = require("./generators/indices/seed-template.generator");
|
|
61
|
-
const seed_template_decoder_generator_1 = require("./generators/indices/seed-template-decoder.generator");
|
|
62
|
-
const seeddata_type_generator_1 = require("./generators/indices/seeddata-type.generator");
|
|
63
65
|
const selectors_generator_1 = require("./generators/indices/selectors.generator");
|
|
64
66
|
const stubs_generator_1 = require("./generators/indices/stubs.generator");
|
|
65
67
|
const testdata_service_generator_1 = require("./generators/indices/testdata-service.generator");
|
|
66
68
|
const types_generator_2 = require("./generators/indices/types.generator");
|
|
67
69
|
const businesslogic_update_generator_1 = require("./generators/models/businesslogic-update.generator");
|
|
68
70
|
const businesslogic_view_generator_1 = require("./generators/models/businesslogic-view.generator");
|
|
71
|
+
const importexport_decoder_generator_1 = require("./generators/models/importexport-decoder.generator");
|
|
69
72
|
const react_generator_2 = require("./generators/models/react.generator");
|
|
70
73
|
const repository_generator_1 = require("./generators/models/repository.generator");
|
|
71
74
|
const route_generator_1 = require("./generators/models/route.generator");
|
|
@@ -80,14 +83,15 @@ const parse_1 = require("./prisma/parse");
|
|
|
80
83
|
const CONFIG_SCHEMA = zod_1.z
|
|
81
84
|
.object({
|
|
82
85
|
project: zod_1.z.string(),
|
|
83
|
-
pathToTypes: zod_1.z.string().optional(),
|
|
84
86
|
pathToDataLib: zod_1.z.string().optional(),
|
|
85
87
|
pathToCypress: zod_1.z.string().optional(),
|
|
86
88
|
pathToE2ELib: zod_1.z.string().optional(),
|
|
89
|
+
pathToImportExport: zod_1.z.string().optional(),
|
|
87
90
|
pathToActions: zod_1.z.string().optional(),
|
|
88
91
|
pathToBusinessLogic: zod_1.z.string().optional(),
|
|
89
|
-
pathToSeedLib: zod_1.z.string().optional(),
|
|
90
92
|
pathToSeedData: zod_1.z.string().optional(),
|
|
93
|
+
pathToSeedLib: zod_1.z.string().optional(),
|
|
94
|
+
pathToTypes: zod_1.z.string().optional(),
|
|
91
95
|
trpcRoutesFolder: zod_1.z.string().optional(),
|
|
92
96
|
reactFolderOutput: zod_1.z.string().optional(),
|
|
93
97
|
migrationsFolder: zod_1.z.string().optional(),
|
|
@@ -107,25 +111,27 @@ const CONFIG_SCHEMA = zod_1.z
|
|
|
107
111
|
dataLibPath: (0, types_1.toPath)(s.pathToDataLib || 'repos'),
|
|
108
112
|
cypressPath: (0, types_1.toPath)(s.pathToCypress || './e2e/cypress/'),
|
|
109
113
|
e2eLibPath: (0, types_1.toPath)(s.pathToE2ELib || './e2e/src/'),
|
|
114
|
+
importExportPath: (0, types_1.toPath)(s.pathToImportExport || 'import-export'),
|
|
110
115
|
actionsPath: (0, types_1.toPath)(s.pathToActions || 'actions'),
|
|
111
116
|
businessLogicPath: (0, types_1.toPath)(s.pathToBusinessLogic || 'business-logic'),
|
|
112
|
-
|
|
117
|
+
migrationsFolderPath: (0, types_1.toPath)(s.migrationsFolder || 'migrations'),
|
|
113
118
|
modelTypeDefinitionsPath: (0, types_1.toPath)(s.pathToTypes || 'types'),
|
|
114
|
-
|
|
119
|
+
reactFolderPath: (0, types_1.toPath)(s.reactFolderOutput || 'react'),
|
|
115
120
|
seedDataPath: (0, types_1.toPath)(s.pathToSeedData || 'seed-data'),
|
|
121
|
+
seedLibPath: (0, types_1.toPath)(s.pathToSeedLib || 'seed'),
|
|
116
122
|
trpcRoutesFolderPath: (0, types_1.toPath)(s.trpcRoutesFolder || 'trpc'),
|
|
117
|
-
migrationsFolderPath: (0, types_1.toPath)(s.migrationsFolder || 'migrations'),
|
|
118
123
|
},
|
|
119
124
|
randomSeed: s.randomSeed,
|
|
120
125
|
force: s.force,
|
|
121
126
|
disableGenerators: {
|
|
122
|
-
types: s.pathToTypes === undefined,
|
|
123
|
-
data: s.pathToDataLib === undefined,
|
|
124
127
|
actions: s.pathToActions === undefined,
|
|
125
128
|
businessLogic: s.pathToBusinessLogic === undefined,
|
|
129
|
+
data: s.pathToDataLib === undefined,
|
|
130
|
+
importExport: s.pathToImportExport === undefined,
|
|
131
|
+
react: s.reactFolderOutput === undefined,
|
|
126
132
|
seed: s.pathToSeedLib === undefined,
|
|
127
133
|
trpc: s.trpcRoutesFolder === undefined,
|
|
128
|
-
|
|
134
|
+
types: s.pathToTypes === undefined,
|
|
129
135
|
},
|
|
130
136
|
userType: (0, types_1.toTypeName)(`User`),
|
|
131
137
|
};
|
|
@@ -176,13 +182,17 @@ function generate({ models, enums, config, prismaClientPath, logger, }) {
|
|
|
176
182
|
if (!config.disableGenerators.seed) {
|
|
177
183
|
generated.write(`/${meta.seed.filePath}.ts`, (0, seed_generator_1.generateSeedModel)({ model, itemCount: 5, meta }));
|
|
178
184
|
}
|
|
179
|
-
//
|
|
185
|
+
// Data
|
|
180
186
|
if (!config.disableGenerators.data) {
|
|
181
187
|
generated.write(`/${meta.data.stubFilePath}.ts`, (0, stub_generator_1.generateStub)({ model, meta }));
|
|
182
|
-
generated.write(`/${meta.data.
|
|
183
|
-
generated.write(`/${meta.data.
|
|
188
|
+
generated.write(`/${meta.data.repository.filePath}.ts`, (0, repository_generator_1.generateRepository)({ model, meta }));
|
|
189
|
+
generated.write(`/${meta.data.mockRepository.filePath}.ts`, (0, repository_generator_1.generateMockRepository)({ model, meta }));
|
|
184
190
|
generated.write(`/${meta.data.dataMockerStubFilePath}.ts`, (0, stub_generator_1.generateStub)({ model, meta }));
|
|
185
191
|
}
|
|
192
|
+
// Import-Export
|
|
193
|
+
if (!config.disableGenerators.importExport) {
|
|
194
|
+
generated.write(`/${meta.importExport.decoder.filePath}.ts`, (0, importexport_decoder_generator_1.generateModelImportExportDecoder)({ model, meta }));
|
|
195
|
+
}
|
|
186
196
|
// Business Logic
|
|
187
197
|
if (!config.disableGenerators.businessLogic) {
|
|
188
198
|
generated.write(`/${meta.businessLogic.view.serviceFilePath}.ts`, (0, businesslogic_view_generator_1.generateModelBusinessLogicView)({ model, meta }));
|
|
@@ -213,14 +223,15 @@ function generate({ models, enums, config, prismaClientPath, logger, }) {
|
|
|
213
223
|
if (!config.disableGenerators.data) {
|
|
214
224
|
generated.write(`/${meta.data.dataMockModuleFilePath}.ts`, (0, datamock_module_generator_1.generateDataMockModule)({ models, meta }));
|
|
215
225
|
generated.write(`/${meta.data.dataModuleFilePath}.ts`, (0, datamodule_generator_1.generateDataModule)({ models, meta }));
|
|
216
|
-
generated.write(`/${meta.data.
|
|
226
|
+
generated.write(`/${meta.data.dataService.filePath}.ts`, (0, dataservice_generator_1.generateDataService)({ models, meta }));
|
|
217
227
|
generated.write(`/${meta.data.dataMockerFilePath}.ts`, (0, datamocker_generator_1.generateDataMocker)({ models, meta }));
|
|
218
228
|
generated.write(`/${meta.data.selectorsFilePath}.ts`, (0, selectors_generator_1.generateSelectors)());
|
|
219
229
|
generated.write(`/${meta.data.testDataServiceFilePath}.ts`, (0, testdata_service_generator_1.generateTestDataService)({ models, meta }));
|
|
220
230
|
generated.write(`/${meta.data.dataMockerStubIndexFilePath}.ts`, (0, stubs_generator_1.generateDataMockerStubsIndex)({ models, meta }));
|
|
221
|
-
generated.write(`/${meta.data.
|
|
222
|
-
generated.write(`/${meta.data.
|
|
231
|
+
generated.write(`/${meta.data.repository.constFilePath}.ts`, (0, repositories_generator_1.generateRepositoriesArray)({ models, meta }));
|
|
232
|
+
generated.write(`/${meta.data.repository.indexFilePath}.ts`, (0, repositories_generator_1.generateRepositoriesIndex)({ models, meta }));
|
|
223
233
|
generated.write(`/${meta.data.stubIndexFilePath}.ts`, (0, stubs_generator_1.generateStubsIndex)({ models, meta }));
|
|
234
|
+
generated.write(`/${meta.data.types.filePath}.ts`, (0, data_types_generator_1.generateDataTypes)({ models, meta }));
|
|
224
235
|
// We only generate the empty database migration if the migration folder already has an existing migration
|
|
225
236
|
// Else we would generate a migration that deletes from tables that have not yet been created in the database
|
|
226
237
|
// We include this check here as the template does not come with any migration - hence this migration should also not be generated
|
|
@@ -228,8 +239,16 @@ function generate({ models, enums, config, prismaClientPath, logger, }) {
|
|
|
228
239
|
generated.write((0, emptydatabasemigration_generator_1.deriveEmptyDatabaseMigrationFilePath)(meta), (0, emptydatabasemigration_generator_1.generateEmptyDatabaseStoredProcedure)({ models, meta }));
|
|
229
240
|
}
|
|
230
241
|
}
|
|
242
|
+
if (!config.disableGenerators.importExport) {
|
|
243
|
+
generated.write(`/${meta.importExport.types.filePath}.ts`, (0, importexport_types_generator_1.generateImportExportTypes)({ models, meta }));
|
|
244
|
+
generated.write(`/${meta.importExport.exporterClass.filePath}.ts`, (0, importexport_exporter_class_generator_1.generateImportExportExporterClass)({ models, meta }));
|
|
245
|
+
generated.write(`/${meta.importExport.importService.filePath}.ts`, (0, importexport_import_service_generator_1.generateImportExportImportService)({ models, meta }));
|
|
246
|
+
generated.write(`/${meta.importExport.decoder.indexFilePath}.ts`, (0, importexport_decoder_generator_1.generateImportExportDecoderIndex)({ models, meta }));
|
|
247
|
+
generated.write(`/${meta.importExport.decoder.fullDecoderFilePath}.ts`, (0, importexport_decoder_generator_1.generateImportExportDecoder)({ models, meta }));
|
|
248
|
+
generated.write(`/${meta.importExport.converterFunctions.filePath}.ts`, (0, importexport_convert_import_functions_generator_1.generateImportExportConvertImportFunctions)({ models, meta }));
|
|
249
|
+
}
|
|
231
250
|
if (!config.disableGenerators.actions) {
|
|
232
|
-
generated.write(`/${meta.actions.
|
|
251
|
+
generated.write(`/${meta.actions.dispatcherService.filePath}.ts`, (0, dispatcher_service_generator_1.generateActionsDispatcherService)({ models, meta }));
|
|
233
252
|
}
|
|
234
253
|
if (!config.disableGenerators.businessLogic) {
|
|
235
254
|
generated.write(`/${meta.businessLogic.view.indexFilePath}.ts`, (0, businesslogic_view_index_generator_1.generateBusinessLogicViewIndex)({ models, meta }));
|
|
@@ -241,11 +260,8 @@ function generate({ models, enums, config, prismaClientPath, logger, }) {
|
|
|
241
260
|
generated.write(`/${meta.businessLogic.update.actionTypesFilePath}.ts`, (0, businesslogic_actiontypes_generator_1.generateBusinessLogicActionTypes)({ models, meta }));
|
|
242
261
|
}
|
|
243
262
|
if (!config.disableGenerators.seed) {
|
|
244
|
-
generated.write(`/${meta.seed.seedDataTypeFilePath}.ts`, (0, seeddata_type_generator_1.generateSeedDataType)({ models, meta }));
|
|
245
|
-
generated.write(`/${meta.seed.serviceFilePath}.ts`, (0, seed_service_generator_1.generateSeedService)({ models, meta }));
|
|
246
263
|
generated.write(`/${meta.seedData.initialMigrationFilePath}.ts`, (0, seed_migration_generator_1.generateSeedMigration)({ models, meta }));
|
|
247
264
|
generated.write(`/${meta.seedData.templateExcelFilePath}`, yield (0, seed_template_generator_1.generateSeedExcelTemplate)({ models }));
|
|
248
|
-
generated.write(`/${meta.seedData.templateDecoderFilePath}.ts`, (0, seed_template_decoder_generator_1.generateSeedTemplateDecoder)({ models, meta }));
|
|
249
265
|
}
|
|
250
266
|
if (!config.disableGenerators.trpc) {
|
|
251
267
|
generated.write(`/${meta.trpc.routesFilePath}.ts`, (0, route_generator_1.generateRoutesIndex)({ models, meta }));
|
|
@@ -41,7 +41,7 @@ export class ${moduleName} {
|
|
|
41
41
|
*/
|
|
42
42
|
static getInstance(): DynamicModule {
|
|
43
43
|
if (!${moduleName}.cachedModule) {
|
|
44
|
-
throw new Error('${moduleName} must be called via .
|
|
44
|
+
throw new Error('${moduleName} must be called via .forRoot first!')
|
|
45
45
|
}
|
|
46
46
|
return ${moduleName}.cachedModule
|
|
47
47
|
}
|
|
@@ -40,7 +40,7 @@ export class ${moduleName} {
|
|
|
40
40
|
*/
|
|
41
41
|
static getInstance(): DynamicModule {
|
|
42
42
|
if (!${moduleName}.cachedModule) {
|
|
43
|
-
throw new Error('${moduleName} must be called via .
|
|
43
|
+
throw new Error('${moduleName} must be called via .forRoot first!')
|
|
44
44
|
}
|
|
45
45
|
return ${moduleName}.cachedModule
|
|
46
46
|
}
|
|
@@ -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 type for BulkMutations.
|
|
5
5
|
*/
|
|
6
|
-
export declare function
|
|
6
|
+
export declare function generateDataTypes({ models, meta }: {
|
|
7
7
|
models: Model[];
|
|
8
8
|
meta: SchemaMetaData;
|
|
9
9
|
}): string;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateDataTypes = void 0;
|
|
4
|
+
const imports_1 = require("../../lib/imports");
|
|
5
|
+
const meta_1 = require("../../lib/meta");
|
|
6
|
+
/**
|
|
7
|
+
* Generates type for BulkMutations.
|
|
8
|
+
*/
|
|
9
|
+
function generateDataTypes({ models, meta }) {
|
|
10
|
+
const { types } = meta.data;
|
|
11
|
+
const imports = imports_1.ImportsGenerator.from(types.filePath);
|
|
12
|
+
const dto = meta.types.dto;
|
|
13
|
+
imports.addImports({
|
|
14
|
+
[meta.types.importPath]: [dto.create, dto.update, dto.upsert, dto.genericModel, dto.idType],
|
|
15
|
+
});
|
|
16
|
+
const modelTypes = [];
|
|
17
|
+
for (const model of models) {
|
|
18
|
+
const modelMeta = (0, meta_1.getModelMetadata)({ model });
|
|
19
|
+
imports.addImport({
|
|
20
|
+
items: [modelMeta.types.typeName, modelMeta.types.brandedIdType],
|
|
21
|
+
from: modelMeta.types.importPath,
|
|
22
|
+
});
|
|
23
|
+
modelTypes.push(`${modelMeta.seed.constantName}?: ${types.bulkMutationForModel}<${modelMeta.types.typeName}, ${modelMeta.types.brandedIdType}>`);
|
|
24
|
+
}
|
|
25
|
+
return /* ts */ `
|
|
26
|
+
${imports.generate()}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Generic type for BulkMutation for a model.
|
|
30
|
+
*/
|
|
31
|
+
export type ${types.bulkMutationForModel}<
|
|
32
|
+
Model extends ${dto.genericModel}<ID>,
|
|
33
|
+
ID extends ${dto.idType}
|
|
34
|
+
> = {
|
|
35
|
+
create?: ${dto.create}<Model, ID>[]
|
|
36
|
+
update?: ${dto.update}<Model, ID>[]
|
|
37
|
+
upsert?: ${dto.upsert}<Model, ID>[]
|
|
38
|
+
delete?: ID[]
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Bulk changes for all models.
|
|
43
|
+
*/
|
|
44
|
+
export type ${types.bulkMutation} = {
|
|
45
|
+
${modelTypes.join('\n')}
|
|
46
|
+
}`;
|
|
47
|
+
}
|
|
48
|
+
exports.generateDataTypes = generateDataTypes;
|
|
@@ -34,20 +34,20 @@ function generateDataMockModule({ models, meta }) {
|
|
|
34
34
|
const mm = models.map((model) => ({ model, meta: (0, meta_1.getModelMetadata)({ model }) }));
|
|
35
35
|
const imports = imports_1.ImportsGenerator.from(meta.data.dataMockModuleFilePath).addImports({
|
|
36
36
|
[meta.data.dataModuleFilePath]: [Types.toVariableName('DataModule')],
|
|
37
|
-
[meta.data.
|
|
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.actionExecution.mock],
|
|
40
40
|
});
|
|
41
41
|
for (const { model, meta } of mm) {
|
|
42
42
|
imports.addImport({ items: [model.typeName], from: meta.types.importPath });
|
|
43
|
-
imports.addImport({ items: [meta.data.
|
|
44
|
-
imports.addImport({ items: [meta.data.
|
|
43
|
+
imports.addImport({ items: [meta.data.repository.className], from: meta.data.repository.filePath });
|
|
44
|
+
imports.addImport({ items: [meta.data.mockRepository.className], from: meta.data.mockRepository.filePath });
|
|
45
45
|
}
|
|
46
46
|
const providers = mm
|
|
47
47
|
.map(({ meta }) => `{
|
|
48
|
-
provide: ${meta.data.
|
|
48
|
+
provide: ${meta.data.repository.className},
|
|
49
49
|
useFactory: async () => {
|
|
50
|
-
const repository = new ${meta.data.
|
|
50
|
+
const repository = new ${meta.data.mockRepository.className}()
|
|
51
51
|
if (!!seed && !!seed.${meta.seed.constantName}) {
|
|
52
52
|
await repository.reInit({items: seed.${meta.seed.constantName}, execution })
|
|
53
53
|
}
|
|
@@ -73,7 +73,7 @@ export class ${meta.data.dataMockModuleName} {
|
|
|
73
73
|
const cachedModule = {
|
|
74
74
|
module: ${meta.data.moduleName},
|
|
75
75
|
imports: [DbModule.provideMock()],
|
|
76
|
-
providers
|
|
76
|
+
providers,
|
|
77
77
|
exports: providers,
|
|
78
78
|
global: true,
|
|
79
79
|
}
|
|
@@ -1,45 +1,21 @@
|
|
|
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
3
|
exports.generateDataModule = void 0;
|
|
27
4
|
const imports_1 = require("../../lib/imports");
|
|
28
5
|
const meta_1 = require("../../lib/meta");
|
|
29
|
-
const Types = __importStar(require("../../lib/schema/types"));
|
|
30
6
|
/**
|
|
31
7
|
* Generates a data module class.
|
|
32
8
|
*/
|
|
33
9
|
function generateDataModule({ models, meta }) {
|
|
34
10
|
const mm = models.map((model) => ({ model, meta: (0, meta_1.getModelMetadata)({ model }) }));
|
|
35
11
|
const imports = imports_1.ImportsGenerator.from(meta.data.dataModuleFilePath).addImports({
|
|
36
|
-
[meta.data.
|
|
12
|
+
[meta.data.dataService.filePath]: [meta.data.dataService.class],
|
|
37
13
|
[meta.data.dataMockModuleFilePath]: [meta.data.dataMockModuleName],
|
|
38
14
|
});
|
|
39
15
|
for (const { meta } of mm) {
|
|
40
16
|
imports.addImport({
|
|
41
|
-
items: [meta.data.
|
|
42
|
-
from: meta.data.
|
|
17
|
+
items: [meta.data.repository.className],
|
|
18
|
+
from: meta.data.repository.filePath,
|
|
43
19
|
});
|
|
44
20
|
}
|
|
45
21
|
const moduleName = meta.data.moduleName;
|
|
@@ -63,7 +39,7 @@ export class ${moduleName} {
|
|
|
63
39
|
*/
|
|
64
40
|
static getInstance(): DynamicModule {
|
|
65
41
|
if (!${moduleName}.cachedModule) {
|
|
66
|
-
throw new Error('${moduleName} must be called via .
|
|
42
|
+
throw new Error('${moduleName} must be called via .forRoot first!')
|
|
67
43
|
}
|
|
68
44
|
return ${moduleName}.cachedModule
|
|
69
45
|
}
|
|
@@ -91,7 +67,7 @@ export class ${moduleName} {
|
|
|
91
67
|
// We need to initialize the user repository right at the beginning,
|
|
92
68
|
// so that we have the rootUser available for the other modules - including
|
|
93
69
|
// the action and seed modules which will ensure that seed data is created.
|
|
94
|
-
const
|
|
70
|
+
const userRepositoryProvider: FactoryProvider<UserRepository> = {
|
|
95
71
|
provide: UserRepository,
|
|
96
72
|
inject: [DbService],
|
|
97
73
|
useFactory: async (dbService: DbService) => {
|
|
@@ -101,11 +77,14 @@ export class ${moduleName} {
|
|
|
101
77
|
},
|
|
102
78
|
}
|
|
103
79
|
|
|
104
|
-
const
|
|
105
|
-
|
|
80
|
+
const providers = [
|
|
81
|
+
DataService,
|
|
82
|
+
|
|
83
|
+
userRepositoryProvider,
|
|
84
|
+
|
|
106
85
|
${mm
|
|
107
86
|
.filter((mm) => mm.model.name !== 'User')
|
|
108
|
-
.map(({ meta }) => meta.data.
|
|
87
|
+
.map(({ meta }) => meta.data.repository.className)
|
|
109
88
|
.join(',')}
|
|
110
89
|
]
|
|
111
90
|
|
|
@@ -113,8 +92,8 @@ export class ${moduleName} {
|
|
|
113
92
|
module: ${moduleName},
|
|
114
93
|
global: true,
|
|
115
94
|
imports: [DbModule.forRoot()],
|
|
116
|
-
providers
|
|
117
|
-
exports:
|
|
95
|
+
providers,
|
|
96
|
+
exports: providers,
|
|
118
97
|
}
|
|
119
98
|
|
|
120
99
|
return ${moduleName}.cachedModule
|
|
@@ -8,30 +8,55 @@ const meta_1 = require("../../lib/meta");
|
|
|
8
8
|
*/
|
|
9
9
|
function generateDataService({ models, meta }) {
|
|
10
10
|
const mm = models.map((model) => ({ model, meta: (0, meta_1.getModelMetadata)({ model }) }));
|
|
11
|
-
const imports = imports_1.ImportsGenerator.from(meta.data.
|
|
11
|
+
const imports = imports_1.ImportsGenerator.from(meta.data.dataService.filePath);
|
|
12
12
|
for (const { meta } of mm) {
|
|
13
13
|
imports.addImport({
|
|
14
|
-
items: [meta.data.
|
|
15
|
-
from: meta.data.
|
|
14
|
+
items: [meta.data.repository.className],
|
|
15
|
+
from: meta.data.repository.filePath,
|
|
16
16
|
});
|
|
17
17
|
}
|
|
18
18
|
const constructor = mm
|
|
19
|
-
.map(({ meta }) => `public ${meta.data.dataServiceName} :${meta.data.
|
|
19
|
+
.map(({ meta }) => `public ${meta.data.dataServiceName} :${meta.data.repository.className}`)
|
|
20
20
|
.join(',\n');
|
|
21
21
|
const initializer = mm.map(({ meta }) => `await this.${meta.data.dataServiceName}.init()`).join('\n');
|
|
22
22
|
const excelExports = mm
|
|
23
|
-
.map(({ meta }) => `${meta.
|
|
23
|
+
.map(({ meta }) => `${meta.importExport.tableName}: mapValues(await this.${meta.data.dataServiceName}.getAll()),`)
|
|
24
24
|
.join('\n');
|
|
25
25
|
const isEmptyChecks = mm.map(({ meta }) => `(await this.${meta.data.dataServiceName}.count()) === 0`).join(' &&');
|
|
26
|
+
// Building blocks for bulk mutations
|
|
27
|
+
imports.addImports({
|
|
28
|
+
[meta.types.importPath]: [meta.types.dto.create, meta.types.dto.update],
|
|
29
|
+
[meta.data.repository.typeFilePath]: [meta.data.repository.typeName],
|
|
30
|
+
[meta.data.types.filePath]: [meta.data.types.bulkMutation],
|
|
31
|
+
[meta.actions.importPath]: [meta.actions.actionExecution.interface],
|
|
32
|
+
});
|
|
33
|
+
const creates = [];
|
|
34
|
+
const updates = [];
|
|
35
|
+
const upserts = [];
|
|
36
|
+
const deletes = [];
|
|
37
|
+
for (const model of models) {
|
|
38
|
+
const modelMeta = (0, meta_1.getModelMetadata)({ model });
|
|
39
|
+
creates.push(`await this.create({ name: '${modelMeta.userFriendlyName}', data: data.${modelMeta.seed.constantName}?.create, repo: this.${modelMeta.data.dataServiceName}, execution })`);
|
|
40
|
+
updates.push(`await this.update({ name: '${modelMeta.userFriendlyName}', data: data.${modelMeta.seed.constantName}?.update, repo: this.${modelMeta.data.dataServiceName}, execution })`);
|
|
41
|
+
upserts.push(`await this.upsert({ name: '${modelMeta.userFriendlyName}', data: data.${modelMeta.seed.constantName}?.upsert, repo: this.${modelMeta.data.dataServiceName}, execution })`);
|
|
42
|
+
deletes.push(`await this.delete({ name: '${modelMeta.userFriendlyName}', data: data.${modelMeta.seed.constantName}?.delete, repo: this.${modelMeta.data.dataServiceName}, execution })`);
|
|
43
|
+
}
|
|
26
44
|
return /* ts */ `
|
|
27
|
-
import { Injectable } from '@nestjs/common'
|
|
45
|
+
import { Injectable, Logger } from '@nestjs/common'
|
|
28
46
|
|
|
29
|
-
import { mapValues } from '@pxl/common'
|
|
47
|
+
import { format, mapValues, pluralize } from '@pxl/common'
|
|
30
48
|
|
|
31
49
|
${imports.generate()}
|
|
32
50
|
|
|
51
|
+
// If true, the bulk mutation will be executed one by one, instead of all at once (which is the default).
|
|
52
|
+
// Also, each item will be logged to the console.
|
|
53
|
+
// This should help to quickly identify the item that causes an error in a bulk mutation.
|
|
54
|
+
const DEBUG = false
|
|
55
|
+
|
|
33
56
|
@Injectable()
|
|
34
|
-
export class ${meta.data.
|
|
57
|
+
export class ${meta.data.dataService.class} {
|
|
58
|
+
private readonly logger = new Logger(${meta.data.dataService.class}.name)
|
|
59
|
+
|
|
35
60
|
constructor(${constructor}) {}
|
|
36
61
|
|
|
37
62
|
public async prepareExcelExport() {
|
|
@@ -49,6 +74,174 @@ export class ${meta.data.dataServiceClassName} {
|
|
|
49
74
|
${isEmptyChecks}
|
|
50
75
|
)
|
|
51
76
|
}
|
|
77
|
+
public async ${meta.data.dataService.executeBulkMutations}(
|
|
78
|
+
{ steps, execution }:
|
|
79
|
+
{ steps: ${meta.data.types.bulkMutation}[]; execution: ${meta.actions.actionExecution.interface} }
|
|
80
|
+
) {
|
|
81
|
+
let index = 0
|
|
82
|
+
for (const step of steps) {
|
|
83
|
+
this.logger.log(\`Uploading data step \${++index}/\${steps.length}\`)
|
|
84
|
+
await this.${meta.data.dataService.executeBulkMutation}({ data: step, execution })
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
public async ${meta.data.dataService.executeBulkMutation}(
|
|
89
|
+
{ data, execution }:
|
|
90
|
+
{ data: ${meta.data.types.bulkMutation}, execution: ${meta.actions.actionExecution.interface}}
|
|
91
|
+
) {
|
|
92
|
+
// NOTE: the order of these calls is important, because of foreign key constraints
|
|
93
|
+
// The current order is based on the order of the models in the schema
|
|
94
|
+
// Change the order based on your needs.
|
|
95
|
+
// Attention: Depending on the dependencies in seed data, you may also have to take care of relations,
|
|
96
|
+
// e.g. by removing any foreign key first - and then update these after all data is created.
|
|
97
|
+
// Alternatively, you can also do this in multiple steps
|
|
98
|
+
${creates.join('\n')}
|
|
99
|
+
|
|
100
|
+
${updates.join('\n')}
|
|
101
|
+
|
|
102
|
+
${upserts.join('\n')}
|
|
103
|
+
|
|
104
|
+
${deletes.join('\n')}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
private async create<T extends { id: ID }, ID extends number | string | boolean>({
|
|
108
|
+
name,
|
|
109
|
+
data,
|
|
110
|
+
repo,
|
|
111
|
+
execution,
|
|
112
|
+
}: {
|
|
113
|
+
name: string
|
|
114
|
+
data: ${meta.types.dto.create}<T, ID>[] | undefined
|
|
115
|
+
repo: ${meta.data.repository.typeName}<T, ID>
|
|
116
|
+
execution: ${meta.actions.actionExecution.interface}
|
|
117
|
+
}): Promise<void> {
|
|
118
|
+
if (!data) {
|
|
119
|
+
return
|
|
120
|
+
}
|
|
121
|
+
if (!DEBUG) {
|
|
122
|
+
await repo.createMany?.({ items: data, execution })
|
|
123
|
+
} else {
|
|
124
|
+
let i = 0
|
|
125
|
+
for (const item of data) {
|
|
126
|
+
i++
|
|
127
|
+
this.logger.log(\`Creating \${name} \${i} - \${_getItemDescription(item)}\`)
|
|
128
|
+
try {
|
|
129
|
+
await repo.create?.({ item, execution })
|
|
130
|
+
} catch (error) {
|
|
131
|
+
this.logger.error(\`Error creating \${name} \${i} - \${_getItemDescription(item)}\`, error)
|
|
132
|
+
throw error
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
this.logger.log(\`✅ Created \${format(data.length)} \${pluralize(name)}\`)
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
private async update<T extends { id: ID }, ID extends number | string | boolean>({
|
|
140
|
+
name,
|
|
141
|
+
data,
|
|
142
|
+
repo,
|
|
143
|
+
execution,
|
|
144
|
+
}: {
|
|
145
|
+
name: string
|
|
146
|
+
data: ${meta.types.dto.update}<T, ID>[] | undefined
|
|
147
|
+
repo: ${meta.data.repository.typeName}<T, ID>
|
|
148
|
+
execution: ${meta.actions.actionExecution.interface}
|
|
149
|
+
}): Promise<void> {
|
|
150
|
+
if (!data) {
|
|
151
|
+
return
|
|
152
|
+
}
|
|
153
|
+
if (!DEBUG) {
|
|
154
|
+
await repo.updateMany?.({ items: data, execution })
|
|
155
|
+
} else {
|
|
156
|
+
let i = 0
|
|
157
|
+
for (const item of data) {
|
|
158
|
+
i++
|
|
159
|
+
this.logger.log(\`Updating \${name} \${i} - \${_getItemDescription(item)}\`)
|
|
160
|
+
try {
|
|
161
|
+
await repo.update?.({ item, execution })
|
|
162
|
+
} catch (error) {
|
|
163
|
+
this.logger.error(\`Error updating \${name} \${i} - \${_getItemDescription(item)}\`, error)
|
|
164
|
+
throw error
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
this.logger.log(\`✅ Updated \${format(data.length)} \${pluralize(name)}\`)
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
private async upsert<T extends { id: ID }, ID extends number | string | boolean>({
|
|
172
|
+
name,
|
|
173
|
+
data,
|
|
174
|
+
repo,
|
|
175
|
+
execution,
|
|
176
|
+
}: {
|
|
177
|
+
name: string
|
|
178
|
+
data: (${meta.types.dto.create}<T, ID> | ${meta.types.dto.update}<T, ID>)[] | undefined
|
|
179
|
+
repo: ${meta.data.repository.typeName}<T, ID>
|
|
180
|
+
execution: ${meta.actions.actionExecution.interface}
|
|
181
|
+
}): Promise<void> {
|
|
182
|
+
if (!data) {
|
|
183
|
+
return
|
|
184
|
+
}
|
|
185
|
+
if (!DEBUG) {
|
|
186
|
+
await repo.upsertMany?.({ items: data, execution })
|
|
187
|
+
} else {
|
|
188
|
+
let i = 0
|
|
189
|
+
for (const item of data) {
|
|
190
|
+
i++
|
|
191
|
+
this.logger.log(\`Upserting \${name} \${i} - \${_getItemDescription(item)}\`)
|
|
192
|
+
try {
|
|
193
|
+
await repo.upsert?.({ item, execution })
|
|
194
|
+
} catch (error) {
|
|
195
|
+
this.logger.error(\`Error upserting \${name} \${i} - \${_getItemDescription(item)}\`, error)
|
|
196
|
+
throw error
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
this.logger.log(\`✅ Upserted \${format(data.length)} \${pluralize(name)}\`)
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
private async delete<T extends { id: ID }, ID extends number | string | boolean>({
|
|
204
|
+
name,
|
|
205
|
+
data,
|
|
206
|
+
repo,
|
|
207
|
+
execution,
|
|
208
|
+
}: {
|
|
209
|
+
name: string
|
|
210
|
+
data: ID[] | undefined
|
|
211
|
+
repo: ${meta.data.repository.typeName}<T, ID>
|
|
212
|
+
execution: ${meta.actions.actionExecution.interface}
|
|
213
|
+
}): Promise<void> {
|
|
214
|
+
if (!data) {
|
|
215
|
+
return
|
|
216
|
+
}
|
|
217
|
+
if (!DEBUG) {
|
|
218
|
+
await repo.deleteMany?.({ ids: data, execution })
|
|
219
|
+
} else {
|
|
220
|
+
let i = 0
|
|
221
|
+
for (const id of data) {
|
|
222
|
+
i++
|
|
223
|
+
this.logger.log(\`Deleting \${name} \${i} - id: \${id.toString()}\`)
|
|
224
|
+
try {
|
|
225
|
+
await repo.delete?.({ id, execution })
|
|
226
|
+
} catch (error) {
|
|
227
|
+
this.logger.error(\`Error deleting \${name} \${i} - id: \${id.toString()}\`, error)
|
|
228
|
+
throw error
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
this.logger.log(\`✅ Deleted \${format(data.length)} \${pluralize(name)}\`)
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
function _getItemDescription<T extends Partial<{ id: ID }>, ID extends number | string | boolean>(item: T): string {
|
|
237
|
+
const id = \`id: \${item.id !== undefined ? item.id.toString() : 'not provided'}\`
|
|
238
|
+
|
|
239
|
+
// If the item has a name, we can assume it is a string and add it to the description
|
|
240
|
+
if ('name' in item) {
|
|
241
|
+
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
|
242
|
+
return \`\${id}, name: \${item.name}\`
|
|
243
|
+
}
|
|
244
|
+
return id
|
|
52
245
|
}
|
|
53
246
|
`;
|
|
54
247
|
}
|
|
@@ -7,8 +7,9 @@ const meta_1 = require("../../lib/meta");
|
|
|
7
7
|
* Generates the action dispatcher service.
|
|
8
8
|
*/
|
|
9
9
|
function generateActionsDispatcherService({ models, meta }) {
|
|
10
|
-
const imports = imports_1.ImportsGenerator.from(meta.
|
|
10
|
+
const imports = imports_1.ImportsGenerator.from(meta.actions.dispatcherService.filePath).addImports({
|
|
11
11
|
[meta.seed.importPath]: [meta.seed.serviceClassName],
|
|
12
|
+
[meta.importExport.importPath]: [meta.importExport.importService.name],
|
|
12
13
|
[meta.businessLogic.update.importPath]: [meta.businessLogic.update.serviceClassName],
|
|
13
14
|
[meta.types.importPath]: meta.config.userType,
|
|
14
15
|
});
|
|
@@ -30,11 +31,15 @@ import { Action, ResultOfAction } from './actions.types'
|
|
|
30
31
|
|
|
31
32
|
|
|
32
33
|
@Injectable()
|
|
33
|
-
export class
|
|
34
|
-
|
|
35
|
-
//
|
|
34
|
+
export class ${meta.actions.dispatcherService.class} {
|
|
35
|
+
|
|
36
|
+
// As SeedModule and ImportExportModule get instantiated after the ActionsModule, we use this hack to avoid a circular dependency:
|
|
37
|
+
// we set the seedService and the importService to value and then overwrite it in the services' constructors.
|
|
36
38
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment
|
|
37
|
-
public seedService:
|
|
39
|
+
public seedService: SeedService = {} as unknown as any
|
|
40
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment
|
|
41
|
+
public ${meta.importExport.importService.sharedName}: ImportService = {} as unknown as any
|
|
42
|
+
|
|
38
43
|
constructor(
|
|
39
44
|
private readonly updateService: ${meta.businessLogic.update.serviceClassName},
|
|
40
45
|
private readonly dbService: DbService,
|
|
@@ -72,6 +77,10 @@ export class DispatcherService {
|
|
|
72
77
|
.join('\n')}
|
|
73
78
|
case 'seed':
|
|
74
79
|
return this.seedService.dispatch({ action, execution })
|
|
80
|
+
|
|
81
|
+
case 'import':
|
|
82
|
+
return this.importService.dispatch({ action, execution })
|
|
83
|
+
|
|
75
84
|
default:
|
|
76
85
|
throw new ExhaustiveSwitchCheck(action)
|
|
77
86
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { SchemaMetaData } from '../../lib/meta';
|
|
2
|
+
import { Model } from '../../lib/schema/schema';
|
|
3
|
+
/**
|
|
4
|
+
* Generates the Exporter class for the Import-Export module
|
|
5
|
+
*/
|
|
6
|
+
export declare function generateImportExportConvertImportFunctions({ models, meta, }: {
|
|
7
|
+
models: Model[];
|
|
8
|
+
meta: SchemaMetaData;
|
|
9
|
+
}): string;
|