@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.
Files changed (38) hide show
  1. package/dist/generator.js +37 -21
  2. package/dist/generators/indices/businesslogic-update-module.generator.js +1 -1
  3. package/dist/generators/indices/businesslogic-view-module.generator.js +1 -1
  4. package/dist/generators/indices/{seed-service.generator.d.ts → data-types.generator.d.ts} +2 -2
  5. package/dist/generators/indices/data-types.generator.js +48 -0
  6. package/dist/generators/indices/datamock-module.generator.js +7 -7
  7. package/dist/generators/indices/datamodule.generator.js +13 -34
  8. package/dist/generators/indices/dataservice.generator.js +201 -8
  9. package/dist/generators/indices/dispatcher-service.generator.js +14 -5
  10. package/dist/generators/indices/importexport-convert-import-functions.generator.d.ts +9 -0
  11. package/dist/generators/indices/importexport-convert-import-functions.generator.js +528 -0
  12. package/dist/generators/indices/{seed-template-decoder.generator.d.ts → importexport-exporter-class.generator.d.ts} +2 -2
  13. package/dist/generators/indices/importexport-exporter-class.generator.js +116 -0
  14. package/dist/generators/indices/importexport-import-service.generator.d.ts +9 -0
  15. package/dist/generators/indices/importexport-import-service.generator.js +563 -0
  16. package/dist/generators/indices/{seeddata-type.generator.d.ts → importexport-types.generator.d.ts} +2 -2
  17. package/dist/generators/indices/importexport-types.generator.js +234 -0
  18. package/dist/generators/indices/repositories.generator.js +7 -7
  19. package/dist/generators/indices/seed-template.generator.js +1 -1
  20. package/dist/generators/indices/testdata-service.generator.js +5 -4
  21. package/dist/generators/models/businesslogic-update.generator.js +5 -5
  22. package/dist/generators/models/businesslogic-view.generator.js +3 -3
  23. package/dist/generators/models/importexport-decoder.generator.d.ts +23 -0
  24. package/dist/generators/models/importexport-decoder.generator.js +234 -0
  25. package/dist/generators/models/repository.generator.js +50 -21
  26. package/dist/lib/imports.d.ts +1 -1
  27. package/dist/lib/meta.d.ts +468 -134
  28. package/dist/lib/meta.js +187 -80
  29. package/dist/lib/schema/schema.d.ts +54 -43
  30. package/dist/lib/schema/types.d.ts +63 -12
  31. package/dist/lib/schema/types.js +27 -7
  32. package/dist/lib/utils/string.d.ts +1 -0
  33. package/dist/lib/utils/string.js +4 -0
  34. package/dist/prisma/parse.js +4 -4
  35. package/package.json +1 -1
  36. package/dist/generators/indices/seed-service.generator.js +0 -354
  37. package/dist/generators/indices/seed-template-decoder.generator.js +0 -151
  38. package/dist/generators/indices/seeddata-type.generator.js +0 -42
@@ -14,8 +14,8 @@ const string_1 = require("../../lib/utils/string");
14
14
  function generateRepository({ model, meta }) {
15
15
  const { idField } = model;
16
16
  const schemaMeta = (0, meta_1.getSchemaMetadata)({ config: model.schemaConfig });
17
- const imports = imports_1.ImportsGenerator.from(meta.data.repoFilePath).addImports({
18
- [schemaMeta.data.repositoryTypeFilePath]: schemaMeta.data.repositoryTypeName,
17
+ const imports = imports_1.ImportsGenerator.from(meta.data.repository.filePath).addImports({
18
+ [schemaMeta.data.repository.typeFilePath]: schemaMeta.data.repository.typeName,
19
19
  [meta.types.importPath]: [
20
20
  model.typeName,
21
21
  model.brandedIdType,
@@ -24,7 +24,7 @@ function generateRepository({ model, meta }) {
24
24
  meta.types.dto.update,
25
25
  meta.types.dto.upsert,
26
26
  ],
27
- [schemaMeta.actions.importPath]: [schemaMeta.actions.actionExecutionInterface],
27
+ [schemaMeta.actions.importPath]: [schemaMeta.actions.actionExecution.interface],
28
28
  });
29
29
  // NOTE: We first generate different parts of the code responsible for a particular task
30
30
  // and then we combine them into the final code block.
@@ -37,7 +37,7 @@ function generateRepository({ model, meta }) {
37
37
  // and allow being called with an id,
38
38
  // 3.) unique string fields are ensured to be unique,
39
39
  // 4.) max length string fields are ensured to not exceed their max length,
40
- // 5.) index for fields marked with index attribute,
40
+ // 5.) index for fields marked with index or unique attribute,
41
41
  // 6.) relations are indexed by the foreign key.
42
42
  //
43
43
  // The repository is generated differently based on whether the model is stored in the database or in memory.
@@ -47,6 +47,7 @@ function generateRepository({ model, meta }) {
47
47
  const defaultValueBlocks = generateDefaultBlocks({ model, meta });
48
48
  const uniqueStringFieldsBlocks = generateUniqueFieldsBlocks({ model, meta });
49
49
  const maxLengthBlocks = generateMaxLengthBlocks({ model, meta });
50
+ const validationBlocks = generateValidationBlocks({ model, meta });
50
51
  const indexBlocks = generateIndexBlocks({ model, meta, imports });
51
52
  const relationsBlocks = generateRelationsBlocks({ model, meta, imports });
52
53
  let mainBlocks;
@@ -62,6 +63,7 @@ function generateRepository({ model, meta }) {
62
63
  idBlocks,
63
64
  indexBlocks,
64
65
  maxLengthBlocks,
66
+ validationBlocks,
65
67
  },
66
68
  });
67
69
  }
@@ -77,6 +79,7 @@ function generateRepository({ model, meta }) {
77
79
  idBlocks,
78
80
  indexBlocks,
79
81
  maxLengthBlocks,
82
+ validationBlocks,
80
83
  },
81
84
  });
82
85
  }
@@ -86,9 +89,9 @@ ${idBlocks.libraryImports}
86
89
  ${imports.generate()}
87
90
 
88
91
  @Injectable()
89
- export class ${meta.data.repositoryClassName} implements Repository<${model.typeName}, ${idField.unbrandedTypeName}> {
92
+ export class ${meta.data.repository.className} implements Repository<${model.typeName}, ${idField.unbrandedTypeName}> {
90
93
  protected data: Map<${model.brandedIdType}, ${model.typeName}> = new Map()
91
- protected logger = new Logger(${meta.data.repositoryClassName}.name)
94
+ protected logger = new Logger(${meta.data.repository.className}.name)
92
95
 
93
96
  ${relationsBlocks.mapDeclarations.join('\n')}
94
97
 
@@ -97,9 +100,9 @@ export class ${meta.data.repositoryClassName} implements Repository<${model.type
97
100
  ${idBlocks.generateNextIdFunctionName}
98
101
 
99
102
  protected uniqueIds = {
100
- ${uniqueStringFieldsBlocks.mapDeclarations.join(',\n')}
103
+ ${uniqueStringFieldsBlocks.mapDeclarations.join(',\n')}
101
104
  }
102
-
105
+
103
106
  ${indexBlocks.nestedMapDeclarations.join('\n')}
104
107
 
105
108
  ${mainBlocks.userRepositorySpecificBlocks.rootUserNameConst}
@@ -133,6 +136,8 @@ export class ${meta.data.repositoryClassName} implements Repository<${model.type
133
136
 
134
137
  ${indexBlocks.getterFunctions.join('\n')}
135
138
 
139
+ ${uniqueStringFieldsBlocks.getByFunctions.join('\n')}
140
+
136
141
  public async filter(predicate: (item: ${model.typeName}) => boolean): Promise<${model.typeName}[]> {
137
142
  return (await this.getAllAsArray()).filter(predicate)
138
143
  }
@@ -204,7 +209,7 @@ exports.generateRepository = generateRepository;
204
209
  */
205
210
  function generateMockRepository({ model: modelSource, meta: metaSource, }) {
206
211
  // We re-use the repository block, but we change the meta data to use the mock repository name and the model to be in memory only
207
- const meta = Object.assign(Object.assign({}, metaSource), { data: Object.assign(Object.assign({}, metaSource.data), { repositoryClassName: metaSource.data.mockRepositoryClassName, repoFilePath: metaSource.data.mockRepoFilePath }) });
212
+ const meta = Object.assign(Object.assign({}, metaSource), { data: Object.assign(Object.assign({}, metaSource.data), { repository: Object.assign(Object.assign({}, metaSource.data.repository), { className: metaSource.data.mockRepository.className, filePath: metaSource.data.mockRepository.filePath }) }) });
208
213
  const model = Object.assign(Object.assign({}, modelSource), { attributes: Object.assign(Object.assign({}, modelSource.attributes), { inMemoryOnly: true }) });
209
214
  return generateRepository({ model, meta });
210
215
  }
@@ -256,6 +261,8 @@ function _generateMainBuildingBlocks_InMemoryOnly({ model, meta, imports, blocks
256
261
 
257
262
  ${blocks.uniqueStringFieldsBlocks.verifyCode.join('\n')}
258
263
 
264
+ ${blocks.validationBlocks.verifyCode.join('\n')}
265
+
259
266
  return {
260
267
  ${model.idField.name},
261
268
  ${model.fields
@@ -527,6 +534,8 @@ function generateMainBuildingBlocks_InDatabase({ model, meta, imports, blocks, }
527
534
  ${blocks.maxLengthBlocks.verifyCode.join('\n')}
528
535
 
529
536
  ${blocks.uniqueStringFieldsBlocks.verifyCode.join('\n')}
537
+
538
+ ${blocks.validationBlocks.verifyCode.join('\n')}
530
539
 
531
540
  return {
532
541
  ${idField.name},
@@ -780,7 +789,7 @@ function generateUserRepositorySpecificBlocks_InDatabase({ model, meta, imports,
780
789
  initCall: `await this.initializeRootUser()`,
781
790
  rootUserInitializeBlock: `
782
791
  private async initializeRootUser(): Promise<void> {
783
- const existingRootUser = await this.get(${meta.data.repositoryClassName}.ROOT_USER_ID)
792
+ const existingRootUser = await this.get(${meta.data.repository.className}.ROOT_USER_ID)
784
793
  if (existingRootUser) {
785
794
  this._rootUser = existingRootUser
786
795
  return
@@ -788,7 +797,7 @@ function generateUserRepositorySpecificBlocks_InDatabase({ model, meta, imports,
788
797
 
789
798
  const rawUser = await this.db.user.create({
790
799
  data: {
791
- id: ${meta.data.repositoryClassName}.ROOT_USER_ID,
800
+ id: ${meta.data.repository.className}.ROOT_USER_ID,
792
801
  name: 'System',
793
802
  email: 'system@postxl.com',
794
803
  role: UserRole.Admin,
@@ -828,14 +837,14 @@ function generateUserRepositorySpecificBlocks_InMemoryOnly({ model, meta, import
828
837
  initCall: `await this.initializeRootUser()`,
829
838
  rootUserInitializeBlock: `
830
839
  private async initializeRootUser(): Promise<void> {
831
- const existingRootUser = await this.get(${meta.data.repositoryClassName}.ROOT_USER_ID)
840
+ const existingRootUser = await this.get(${meta.data.repository.className}.ROOT_USER_ID)
832
841
  if (existingRootUser) {
833
842
  this._rootUser = existingRootUser
834
843
  return
835
844
  }
836
845
 
837
846
  const rawUser = {
838
- id: ${meta.data.repositoryClassName}.ROOT_USER_ID,
847
+ id: ${meta.data.repository.className}.ROOT_USER_ID,
839
848
  name: 'System',
840
849
  email: 'system@postxl.com',
841
850
  role: UserRole.Admin,
@@ -877,42 +886,42 @@ function getRepositoryMethodsTypeSignatures({ model, meta }) {
877
886
  return {
878
887
  create: {
879
888
  jsDoc: [`Creates a new ${meta.userFriendlyName} and returns it.`],
880
- parameters: [`{item: ${meta.types.dto.create}, execution: ${schemaMeta.actions.actionExecutionInterface}}`],
889
+ parameters: [`{item: ${meta.types.dto.create}, execution: ${schemaMeta.actions.actionExecution.interface}}`],
881
890
  returnType: `Promise<${model.typeName}>`,
882
891
  },
883
892
  createMany: {
884
893
  jsDoc: [`Creates multiple new ${meta.userFriendlyNamePlural} and returns them.`],
885
- parameters: [`{items: ${meta.types.dto.create}[], execution: ${schemaMeta.actions.actionExecutionInterface}}`],
894
+ parameters: [`{items: ${meta.types.dto.create}[], execution: ${schemaMeta.actions.actionExecution.interface}}`],
886
895
  returnType: `Promise<${model.typeName}[]>`,
887
896
  },
888
897
  update: {
889
898
  jsDoc: [`Updates a ${meta.userFriendlyName} and returns it.`],
890
- parameters: [`{item: ${meta.types.dto.update}, execution: ${schemaMeta.actions.actionExecutionInterface}}`],
899
+ parameters: [`{item: ${meta.types.dto.update}, execution: ${schemaMeta.actions.actionExecution.interface}}`],
891
900
  returnType: `Promise<${model.typeName}>`,
892
901
  },
893
902
  updateMany: {
894
903
  jsDoc: [`Updates multiple ${meta.userFriendlyNamePlural} and returns them.`],
895
- parameters: [`{items: ${meta.types.dto.update}[], execution: ${schemaMeta.actions.actionExecutionInterface}}`],
904
+ parameters: [`{items: ${meta.types.dto.update}[], execution: ${schemaMeta.actions.actionExecution.interface}}`],
896
905
  returnType: `Promise<${model.typeName}[]>`,
897
906
  },
898
907
  upsert: {
899
908
  jsDoc: [`Creates or updates a ${meta.userFriendlyName} and returns it.`],
900
- parameters: [`{item: ${meta.types.dto.upsert}, execution: ${schemaMeta.actions.actionExecutionInterface}}`],
909
+ parameters: [`{item: ${meta.types.dto.upsert}, execution: ${schemaMeta.actions.actionExecution.interface}}`],
901
910
  returnType: `Promise<${model.typeName}>`,
902
911
  },
903
912
  upsertMany: {
904
913
  jsDoc: [`Creates or updates multiple ${meta.userFriendlyNamePlural} and returns them.`],
905
- parameters: [`{items: ${meta.types.dto.upsert}[], execution: ${schemaMeta.actions.actionExecutionInterface}}`],
914
+ parameters: [`{items: ${meta.types.dto.upsert}[], execution: ${schemaMeta.actions.actionExecution.interface}}`],
906
915
  returnType: `Promise<${model.typeName}[]>`,
907
916
  },
908
917
  delete: {
909
918
  jsDoc: [`Deletes a ${meta.userFriendlyName} and returns its id.`],
910
- parameters: [`{id: ${model.brandedIdType}, execution: ${schemaMeta.actions.actionExecutionInterface}}`],
919
+ parameters: [`{id: ${model.brandedIdType}, execution: ${schemaMeta.actions.actionExecution.interface}}`],
911
920
  returnType: `Promise<${model.brandedIdType}>`,
912
921
  },
913
922
  deleteMany: {
914
923
  jsDoc: [`Deletes multiple ${meta.userFriendlyNamePlural} and returns their ids.`],
915
- parameters: [`{ids: ${model.brandedIdType}[], execution: ${schemaMeta.actions.actionExecutionInterface}}`],
924
+ parameters: [`{ids: ${model.brandedIdType}[], execution: ${schemaMeta.actions.actionExecution.interface}}`],
916
925
  returnType: `Promise<${model.brandedIdType}[]>`,
917
926
  },
918
927
  };
@@ -1038,6 +1047,7 @@ function generateUniqueFieldsBlocks({ model }) {
1038
1047
  const fields = model.fields.filter(fields_1.isUniqueStringField);
1039
1048
  const result = {
1040
1049
  mapDeclarations: [],
1050
+ getByFunctions: [],
1041
1051
  clearCode: [],
1042
1052
  verifyFunctionComment: '',
1043
1053
  verifyCode: [],
@@ -1048,6 +1058,10 @@ function generateUniqueFieldsBlocks({ model }) {
1048
1058
  };
1049
1059
  for (const f of fields) {
1050
1060
  result.mapDeclarations.push(`'${f.name}': new Map<string, ${model.typeName}>()`);
1061
+ result.getByFunctions.push(`
1062
+ public async getBy${(0, string_1.toPascalCase)(f.name)}(${f.name}: string): Promise<${model.typeName} | undefined> {
1063
+ return Promise.resolve(this.uniqueIds.${f.name}.get(${(0, string_1.toCamelCase)(f.name)}))
1064
+ }`);
1051
1065
  result.clearCode.push(`this.uniqueIds.${f.name}.clear()`);
1052
1066
  result.verifyCode.push(`this.${getEnsureUniqueFnName(f)}(item)`);
1053
1067
  result.updateCode.push(`
@@ -1134,6 +1148,21 @@ function generateMaxLengthBlocks({ model }) {
1134
1148
  function getEnsureMaxLengthFnName(field) {
1135
1149
  return `ensureMaxLength${(0, string_1.toPascalCase)(field.name)}`;
1136
1150
  }
1151
+ function generateValidationBlocks({ model }) {
1152
+ const fields = model.fields.filter((f) => f.kind === 'scalar' && f.validation && f.validation.type === 'int');
1153
+ const result = {
1154
+ verifyCode: [],
1155
+ };
1156
+ for (const f of fields) {
1157
+ const itemExists = f.isRequired ? '' : `item.${f.name} !== null && `;
1158
+ result.verifyCode.push(`
1159
+ // ensure that ${f.name} is an integer
1160
+ if (${itemExists}item.${f.name} !== Math.floor(item.${f.name})) {
1161
+ throw new Error(\`Invalid value for field ${f.name}: \${item.${f.name}}. Value must be an integer.\`)
1162
+ }`);
1163
+ }
1164
+ return result;
1165
+ }
1137
1166
  function generateIndexBlocks({ model, imports, }) {
1138
1167
  const indexes = model.attributes.index ? [getIndexDefinition({ fieldNames: model.attributes.index, model })] : [];
1139
1168
  if (indexes.length > 0) {
@@ -6,7 +6,7 @@ import * as Types from './schema/types';
6
6
  * Example:
7
7
  * ```
8
8
  * {
9
- * [meta.data.importPath]: meta.data.repositoryClassName,
9
+ * [meta.data.importPath]: meta.data.repository.className,
10
10
  * [meta.types.importPath]: [model.brandedIdType, meta.types.typeName],
11
11
  * }
12
12
  * ```