@postxl/generator 0.54.0 → 0.56.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 CHANGED
@@ -221,7 +221,7 @@ function generate({ models, enums, config, prismaClientPath, logger, }) {
221
221
  generated.write(`/${meta.importExport.decoder.fullDecoderFilePath}.ts`, (0, importexport_decoder_generator_1.generateImportExportDecoder)({ models, meta }));
222
222
  generated.write(`/${meta.importExport.converterFunctions.filePath}.ts`, (0, importexport_convert_import_functions_generator_1.generateImportExportConvertImportFunctions)({ models, meta }));
223
223
  // Actions
224
- generated.write(`/${meta.actions.dispatcherService.filePath}.ts`, (0, dispatcher_service_generator_1.generateActionsDispatcherService)({ models, meta }));
224
+ generated.write(`/${meta.actions.dispatcher.filePath}.ts`, (0, dispatcher_service_generator_1.generateActionsDispatcherService)({ models, meta }));
225
225
  // Business Logic
226
226
  generated.write(`/${meta.businessLogic.view.indexFilePath}.ts`, (0, businesslogic_view_index_generator_1.generateBusinessLogicViewIndex)({ models, meta }));
227
227
  generated.write(`/${meta.businessLogic.view.moduleFilePath}.ts`, (0, businesslogic_view_module_generator_1.generateBusinessLogicViewModule)({ models, meta }));
@@ -3,27 +3,38 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.generateBusinessLogicActionTypes = void 0;
4
4
  const imports_1 = require("../../lib/imports");
5
5
  const meta_1 = require("../../lib/meta");
6
+ const types_1 = require("../../lib/schema/types");
7
+ const file_1 = require("../../lib/utils/file");
6
8
  /**
7
9
  * Generates the action types for the BusinessLogicModule.
8
10
  */
9
11
  function generateBusinessLogicActionTypes({ models, meta }) {
10
- const imports = imports_1.ImportsGenerator.from(meta.businessLogic.update.actionTypesFilePath);
12
+ const imports = imports_1.ImportsGenerator.from(meta.businessLogic.update.actionTypesFilePath).addImport({
13
+ from: meta.actions.importPath,
14
+ items: [(0, types_1.toTypeName)('ActionDefPayload'), (0, types_1.toTypeName)('ActionDefResult')],
15
+ });
16
+ const updateServiceImports = [];
11
17
  const modelNameTypeElements = [];
12
18
  const actionsTypeElements = [];
13
19
  const actionResultTypeElements = [];
14
20
  for (const model of models) {
15
21
  const modelMeta = (0, meta_1.getModelMetadata)({ model });
16
- imports.addImport({
17
- items: [modelMeta.businessLogic.update.actionName, modelMeta.businessLogic.update.actionResultName],
18
- from: modelMeta.businessLogic.update.serviceFilePath,
22
+ const className = modelMeta.businessLogic.update.serviceClassName;
23
+ const scope = modelMeta.businessLogic.update.actionModelDiscriminantName;
24
+ modelNameTypeElements.push(`'${scope}'`);
25
+ const relativeImportPath = (0, file_1.getRelativePath)({
26
+ from: meta.businessLogic.update.actionTypesFilePath,
27
+ to: modelMeta.businessLogic.update.serviceFilePath,
19
28
  });
20
- modelNameTypeElements.push(`'${modelMeta.businessLogic.update.actionModelDiscriminantName}'`);
21
- actionsTypeElements.push(modelMeta.businessLogic.update.actionName);
22
- actionResultTypeElements.push(`${modelMeta.businessLogic.update.actionModelDiscriminantName}: ${modelMeta.businessLogic.update.actionResultName}`);
29
+ updateServiceImports.push(`import type * as ${className} from '${relativeImportPath}'`);
30
+ actionsTypeElements.push(`ActionDefPayload<${className}.Scope, ${className}.Actions>`);
31
+ actionResultTypeElements.push(`${scope}: ActionDefResult<${className}.Actions>`);
23
32
  }
24
33
  return /* ts */ `
25
34
  ${imports.generate()}
26
35
 
36
+ ${updateServiceImports.join('\n')}
37
+
27
38
  /**
28
39
  * Used by any of the default actions (create, update, delete) to identify the model.
29
40
  */
@@ -13,7 +13,9 @@ function generateBusinessLogicUpdateIndex({ models, meta }) {
13
13
  exports.exportEverythingFromPath(meta.businessLogic.update.actionTypesFilePath);
14
14
  for (const model of models) {
15
15
  const meta = (0, meta_1.getModelMetadata)({ model });
16
- exports.exportEverythingFromPath(meta.businessLogic.update.serviceFilePath);
16
+ exports.exportSelectionFromPath(meta.businessLogic.update.serviceFilePath, [
17
+ meta.businessLogic.update.serviceClassName,
18
+ ]);
17
19
  }
18
20
  return exports.generate();
19
21
  }
@@ -8,7 +8,7 @@ const types_1 = require("../../lib/schema/types");
8
8
  * Generates the action dispatcher service.
9
9
  */
10
10
  function generateActionsDispatcherService({ models, meta }) {
11
- const imports = imports_1.ImportsGenerator.from(meta.actions.dispatcherService.filePath).addImports({
11
+ const imports = imports_1.ImportsGenerator.from(meta.actions.dispatcher.filePath).addImports({
12
12
  [meta.seed.importPath]: [meta.seed.serviceClassName],
13
13
  [meta.importExport.importPath]: [meta.importExport.importService.name],
14
14
  [meta.businessLogic.update.importPath]: [meta.businessLogic.update.serviceClassName],
@@ -32,7 +32,7 @@ import { Action, ResultOfAction } from './actions.types'
32
32
 
33
33
 
34
34
  @Injectable()
35
- export class ${meta.actions.dispatcherService.class} {
35
+ export class ${meta.actions.dispatcher.class} {
36
36
 
37
37
  // As SeedModule and ImportExportModule get instantiated after the ActionsModule, we use this hack to avoid a circular dependency:
38
38
  // we set the seedService and the importService to value and then overwrite it in the services' constructors.
@@ -9,6 +9,7 @@ const types_1 = require("../../lib/schema/types");
9
9
  */
10
10
  function generateImportExportExporterClass({ models, meta }) {
11
11
  const imports = imports_1.ImportsGenerator.from(meta.importExport.exporterClass.filePath);
12
+ const modelsMap = new Map(models.map((model) => [model.name, model]));
12
13
  imports.addImports({
13
14
  [meta.businessLogic.view.importPath]: [meta.businessLogic.view.serviceClassName],
14
15
  [meta.importExport.decoder.fullDecoderFilePath]: [
@@ -39,20 +40,50 @@ function generateImportExportExporterClass({ models, meta }) {
39
40
  }
40
41
  const linkedModelMeta = (0, meta_1.getModelMetadata)({ model: field.relationToModel });
41
42
  if (field.isRequired) {
42
- linkedItems.push(`await this.${linkedModelMeta.importExport.exportAddFunctionName}(item.${field.name})`);
43
+ linkedItems.push(`await this.${linkedModelMeta.importExport.exportAddFunctionName}({id: item.${field.name}, includeChildren: false})`);
43
44
  }
44
45
  else {
45
46
  linkedItems.push(`
46
47
  if (item.${field.name}) {
47
- await this.${linkedModelMeta.importExport.exportAddFunctionName}(item.${field.name})
48
+ await this.${linkedModelMeta.importExport.exportAddFunctionName}({id: item.${field.name}, includeChildren: false})
48
49
  }`);
49
50
  }
50
51
  }
52
+ const childItemCalls = [];
53
+ for (const relatedModelCore of model.relatedModels) {
54
+ const relatedModel = modelsMap.get(relatedModelCore.name);
55
+ // This should not happen as the related models are always present
56
+ if (!relatedModel) {
57
+ continue;
58
+ }
59
+ for (const field of relatedModel.fields) {
60
+ if (field.kind !== 'relation') {
61
+ continue;
62
+ }
63
+ if (field.relationToModel.name !== model.name) {
64
+ continue;
65
+ }
66
+ const linkedModelMeta = (0, meta_1.getModelMetadata)({ model: relatedModel });
67
+ const linkedFieldMeta = (0, meta_1.getFieldMetadata)({ field: field });
68
+ childItemCalls.push(`
69
+ // Add all ${linkedModelMeta.userFriendlyNamePlural} that are related to the ${modelMeta.userFriendlyName} via ${field.name}
70
+ for (const ${field.name} of await this.viewService.${linkedModelMeta.businessLogic.view.serviceVariableName}.data.${linkedFieldMeta.getByForeignKeyIdsMethodFnName}(id)) {
71
+ await this.${linkedModelMeta.importExport.exportAddFunctionName}({id: ${field.name}, includeChildren})
72
+ }`);
73
+ }
74
+ }
75
+ const childItems = childItemCalls.length > 0
76
+ ? `
77
+ if (includeChildren) {
78
+ ${childItemCalls.join('\n')}
79
+ }`
80
+ : '';
81
+ const signature = `{id, includeChildren = true}: {id: ${model.brandedIdType}, includeChildren?: boolean}`;
51
82
  addFunctions.push(`
52
83
  /**
53
84
  * Adds a ${modelMeta.userFriendlyName} and all related (and nested) dependencies to the export.
54
85
  */
55
- public async ${modelMeta.importExport.exportAddFunctionName}(id: ${model.brandedIdType}) {
86
+ public async ${modelMeta.importExport.exportAddFunctionName}(${signature}) {
56
87
  if (this.${modelMeta.internalPluralName}.has(id)) {
57
88
  return
58
89
  }
@@ -64,11 +95,17 @@ function generateImportExportExporterClass({ models, meta }) {
64
95
  this.${modelMeta.internalPluralName}.set(id, item)
65
96
 
66
97
  ${linkedItems.join('\n')}
98
+
99
+ ${childItems}
67
100
  }
68
101
  `);
69
102
  addAllCalls.push(`this.${modelMeta.internalPluralName} = await this.viewService.${modelMeta.businessLogic.view.serviceVariableName}.getAll()`);
70
103
  }
71
104
  return /* ts */ `
105
+ // For consistency, we include \`{ includeChildren = true }\` in the signature of every add function.
106
+ // If the model does not have any related models, the \`includeChildren\` parameter is ignored.
107
+ /* eslint-disable @typescript-eslint/no-unused-vars */
108
+
72
109
  import { Logger } from '@nestjs/common'
73
110
 
74
111
  import { mapValues } from '@backend/common'
@@ -79,7 +116,7 @@ ${imports.generate()}
79
116
  *
80
117
  * Usage:
81
118
  * - Create an instance of the Exporter
82
- * - Call the \`add{ModelName}(itemId)\` methods to add the items you want to export.
119
+ * - Call the \`add{ModelName}({id})\` methods to add the items you want to export.
83
120
  * This will automatically add all dependencies of the item.
84
121
  * - Call the \`exportData()\` method to get the encoded Excel data.
85
122
  * - Alternatively, you can call 'exportAll()' to dump all data.
@@ -22,7 +22,7 @@ function generateImportExportImportService({ models, meta }) {
22
22
  (0, types_1.toAnnotatedTypeName)(dto.idType),
23
23
  (0, types_1.toAnnotatedTypeName)(dto.update),
24
24
  ],
25
- [meta.actions.importPath]: [meta.actions.actionExecution.interface, meta.actions.dispatcherService.class],
25
+ [meta.actions.importPath]: [meta.actions.actionExecution.interface, meta.actions.dispatcher.class],
26
26
  [types.filePath]: [
27
27
  (0, types_1.toAnnotatedTypeName)(delta_Fields),
28
28
  (0, types_1.toAnnotatedTypeName)(delta_Model.type),
@@ -61,7 +61,7 @@ type Delta_Result<Model extends ${dto.genericModel}<ID>, ID extends ${dto.idType
61
61
  export class ${meta.importExport.importService.name} {
62
62
  constructor(
63
63
  private readonly data: ${meta.data.dataService.class},
64
- private readonly dispatcher: ${meta.actions.dispatcherService.class},
64
+ private readonly dispatcher: ${meta.actions.dispatcher.class},
65
65
  ) {
66
66
  // We have a circular dependency between DispatcherService and ${meta.importExport.importService.name}.
67
67
  // In order to avoid trouble, instead of using Nest's forwardRef(), we inject the dispatcher service here
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.generateSeedMigration = void 0;
4
4
  const imports_1 = require("../../lib/imports");
5
5
  const meta_1 = require("../../lib/meta");
6
+ const types_1 = require("../../lib/schema/types");
6
7
  /**
7
8
  * Generates the initial migration based on the generated seed data.
8
9
  */
@@ -14,21 +15,22 @@ function generateSeedMigration({ models, meta }) {
14
15
  imports.addImports({
15
16
  [modelMeta.seed.filePath]: [modelMeta.seed.constantName],
16
17
  [meta.importExport.importPath]: [meta.importExport.converterFunctions.importedDataToBulkMutations],
18
+ [meta.seed.importPath]: [(0, types_1.toTypeName)('Action_Seed_Data')],
17
19
  });
18
20
  modelTypes.push(`${modelMeta.seed.constantName}`);
19
21
  }
20
22
  return /* ts */ `
21
- import { createActionSeedData } from '${meta.seed.importPath}'
22
23
  ${imports.generate()}
23
24
 
24
- export const MIGRATION_001_BASEDATA = createActionSeedData({
25
+ export const MIGRATION_001_BASEDATA: Action_Seed_Data = {
26
+ scope: 'seed',
27
+ type: 'data',
25
28
  name: 'Base data',
26
29
  order: 1,
27
- data: ${meta.importExport.converterFunctions.importedDataToBulkMutations}({
28
- ${modelTypes.join(',\n')}
29
- },
30
- ),
31
- })
30
+ payload: ${meta.importExport.converterFunctions.importedDataToBulkMutations}({
31
+ ${modelTypes.join(',\n')}
32
+ }),
33
+ }
32
34
  `;
33
35
  }
34
36
  exports.generateSeedMigration = generateSeedMigration;
@@ -16,7 +16,6 @@ function generateTestDataService({ models, meta: schemaMeta, }) {
16
16
  (0, types_1.toAnnotatedTypeName)(schemaMeta.data.dataMockDataType),
17
17
  ],
18
18
  [schemaMeta.importExport.importPath]: [schemaMeta.importExport.converterFunctions.mockDataToBulkMutations],
19
- [schemaMeta.seed.importPath]: [(0, types_1.toClassName)('createActionSeedData')],
20
19
  });
21
20
  const reInitCalls = [];
22
21
  const modelMetas = models.map((model) => ({ model, meta: (0, meta_1.getModelMetadata)({ model }) }));
@@ -57,12 +56,19 @@ export class TestDataService {
57
56
  this.logger.log('✍ Setting test data')
58
57
 
59
58
  const mockData = ${schemaMeta.importExport.converterFunctions.mockDataToBulkMutations}(data)
60
- const action = createActionSeedData({ name: 'E2E', order: 0, data: [] })
59
+
61
60
  const actionExecution = await this.actionExecutionFactory.create({
62
- action,
61
+ action: {
62
+ scope: 'seed',
63
+ type: 'data',
64
+ name: 'E2E',
65
+ order: 0,
66
+ payload: []
67
+ },
63
68
  dbService: this.db,
64
69
  user: this.dataService.users.rootUser,
65
70
  })
71
+
66
72
  try {
67
73
  ${reInitCalls.join('\n')}
68
74