@postxl/generator 0.38.2 → 0.40.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.
Files changed (56) hide show
  1. package/dist/generator.js +43 -21
  2. package/dist/generators/enums/types.generator.js +1 -1
  3. package/dist/generators/indices/businesslogic-actiontypes.generator.js +1 -1
  4. package/dist/generators/indices/businesslogic-update-module.generator.js +2 -2
  5. package/dist/generators/indices/businesslogic-update-service.generator.js +1 -1
  6. package/dist/generators/indices/businesslogic-view-module.generator.js +2 -2
  7. package/dist/generators/indices/businesslogic-view-service.generator.js +1 -1
  8. package/dist/generators/indices/{seed-service.generator.d.ts → data-types.generator.d.ts} +2 -2
  9. package/dist/generators/indices/data-types.generator.js +48 -0
  10. package/dist/generators/indices/datamock-module.generator.js +11 -11
  11. package/dist/generators/indices/datamocker.generator.js +1 -1
  12. package/dist/generators/indices/datamodule.generator.js +34 -52
  13. package/dist/generators/indices/dataservice.generator.js +202 -9
  14. package/dist/generators/indices/dispatcher-service.generator.js +20 -10
  15. package/dist/generators/indices/emptydatabasemigration.generator.d.ts +2 -0
  16. package/dist/generators/indices/emptydatabasemigration.generator.js +14 -7
  17. package/dist/generators/indices/importexport-convert-import-functions.generator.d.ts +9 -0
  18. package/dist/generators/indices/importexport-convert-import-functions.generator.js +528 -0
  19. package/dist/generators/indices/importexport-exporter-class.generator.d.ts +9 -0
  20. package/dist/generators/indices/importexport-exporter-class.generator.js +116 -0
  21. package/dist/generators/indices/importexport-import-service.generator.d.ts +9 -0
  22. package/dist/generators/indices/importexport-import-service.generator.js +563 -0
  23. package/dist/generators/indices/{seeddata-type.generator.d.ts → importexport-types.generator.d.ts} +2 -2
  24. package/dist/generators/indices/importexport-types.generator.js +234 -0
  25. package/dist/generators/indices/repositories.generator.js +8 -8
  26. package/dist/generators/indices/seed-migration.generator.js +1 -1
  27. package/dist/generators/indices/seed-template.generator.js +1 -1
  28. package/dist/generators/indices/selectors.generator.d.ts +7 -0
  29. package/dist/generators/indices/selectors.generator.js +82 -0
  30. package/dist/generators/indices/{seed-template-decoder.generator.d.ts → testdata-service.generator.d.ts} +2 -2
  31. package/dist/generators/indices/testdata-service.generator.js +71 -0
  32. package/dist/generators/models/businesslogic-update.generator.js +6 -6
  33. package/dist/generators/models/businesslogic-view.generator.js +4 -4
  34. package/dist/generators/models/importexport-decoder.generator.d.ts +23 -0
  35. package/dist/generators/models/importexport-decoder.generator.js +234 -0
  36. package/dist/generators/models/react.generator/library.generator.js +4 -0
  37. package/dist/generators/models/react.generator/modals.generator.js +35 -8
  38. package/dist/generators/models/repository.generator.js +156 -18
  39. package/dist/generators/models/route.generator.js +2 -2
  40. package/dist/generators/models/stub.generator.js +1 -1
  41. package/dist/generators/models/types.generator.js +1 -1
  42. package/dist/lib/id-collector.d.ts +43 -0
  43. package/dist/lib/id-collector.js +53 -0
  44. package/dist/lib/imports.d.ts +1 -1
  45. package/dist/lib/meta.d.ts +480 -122
  46. package/dist/lib/meta.js +187 -74
  47. package/dist/lib/schema/schema.d.ts +58 -43
  48. package/dist/lib/schema/types.d.ts +63 -12
  49. package/dist/lib/schema/types.js +27 -7
  50. package/dist/lib/utils/string.d.ts +1 -0
  51. package/dist/lib/utils/string.js +1 -0
  52. package/dist/prisma/parse.js +4 -4
  53. package/package.json +2 -2
  54. package/dist/generators/indices/seed-service.generator.js +0 -356
  55. package/dist/generators/indices/seed-template-decoder.generator.js +0 -151
  56. 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;
@@ -55,12 +56,14 @@ function generateRepository({ model, meta }) {
55
56
  model,
56
57
  meta,
57
58
  schemaMeta,
59
+ imports,
58
60
  blocks: {
59
61
  uniqueStringFieldsBlocks,
60
62
  defaultValueBlocks,
61
63
  idBlocks,
62
64
  indexBlocks,
63
65
  maxLengthBlocks,
66
+ validationBlocks,
64
67
  },
65
68
  });
66
69
  }
@@ -76,6 +79,7 @@ function generateRepository({ model, meta }) {
76
79
  idBlocks,
77
80
  indexBlocks,
78
81
  maxLengthBlocks,
82
+ validationBlocks,
79
83
  },
80
84
  });
81
85
  }
@@ -85,9 +89,9 @@ ${idBlocks.libraryImports}
85
89
  ${imports.generate()}
86
90
 
87
91
  @Injectable()
88
- export class ${meta.data.repositoryClassName} implements Repository<${model.typeName}, ${idField.unbrandedTypeName}> {
92
+ export class ${meta.data.repository.className} implements Repository<${model.typeName}, ${idField.unbrandedTypeName}> {
89
93
  protected data: Map<${model.brandedIdType}, ${model.typeName}> = new Map()
90
- protected logger = new Logger(${meta.data.repositoryClassName}.name)
94
+ protected logger = new Logger(${meta.data.repository.className}.name)
91
95
 
92
96
  ${relationsBlocks.mapDeclarations.join('\n')}
93
97
 
@@ -96,11 +100,15 @@ export class ${meta.data.repositoryClassName} implements Repository<${model.type
96
100
  ${idBlocks.generateNextIdFunctionName}
97
101
 
98
102
  protected uniqueIds = {
99
- ${uniqueStringFieldsBlocks.mapDeclarations.join(',\n')}
103
+ ${uniqueStringFieldsBlocks.mapDeclarations.join(',\n')}
100
104
  }
101
-
105
+
102
106
  ${indexBlocks.nestedMapDeclarations.join('\n')}
103
107
 
108
+ ${mainBlocks.userRepositorySpecificBlocks.rootUserNameConst}
109
+
110
+ ${mainBlocks.userRepositorySpecificBlocks.getterBlock}
111
+
104
112
  ${mainBlocks.constructorCode}
105
113
 
106
114
  ${mainBlocks.initCode}
@@ -109,6 +117,8 @@ export class ${meta.data.repositoryClassName} implements Repository<${model.type
109
117
 
110
118
  ${mainBlocks.deleteAllCode}
111
119
 
120
+ ${mainBlocks.userRepositorySpecificBlocks.rootUserInitializeBlock}
121
+
112
122
  public async get(id: ${model.brandedIdType} | null): Promise<${model.typeName} | null> {
113
123
  if (id === null) {
114
124
  return Promise.resolve(null)
@@ -126,6 +136,8 @@ export class ${meta.data.repositoryClassName} implements Repository<${model.type
126
136
 
127
137
  ${indexBlocks.getterFunctions.join('\n')}
128
138
 
139
+ ${uniqueStringFieldsBlocks.getByFunctions.join('\n')}
140
+
129
141
  public async filter(predicate: (item: ${model.typeName}) => boolean): Promise<${model.typeName}[]> {
130
142
  return (await this.getAllAsArray()).filter(predicate)
131
143
  }
@@ -197,7 +209,7 @@ exports.generateRepository = generateRepository;
197
209
  */
198
210
  function generateMockRepository({ model: modelSource, meta: metaSource, }) {
199
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
200
- 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 }) }) });
201
213
  const model = Object.assign(Object.assign({}, modelSource), { attributes: Object.assign(Object.assign({}, modelSource.attributes), { inMemoryOnly: true }) });
202
214
  return generateRepository({ model, meta });
203
215
  }
@@ -205,10 +217,12 @@ exports.generateMockRepository = generateMockRepository;
205
217
  /**
206
218
  * Generates the main building blocks of the repository for in-memory model.
207
219
  */
208
- function _generateMainBuildingBlocks_InMemoryOnly({ model, meta, blocks, }) {
220
+ function _generateMainBuildingBlocks_InMemoryOnly({ model, meta, imports, blocks, }) {
209
221
  const methodTypeSignatures = getRepositoryMethodsTypeSignatures({ model, meta });
222
+ const userRepositorySpecificBlocks = generateUserRepositorySpecificBlocks_InMemoryOnly({ model, meta, imports });
210
223
  return {
211
224
  constructorCode: '',
225
+ userRepositorySpecificBlocks,
212
226
  initCode: `
213
227
  public async init() {
214
228
  this.data.clear()
@@ -218,6 +232,8 @@ function _generateMainBuildingBlocks_InMemoryOnly({ model, meta, blocks, }) {
218
232
 
219
233
  ${blocks.indexBlocks.initCode.join('\n')}
220
234
 
235
+ ${userRepositorySpecificBlocks.initCall}
236
+
221
237
  return Promise.resolve()
222
238
  }`,
223
239
  reInitCode: `
@@ -245,6 +261,8 @@ function _generateMainBuildingBlocks_InMemoryOnly({ model, meta, blocks, }) {
245
261
 
246
262
  ${blocks.uniqueStringFieldsBlocks.verifyCode.join('\n')}
247
263
 
264
+ ${blocks.validationBlocks.verifyCode.join('\n')}
265
+
248
266
  return {
249
267
  ${model.idField.name},
250
268
  ${model.fields
@@ -446,8 +464,10 @@ function generateMainBuildingBlocks_InDatabase({ model, meta, imports, blocks, }
446
464
  .map((part) => `"${part}"`)
447
465
  .join('.');
448
466
  const methodTypeSignatures = getRepositoryMethodsTypeSignatures({ model, meta });
467
+ const userRepositorySpecificBlocks = generateUserRepositorySpecificBlocks_InDatabase({ model, meta, imports });
449
468
  return {
450
469
  constructorCode: `constructor(protected db: DbService) {}`,
470
+ userRepositorySpecificBlocks,
451
471
  initCode: `
452
472
  public async init() {
453
473
  this.data.clear()
@@ -471,6 +491,8 @@ function generateMainBuildingBlocks_InDatabase({ model, meta, imports, blocks, }
471
491
 
472
492
  ${blocks.defaultValueBlocks.init.checkCode}
473
493
 
494
+ ${userRepositorySpecificBlocks.initCall}
495
+
474
496
  this.logger.log(\`\${format(this.data.size)} \${pluralize('${model.typeName}', this.data.size)} loaded\`)
475
497
  ${blocks.indexBlocks.initLogCode.join('\n')}
476
498
  }`,
@@ -512,6 +534,8 @@ function generateMainBuildingBlocks_InDatabase({ model, meta, imports, blocks, }
512
534
  ${blocks.maxLengthBlocks.verifyCode.join('\n')}
513
535
 
514
536
  ${blocks.uniqueStringFieldsBlocks.verifyCode.join('\n')}
537
+
538
+ ${blocks.validationBlocks.verifyCode.join('\n')}
515
539
 
516
540
  return {
517
541
  ${idField.name},
@@ -741,6 +765,100 @@ function generateMainBuildingBlocks_InDatabase({ model, meta, imports, blocks, }
741
765
  }`,
742
766
  };
743
767
  }
768
+ function generateUserRepositorySpecificBlocks_InDatabase({ model, meta, imports, }) {
769
+ if (model.name !== 'User') {
770
+ return {
771
+ rootUserNameConst: '',
772
+ getterBlock: '',
773
+ initCall: '',
774
+ rootUserInitializeBlock: '',
775
+ };
776
+ }
777
+ imports.addImport({
778
+ from: meta.types.importPath,
779
+ items: [(0, types_1.toTypeName)('UserRole')],
780
+ });
781
+ return {
782
+ rootUserNameConst: `public static ROOT_USER_ID = ${meta.types.toBrandedIdTypeFnName}('root')`,
783
+ getterBlock: `
784
+ // We initialize the root user in the init() function
785
+ private _rootUser!: ${meta.types.typeName}
786
+ public get rootUser(): ${meta.types.typeName} {
787
+ return this._rootUser
788
+ }`,
789
+ initCall: `await this.initializeRootUser()`,
790
+ rootUserInitializeBlock: `
791
+ private async initializeRootUser(): Promise<void> {
792
+ const existingRootUser = await this.get(${meta.data.repository.className}.ROOT_USER_ID)
793
+ if (existingRootUser) {
794
+ this._rootUser = existingRootUser
795
+ return
796
+ }
797
+
798
+ const rawUser = await this.db.user.create({
799
+ data: {
800
+ id: ${meta.data.repository.className}.ROOT_USER_ID,
801
+ name: 'System',
802
+ email: 'system@postxl.com',
803
+ role: UserRole.Admin,
804
+ login: 'not-set',
805
+ familyName: 'System user',
806
+ age: 0,
807
+ countryId: null,
808
+ },
809
+ })
810
+ const newRootUser = this.toUser(rawUser)
811
+ this.set(newRootUser)
812
+ this._rootUser = newRootUser
813
+ }`,
814
+ };
815
+ }
816
+ function generateUserRepositorySpecificBlocks_InMemoryOnly({ model, meta, imports, }) {
817
+ if (model.name !== 'User') {
818
+ return {
819
+ rootUserNameConst: '',
820
+ getterBlock: '',
821
+ initCall: '',
822
+ rootUserInitializeBlock: '',
823
+ };
824
+ }
825
+ imports.addImport({
826
+ from: meta.types.importPath,
827
+ items: [(0, types_1.toTypeName)('UserRole')],
828
+ });
829
+ return {
830
+ rootUserNameConst: `public static ROOT_USER_ID = ${meta.types.toBrandedIdTypeFnName}('root')`,
831
+ getterBlock: `
832
+ // We initialize the root user in the init() function
833
+ private _rootUser!: ${meta.types.typeName}
834
+ public get rootUser(): ${meta.types.typeName} {
835
+ return this._rootUser
836
+ }`,
837
+ initCall: `await this.initializeRootUser()`,
838
+ rootUserInitializeBlock: `
839
+ private async initializeRootUser(): Promise<void> {
840
+ const existingRootUser = await this.get(${meta.data.repository.className}.ROOT_USER_ID)
841
+ if (existingRootUser) {
842
+ this._rootUser = existingRootUser
843
+ return
844
+ }
845
+
846
+ const rawUser = {
847
+ id: ${meta.data.repository.className}.ROOT_USER_ID,
848
+ name: 'System',
849
+ email: 'system@postxl.com',
850
+ role: UserRole.Admin,
851
+ login: 'not-set',
852
+ familyName: 'System user',
853
+ age: 0,
854
+ countryId: null,
855
+ }
856
+ const newRootUser = this.verifyItem (rawUser)
857
+ this.set(newRootUser)
858
+ this._rootUser = newRootUser
859
+ }`,
860
+ };
861
+ }
744
862
  /**
745
863
  * Generates code chunks responsible for verifying the ID validity of a model instance and generating the id
746
864
  * value of a model with auto-generated id.
@@ -768,42 +886,42 @@ function getRepositoryMethodsTypeSignatures({ model, meta }) {
768
886
  return {
769
887
  create: {
770
888
  jsDoc: [`Creates a new ${meta.userFriendlyName} and returns it.`],
771
- parameters: [`{item: ${meta.types.dto.create}, execution: ${schemaMeta.actions.actionExecutionInterface}}`],
889
+ parameters: [`{item: ${meta.types.dto.create}, execution: ${schemaMeta.actions.actionExecution.interface}}`],
772
890
  returnType: `Promise<${model.typeName}>`,
773
891
  },
774
892
  createMany: {
775
893
  jsDoc: [`Creates multiple new ${meta.userFriendlyNamePlural} and returns them.`],
776
- parameters: [`{items: ${meta.types.dto.create}[], execution: ${schemaMeta.actions.actionExecutionInterface}}`],
894
+ parameters: [`{items: ${meta.types.dto.create}[], execution: ${schemaMeta.actions.actionExecution.interface}}`],
777
895
  returnType: `Promise<${model.typeName}[]>`,
778
896
  },
779
897
  update: {
780
898
  jsDoc: [`Updates a ${meta.userFriendlyName} and returns it.`],
781
- parameters: [`{item: ${meta.types.dto.update}, execution: ${schemaMeta.actions.actionExecutionInterface}}`],
899
+ parameters: [`{item: ${meta.types.dto.update}, execution: ${schemaMeta.actions.actionExecution.interface}}`],
782
900
  returnType: `Promise<${model.typeName}>`,
783
901
  },
784
902
  updateMany: {
785
903
  jsDoc: [`Updates multiple ${meta.userFriendlyNamePlural} and returns them.`],
786
- parameters: [`{items: ${meta.types.dto.update}[], execution: ${schemaMeta.actions.actionExecutionInterface}}`],
904
+ parameters: [`{items: ${meta.types.dto.update}[], execution: ${schemaMeta.actions.actionExecution.interface}}`],
787
905
  returnType: `Promise<${model.typeName}[]>`,
788
906
  },
789
907
  upsert: {
790
908
  jsDoc: [`Creates or updates a ${meta.userFriendlyName} and returns it.`],
791
- parameters: [`{item: ${meta.types.dto.upsert}, execution: ${schemaMeta.actions.actionExecutionInterface}}`],
909
+ parameters: [`{item: ${meta.types.dto.upsert}, execution: ${schemaMeta.actions.actionExecution.interface}}`],
792
910
  returnType: `Promise<${model.typeName}>`,
793
911
  },
794
912
  upsertMany: {
795
913
  jsDoc: [`Creates or updates multiple ${meta.userFriendlyNamePlural} and returns them.`],
796
- parameters: [`{items: ${meta.types.dto.upsert}[], execution: ${schemaMeta.actions.actionExecutionInterface}}`],
914
+ parameters: [`{items: ${meta.types.dto.upsert}[], execution: ${schemaMeta.actions.actionExecution.interface}}`],
797
915
  returnType: `Promise<${model.typeName}[]>`,
798
916
  },
799
917
  delete: {
800
918
  jsDoc: [`Deletes a ${meta.userFriendlyName} and returns its id.`],
801
- parameters: [`{id: ${model.brandedIdType}, execution: ${schemaMeta.actions.actionExecutionInterface}}`],
919
+ parameters: [`{id: ${model.brandedIdType}, execution: ${schemaMeta.actions.actionExecution.interface}}`],
802
920
  returnType: `Promise<${model.brandedIdType}>`,
803
921
  },
804
922
  deleteMany: {
805
923
  jsDoc: [`Deletes multiple ${meta.userFriendlyNamePlural} and returns their ids.`],
806
- parameters: [`{ids: ${model.brandedIdType}[], execution: ${schemaMeta.actions.actionExecutionInterface}}`],
924
+ parameters: [`{ids: ${model.brandedIdType}[], execution: ${schemaMeta.actions.actionExecution.interface}}`],
807
925
  returnType: `Promise<${model.brandedIdType}[]>`,
808
926
  },
809
927
  };
@@ -929,6 +1047,7 @@ function generateUniqueFieldsBlocks({ model }) {
929
1047
  const fields = model.fields.filter(fields_1.isUniqueStringField);
930
1048
  const result = {
931
1049
  mapDeclarations: [],
1050
+ getByFunctions: [],
932
1051
  clearCode: [],
933
1052
  verifyFunctionComment: '',
934
1053
  verifyCode: [],
@@ -939,6 +1058,10 @@ function generateUniqueFieldsBlocks({ model }) {
939
1058
  };
940
1059
  for (const f of fields) {
941
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
+ }`);
942
1065
  result.clearCode.push(`this.uniqueIds.${f.name}.clear()`);
943
1066
  result.verifyCode.push(`this.${getEnsureUniqueFnName(f)}(item)`);
944
1067
  result.updateCode.push(`
@@ -1025,6 +1148,21 @@ function generateMaxLengthBlocks({ model }) {
1025
1148
  function getEnsureMaxLengthFnName(field) {
1026
1149
  return `ensureMaxLength${(0, string_1.toPascalCase)(field.name)}`;
1027
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
+ }
1028
1166
  function generateIndexBlocks({ model, imports, }) {
1029
1167
  const indexes = model.attributes.index ? [getIndexDefinition({ fieldNames: model.attributes.index, model })] : [];
1030
1168
  if (indexes.length > 0) {
@@ -31,7 +31,7 @@ function generateRoute({ model, meta }) {
31
31
  meta.businessLogic.update.createActionFunctionNameDeleteMany,
32
32
  ],
33
33
  });
34
- return `
34
+ return /* ts */ `
35
35
  import { z } from 'zod'
36
36
  import { procedure, router } from '../trpc'
37
37
 
@@ -107,7 +107,7 @@ function generateRoutesIndex({ models, meta }) {
107
107
  for (const { meta } of mm) {
108
108
  imports.addImport({ items: [meta.trpc.routerName], from: meta.trpc.routerFilePath });
109
109
  }
110
- return `
110
+ return /* ts */ `
111
111
  ${imports.generate()}
112
112
 
113
113
  /**
@@ -20,7 +20,7 @@ function generateStub({ model, meta }) {
20
20
  modelName: model.name,
21
21
  imports,
22
22
  });
23
- return `
23
+ return /* ts */ `
24
24
  ${imports.generate()}
25
25
 
26
26
  /**
@@ -40,7 +40,7 @@ function generateModelTypes({ model, meta }) {
40
40
  from: schemaMeta.types.dto.path,
41
41
  });
42
42
  const decoderNames = meta.types.zodDecoderFnNames;
43
- return `
43
+ return /* ts */ `
44
44
  import { z } from 'zod'
45
45
 
46
46
  ${imports.generate()}
@@ -0,0 +1,43 @@
1
+ type ElementId = string & {
2
+ __brand: 'ElementId';
3
+ };
4
+ /**
5
+ * The SelectorCollector is used to generate and track HTML element IDs.
6
+ * The idea is that it is instantiated once and then used to generate IDs throughout the generators.
7
+ * After the files are generated, all generated IDs can be serialized to a file.
8
+ *
9
+ * An ID can for instance be something like `post-create-name, `${model.name}-${componentType}-${fieldName}`.
10
+ *
11
+ * Each code generator can instantiate an SelectorCollector - the constructor will require the current model & component type.
12
+ * All generated Ids will be stored in a global static Set so we can serialize them later.
13
+ */
14
+ export declare class SelectorCollector {
15
+ private _prefix;
16
+ /**
17
+ * We store all generated IDs in a global static Set so we can serialize them later.
18
+ */
19
+ private static _ids;
20
+ constructor(_prefix: string);
21
+ /**
22
+ * Creates a new instance of the SelectorCollector.
23
+ */
24
+ static from(prefix: string): SelectorCollector;
25
+ /**
26
+ * Generates a new ID for an element and stores it in the collector
27
+ */
28
+ idFor(
29
+ /**
30
+ * The name of the element, e.g. `age`, `submit`.
31
+ */
32
+ elementName: string, options?: {
33
+ /**
34
+ * Optional prefix for the type of the element, e.g. `field` or `button`.
35
+ */
36
+ typePrefix?: string;
37
+ }): string;
38
+ /**
39
+ * Returns all generated IDs and resets the stored IDs.
40
+ */
41
+ static flush(): ElementId[];
42
+ }
43
+ export {};
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SelectorCollector = void 0;
4
+ /**
5
+ * The SelectorCollector is used to generate and track HTML element IDs.
6
+ * The idea is that it is instantiated once and then used to generate IDs throughout the generators.
7
+ * After the files are generated, all generated IDs can be serialized to a file.
8
+ *
9
+ * An ID can for instance be something like `post-create-name, `${model.name}-${componentType}-${fieldName}`.
10
+ *
11
+ * Each code generator can instantiate an SelectorCollector - the constructor will require the current model & component type.
12
+ * All generated Ids will be stored in a global static Set so we can serialize them later.
13
+ */
14
+ class SelectorCollector {
15
+ constructor(_prefix) {
16
+ this._prefix = _prefix;
17
+ }
18
+ /**
19
+ * Creates a new instance of the SelectorCollector.
20
+ */
21
+ static from(prefix) {
22
+ return new SelectorCollector(prefix);
23
+ }
24
+ /**
25
+ * Generates a new ID for an element and stores it in the collector
26
+ */
27
+ idFor(
28
+ /**
29
+ * The name of the element, e.g. `age`, `submit`.
30
+ */
31
+ elementName, options) {
32
+ const { typePrefix } = options !== null && options !== void 0 ? options : {};
33
+ const id = [this._prefix, typePrefix, elementName].filter((x) => x !== undefined && x !== '').join('-');
34
+ if (SelectorCollector._ids.has(id)) {
35
+ throw new Error(`ID ${id} already exists.`);
36
+ }
37
+ SelectorCollector._ids.add(id);
38
+ return id;
39
+ }
40
+ /**
41
+ * Returns all generated IDs and resets the stored IDs.
42
+ */
43
+ static flush() {
44
+ const result = [...SelectorCollector._ids.values()];
45
+ SelectorCollector._ids.clear();
46
+ return result;
47
+ }
48
+ }
49
+ exports.SelectorCollector = SelectorCollector;
50
+ /**
51
+ * We store all generated IDs in a global static Set so we can serialize them later.
52
+ */
53
+ SelectorCollector._ids = new Set();
@@ -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
  * ```