@postxl/generator 0.74.2 → 1.0.3

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 +53 -31
  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,710 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
- Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.generateDeleteModalModelComponent = exports.generateEditModalModelComponent = exports.generateModelCreateModalComponent = void 0;
27
- const imports_1 = require("../../../lib/imports");
28
- const meta_1 = require("../../../lib/meta");
29
- const fields_1 = require("../../../lib/schema/fields");
30
- const serializer_1 = require("../../../lib/serializer");
31
- const test_id_collector_1 = require("../../../lib/test-id-collector");
32
- const types_1 = require("../../../lib/types");
33
- const StringUtils = __importStar(require("../../../lib/utils/string"));
34
- /**
35
- * Utility generator that creates a create modal component for a given model.
36
- */
37
- function generateModelCreateModalComponent({ model, meta }) {
38
- const { fields } = model;
39
- const { react: { components: { modals }, }, trpc, } = meta;
40
- const testIdCollector = test_id_collector_1.TestIdCollector.from(meta.seed.constantName + '-createModal');
41
- const dimensions = getModalComponentDimensions({ model });
42
- return `
43
- /* eslint-disable @typescript-eslint/no-unused-vars */
44
- ${getFormImports({ model, meta })}
45
-
46
- type CreateInputData = {
47
- ${getCreateFormInputFields({ model })}
48
- }
49
-
50
- const INITIAL_VALUES = {
51
- ${fields
52
- .filter((f) => f.kind !== 'id' && !f.attributes.isReadonly)
53
- .map((field) => `${getFormikFieldName(field.name)}: null,`)
54
- .join('\n')}
55
- }
56
-
57
- /**
58
- * A modal component that lets the user create a new ${meta.userFriendlyName} instance.
59
- */
60
- export const ${modals.createComponentName} = ({
61
- show,
62
- onHide,
63
- data
64
- }: {
65
- show: boolean;
66
- onHide: () => void;
67
- data?: Partial<CreateInputData>
68
- }) => {
69
- const Typed = React.useMemo(
70
- () => createTypedForm<CreateInputData>().with({ ${(() => {
71
- const components = new Set();
72
- for (const field of fields.values()) {
73
- if (field.attributes.isReadonly) {
74
- continue;
75
- }
76
- switch (field.kind) {
77
- case 'enum': {
78
- const enumMeta = (0, meta_1.getEnumMetadata)({ enumerator: field.enumerator });
79
- components.add(enumMeta.react.selectFieldName);
80
- break;
81
- }
82
- case 'relation': {
83
- const refMeta = (0, meta_1.getModelMetadata)({ model: field.relationToModel });
84
- components.add(refMeta.react.components.forms.searchFieldName);
85
- break;
86
- }
87
- default:
88
- continue;
89
- }
90
- }
91
- return [...components].join(', ');
92
- })()} }),
93
- []
94
- )
95
-
96
- const cache = trpc.useContext()
97
- const mutation = trpc.${trpc.create.reactQueryMethod}.useMutation()
98
-
99
- return (
100
- <ModalWithNavigationContainer label="Create new ${meta.userFriendlyName}" show={show} onHide={onHide} ${dimensions}>
101
- <Typed.Formik
102
- initialValues={{ ...INITIAL_VALUES, ...data }}
103
- validate={(values) => {
104
- const errors: { [K in keyof CreateInputData]?: string } = {}
105
-
106
- ${getFormikValidationCases({ model })}
107
-
108
- return errors
109
- }}
110
- onSubmit={async (values) => {
111
-
112
- try {
113
- const res = await toast.promise(
114
- mutation.mutateAsync(
115
- {
116
- ${getFormikCreateMutationData({ model })}
117
- },
118
- {
119
- async onSuccess() {
120
- await cache.${trpc.routerName}.invalidate()
121
- },
122
- },
123
- ),
124
- {
125
- loading: "Creating new ${meta.userFriendlyName}...",
126
- success: "New ${meta.userFriendlyName} created!",
127
- error: (error) => {
128
- if (error instanceof TRPCClientError) {
129
- return error.message
130
- }
131
-
132
- return 'Something went wrong...'
133
- },
134
- },
135
- )
136
-
137
- if (res.id) {
138
- onHide()
139
- }
140
- } catch (err) {
141
- console.error(err)
142
- }
143
- }}
144
- >
145
- {({ isSubmitting, submitForm }) => (
146
- <ModalWithActions actions={
147
- <ConfirmButton
148
- color="primary"
149
- label="Create"
150
- fill="fill"
151
- onClick={submitForm}
152
- loading={isSubmitting}
153
- __e2e_test_id__="${testIdCollector.idFor('submit', { typePrefix: 'buttons' })}"
154
- />
155
- }>
156
- ${getFormFieldComponents({ model, testIdCollector: testIdCollector })}
157
- </ModalWithActions>
158
- )}
159
- </Typed.Formik>
160
- </ModalWithNavigationContainer>
161
- )
162
- }
163
-
164
- `;
165
- }
166
- exports.generateModelCreateModalComponent = generateModelCreateModalComponent;
167
- /**
168
- * Returns a React component that lets you edit a model instance.
169
- */
170
- function generateEditModalModelComponent({ model, meta }) {
171
- const { fields } = model;
172
- const { react: { components }, trpc, } = meta;
173
- const testIdCollector = test_id_collector_1.TestIdCollector.from(meta.seed.constantName + '-editModal');
174
- const dimensions = getModalComponentDimensions({ model });
175
- return `
176
- /* eslint-disable @typescript-eslint/no-unused-vars */
177
- ${getFormImports({ model, meta })}
178
-
179
-
180
- type EditInputData = {
181
- ${getFormikFieldName(model.idField.name)}: ${model.brandedIdType}
182
- ${getEditFormInputFields({ model })}
183
- }
184
-
185
- /**
186
- * Modal component that may be used to edit a ${model.name} instance.
187
- */
188
- export const ${components.modals.editComponentName} = ({
189
- data,
190
- show,
191
- onHide
192
- }: { data: ${model.typeName}; show: boolean; onHide: () => void }) => {
193
- const Typed = React.useMemo(
194
- () => createTypedForm<EditInputData>().with({ ${(() => {
195
- const components = new Set();
196
- for (const field of fields.values()) {
197
- switch (field.kind) {
198
- case 'enum': {
199
- const enumMeta = (0, meta_1.getEnumMetadata)({ enumerator: field.enumerator });
200
- components.add(enumMeta.react.selectFieldName);
201
- break;
202
- }
203
- case 'relation': {
204
- const refMeta = (0, meta_1.getModelMetadata)({ model: field.relationToModel });
205
- components.add(refMeta.react.components.forms.searchFieldName);
206
- break;
207
- }
208
- default:
209
- continue;
210
- }
211
- }
212
- return [...components].join(', ');
213
- })()} }),
214
- []
215
- )
216
- const cache = trpc.useContext()
217
- const mutation = trpc.${trpc.update.reactQueryMethod}.useMutation()
218
-
219
- return (
220
- <ModalWithNavigationContainer label="Edit ${meta.userFriendlyName}" show={show} onHide={onHide} ${dimensions}>
221
- <Typed.Formik
222
- initialValues={{
223
- ${fields
224
- .filter((f) => !f.attributes.isReadonly || f.kind === 'id')
225
- .map((field) => {
226
- switch (field.kind) {
227
- case 'enum':
228
- case 'relation':
229
- if (field.isRequired) {
230
- return `${getFormikFieldName(field.name)}: { id: data.${field.name} },`;
231
- }
232
- return `${getFormikFieldName(field.name)}: data.${field.name} ? { id: data.${field.name} } : null,`;
233
- case 'id':
234
- case 'scalar':
235
- return `${getFormikFieldName(field.name)}: data.${field.name},`;
236
- default:
237
- throw new types_1.ExhaustiveSwitchCheck(field);
238
- }
239
- })
240
- .join('\n')}
241
- }}
242
- validate={(values) => {
243
- const errors: { [K in keyof EditInputData]?: string } = {}
244
-
245
- ${getFormikValidationCases({ model })}
246
-
247
- return errors
248
- }}
249
- onSubmit={async (values) => {
250
- try {
251
- await toast.promise(
252
- mutation.mutateAsync(
253
- {
254
- ${getEditFormikMutationData({ model })}
255
- },
256
- {
257
- async onSuccess() {
258
- await cache.${trpc.routerName}.invalidate()
259
- },
260
- },
261
- ),
262
- {
263
- loading: "Updating ${meta.userFriendlyName}...",
264
- success: "${meta.userFriendlyName} updated!",
265
- error: (error) => {
266
- if (error instanceof TRPCClientError) {
267
- return error.message
268
- }
269
-
270
- return 'Something went wrong...'
271
- },
272
- },
273
- )
274
-
275
- onHide()
276
- } catch (err) {
277
- console.error(err)
278
- }
279
- }}
280
- >
281
- {({ isSubmitting, submitForm }) => (
282
- <ModalWithActions
283
- actions={
284
- <ConfirmButton
285
- label="Save"
286
- color="primary"
287
- onClick={submitForm}
288
- loading={isSubmitting}
289
- __e2e_test_id__="${testIdCollector.idFor('submit', { typePrefix: 'buttons' })}"
290
- />
291
- }
292
- >
293
- ${getFormFieldComponents({ model, testIdCollector: testIdCollector })}
294
- </ModalWithActions>
295
- )}
296
- </Typed.Formik>
297
- </ModalWithNavigationContainer>
298
- )
299
- }
300
- `;
301
- }
302
- exports.generateEditModalModelComponent = generateEditModalModelComponent;
303
- /**
304
- * Generates a modal component that lets you delete a model instance.
305
- */
306
- function generateDeleteModalModelComponent({ model, meta }) {
307
- const { react: { components }, trpc, } = meta;
308
- const imports = imports_1.ImportsGenerator.from(meta.react.folderPath).addTypeImport({
309
- items: [model.brandedIdType],
310
- from: meta.types.importPath,
311
- });
312
- return `
313
- /* eslint-disable @typescript-eslint/no-unused-vars */
314
- import { TRPCClientError } from '@trpc/client'
315
-
316
- import { Formik } from 'formik'
317
- import React, { useCallback } from 'react'
318
- import { toast } from 'react-hot-toast'
319
-
320
- import { ConfirmationModal } from '@components/atoms/Modal'
321
- import { trpc } from '@lib/trpc'
322
-
323
- ${imports.generate()}
324
-
325
- /**
326
- * Modal components that shows a confirmation modal before deleting a ${meta.userFriendlyName}.
327
- */
328
- export const ${components.modals.deleteComponentName} = ({
329
- id,
330
- show,
331
- onHide
332
- }: {
333
- id: ${model.brandedIdType};
334
- show: boolean;
335
- onHide: () => void
336
- }) => {
337
- const cache = trpc.useContext()
338
- const mutation = trpc.${trpc.delete.reactQueryMethod}.useMutation()
339
-
340
- const handleDelete = useCallback(async () => {
341
- try {
342
- await toast.promise(
343
- mutation.mutateAsync(id, {
344
- async onSuccess() {
345
- await cache.${trpc.routerName}.invalidate()
346
- },
347
- }),
348
- {
349
- loading: "Deleting ${meta.userFriendlyName}...",
350
- success: "${meta.userFriendlyName} deleted!",
351
- error: (err) => {
352
- if (err instanceof TRPCClientError) {
353
- return err.message
354
- }
355
- return 'Something went wrong...'
356
- },
357
- },
358
- )
359
- } catch (err) {
360
- console.error(err)
361
- }
362
- }, [mutation, id, cache])
363
-
364
- return (
365
- <ConfirmationModal
366
- show={show}
367
- onHide={onHide}
368
- onConfirm={handleDelete}
369
- label="Delete ${meta.userFriendlyName}"
370
- description="Please confirm that you want to delete this ${meta.userFriendlyName}."
371
- variant="danger"
372
- loading={mutation.isLoading}
373
- />
374
- )
375
- }
376
- `;
377
- }
378
- exports.generateDeleteModalModelComponent = generateDeleteModalModelComponent;
379
- /**
380
- * Returns the import statements to the models that are used in this modal.
381
- */
382
- function getFormImports({ model, meta }) {
383
- const imports = imports_1.ImportsGenerator.from(meta.react.folderPath).addTypeImport({
384
- items: [model.brandedIdType, model.typeName],
385
- from: meta.types.importPath,
386
- });
387
- for (const ref of (0, fields_1.getRelationFields)(model)) {
388
- const refModel = ref.relationToModel;
389
- const refMeta = (0, meta_1.getModelMetadata)({ model: refModel });
390
- imports.addImport({
391
- items: [refMeta.react.components.forms.searchFieldName],
392
- from: refMeta.react.folderPath,
393
- });
394
- imports.addTypeImport({
395
- items: [refModel.brandedIdType],
396
- from: refMeta.types.importPath,
397
- });
398
- }
399
- for (const f of (0, fields_1.getEnumFields)(model)) {
400
- const enumMeta = (0, meta_1.getEnumMetadata)(f);
401
- imports.addTypeImport({
402
- items: [f.enumerator.tsTypeName],
403
- from: enumMeta.types.importPath,
404
- });
405
- imports.addImport({
406
- items: [enumMeta.react.selectFieldName],
407
- from: enumMeta.react.folderPath,
408
- });
409
- }
410
- return `
411
- import { TRPCClientError } from '@trpc/client'
412
- import React from 'react'
413
- import { toast } from 'react-hot-toast'
414
-
415
- import { createTypedForm } from '@components/atoms/Form'
416
- import { ConfirmButton, ModalWithNavigationContainer, Label, ModalWithActions } from '@components/atoms/Modal'
417
-
418
- import { trpc } from '@lib/trpc'
419
-
420
- ${imports.generate()}
421
- `;
422
- }
423
- /**
424
- * Returns a string containing TypeScript type definition for the input data of the create mutation.
425
- *
426
- * NOTE: This function assumes that fields might also be null because we have no data yet.
427
- */
428
- function getCreateFormInputFields({ model }) {
429
- const form = new serializer_1.Serializer();
430
- for (const field of model.fields.values()) {
431
- if (field.attributes.isReadonly) {
432
- continue;
433
- }
434
- switch (field.kind) {
435
- case 'id':
436
- continue;
437
- case 'relation':
438
- form.append(`${getFormikFieldName(field.name)}: { id: ${field.relationToModel.brandedIdType} } | null`);
439
- break;
440
- case 'scalar':
441
- form.append(`${getFormikFieldName(field.name)}: ${field.tsTypeName} | null`);
442
- break;
443
- case 'enum':
444
- form.append(`${getFormikFieldName(field.name)}: { id: ${field.typeName} } | null`);
445
- break;
446
- default:
447
- throw new types_1.ExhaustiveSwitchCheck(field);
448
- }
449
- }
450
- return form.print();
451
- }
452
- function getFormikCreateMutationData({ model: { fields } }) {
453
- return fields
454
- .filter((f) => !f.attributes.isReadonly)
455
- .map((field) => {
456
- const formikFieldName = getFormikFieldName(field.name);
457
- switch (field.kind) {
458
- case 'id':
459
- case 'scalar':
460
- // NOTE: Create methods generate the ID field upon submission.
461
- if (field.kind === 'id') {
462
- return '';
463
- }
464
- if (field.isRequired) {
465
- return `
466
- // NOTE: We force unwrap values, because we validate values using Formik.
467
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
468
- ${field.name}: values.${formikFieldName}!,
469
- `;
470
- }
471
- return `${field.name}: values.${formikFieldName},`;
472
- case 'relation':
473
- if (field.isRequired) {
474
- return `
475
- // NOTE: We force unwrap values, because we validate values using Formik.
476
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
477
- ${field.name}: values.${formikFieldName}!.id,
478
- `;
479
- }
480
- return `${field.name}: values.${formikFieldName}?.id ? values.${formikFieldName}.id : null,`;
481
- case 'enum':
482
- if (field.isRequired) {
483
- return `
484
- // NOTE: We force unwrap values, because we validate values using Formik.
485
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
486
- ${field.name}: values.${formikFieldName}!.id,
487
- `;
488
- }
489
- return `${field.name}: values.${formikFieldName}?.id ? values.${formikFieldName}.id : null,`;
490
- default:
491
- throw new types_1.ExhaustiveSwitchCheck(field);
492
- }
493
- })
494
- .join('\n');
495
- }
496
- /**
497
- * Returns a string containing the fields of the input data without the ID field.
498
- */
499
- function getEditFormInputFields({ model }) {
500
- const form = new serializer_1.Serializer();
501
- for (const field of model.fields.values()) {
502
- if (field.attributes.isReadonly) {
503
- continue;
504
- }
505
- switch (field.kind) {
506
- case 'id':
507
- continue;
508
- case 'relation':
509
- if (field.isRequired) {
510
- form.append(`${getFormikFieldName(field.name)}: { id: ${field.relationToModel.brandedIdType} }`);
511
- }
512
- else {
513
- form.append(`${getFormikFieldName(field.name)}: { id: ${field.relationToModel.brandedIdType} } | null`);
514
- }
515
- break;
516
- case 'scalar':
517
- if (field.isRequired) {
518
- form.append(`${getFormikFieldName(field.name)}: ${field.tsTypeName}`);
519
- }
520
- else {
521
- form.append(`${getFormikFieldName(field.name)}: ${field.tsTypeName} | null`);
522
- }
523
- break;
524
- case 'enum':
525
- if (field.isRequired) {
526
- form.append(`${getFormikFieldName(field.name)}: { id: ${field.typeName} }`);
527
- }
528
- else {
529
- form.append(`${getFormikFieldName(field.name)}: { id: ${field.typeName} } | null`);
530
- }
531
- break;
532
- default:
533
- throw new types_1.ExhaustiveSwitchCheck(field);
534
- }
535
- }
536
- return form.print();
537
- }
538
- function getEditFormikMutationData({ model: { fields } }) {
539
- return fields
540
- .filter((f) => !f.attributes.isReadonly || f.kind === 'id')
541
- .map((field) => {
542
- const formikFieldName = getFormikFieldName(field.name);
543
- switch (field.kind) {
544
- case 'id':
545
- // NOTE: Edit mutation expects the ID field to identify the object.
546
- // eslint-disable-next-line no-fallthrough
547
- case 'scalar':
548
- return `${field.name}: values.${formikFieldName},`;
549
- case 'relation':
550
- if (field.isRequired) {
551
- return `${field.name}: values.${formikFieldName}.id,`;
552
- }
553
- return `${field.name}: values.${formikFieldName}?.id ? values.${formikFieldName}.id : null,`;
554
- case 'enum':
555
- if (field.isRequired) {
556
- return `${field.name}: values.${formikFieldName}.id,`;
557
- }
558
- return `${field.name}: values.${formikFieldName}?.id ? values.${formikFieldName}.id : null,`;
559
- default:
560
- throw new types_1.ExhaustiveSwitchCheck(field);
561
- }
562
- })
563
- .join('\n');
564
- }
565
- /**
566
- * Returns a string containing all the components that should appear in the Formik form for this model.
567
- */
568
- function getFormFieldComponents({ model, testIdCollector, }) {
569
- var _a;
570
- const form = new serializer_1.Serializer();
571
- for (const field of model.fields.values()) {
572
- // By default, we hide generated fields like createdAt, updatedAt, deletedAt.
573
- if (field.attributes.isReadonly) {
574
- continue;
575
- }
576
- const formikFieldName = getFormikFieldName(field.name);
577
- const label = field.attributes.label;
578
- switch (field.kind) {
579
- case 'id': {
580
- // NOTE: We never show the ID field in the form even if it's in the type signature of the form input.
581
- break;
582
- }
583
- case 'scalar': {
584
- // Each scalar field has a different generic component based on the provided type.
585
- scalar: switch (field.tsTypeName) {
586
- case 'string': {
587
- form.append(`
588
- <div>
589
- <Label>${label}</Label>
590
- <Typed.TextField
591
- name="${formikFieldName}"
592
- placeholder="Type..."
593
- __e2e_field_test_id__="${testIdCollector.idFor(field.name, { typePrefix: 'fields' })}"
594
- />
595
- </div>
596
- `);
597
- break scalar;
598
- }
599
- case 'number': {
600
- let decimals = 0;
601
- if (((_a = field.validation) === null || _a === void 0 ? void 0 : _a.type) === 'float') {
602
- decimals = 2;
603
- }
604
- form.append(`
605
- <div>
606
- <Label>${label}</Label>
607
- <Typed.NumberField
608
- name="${formikFieldName}"
609
- placeholder="2511"
610
- decimals={${decimals}}
611
- __e2e_field_test_id__="${testIdCollector.idFor(field.name, { typePrefix: 'fields' })}"
612
- />
613
- </div>
614
- `);
615
- break scalar;
616
- }
617
- case 'boolean': {
618
- form.append(`
619
- <div>
620
- <Label>Is ${label}</Label>
621
- <Typed.CheckBoxField
622
- name="${formikFieldName}"
623
- label="${label}"
624
- __e2e_field_test_id__="${testIdCollector.idFor(field.name, { typePrefix: 'fields' })}"
625
- />
626
- </div>
627
- `);
628
- break scalar;
629
- }
630
- case 'Date': {
631
- form.append(`{/* Skipped date field ${field.name}. */}`);
632
- break scalar;
633
- }
634
- default: {
635
- console.warn(`Unknown scalar type ${field.tsTypeName} for field ${model.name}.${field.name}.`);
636
- break scalar;
637
- }
638
- }
639
- break;
640
- }
641
- case 'relation': {
642
- const refMeta = (0, meta_1.getModelMetadata)({ model: field.relationToModel });
643
- form.append(`
644
- <div>
645
- <Label>${refMeta.userFriendlyName}</Label>
646
- <Typed.${refMeta.react.components.forms.searchFieldName}
647
- name="${formikFieldName}"
648
- placeholder="Search..."
649
- __e2e_options_test_id__="${testIdCollector.idFor(field.name, { typePrefix: 'options' })}"
650
- __e2e_combobox_test_id__="${testIdCollector.idFor(field.name, { typePrefix: 'fields' })}"
651
- />
652
- </div>
653
- `);
654
- break;
655
- }
656
- case 'enum': {
657
- const enumMeta = (0, meta_1.getEnumMetadata)({ enumerator: field.enumerator });
658
- form.append(`
659
- <div>
660
- <Label>${label}</Label>
661
- <Typed.${enumMeta.react.selectFieldName}
662
- name="${formikFieldName}"
663
- placeholder="Search..."
664
- __e2e_field_test_id__="${testIdCollector.idFor(field.name, { typePrefix: 'fields' })}"
665
- />
666
- </div>
667
- `);
668
- break;
669
- }
670
- default:
671
- throw new types_1.ExhaustiveSwitchCheck(field);
672
- }
673
- }
674
- return form.print();
675
- }
676
- /**
677
- * Returns a string containing a list of checks for Formik validation function.
678
- */
679
- function getFormikValidationCases({ model }) {
680
- const form = new serializer_1.Serializer();
681
- for (const field of model.fields.values()) {
682
- if (field.kind === 'id' || field.attributes.isReadonly) {
683
- continue;
684
- }
685
- const formikFieldName = getFormikFieldName(field.name);
686
- if (field.isRequired) {
687
- form.append(`
688
- if (!values.${formikFieldName}) {
689
- errors.${formikFieldName} = "Required..."
690
- }
691
- `);
692
- }
693
- }
694
- return form.print();
695
- }
696
- // NOTE: This function is separated because many parts rely on the name of the field.
697
- function getFormikFieldName(name) {
698
- return `formik${StringUtils.toPascalCase(name)}`;
699
- }
700
- /**
701
- * Returns a string representing the "missing" dimension parameters for the modal component
702
- * depending on the type of the modal.
703
- */
704
- function getModalComponentDimensions({ model }) {
705
- const _fields = model.fields.filter((f) => f.kind !== 'id' && !f.attributes.isReadonly);
706
- if (_fields.length > 3) {
707
- return 'fixed wide';
708
- }
709
- return '';
710
- }