@comet/admin-generator 8.0.0-beta.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 (55) hide show
  1. package/LICENSE +24 -0
  2. package/bin/admin-generator.js +5 -0
  3. package/lib/adminGenerator.d.ts +1 -0
  4. package/lib/adminGenerator.js +8 -0
  5. package/lib/commands/generate/generate-command.d.ts +197 -0
  6. package/lib/commands/generate/generate-command.js +114 -0
  7. package/lib/commands/generate/generateForm/generateComponentFormField.d.ts +5 -0
  8. package/lib/commands/generate/generateForm/generateComponentFormField.js +18 -0
  9. package/lib/commands/generate/generateForm/generateFields.d.ts +35 -0
  10. package/lib/commands/generate/generateForm/generateFields.js +88 -0
  11. package/lib/commands/generate/generateForm/generateForm.d.ts +13 -0
  12. package/lib/commands/generate/generateForm/generateForm.js +468 -0
  13. package/lib/commands/generate/generateForm/generateFormField.d.ts +12 -0
  14. package/lib/commands/generate/generateForm/generateFormField.js +525 -0
  15. package/lib/commands/generate/generateForm/generateFormLayout.d.ts +12 -0
  16. package/lib/commands/generate/generateForm/generateFormLayout.js +164 -0
  17. package/lib/commands/generate/generateForm/getForwardedGqlArgs.d.ts +19 -0
  18. package/lib/commands/generate/generateForm/getForwardedGqlArgs.js +79 -0
  19. package/lib/commands/generate/generateGrid/combinationColumn.d.ts +43 -0
  20. package/lib/commands/generate/generateGrid/combinationColumn.js +151 -0
  21. package/lib/commands/generate/generateGrid/findInputObjectType.d.ts +2 -0
  22. package/lib/commands/generate/generateGrid/findInputObjectType.js +16 -0
  23. package/lib/commands/generate/generateGrid/generateGqlFieldList.d.ts +5 -0
  24. package/lib/commands/generate/generateGrid/generateGqlFieldList.js +43 -0
  25. package/lib/commands/generate/generateGrid/generateGrid.d.ts +14 -0
  26. package/lib/commands/generate/generateGrid/generateGrid.js +827 -0
  27. package/lib/commands/generate/generateGrid/generateGridToolbar.d.ts +14 -0
  28. package/lib/commands/generate/generateGrid/generateGridToolbar.js +92 -0
  29. package/lib/commands/generate/generateGrid/getForwardedGqlArgs.d.ts +14 -0
  30. package/lib/commands/generate/generateGrid/getForwardedGqlArgs.js +64 -0
  31. package/lib/commands/generate/generateGrid/getPropsForFilterProp.d.ts +12 -0
  32. package/lib/commands/generate/generateGrid/getPropsForFilterProp.js +14 -0
  33. package/lib/commands/generate/generateGrid/usableFields.d.ts +8 -0
  34. package/lib/commands/generate/generateGrid/usableFields.js +2 -0
  35. package/lib/commands/generate/utils/camelCaseToHumanReadable.d.ts +1 -0
  36. package/lib/commands/generate/utils/camelCaseToHumanReadable.js +8 -0
  37. package/lib/commands/generate/utils/columnVisibility.d.ts +6 -0
  38. package/lib/commands/generate/utils/columnVisibility.js +2 -0
  39. package/lib/commands/generate/utils/findMutationType.d.ts +3 -0
  40. package/lib/commands/generate/utils/findMutationType.js +19 -0
  41. package/lib/commands/generate/utils/findQueryType.d.ts +2 -0
  42. package/lib/commands/generate/utils/findQueryType.js +19 -0
  43. package/lib/commands/generate/utils/findRootBlocks.d.ts +8 -0
  44. package/lib/commands/generate/utils/findRootBlocks.js +67 -0
  45. package/lib/commands/generate/utils/generateImportsCode.d.ts +5 -0
  46. package/lib/commands/generate/utils/generateImportsCode.js +27 -0
  47. package/lib/commands/generate/utils/intl.d.ts +1 -0
  48. package/lib/commands/generate/utils/intl.js +7 -0
  49. package/lib/commands/generate/utils/isFieldOptional.d.ts +7 -0
  50. package/lib/commands/generate/utils/isFieldOptional.js +21 -0
  51. package/lib/commands/generate/utils/writeGenerated.d.ts +1 -0
  52. package/lib/commands/generate/utils/writeGenerated.js +57 -0
  53. package/lib/index.d.ts +1 -0
  54. package/lib/index.js +2 -0
  55. package/package.json +67 -0
@@ -0,0 +1,468 @@
1
+ "use strict";
2
+ var __rest = (this && this.__rest) || function (s, e) {
3
+ var t = {};
4
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
5
+ t[p] = s[p];
6
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
7
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
8
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
9
+ t[p[i]] = s[p[i]];
10
+ }
11
+ return t;
12
+ };
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.generateForm = void 0;
15
+ const generate_command_1 = require("../generate-command");
16
+ const findMutationType_1 = require("../utils/findMutationType");
17
+ const generateImportsCode_1 = require("../utils/generateImportsCode");
18
+ const generateFields_1 = require("./generateFields");
19
+ const getForwardedGqlArgs_1 = require("./getForwardedGqlArgs");
20
+ function generateFormPropsCode(props) {
21
+ if (!props.length)
22
+ return { formPropsTypeCode: "", formPropsParamsCode: "" };
23
+ const uniqueProps = props.reduce((acc, item) => {
24
+ const propWithSameName = acc.find((prop) => prop.name == item.name);
25
+ if (!propWithSameName)
26
+ return [item, ...acc];
27
+ if (propWithSameName.type != item.type || propWithSameName.optional != item.optional) {
28
+ // this is currently not supported
29
+ return [item, ...acc];
30
+ }
31
+ return acc;
32
+ }, []);
33
+ return {
34
+ formPropsTypeCode: `interface FormProps {
35
+ ${uniqueProps.map((prop) => `${prop.name}${prop.optional ? `?` : ``}: ${prop.type};`).join("\n")}
36
+ }`,
37
+ formPropsParamsCode: `{${uniqueProps.map((prop) => prop.name).join(", ")}}: FormProps`,
38
+ };
39
+ }
40
+ function generateForm({ exportName, baseOutputFilename, targetDirectory, gqlIntrospection, },
41
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
42
+ config) {
43
+ var _a, _b, _c, _d, _e, _f, _g;
44
+ assertValidConfig(config);
45
+ const gqlType = config.gqlType;
46
+ const instanceGqlType = gqlType[0].toLowerCase() + gqlType.substring(1);
47
+ const formFragmentName = (_a = config.fragmentName) !== null && _a !== void 0 ? _a : `${gqlType}Form`;
48
+ const gqlDocuments = {};
49
+ const imports = [];
50
+ const props = [];
51
+ const mode = (_b = config.mode) !== null && _b !== void 0 ? _b : "all";
52
+ const editMode = mode === "edit" || mode == "all";
53
+ const addMode = mode === "add" || mode == "all";
54
+ const createMutationType = addMode && (0, findMutationType_1.findMutationTypeOrThrow)((_c = config.createMutation) !== null && _c !== void 0 ? _c : `create${gqlType}`, gqlIntrospection);
55
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
56
+ const formFields = config.fields.reduce((acc, field) => {
57
+ if ((0, generate_command_1.isFormLayoutConfig)(field)) {
58
+ // using forEach instead of acc.push(...field.fields.filter(isFormFieldConfig)) because typescript can't handle mixed typing
59
+ field.fields.forEach((nestedFieldConfig) => {
60
+ if ((0, generate_command_1.isFormFieldConfig)(nestedFieldConfig)) {
61
+ acc.push(nestedFieldConfig);
62
+ }
63
+ });
64
+ }
65
+ else if ((0, generate_command_1.isFormFieldConfig)(field)) {
66
+ acc.push(field);
67
+ }
68
+ return acc;
69
+ }, []);
70
+ const gqlArgs = [];
71
+ if (createMutationType) {
72
+ const { imports: forwardedGqlArgsImports, props: forwardedGqlArgsProps, gqlArgs: forwardedGqlArgs, } = (0, getForwardedGqlArgs_1.getForwardedGqlArgs)({
73
+ fields: formFields,
74
+ gqlOperation: createMutationType,
75
+ gqlIntrospection,
76
+ });
77
+ imports.push(...forwardedGqlArgsImports);
78
+ props.push(...forwardedGqlArgsProps);
79
+ gqlArgs.push(...forwardedGqlArgs);
80
+ }
81
+ if (editMode) {
82
+ if (mode === "all") {
83
+ props.push({ name: "id", optional: true, type: "string" });
84
+ }
85
+ else if (mode === "edit") {
86
+ props.push({ name: "id", optional: false, type: "string" });
87
+ }
88
+ }
89
+ const { formPropsTypeCode, formPropsParamsCode } = generateFormPropsCode(props);
90
+ const rootBlockFields = formFields
91
+ .filter((field) => field.type == "block")
92
+ .map((field) => {
93
+ // map is for ts to infer block type correctly
94
+ if (field.type !== "block")
95
+ throw new Error("Field is not a block field");
96
+ return field;
97
+ });
98
+ rootBlockFields.forEach((field) => {
99
+ imports.push({
100
+ name: field.block.name,
101
+ importPath: field.block.import,
102
+ });
103
+ });
104
+ const readOnlyFields = formFields.filter((field) => field.readOnly);
105
+ const fileFields = formFields.filter((field) => field.type == "fileUpload");
106
+ if (fileFields.length > 0) {
107
+ imports.push({ name: "GQLFinalFormFileUploadFragment", importPath: "@comet/cms-admin" });
108
+ }
109
+ // Unnecessary field.type == "fileUpload" check to make TypeScript happy
110
+ const downloadableFileFields = fileFields.filter((field) => field.type == "fileUpload" && field.download);
111
+ if (fileFields.length > 0) {
112
+ imports.push({ name: "GQLFinalFormFileUploadDownloadableFragment", importPath: "@comet/cms-admin" });
113
+ }
114
+ let hooksCode = "";
115
+ let formValueToGqlInputCode = "";
116
+ const formFragmentFields = [];
117
+ const formValuesConfig = [];
118
+ const _h = (0, generateFields_1.generateFields)({
119
+ gqlIntrospection,
120
+ baseOutputFilename,
121
+ fields: config.fields,
122
+ formFragmentName,
123
+ formConfig: config,
124
+ gqlType: config.gqlType,
125
+ }), { code: fieldsCode } = _h, generatedFields = __rest(_h, ["code"]);
126
+ for (const name in generatedFields.gqlDocuments) {
127
+ gqlDocuments[name] = {
128
+ document: generatedFields.gqlDocuments[name].document,
129
+ export: true,
130
+ };
131
+ }
132
+ imports.push(...generatedFields.imports);
133
+ hooksCode += generatedFields.hooksCode;
134
+ formValueToGqlInputCode += generatedFields.formValueToGqlInputCode;
135
+ formFragmentFields.push(...generatedFields.formFragmentFields);
136
+ formValuesConfig.push(...generatedFields.formValuesConfig);
137
+ gqlDocuments[`${instanceGqlType}FormFragment`] = {
138
+ document: `
139
+ fragment ${formFragmentName} on ${gqlType} {
140
+ ${formFragmentFields.join("\n")}
141
+ }
142
+ ${fileFields.length > 0 && fileFields.length !== downloadableFileFields.length ? "${finalFormFileUploadFragment}" : ""}
143
+ ${downloadableFileFields.length > 0 ? "${finalFormFileUploadDownloadableFragment}" : ""}
144
+ `,
145
+ export: editMode,
146
+ };
147
+ if (editMode) {
148
+ gqlDocuments[`${instanceGqlType}Query`] = {
149
+ document: `
150
+ query ${gqlType}($id: ID!) {
151
+ ${instanceGqlType}(id: $id) {
152
+ id
153
+ updatedAt
154
+ ...${formFragmentName}
155
+ }
156
+ }
157
+ \${${`${instanceGqlType}FormFragment`}}
158
+ `,
159
+ export: true,
160
+ };
161
+ }
162
+ if (addMode && createMutationType) {
163
+ gqlDocuments[`create${gqlType}Mutation`] = {
164
+ document: `
165
+ mutation Create${gqlType}(${gqlArgs.filter((gqlArg) => !gqlArg.isInputArgSubfield).length
166
+ ? `${gqlArgs
167
+ .filter((gqlArg) => !gqlArg.isInputArgSubfield)
168
+ .map((gqlArg) => {
169
+ return `$${gqlArg.name}: ${gqlArg.type}!`;
170
+ })
171
+ .join(", ")}, `
172
+ : ``}$input: ${gqlType}Input!) {
173
+ ${createMutationType.name}(${gqlArgs.filter((gqlArg) => !gqlArg.isInputArgSubfield).length
174
+ ? `${gqlArgs
175
+ .filter((gqlArg) => !gqlArg.isInputArgSubfield)
176
+ .map((gqlArg) => {
177
+ return `${gqlArg.name}: $${gqlArg.name}`;
178
+ })
179
+ .join(", ")}, `
180
+ : ``}input: $input) {
181
+ id
182
+ updatedAt
183
+ ...${formFragmentName}
184
+ }
185
+ }
186
+ \${${`${instanceGqlType}FormFragment`}}
187
+ `,
188
+ export: true,
189
+ };
190
+ }
191
+ if (editMode) {
192
+ gqlDocuments[`update${gqlType}Mutation`] = {
193
+ document: `
194
+ mutation Update${gqlType}($id: ID!, $input: ${gqlType}UpdateInput!) {
195
+ update${gqlType}(id: $id, input: $input) {
196
+ id
197
+ updatedAt
198
+ ...${formFragmentName}
199
+ }
200
+ }
201
+ \${${`${instanceGqlType}FormFragment`}}
202
+ `,
203
+ export: true,
204
+ };
205
+ }
206
+ for (const name in gqlDocuments) {
207
+ const gqlDocument = gqlDocuments[name];
208
+ imports.push({
209
+ name: name,
210
+ importPath: `./${baseOutputFilename}.gql`,
211
+ });
212
+ const match = gqlDocument.document.match(/^\s*(query|mutation|fragment)\s+(\w+)/);
213
+ if (!match)
214
+ throw new Error(`Could not find query or mutation name in ${gqlDocument}`);
215
+ const type = match[1];
216
+ const documentName = match[2];
217
+ imports.push({
218
+ name: `GQL${documentName}${type[0].toUpperCase() + type.substring(1)}`,
219
+ importPath: `./${baseOutputFilename}.gql.generated`,
220
+ });
221
+ imports.push({
222
+ name: `GQL${documentName}${type[0].toUpperCase() + type.substring(1)}Variables`,
223
+ importPath: `./${baseOutputFilename}.gql.generated`,
224
+ });
225
+ }
226
+ const finalFormSubscription = Object.keys((_e = (_d = generatedFields.finalFormConfig) === null || _d === void 0 ? void 0 : _d.subscription) !== null && _e !== void 0 ? _e : {});
227
+ const finalFormRenderProps = Object.keys((_g = (_f = generatedFields.finalFormConfig) === null || _f === void 0 ? void 0 : _f.renderProps) !== null && _g !== void 0 ? _g : {});
228
+ let filterByFragmentType = `GQL${formFragmentName}Fragment`;
229
+ let customFilterByFragment = "";
230
+ if (fileFields.length > 0) {
231
+ const keysToOverride = fileFields.map((field) => field.name);
232
+ customFilterByFragment = `type ${formFragmentName}Fragment = Omit<${filterByFragmentType}, ${keysToOverride
233
+ .map((key) => `"${String(key)}"`)
234
+ .join(" | ")}> & {
235
+ ${fileFields
236
+ .map((field) => {
237
+ if (field.type !== "fileUpload") {
238
+ throw new Error("Field is not a file upload field");
239
+ }
240
+ if (("multiple" in field && field.multiple) ||
241
+ ("maxFiles" in field && typeof field.maxFiles === "number" && field.maxFiles > 1)) {
242
+ return `${String(field.name)}: ${field.download ? "GQLFinalFormFileUploadDownloadableFragment" : "GQLFinalFormFileUploadFragment"}[];`;
243
+ }
244
+ return `${String(field.name)}: ${field.download ? "GQLFinalFormFileUploadDownloadableFragment" : "GQLFinalFormFileUploadFragment"} | null;`;
245
+ })
246
+ .join("\n")}
247
+ }`;
248
+ filterByFragmentType = `${formFragmentName}Fragment`;
249
+ }
250
+ const code = `import { useApolloClient, useQuery, gql } from "@apollo/client";
251
+ import {
252
+ AsyncSelectField,
253
+ CheckboxField,
254
+ Field,
255
+ filterByFragment,
256
+ FinalForm,
257
+ FinalFormInput,
258
+ FinalFormRangeInput,
259
+ FinalFormSelect,
260
+ FinalFormSubmitEvent,
261
+ Loading,
262
+ RadioGroupField,
263
+ TextAreaField,
264
+ TextField,
265
+ useFormApiRef,
266
+ useStackSwitchApi,
267
+ } from "@comet/admin";
268
+ import { ArrowLeft, Lock } from "@comet/admin-icons";
269
+ import { DateTimeField, FinalFormDatePicker } from "@comet/admin-date-time";
270
+ import { BlockState, createFinalFormBlock, queryUpdatedAt, resolveHasSaveConflict, useFormSaveConflict, FileUploadField } from "@comet/cms-admin";
271
+ import { FormControlLabel, IconButton, MenuItem, InputAdornment } from "@mui/material";
272
+ import { FormApi } from "final-form";
273
+ import isEqual from "lodash.isequal";
274
+ import { useMemo } from "react";
275
+ import { FormattedMessage } from "react-intl";
276
+ ${(0, generateImportsCode_1.generateImportsCode)(imports)}
277
+ ${rootBlockFields.length > 0
278
+ ? `const rootBlocks = {
279
+ ${rootBlockFields.map((field) => `${String(field.name)}: ${field.block.name}`)}
280
+ };`
281
+ : ""}
282
+
283
+ ${customFilterByFragment}
284
+
285
+ type FormValues = ${formValuesConfig.filter((config) => !!config.omitFromFragmentType).length > 0
286
+ ? `Omit<${filterByFragmentType}, ${formValuesConfig
287
+ .filter((config) => !!config.omitFromFragmentType)
288
+ .map((config) => `"${config.omitFromFragmentType}"`)
289
+ .join(" | ")}>`
290
+ : `${filterByFragmentType}`} ${formValuesConfig.filter((config) => !!config.typeCode).length > 0
291
+ ? `& {
292
+ ${formValuesConfig
293
+ .filter((config) => !!config.typeCode)
294
+ .map((config) => config.typeCode)
295
+ .join("\n")}
296
+ }`
297
+ : ""};
298
+
299
+ ${formPropsTypeCode}
300
+
301
+ export function ${exportName}(${formPropsParamsCode}) {
302
+ const client = useApolloClient();
303
+ ${mode == "all" ? `const mode = id ? "edit" : "add";` : ""}
304
+ const formApiRef = useFormApiRef<FormValues>();
305
+ ${addMode ? `const stackSwitchApi = useStackSwitchApi();` : ""}
306
+
307
+ ${editMode
308
+ ? `
309
+ const { data, error, loading, refetch } = useQuery<GQL${gqlType}Query, GQL${gqlType}QueryVariables>(
310
+ ${instanceGqlType}Query,
311
+ ${mode == "edit" ? `{ variables: { id } }` : `id ? { variables: { id } } : { skip: true }`},
312
+ );
313
+ `
314
+ : ""}
315
+
316
+ ${editMode
317
+ ? `const initialValues = useMemo<Partial<FormValues>>(() => data?.${instanceGqlType}
318
+ ? {
319
+ ...filterByFragment<${filterByFragmentType}>(${instanceGqlType}FormFragment, data.${instanceGqlType}),
320
+ ${formValuesConfig
321
+ .filter((config) => !!config.initializationCode)
322
+ .map((config) => config.initializationCode)
323
+ .join(",\n")}
324
+ }
325
+ : {
326
+ ${formValuesConfig
327
+ .filter((config) => !!config.defaultInitializationCode)
328
+ .map((config) => config.defaultInitializationCode)
329
+ .join(",\n")}
330
+ }
331
+ , [data]);`
332
+ : `const initialValues = {
333
+ ${formValuesConfig
334
+ .filter((config) => !!config.defaultInitializationCode)
335
+ .map((config) => config.defaultInitializationCode)
336
+ .join(",\n")}
337
+ };`}
338
+
339
+ ${editMode
340
+ ? `
341
+ const saveConflict = useFormSaveConflict({
342
+ checkConflict: async () => {
343
+ const updatedAt = await queryUpdatedAt(client, "${instanceGqlType}", id);
344
+ return resolveHasSaveConflict(data?.${instanceGqlType}.updatedAt, updatedAt);
345
+ },
346
+ formApiRef,
347
+ loadLatestVersion: async () => {
348
+ await refetch();
349
+ },
350
+ });
351
+ `
352
+ : ""}
353
+
354
+ const handleSubmit = async (${formValuesConfig.filter((config) => !!config.destructFromFormValues).length
355
+ ? `{ ${formValuesConfig
356
+ .filter((config) => !!config.destructFromFormValues)
357
+ .map((config) => config.destructFromFormValues)
358
+ .join(", ")}, ...formValues }`
359
+ : `formValues`}: FormValues, form: FormApi<FormValues>${addMode ? `, event: FinalFormSubmitEvent` : ""}) => {
360
+ ${editMode ? `if (await saveConflict.checkForConflicts()) throw new Error("Conflicts detected");` : ""}
361
+ const output = {
362
+ ...formValues,
363
+ ${formValueToGqlInputCode}
364
+ };
365
+ ${mode == "all" ? `if (mode === "edit") {` : ""}
366
+ ${editMode
367
+ ? `
368
+ ${readOnlyFields.some((field) => field.name === "id") ? "" : "if (!id) throw new Error();"}
369
+ const { ${readOnlyFields.map((field) => `${String(field.name)},`).join("")} ...updateInput } = output;
370
+ await client.mutate<GQLUpdate${gqlType}Mutation, GQLUpdate${gqlType}MutationVariables>({
371
+ mutation: update${gqlType}Mutation,
372
+ variables: { id, input: updateInput },
373
+ });
374
+ `
375
+ : ""}
376
+ ${mode == "all" ? `} else {` : ""}
377
+ ${addMode && createMutationType
378
+ ? `
379
+ const { data: mutationResponse } = await client.mutate<GQLCreate${gqlType}Mutation, GQLCreate${gqlType}MutationVariables>({
380
+ mutation: create${gqlType}Mutation,
381
+ variables: { input: ${gqlArgs.filter((prop) => prop.isInputArgSubfield).length
382
+ ? `{ ...output, ${gqlArgs
383
+ .filter((prop) => prop.isInputArgSubfield)
384
+ .map((prop) => prop.name)
385
+ .join(",")} }`
386
+ : "output"}${gqlArgs.filter((prop) => !prop.isInputArgSubfield).length
387
+ ? `, ${gqlArgs
388
+ .filter((prop) => !prop.isInputArgSubfield)
389
+ .map((arg) => arg.name)
390
+ .join(",")}`
391
+ : ""} },
392
+ });
393
+ if (!event.navigatingBack) {
394
+ const id = mutationResponse?.${createMutationType.name}.id;
395
+ if (id) {
396
+ setTimeout(() => {
397
+ stackSwitchApi.activatePage(\`edit\`, id);
398
+ });
399
+ }
400
+ }
401
+ `
402
+ : ""}
403
+ ${mode == "all" ? `}` : ""}
404
+ };
405
+
406
+ ${hooksCode}
407
+
408
+ ${editMode
409
+ ? ` if (error) throw error;
410
+
411
+ if (loading) {
412
+ return <Loading behavior="fillPageHeight" />;
413
+ }`
414
+ : ``}
415
+
416
+ return (
417
+ <FinalForm<FormValues>
418
+ apiRef={formApiRef}
419
+ onSubmit={handleSubmit}
420
+ mode=${mode == "all" ? `{mode}` : editMode ? `"edit"` : `"add"`}
421
+ initialValues={initialValues}
422
+ initialValuesEqual={isEqual} //required to compare block data correctly
423
+ subscription={{ ${finalFormSubscription.length ? finalFormSubscription.map((field) => `${field}: true`).join(", ") : ``} }}
424
+ >
425
+ {(${finalFormRenderProps.length ? `{${finalFormRenderProps.join(", ")}}` : ``}) => (
426
+ ${editMode ? `<>` : ``}
427
+ ${editMode ? `{saveConflict.dialogs}` : ``}
428
+ <>
429
+ ${fieldsCode}
430
+ </>
431
+ ${editMode ? `</>` : ``}
432
+ )}
433
+ </FinalForm>
434
+ );
435
+ }
436
+
437
+ `;
438
+ return {
439
+ code,
440
+ gqlDocuments,
441
+ };
442
+ }
443
+ exports.generateForm = generateForm;
444
+ /**
445
+ * Checks if the provided form config is valid.
446
+ *
447
+ * Examples of invalid configs:
448
+ * - The "id" field is not read-only
449
+ *
450
+ * @param config The form config to check.
451
+ * @throws Will throw an error if the provided config is invalid.
452
+ */
453
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
454
+ function assertValidConfig(config) {
455
+ function validateFields(fields) {
456
+ for (const field of fields) {
457
+ if ((0, generate_command_1.isFormFieldConfig)(field)) {
458
+ if (field.name === "id" && !field.readOnly) {
459
+ throw new Error(`Invalid form config: the "id" field must be read-only`);
460
+ }
461
+ }
462
+ else if ((0, generate_command_1.isFormLayoutConfig)(field)) {
463
+ validateFields(field.fields);
464
+ }
465
+ }
466
+ }
467
+ validateFields(config.fields);
468
+ }
@@ -0,0 +1,12 @@
1
+ import { type IntrospectionQuery } from "graphql";
2
+ import { type FormConfig, type FormFieldConfig } from "../generate-command";
3
+ import { type GenerateFieldsReturn } from "./generateFields";
4
+ export declare function generateFormField({ gqlIntrospection, baseOutputFilename, config, formConfig, gqlType, namePrefix, }: {
5
+ gqlIntrospection: IntrospectionQuery;
6
+ baseOutputFilename: string;
7
+ config: FormFieldConfig<any>;
8
+ formFragmentName: string;
9
+ formConfig: FormConfig<any>;
10
+ gqlType: string;
11
+ namePrefix?: string;
12
+ }): GenerateFieldsReturn;