@postxl/generator 0.74.2 → 1.0.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 (189) hide show
  1. package/LICENSE +50 -0
  2. package/README.md +79 -1
  3. package/dist/generator-manager.class.d.ts +59 -0
  4. package/dist/generator-manager.class.js +221 -0
  5. package/dist/generator.class.d.ts +90 -0
  6. package/dist/generator.class.js +32 -0
  7. package/dist/generator.context.d.ts +174 -0
  8. package/dist/generator.context.js +125 -0
  9. package/dist/helpers/branded.types.d.ts +149 -0
  10. package/dist/helpers/branded.types.js +111 -0
  11. package/dist/helpers/config-builder.class.d.ts +27 -0
  12. package/dist/helpers/config-builder.class.js +54 -0
  13. package/dist/helpers/import-generator.class.d.ts +70 -0
  14. package/dist/helpers/import-generator.class.js +166 -0
  15. package/dist/helpers/importable.types.d.ts +52 -0
  16. package/dist/helpers/importable.types.js +15 -0
  17. package/dist/helpers/index-generator.class.d.ts +10 -0
  18. package/dist/helpers/index-generator.class.js +46 -0
  19. package/dist/helpers/index.d.ts +8 -0
  20. package/dist/helpers/index.js +24 -0
  21. package/dist/helpers/package-json.generator.d.ts +56 -0
  22. package/dist/helpers/package-json.generator.js +36 -0
  23. package/dist/helpers/tsconfig.generator.d.ts +1 -0
  24. package/dist/helpers/tsconfig.generator.js +14 -0
  25. package/dist/helpers/verify-context.d.ts +4 -0
  26. package/dist/helpers/verify-context.js +23 -0
  27. package/dist/index.d.ts +5 -0
  28. package/dist/index.js +21 -0
  29. package/dist/utils/checksum.d.ts +10 -0
  30. package/dist/utils/checksum.js +132 -0
  31. package/dist/utils/fs-utils.d.ts +34 -0
  32. package/dist/utils/fs-utils.js +126 -0
  33. package/dist/utils/index.d.ts +10 -0
  34. package/dist/utils/index.js +26 -0
  35. package/dist/utils/jsdoc.d.ts +12 -0
  36. package/dist/utils/jsdoc.js +37 -0
  37. package/dist/utils/lint.d.ts +46 -0
  38. package/dist/utils/lint.js +154 -0
  39. package/dist/utils/lockfile.d.ts +7 -0
  40. package/dist/utils/lockfile.js +80 -0
  41. package/dist/utils/logger.class.d.ts +25 -0
  42. package/dist/utils/logger.class.js +55 -0
  43. package/dist/utils/merge-conflict.d.ts +55 -0
  44. package/dist/utils/merge-conflict.js +264 -0
  45. package/dist/utils/path.d.ts +52 -0
  46. package/dist/utils/path.js +183 -0
  47. package/dist/utils/prettier-config.d.ts +2 -0
  48. package/dist/utils/prettier-config.js +13 -0
  49. package/dist/utils/prettier.d.ts +5 -0
  50. package/dist/utils/prettier.js +67 -0
  51. package/dist/utils/prettier.skiptest.d.ts +1 -0
  52. package/dist/utils/prettier.skiptest.js +22 -0
  53. package/dist/utils/promise.d.ts +2 -0
  54. package/dist/utils/promise.js +10 -0
  55. package/dist/utils/string-functions.d.ts +9 -0
  56. package/dist/utils/string-functions.js +23 -0
  57. package/dist/utils/sync-log-result.d.ts +9 -0
  58. package/dist/utils/sync-log-result.js +90 -0
  59. package/dist/utils/sync.d.ts +143 -0
  60. package/dist/utils/sync.js +325 -0
  61. package/dist/utils/template.d.ts +66 -0
  62. package/dist/utils/template.js +159 -0
  63. package/dist/utils/vfs.class.d.ts +115 -0
  64. package/dist/utils/vfs.class.js +239 -0
  65. package/dist/utils/zip.d.ts +13 -0
  66. package/dist/utils/zip.js +40 -0
  67. package/package.json +57 -34
  68. package/dist/generator.d.ts +0 -13
  69. package/dist/generator.js +0 -455
  70. package/dist/generators/enums/react.generator.d.ts +0 -10
  71. package/dist/generators/enums/react.generator.js +0 -110
  72. package/dist/generators/enums/types.generator.d.ts +0 -10
  73. package/dist/generators/enums/types.generator.js +0 -39
  74. package/dist/generators/indices/data/module.generator.d.ts +0 -9
  75. package/dist/generators/indices/data/module.generator.js +0 -60
  76. package/dist/generators/indices/data/service.generator.d.ts +0 -9
  77. package/dist/generators/indices/data/service.generator.js +0 -249
  78. package/dist/generators/indices/data/types.generator.d.ts +0 -9
  79. package/dist/generators/indices/data/types.generator.js +0 -49
  80. package/dist/generators/indices/dispatcher-service.generator.d.ts +0 -9
  81. package/dist/generators/indices/dispatcher-service.generator.js +0 -107
  82. package/dist/generators/indices/export/class.generator.d.ts +0 -9
  83. package/dist/generators/indices/export/class.generator.js +0 -140
  84. package/dist/generators/indices/export/encoder.generator.d.ts +0 -9
  85. package/dist/generators/indices/export/encoder.generator.js +0 -50
  86. package/dist/generators/indices/import/convert-functions.generator.d.ts +0 -9
  87. package/dist/generators/indices/import/convert-functions.generator.js +0 -509
  88. package/dist/generators/indices/import/decoder.generator.d.ts +0 -9
  89. package/dist/generators/indices/import/decoder.generator.js +0 -40
  90. package/dist/generators/indices/import/service.generator.d.ts +0 -9
  91. package/dist/generators/indices/import/service.generator.js +0 -573
  92. package/dist/generators/indices/import/types.generator.d.ts +0 -9
  93. package/dist/generators/indices/import/types.generator.js +0 -242
  94. package/dist/generators/indices/repositories.generator.d.ts +0 -9
  95. package/dist/generators/indices/repositories.generator.js +0 -25
  96. package/dist/generators/indices/routes.generator.d.ts +0 -9
  97. package/dist/generators/indices/routes.generator.js +0 -29
  98. package/dist/generators/indices/seed-migration.generator.d.ts +0 -9
  99. package/dist/generators/indices/seed-migration.generator.js +0 -36
  100. package/dist/generators/indices/seed-template.generator.d.ts +0 -9
  101. package/dist/generators/indices/seed-template.generator.js +0 -80
  102. package/dist/generators/indices/testids.generator.d.ts +0 -7
  103. package/dist/generators/indices/testids.generator.js +0 -71
  104. package/dist/generators/indices/types.generator.d.ts +0 -10
  105. package/dist/generators/indices/types.generator.js +0 -35
  106. package/dist/generators/indices/update/actiontypes.generator.d.ts +0 -9
  107. package/dist/generators/indices/update/actiontypes.generator.js +0 -49
  108. package/dist/generators/indices/update/module.generator.d.ts +0 -9
  109. package/dist/generators/indices/update/module.generator.js +0 -41
  110. package/dist/generators/indices/update/service.generator.d.ts +0 -9
  111. package/dist/generators/indices/update/service.generator.js +0 -34
  112. package/dist/generators/indices/view/module.generator.d.ts +0 -9
  113. package/dist/generators/indices/view/module.generator.js +0 -39
  114. package/dist/generators/indices/view/service.generator.d.ts +0 -9
  115. package/dist/generators/indices/view/service.generator.js +0 -34
  116. package/dist/generators/models/admin.page.generator.d.ts +0 -7
  117. package/dist/generators/models/admin.page.generator.js +0 -74
  118. package/dist/generators/models/export/encoder.generator.d.ts +0 -9
  119. package/dist/generators/models/export/encoder.generator.js +0 -51
  120. package/dist/generators/models/import/decoder.generator.d.ts +0 -9
  121. package/dist/generators/models/import/decoder.generator.js +0 -148
  122. package/dist/generators/models/react/context.generator.d.ts +0 -9
  123. package/dist/generators/models/react/context.generator.js +0 -71
  124. package/dist/generators/models/react/index.d.ts +0 -10
  125. package/dist/generators/models/react/index.js +0 -31
  126. package/dist/generators/models/react/library.generator.d.ts +0 -10
  127. package/dist/generators/models/react/library.generator.js +0 -94
  128. package/dist/generators/models/react/lookup.generator.d.ts +0 -9
  129. package/dist/generators/models/react/lookup.generator.js +0 -175
  130. package/dist/generators/models/react/modals.generator.d.ts +0 -23
  131. package/dist/generators/models/react/modals.generator.js +0 -710
  132. package/dist/generators/models/repository.generator.d.ts +0 -9
  133. package/dist/generators/models/repository.generator.js +0 -955
  134. package/dist/generators/models/route.generator.d.ts +0 -9
  135. package/dist/generators/models/route.generator.js +0 -92
  136. package/dist/generators/models/seed.generator.d.ts +0 -21
  137. package/dist/generators/models/seed.generator.js +0 -285
  138. package/dist/generators/models/stub.generator.d.ts +0 -9
  139. package/dist/generators/models/stub.generator.js +0 -92
  140. package/dist/generators/models/types.generator.d.ts +0 -9
  141. package/dist/generators/models/types.generator.js +0 -125
  142. package/dist/generators/models/update/service.generator.d.ts +0 -10
  143. package/dist/generators/models/update/service.generator.js +0 -302
  144. package/dist/generators/models/view/service.generator.d.ts +0 -10
  145. package/dist/generators/models/view/service.generator.js +0 -239
  146. package/dist/lib/attributes.d.ts +0 -114
  147. package/dist/lib/attributes.js +0 -2
  148. package/dist/lib/exports.d.ts +0 -45
  149. package/dist/lib/exports.js +0 -90
  150. package/dist/lib/imports.d.ts +0 -65
  151. package/dist/lib/imports.js +0 -114
  152. package/dist/lib/meta.d.ts +0 -1191
  153. package/dist/lib/meta.js +0 -434
  154. package/dist/lib/schema/fields.d.ts +0 -46
  155. package/dist/lib/schema/fields.js +0 -62
  156. package/dist/lib/schema/schema.d.ts +0 -466
  157. package/dist/lib/schema/schema.js +0 -18
  158. package/dist/lib/schema/types.d.ts +0 -201
  159. package/dist/lib/schema/types.js +0 -112
  160. package/dist/lib/serializer.d.ts +0 -15
  161. package/dist/lib/serializer.js +0 -24
  162. package/dist/lib/test-id-collector.d.ts +0 -42
  163. package/dist/lib/test-id-collector.js +0 -53
  164. package/dist/lib/types.d.ts +0 -7
  165. package/dist/lib/types.js +0 -13
  166. package/dist/lib/typescript.d.ts +0 -5
  167. package/dist/lib/typescript.js +0 -22
  168. package/dist/lib/utils/ast.d.ts +0 -29
  169. package/dist/lib/utils/ast.js +0 -23
  170. package/dist/lib/utils/error.d.ts +0 -17
  171. package/dist/lib/utils/error.js +0 -52
  172. package/dist/lib/utils/file.d.ts +0 -10
  173. package/dist/lib/utils/file.js +0 -56
  174. package/dist/lib/utils/jsdoc.d.ts +0 -9
  175. package/dist/lib/utils/jsdoc.js +0 -37
  176. package/dist/lib/utils/logger.d.ts +0 -17
  177. package/dist/lib/utils/logger.js +0 -12
  178. package/dist/lib/utils/string.d.ts +0 -40
  179. package/dist/lib/utils/string.js +0 -187
  180. package/dist/lib/utils/types.d.ts +0 -12
  181. package/dist/lib/utils/types.js +0 -2
  182. package/dist/lib/zod.d.ts +0 -8
  183. package/dist/lib/zod.js +0 -60
  184. package/dist/prisma/attributes.d.ts +0 -21
  185. package/dist/prisma/attributes.js +0 -175
  186. package/dist/prisma/client-path.d.ts +0 -7
  187. package/dist/prisma/client-path.js +0 -29
  188. package/dist/prisma/parse.d.ts +0 -12
  189. package/dist/prisma/parse.js +0 -452
@@ -1,50 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.generateExportEncoder = void 0;
4
- const imports_1 = require("../../../lib/imports");
5
- const meta_1 = require("../../../lib/meta");
6
- const types_1 = require("../../../lib/schema/types");
7
- /**
8
- * Generates the data encoder, aggregating all the models.
9
- */
10
- function generateExportEncoder({ models, meta }) {
11
- const schemaMeta = (0, meta_1.getSchemaMetadata)({ config: meta.config });
12
- const { encodedExcelDataTypeName, fullEncoderFunctionName } = meta.export.encoder;
13
- const imports = imports_1.ImportsGenerator.from(meta.export.encoder.location.path);
14
- const { decodedPXLModelDataTypeName } = schemaMeta.import.decoder;
15
- imports.addImports({
16
- [schemaMeta.import.decoder.location.import]: [decodedPXLModelDataTypeName],
17
- });
18
- const modelTypes = [];
19
- const exportFields = [];
20
- for (const model of models) {
21
- const modelMeta = (0, meta_1.getModelMetadata)({ model });
22
- imports.addImport({
23
- from: modelMeta.export.encoder.location.path,
24
- items: [
25
- modelMeta.export.encoder.arrayEncoderFunctionName,
26
- (0, types_1.toAnnotatedTypeName)(modelMeta.export.encoder.encodedExcelType),
27
- ],
28
- });
29
- modelTypes.push(`${modelMeta.export.tableName}?: ${modelMeta.export.encoder.encodedExcelType}[]`);
30
- exportFields.push(`${modelMeta.import.tableName}:
31
- data.${modelMeta.export.exportDataFullPropertyName} !== undefined ?
32
- ${modelMeta.export.encoder.arrayEncoderFunctionName}(data.${modelMeta.export.exportDataFullPropertyName})
33
- : undefined`);
34
- }
35
- return `
36
- ${imports.generate()}
37
-
38
- export type ${encodedExcelDataTypeName} = {
39
- ${modelTypes.join(',\n')}
40
- }
41
-
42
- /**
43
- * Converts the model data to Excel format
44
- */
45
- export const ${fullEncoderFunctionName} = (data: ${decodedPXLModelDataTypeName}): ${encodedExcelDataTypeName} => ({
46
- ${exportFields.join(',\n')}
47
- })
48
- `;
49
- }
50
- exports.generateExportEncoder = generateExportEncoder;
@@ -1,9 +0,0 @@
1
- import { SchemaMetaData } from '../../../lib/meta';
2
- import { Model } from '../../../lib/schema/schema';
3
- /**
4
- * Generates the Convert function for the Import module
5
- */
6
- export declare function generateConvertImportFunctions({ models, meta }: {
7
- models: Model[];
8
- meta: SchemaMetaData;
9
- }): string;
@@ -1,509 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.generateConvertImportFunctions = void 0;
4
- const imports_1 = require("../../../lib/imports");
5
- const meta_1 = require("../../../lib/meta");
6
- const types_1 = require("../../../lib/schema/types");
7
- const types_2 = require("../../../lib/types");
8
- /**
9
- * Generates the Convert function for the Import module
10
- */
11
- function generateConvertImportFunctions({ models, meta }) {
12
- const { dto } = meta.types;
13
- const { importedDataToBulkMutations, deltaToBulkMutations } = meta.import.converterFunctions;
14
- const { types } = meta.import;
15
- const { delta } = types;
16
- const imports = imports_1.ImportsGenerator.from(meta.import.converterFunctions.location.path);
17
- imports.addImports({
18
- [meta.import.decoder.location.path]: [(0, types_1.toAnnotatedTypeName)(meta.import.decoder.decodedPXLModelDataTypeName)],
19
- [meta.data.types.location.import]: [
20
- (0, types_1.toAnnotatedTypeName)(meta.data.types.bulkMutation),
21
- (0, types_1.toAnnotatedTypeName)(meta.data.types.bulkMutationForModel),
22
- ],
23
- [meta.types.importPath]: [(0, types_1.toAnnotatedTypeName)(dto.genericModel), (0, types_1.toAnnotatedTypeName)(dto.idType)],
24
- [types.location.path]: [(0, types_1.toAnnotatedTypeName)(types.delta), (0, types_1.toAnnotatedTypeName)(types.delta_Model.type)],
25
- });
26
- const importConverterBlocks = [];
27
- const deltaConverterBlocks = [];
28
- let state = initializeModelsState(models);
29
- let nextStep = determineNextStep(state);
30
- // logState({ state, nextStep, lastStep: 'init' })
31
- let iteration = 0;
32
- while (nextStep !== 'completed') {
33
- iteration++;
34
- const { importConvertBlock, deltaConvertBlock, state: stateUpdated, } = generateBlocks({ state, nextStep, imports, iteration, schemaMeta: meta });
35
- importConverterBlocks.push(importConvertBlock);
36
- deltaConverterBlocks.push(deltaConvertBlock);
37
- state = updateModelState(stateUpdated);
38
- nextStep = determineNextStep(state);
39
- // logState({ state, nextStep, lastStep: 'updateModelState' })
40
- }
41
- return /* ts */ `
42
- import { ExhaustiveSwitchCheck } from '@postxl/runtime'
43
- ${imports.generate()}
44
-
45
- /**
46
- * Converts ${types.delta} to ${meta.data.types.bulkMutation} steps, taking into account the order of dependencies.
47
- * **Important**: It assumes that data has been pre-checked and converted to \`${delta}\`.
48
- */
49
- export function ${deltaToBulkMutations}(
50
- input: ${types.delta}
51
- ): ${meta.data.types.bulkMutation}[] {
52
- return [${deltaConverterBlocks.join(',\n')}]
53
- }
54
-
55
- /**
56
- * Converts any models to ${meta.data.types.bulkMutation} steps, taking into account the order of dependencies.
57
- * **Important**: It does not check if the items exist, ie. it is meant mainly for seeding.
58
- * For sophisticated imports that handle deltas, use \`${deltaToBulkMutations}\` instead!
59
- */
60
- export function ${importedDataToBulkMutations}(
61
- input: ${meta.import.decoder.decodedPXLModelDataTypeName}
62
- ): ${meta.data.types.bulkMutation}[] {
63
- return [${importConverterBlocks.join(',\n')}]
64
- }
65
-
66
- /**
67
- * Removes empty arrays from a ${meta.data.types.bulkMutation} object.
68
- */
69
- function _removeBlank${meta.data.types.bulkMutation}<Model extends ${dto.genericModel}<ID>, ID extends ${dto.idType}>(
70
- bulk: ${meta.data.types.bulkMutationForModel}<Model, ID>,
71
- ): ${meta.data.types.bulkMutationForModel}<Model, ID> {
72
- const result: ${meta.data.types.bulkMutationForModel}<Model, ID> = {}
73
- if (bulk.create && bulk.create.length > 0) { result.create = bulk.create }
74
- if (bulk.update && bulk.update.length > 0) { result.update = bulk.update }
75
- if (bulk.upsert && bulk.upsert.length > 0) { result.upsert = bulk.upsert }
76
- if (bulk.delete && bulk.delete.length > 0) { result.delete = bulk.delete }
77
-
78
- return result
79
- }
80
-
81
- /**
82
- * Converts a list of Deltas for a model to a ${meta.data.types.bulkMutation} object.
83
- */
84
- function deltaModelTo${meta.data.types.bulkMutation}<
85
- Model extends ${dto.genericModel}<ID>,
86
- ID extends ${dto.idType},
87
- ModelErrors
88
- >(
89
- items?: ${types.delta_Model.type}<Model, ID, ModelErrors>[],
90
- ): ${meta.data.types.bulkMutationForModel}<Model, ID> {
91
- const result: Required<${meta.data.types.bulkMutationForModel}<Model, ID>> = {
92
- create: [],
93
- update: [],
94
- upsert: [],
95
- delete: [],
96
- }
97
-
98
- for (const item of items ?? []) {
99
- switch (item.type) {
100
- case 'create':
101
- result.create.push(item.createDTO)
102
- break
103
- case 'update':
104
- result.update.push(item.updateDTO)
105
- break
106
- case 'delete':
107
- result.delete.push(item.input.id)
108
- break
109
- case 'unchanged':
110
- break
111
- case 'errors':
112
- throw new Error('Cannot convert delta to bulk mutation as it contains errors')
113
- default:
114
- throw new ExhaustiveSwitchCheck(item)
115
- }
116
- }
117
-
118
- return _removeBlank${meta.data.types.bulkMutation}(result)
119
- }
120
- `;
121
- }
122
- exports.generateConvertImportFunctions = generateConvertImportFunctions;
123
- // Helpful for debugging the complex logic, so should not be removed
124
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
125
- function logState({ iteration, state, nextStep, lastStep, }) {
126
- console.log(`
127
- Iteration: ${iteration++}
128
- LastStep: ${lastStep}
129
- Completed: ${[...state.completed.values()].map((model) => model.name).join(', ')}
130
- CreatedToBeLinked: ${[...state.createdToBeLinked.values()].map((x) => x.model.name).join(', ')}
131
- CanBeCreatedFullyLinked: ${[...state.canBeCreatedFullyLinked.values()].map((x) => x.model.name).join(', ')}
132
- CanBeCreatedPartiallyLinked: ${[...state.canBeCreatedPartiallyLinked.values()].map((x) => x.model.name).join(', ')}
133
- Blocked: ${[...state.blocked.values()].map((x) => x.model.name).join(', ')}
134
- NextStep: ${nextStep}`);
135
- }
136
- /**
137
- * Groups the fields of a model into fields that can be created, fields that can be created as null, and fields that block the creation of the model.
138
- */
139
- function groupModelFields({ state, model }) {
140
- const result = {
141
- model,
142
- create: new Set(),
143
- nullableFieldsForLaterLinking: new Set(),
144
- requiredFieldsBlockingLinking: new Set(),
145
- ignoreFields: new Set(),
146
- };
147
- for (const field of model.fields) {
148
- // We ignore createdAt and updatedAt fields as they are set automatically.
149
- if (field.attributes.ignore || field.attributes.isCreatedAt || field.attributes.isUpdatedAt) {
150
- result.ignoreFields.add(field);
151
- continue;
152
- }
153
- // Non-relations can always be created without extra checks.
154
- if (field.kind !== 'relation') {
155
- result.create.add(field);
156
- continue;
157
- }
158
- // Related model is already created so we can create the field.
159
- if (state.completed.has(field.relationToModel.name) || state.createdToBeLinked.has(field.relationToModel.name)) {
160
- result.create.add(field);
161
- continue;
162
- }
163
- // In nullable relation we can set the field to null and link it later.
164
- if (!field.isRequired) {
165
- result.nullableFieldsForLaterLinking.add(field);
166
- continue;
167
- }
168
- // All other options are exhausted meaning this is a required relation and the related model hasn't been created yet.
169
- // We cannot create the field yet so we add it to backlog.
170
- result.requiredFieldsBlockingLinking.add(field);
171
- }
172
- return result;
173
- }
174
- /**
175
- * Determines the state (created partially linked, or can be created fully linked) of a model based on its fields
176
- */
177
- function determineModelNextStep(fieldsGrouped) {
178
- // If we have blocking fields, we cannot create the model yet
179
- if (fieldsGrouped.requiredFieldsBlockingLinking.size > 0) {
180
- return 'blocked';
181
- }
182
- // If we have no blocking fields, we can create the model but need to link some fields later
183
- if (fieldsGrouped.nullableFieldsForLaterLinking.size > 0) {
184
- return 'canBeCreatedPartiallyLinked';
185
- }
186
- // If no field is blocking and all nullable fields can be linked, we can create the model and link all fields
187
- return 'canBeCreatedFullyLinked';
188
- }
189
- function assignModelToState({ state, modelNextStep, fieldsGrouped, }) {
190
- switch (modelNextStep) {
191
- case 'blocked':
192
- state.blocked.set(fieldsGrouped.model.name, fieldsGrouped);
193
- break;
194
- case 'canBeCreatedPartiallyLinked':
195
- state.canBeCreatedPartiallyLinked.set(fieldsGrouped.model.name, fieldsGrouped);
196
- break;
197
- case 'canBeCreatedFullyLinked':
198
- state.canBeCreatedFullyLinked.set(fieldsGrouped.model.name, fieldsGrouped);
199
- break;
200
- default:
201
- throw new types_2.ExhaustiveSwitchCheck(modelNextStep);
202
- }
203
- }
204
- function initializeModelsState(models) {
205
- const state = {
206
- completed: new Map(),
207
- createdToBeLinked: new Map(),
208
- canBeCreatedFullyLinked: new Map(),
209
- canBeCreatedPartiallyLinked: new Map(),
210
- blocked: new Map(),
211
- };
212
- for (const model of models) {
213
- const fieldsGrouped = groupModelFields({ state, model });
214
- const modelNextStep = determineModelNextStep(fieldsGrouped);
215
- assignModelToState({ state, modelNextStep, fieldsGrouped });
216
- }
217
- return state;
218
- }
219
- /**
220
- * Checks if any of the blocked or partially linked models can be created now.
221
- */
222
- function updateModelState(oldState) {
223
- const newState = copyModelState(oldState);
224
- newState.blocked = new Map();
225
- newState.canBeCreatedPartiallyLinked = new Map();
226
- // We iterate over all blocked models and check if they can be created now
227
- for (const [, fieldsGrouped] of oldState.blocked) {
228
- const fieldsGroupedUpdated = groupModelFields({ state: oldState, model: fieldsGrouped.model });
229
- const modelNextStep = determineModelNextStep(fieldsGroupedUpdated);
230
- assignModelToState({ state: newState, modelNextStep, fieldsGrouped: fieldsGroupedUpdated });
231
- }
232
- // We iterate over all partially linked models and check if they can be created fully linked now
233
- for (const [, fieldsGrouped] of oldState.canBeCreatedPartiallyLinked) {
234
- const fieldsGroupedUpdated = groupModelFields({ state: oldState, model: fieldsGrouped.model });
235
- const modelNextStep = determineModelNextStep(fieldsGroupedUpdated);
236
- assignModelToState({ state: newState, modelNextStep, fieldsGrouped: fieldsGroupedUpdated });
237
- }
238
- return newState;
239
- }
240
- function determineNextStep(modelsState) {
241
- // We prioritize models that can be created fully linked, so we do not need unnecessary linking steps later
242
- if (modelsState.canBeCreatedFullyLinked.size > 0) {
243
- return 'createFullyLinked';
244
- }
245
- // If no model can be created fully linked, we check if we can create models partially linked
246
- if (modelsState.canBeCreatedPartiallyLinked.size > 0) {
247
- return 'createPartiallyLinked';
248
- }
249
- // Lastly, we link all models that require linking
250
- if (modelsState.createdToBeLinked.size > 0) {
251
- return 'link';
252
- }
253
- // If we now still have blocked models, we have a circular dependency
254
- if (modelsState.blocked.size > 0) {
255
- throw new Error(`Cannot create the following models because they have a circular dependency: ${Array.from(modelsState.blocked.values())
256
- .map((model) => model.model.name)
257
- .join(', ')}`);
258
- }
259
- // If we have no blocked models, we are done
260
- return 'completed';
261
- }
262
- function generateBlocks({ state, nextStep, imports, iteration, schemaMeta, }) {
263
- switch (nextStep) {
264
- case 'createFullyLinked':
265
- return generateBulkMutationBlockCreateFullyLinked({ state, imports, iteration, schemaMeta });
266
- case 'createPartiallyLinked':
267
- return generateBulkMutationBlockCreatePartiallyLinked({ state, imports, iteration, schemaMeta });
268
- case 'link':
269
- return generateBulkMutationBlockLink({ state, imports, iteration, schemaMeta });
270
- default:
271
- throw new types_2.ExhaustiveSwitchCheck(nextStep);
272
- }
273
- }
274
- function copyModelState(state) {
275
- return {
276
- completed: new Map(state.completed),
277
- createdToBeLinked: new Map(state.createdToBeLinked),
278
- canBeCreatedFullyLinked: new Map(state.canBeCreatedFullyLinked),
279
- canBeCreatedPartiallyLinked: new Map(state.canBeCreatedPartiallyLinked),
280
- blocked: new Map(state.blocked),
281
- };
282
- }
283
- function generateBulkMutationBlockCreateFullyLinked({ state, iteration, imports, schemaMeta, }) {
284
- const newState = copyModelState(state);
285
- newState.canBeCreatedFullyLinked = new Map();
286
- const models = state.canBeCreatedFullyLinked;
287
- const importConvertBlocks = [];
288
- const deltaConvertBlocks = [];
289
- const modelNames = [];
290
- for (const [, fieldsGrouped] of models) {
291
- const modelMeta = (0, meta_1.getModelMetadata)({ model: fieldsGrouped.model });
292
- imports.addTypeImport({
293
- from: schemaMeta.types.importPath,
294
- items: [modelMeta.types.dto.create],
295
- });
296
- const { block: importConvertBlock } = generateModelCreateBlock({ fieldsGrouped, modelMeta });
297
- importConvertBlocks.push(importConvertBlock);
298
- deltaConvertBlocks.push(`${modelMeta.seed.constantName}: deltaModelTo${schemaMeta.data.types.bulkMutation}(input.${modelMeta.seed.constantName})`);
299
- newState.completed.set(fieldsGrouped.model.name, fieldsGrouped.model);
300
- modelNames.push(modelMeta.userFriendlyNamePlural);
301
- }
302
- const importConvertBlock = `
303
- // Step ${iteration}: Create fully linked models: ${modelNames.join(', ')}
304
- {
305
- ${importConvertBlocks.join(',\n')}
306
- }`;
307
- const deltaConvertBlock = `
308
- // Step ${iteration}: Create/update entire entries for: ${modelNames.join(', ')}
309
- {
310
- ${deltaConvertBlocks.join(',\n')}
311
- }`;
312
- return { importConvertBlock, deltaConvertBlock, state: newState };
313
- }
314
- function generateBulkMutationBlockCreatePartiallyLinked({ state, imports, iteration, schemaMeta, }) {
315
- const newState = copyModelState(state);
316
- newState.canBeCreatedPartiallyLinked = new Map();
317
- const models = state.canBeCreatedPartiallyLinked;
318
- const importConvertBlocks = [];
319
- const deltaConvertBlocks = [];
320
- const modelNames = [];
321
- for (const [, fieldsGrouped] of models) {
322
- const modelMeta = (0, meta_1.getModelMetadata)({ model: fieldsGrouped.model });
323
- imports.addTypeImport({
324
- from: modelMeta.types.importPath,
325
- items: [modelMeta.types.dto.create],
326
- });
327
- const { block: importConvertBlock, fieldsToBeLinkedLater } = generateModelCreateBlock({ fieldsGrouped, modelMeta });
328
- importConvertBlocks.push(importConvertBlock);
329
- const deltaConvertBlock = generateDeltaBlock({ fieldsGrouped, modelMeta, schemaMeta, imports });
330
- deltaConvertBlocks.push(deltaConvertBlock);
331
- newState.createdToBeLinked.set(fieldsGrouped.model.name, fieldsGrouped);
332
- modelNames.push(`${modelMeta.userFriendlyNamePlural} (without ${fieldsToBeLinkedLater.join(', ')})`);
333
- }
334
- const importConvertBlock = `
335
- // Step ${iteration}: Create partially linked models:
336
- // * ${modelNames.join('\n // * ')}
337
- {
338
- ${importConvertBlocks.join(',\n')}
339
- }`;
340
- const deltaConvertBlock = `
341
- // Step ${iteration}: Create partially linked models:
342
- // * ${modelNames.join('\n // * ')}
343
- {
344
- ${deltaConvertBlocks.join(',\n')}
345
- }`;
346
- return { importConvertBlock, deltaConvertBlock, state: newState };
347
- }
348
- function generateModelCreateBlock({ fieldsGrouped, modelMeta, }) {
349
- const { createFromObject: createAssignments, fieldsToBeLinkedLater } = generateFieldAssignmentBlocks({
350
- fieldsGrouped,
351
- modelMeta,
352
- });
353
- return {
354
- block: /* ts */ `
355
- ${modelMeta.seed.constantName}: {
356
- create: input.${modelMeta.import.decoder.decodedModelArrayName}?.map(
357
- (item: ${modelMeta.types.dto.create}) => ({
358
- ${createAssignments.join(',\n')}
359
- }))
360
- ?? []
361
- }`,
362
- fieldsToBeLinkedLater,
363
- };
364
- }
365
- function generateDeltaBlock({ fieldsGrouped, modelMeta, schemaMeta, imports, }) {
366
- const { createFromDelta: createAssignments, updateFromDelta: updateAssignments } = generateFieldAssignmentBlocks({
367
- fieldsGrouped,
368
- modelMeta,
369
- });
370
- const genericsDefinition = `${modelMeta.types.typeName}, ${modelMeta.types.brandedIdType}`;
371
- const { type, create, update } = schemaMeta.import.types.delta_Model;
372
- imports.addTypeImport({
373
- from: modelMeta.types.importPath,
374
- items: [modelMeta.types.typeName, modelMeta.types.brandedIdType],
375
- });
376
- imports.addTypeImport({
377
- from: schemaMeta.import.types.location.path,
378
- items: [type, create.type, update.type],
379
- });
380
- imports.addImport({
381
- from: schemaMeta.import.types.location.path,
382
- items: [create.typeGuard, update.typeGuard],
383
- });
384
- return /* ts */ `
385
- ${modelMeta.seed.constantName}: {
386
- create:
387
- input.${modelMeta.seed.constantName}
388
- ?.filter(${create.typeGuard})
389
- .map((item: ${create.type}<${genericsDefinition}>) => ({
390
- ${createAssignments.join(',\n')}
391
- })) ?? [],
392
- update:
393
- input.${modelMeta.seed.constantName}
394
- ?.filter(${update.typeGuard})
395
- .map((item: ${update.type}<${genericsDefinition}>) => ({
396
- id: item.input.id,
397
- ${updateAssignments.join(',\n')},
398
- })) ?? [],
399
- }`;
400
- }
401
- function generateBulkMutationBlockLink({ state, imports, iteration, schemaMeta, }) {
402
- const newState = copyModelState(state);
403
- newState.createdToBeLinked = new Map();
404
- const models = state.createdToBeLinked;
405
- const importConvertBlocks = [];
406
- const deltaConvertBlocks = [];
407
- const modelNames = [];
408
- for (const [, fieldsGrouped] of models) {
409
- const modelMeta = (0, meta_1.getModelMetadata)({ model: fieldsGrouped.model });
410
- imports.addTypeImport({
411
- from: modelMeta.types.importPath,
412
- items: [modelMeta.types.dto.update],
413
- });
414
- const { importConvertBlock, deltaConvertBlock } = generateModelLinkBlocks({ fieldsGrouped, modelMeta, schemaMeta });
415
- importConvertBlocks.push(importConvertBlock);
416
- deltaConvertBlocks.push(deltaConvertBlock);
417
- newState.completed.set(fieldsGrouped.model.name, fieldsGrouped.model);
418
- modelNames.push(modelMeta.userFriendlyNamePlural);
419
- }
420
- const importConvertBlock = `
421
- // Step ${iteration}: Link models: ${modelNames.join(', ')}
422
- {
423
- ${importConvertBlocks.join(',\n')}
424
- }`;
425
- const deltaConvertBlock = `
426
- // Step ${iteration}: Link models: ${modelNames.join(', ')}
427
- {
428
- ${deltaConvertBlocks.join(',\n')}
429
- }`;
430
- return { importConvertBlock, deltaConvertBlock, state: newState };
431
- }
432
- function generateModelLinkBlocks({ fieldsGrouped, modelMeta, schemaMeta, }) {
433
- const { model, nullableFieldsForLaterLinking } = fieldsGrouped;
434
- const genericsDefinition = `${modelMeta.types.typeName}, ${modelMeta.types.brandedIdType}`;
435
- const { create, update } = schemaMeta.import.types.delta_Model;
436
- if (nullableFieldsForLaterLinking.size === 0) {
437
- throw new Error(`Cannot link fields for ${model.name} as it does not have any nullable fields`);
438
- }
439
- const { linkFromObject, linkFromCreateDTO, linkFromDelta } = generateFieldAssignmentBlocks({
440
- fieldsGrouped,
441
- modelMeta,
442
- });
443
- return {
444
- importConvertBlock: /* ts */ `
445
- ${modelMeta.seed.constantName}: {
446
- update: input.${modelMeta.import.decoder.decodedModelArrayName}?.map(
447
- (item: ${modelMeta.types.dto.update}) => ({
448
- id: item.id,
449
- ${linkFromObject.join(',\n')}
450
- }))
451
- ?? []
452
- }`,
453
- deltaConvertBlock: /* ts */ `
454
- ${modelMeta.seed.constantName}: {
455
- update: [
456
- ...input.${modelMeta.seed.constantName}
457
- ?.filter(${create.typeGuard})
458
- .map((item: ${create.type}<${genericsDefinition}>) => ({
459
- id: item.input.id,
460
- ${linkFromCreateDTO.join(',\n')}
461
- })) ?? [],
462
-
463
- ...input.${modelMeta.seed.constantName}
464
- ?.filter(${update.typeGuard})
465
- .map((item: ${update.type}<${genericsDefinition}>) => ({
466
- id: item.input.id,
467
- ${linkFromDelta.join(',\n')},
468
- })) ?? [],
469
- ]
470
- }`,
471
- };
472
- }
473
- function generateFieldAssignmentBlocks({ fieldsGrouped, }) {
474
- const { model, create, nullableFieldsForLaterLinking, requiredFieldsBlockingLinking } = fieldsGrouped;
475
- if (requiredFieldsBlockingLinking.size > 0) {
476
- const _fields = Array.from(requiredFieldsBlockingLinking.values())
477
- .map((field) => field.name)
478
- .join(', ');
479
- throw new Error(`Cannot create model ${model.name} because some required fields don't exist yet: ${_fields}`);
480
- }
481
- const result = {
482
- fieldsToBeLinkedLater: [],
483
- createFromObject: [],
484
- createFromDelta: [],
485
- updateFromDelta: [],
486
- linkFromObject: [],
487
- linkFromCreateDTO: [],
488
- linkFromDelta: [],
489
- };
490
- for (const field of create) {
491
- result.createFromObject.push(`${field.name}: item.${field.name}`);
492
- result.createFromDelta.push(`${field.name}: item.input.${field.name}`);
493
- if (field.kind !== 'id') {
494
- result.updateFromDelta.push(`${field.name}: '${field.name}' in item.delta && item.delta['${field.name}'] ? item.delta['${field.name}'].new : undefined`);
495
- }
496
- }
497
- for (const field of nullableFieldsForLaterLinking) {
498
- result.createFromObject.push(`${field.name}: null`);
499
- result.createFromDelta.push(`${field.name}: null`);
500
- if (field.kind !== 'id') {
501
- result.updateFromDelta.push(`${field.name}: '${field.name}' in item.delta ? null : undefined`);
502
- }
503
- result.fieldsToBeLinkedLater.push(field.name);
504
- result.linkFromObject.push(`${field.name}: item.${field.name}`);
505
- result.linkFromCreateDTO.push(`${field.name}: item.input.${field.name}`);
506
- result.linkFromDelta.push(`${field.name}: '${field.name}' in item.delta && item.delta['${field.name}'] ? item.delta['${field.name}'].new : undefined`);
507
- }
508
- return result;
509
- }
@@ -1,9 +0,0 @@
1
- import { SchemaMetaData } from '../../../lib/meta';
2
- import { Model } from '../../../lib/schema/schema';
3
- /**
4
- * Generates the data decoder, aggregating all the models.
5
- */
6
- export declare function generateImportDecoder({ models, meta }: {
7
- models: Model[];
8
- meta: SchemaMetaData;
9
- }): string;
@@ -1,40 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.generateImportDecoder = void 0;
4
- const imports_1 = require("../../../lib/imports");
5
- const meta_1 = require("../../../lib/meta");
6
- /**
7
- * Generates the data decoder, aggregating all the models.
8
- */
9
- function generateImportDecoder({ models, meta }) {
10
- const { decodedPXLModelDataTypeName, fullDecoderName } = meta.import.decoder;
11
- const imports = imports_1.ImportsGenerator.from(meta.import.decoder.location.path);
12
- const decoderEntries = [];
13
- for (const model of models) {
14
- const modelMeta = (0, meta_1.getModelMetadata)({ model });
15
- imports.addImport({
16
- from: modelMeta.import.decoder.location.path,
17
- items: [modelMeta.import.decoder.tableDecoder],
18
- });
19
- decoderEntries.push(`${modelMeta.import.tableName}: ${modelMeta.import.decoder.tableDecoder}.optional()`);
20
- }
21
- return `
22
- import * as z from 'zod'
23
-
24
- import { uncapitalizeKeys } from '@postxl/runtime'
25
-
26
- ${imports.generate()}
27
-
28
- /**
29
- * Decoder that converts Excel data to model data
30
- */
31
- export const ${fullDecoderName} = z
32
- .object({
33
- ${decoderEntries.join(',\n')}
34
- })
35
- .transform(uncapitalizeKeys)
36
-
37
- export type ${decodedPXLModelDataTypeName} = z.infer<typeof excelDataDecoder>
38
- `;
39
- }
40
- exports.generateImportDecoder = generateImportDecoder;
@@ -1,9 +0,0 @@
1
- import { SchemaMetaData } from '../../../lib/meta';
2
- import { Model } from '../../../lib/schema/schema';
3
- /**
4
- * Generates the Import Service class for the Import module
5
- */
6
- export declare function generateImportService({ models, meta }: {
7
- models: Model[];
8
- meta: SchemaMetaData;
9
- }): string;