@comet/admin-generator 9.0.0-canary-20251002124333 → 9.0.0-canary-20251113142723

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 (36) hide show
  1. package/lib/commands/generate/config/transformConfig.d.ts +6 -0
  2. package/lib/commands/generate/config/transformConfig.js +36 -8
  3. package/lib/commands/generate/generate-command.d.ts +49 -15
  4. package/lib/commands/generate/generate-command.js +5 -0
  5. package/lib/commands/generate/generateForm/asyncSelect/generateAsyncSelect.js +46 -22
  6. package/lib/commands/generate/generateForm/flatFormFieldsFromFormConfig.d.ts +2 -0
  7. package/lib/commands/generate/generateForm/flatFormFieldsFromFormConfig.js +22 -0
  8. package/lib/commands/generate/generateForm/formField/findIntrospectionFieldType.d.ts +6 -0
  9. package/lib/commands/generate/generateForm/formField/findIntrospectionFieldType.js +22 -0
  10. package/lib/commands/generate/generateForm/formField/options.d.ts +1 -5
  11. package/lib/commands/generate/generateForm/formField/options.js +2 -11
  12. package/lib/commands/generate/generateForm/generateComponentFormField.js +0 -1
  13. package/lib/commands/generate/generateForm/generateFields.d.ts +9 -4
  14. package/lib/commands/generate/generateForm/generateFields.js +0 -3
  15. package/lib/commands/generate/generateForm/generateForm.js +99 -132
  16. package/lib/commands/generate/generateForm/generateFormField.js +34 -44
  17. package/lib/commands/generate/generateForm/generateFormLayout.js +23 -44
  18. package/lib/commands/generate/generateForm/generateFormValues.d.ts +39 -0
  19. package/lib/commands/generate/generateForm/generateFormValues.js +217 -0
  20. package/lib/commands/generate/generateForm/generateFragmentByFormFragmentFields.d.ts +1 -1
  21. package/lib/commands/generate/generateForm/generateFragmentByFormFragmentFields.js +3 -36
  22. package/lib/commands/generate/generateForm/getForwardedGqlArgs.d.ts +4 -5
  23. package/lib/commands/generate/generateForm/getForwardedGqlArgs.js +18 -17
  24. package/lib/commands/generate/generateGrid/generateGrid.js +49 -35
  25. package/lib/commands/generate/generateGrid/getForwardedGqlArgs.d.ts +3 -3
  26. package/lib/commands/generate/generateGrid/getForwardedGqlArgs.js +12 -16
  27. package/lib/commands/generate/generateGrid/usableFields.d.ts +6 -1
  28. package/lib/commands/generate/utils/convertConfigImport.d.ts +1 -0
  29. package/lib/commands/generate/utils/convertConfigImport.js +1 -1
  30. package/lib/commands/generate/utils/generateGqlOperation.d.ts +12 -0
  31. package/lib/commands/generate/utils/generateGqlOperation.js +87 -0
  32. package/lib/commands/generate/utils/generateImportsCode.d.ts +1 -0
  33. package/lib/commands/generate/utils/generateImportsCode.js +6 -1
  34. package/lib/index.d.ts +2 -2
  35. package/lib/index.js +2 -1
  36. package/package.json +11 -8
@@ -0,0 +1,39 @@
1
+ import { type IntrospectionQuery } from "graphql";
2
+ import { type GenerateFieldsReturn } from "./generateFields";
3
+ type FormValuesConfigTreeNode = {
4
+ config?: GenerateFieldsReturn["formValuesConfig"][0];
5
+ nullable?: boolean;
6
+ children: FormValuesConfigTree;
7
+ };
8
+ type FormValuesConfigTree = {
9
+ [key: string]: FormValuesConfigTreeNode;
10
+ };
11
+ export declare function formValuesConfigToTree({ formValuesConfig, gqlIntrospection, gqlType, }: {
12
+ formValuesConfig: GenerateFieldsReturn["formValuesConfig"];
13
+ gqlIntrospection: IntrospectionQuery;
14
+ gqlType: string;
15
+ }): FormValuesConfigTree;
16
+ export declare function generateFormValuesType({ formValuesConfig, filterByFragmentType, gqlIntrospection, gqlType, }: {
17
+ formValuesConfig: GenerateFieldsReturn["formValuesConfig"];
18
+ filterByFragmentType: string;
19
+ gqlIntrospection: IntrospectionQuery;
20
+ gqlType: string;
21
+ }): string;
22
+ export declare function generateInitialValues({ mode, formValuesConfig, filterByFragmentType, gqlIntrospection, gqlType, }: {
23
+ mode: "all" | "edit" | "add";
24
+ formValuesConfig: GenerateFieldsReturn["formValuesConfig"];
25
+ filterByFragmentType: string;
26
+ gqlIntrospection: IntrospectionQuery;
27
+ gqlType: string;
28
+ }): string;
29
+ export declare function generateDestructFormValueForInput({ formValuesConfig, gqlIntrospection, gqlType, }: {
30
+ formValuesConfig: GenerateFieldsReturn["formValuesConfig"];
31
+ gqlIntrospection: IntrospectionQuery;
32
+ gqlType: string;
33
+ }): string;
34
+ export declare function generateFormValuesToGqlInput({ formValuesConfig, gqlIntrospection, gqlType, }: {
35
+ formValuesConfig: GenerateFieldsReturn["formValuesConfig"];
36
+ gqlIntrospection: IntrospectionQuery;
37
+ gqlType: string;
38
+ }): string;
39
+ export {};
@@ -0,0 +1,217 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.formValuesConfigToTree = formValuesConfigToTree;
4
+ exports.generateFormValuesType = generateFormValuesType;
5
+ exports.generateInitialValues = generateInitialValues;
6
+ exports.generateDestructFormValueForInput = generateDestructFormValueForInput;
7
+ exports.generateFormValuesToGqlInput = generateFormValuesToGqlInput;
8
+ // internal represenstation of formValuesConfig as tree to allow recursive processing
9
+ function formValuesConfigToTree({ formValuesConfig, gqlIntrospection, gqlType, }) {
10
+ const treeRoot = { children: {} };
11
+ for (const formValueConfig of formValuesConfig) {
12
+ const fieldName = formValueConfig.fieldName;
13
+ let currentTreeNode = treeRoot;
14
+ let currentGqlType = gqlType;
15
+ for (const part of fieldName.split(".")) {
16
+ const introspectionObject = gqlIntrospection.__schema.types.find((type) => type.kind === "OBJECT" && type.name === currentGqlType);
17
+ if (!introspectionObject)
18
+ throw new Error(`didn't find object ${gqlType} in gql introspection`);
19
+ const introspectionField = introspectionObject.fields.find((field) => field.name === part);
20
+ const introspectionFieldType = introspectionField
21
+ ? introspectionField.type.kind === "NON_NULL"
22
+ ? introspectionField.type.ofType
23
+ : introspectionField.type
24
+ : undefined;
25
+ if ((introspectionFieldType === null || introspectionFieldType === void 0 ? void 0 : introspectionFieldType.kind) === "OBJECT") {
26
+ // for next loop iteration (nested fields)
27
+ currentGqlType = introspectionFieldType.name;
28
+ }
29
+ if (!currentTreeNode.children[part]) {
30
+ currentTreeNode.children[part] = { children: {} };
31
+ }
32
+ currentTreeNode.children[part].nullable = (introspectionField === null || introspectionField === void 0 ? void 0 : introspectionField.type.kind) !== "NON_NULL";
33
+ currentTreeNode = currentTreeNode.children[part];
34
+ }
35
+ currentTreeNode.config = formValueConfig;
36
+ }
37
+ return treeRoot.children;
38
+ }
39
+ function generateFormValuesTypeFromTree(tree, currentTypeName, currentIsNullable) {
40
+ var _a, _b, _c;
41
+ const omitKeys = [];
42
+ let appendCode = "";
43
+ for (const [key, value] of Object.entries(tree)) {
44
+ if (Object.keys(value.children).length > 0) {
45
+ let childRootType = `${currentTypeName}["${key}"]`;
46
+ if (currentIsNullable) {
47
+ childRootType = `NonNullable<${currentTypeName}>["${key}"]`;
48
+ }
49
+ const childOmit = generateFormValuesTypeFromTree(value.children, childRootType, (_a = value.nullable) !== null && _a !== void 0 ? _a : false);
50
+ if (childOmit !== childRootType) {
51
+ appendCode += `${key}: ${childOmit}`;
52
+ omitKeys.push(key);
53
+ }
54
+ if ((_b = value.config) === null || _b === void 0 ? void 0 : _b.typeCode) {
55
+ throw new Error("Field has both subfields and direct typeCode, which is not supported.");
56
+ }
57
+ if ((_c = value.config) === null || _c === void 0 ? void 0 : _c.omitFromFragmentType) {
58
+ throw new Error("Field has both subfields and direct omitFromFragmentType, which is not supported.");
59
+ }
60
+ }
61
+ else if (value.config) {
62
+ if (value.config.typeCode) {
63
+ appendCode += `${key}${value.config.typeCode.nullable ? "?" : ""}: ${value.config.typeCode.type}; `;
64
+ }
65
+ if (value.config.omitFromFragmentType) {
66
+ omitKeys.push(key);
67
+ }
68
+ }
69
+ }
70
+ let code = omitKeys.length
71
+ ? `Omit<${currentIsNullable ? `NonNullable<` : ""}${currentTypeName}${currentIsNullable ? `>` : ""}, ${omitKeys.map((k) => `"${k}"`).join(" | ")}>`
72
+ : currentTypeName;
73
+ if (appendCode.length) {
74
+ code += ` & { ${appendCode} }`;
75
+ }
76
+ return code;
77
+ }
78
+ function generateFormValuesType({ formValuesConfig, filterByFragmentType, gqlIntrospection, gqlType, }) {
79
+ const tree = formValuesConfigToTree({ formValuesConfig, gqlIntrospection, gqlType });
80
+ return `type FormValues = ${generateFormValuesTypeFromTree(tree, filterByFragmentType, false)};`;
81
+ }
82
+ function generateInitialValuesFromTree(tree, dataObject, generationType) {
83
+ var _a;
84
+ let code = "";
85
+ for (const [key, value] of Object.entries(tree)) {
86
+ if (Object.keys(value.children).length > 0) {
87
+ let childCode = generateInitialValuesFromTree(value.children, `${dataObject}.${key}`, generationType);
88
+ if (childCode.length) {
89
+ if (generationType == "initializationCode") {
90
+ childCode = `{ ...${dataObject}.${key}, ${childCode} }`;
91
+ if (value.nullable) {
92
+ code += `${key}: ${dataObject}.${key} ? ${childCode} : undefined, `;
93
+ }
94
+ else {
95
+ code += `${key}: ${childCode}, `;
96
+ }
97
+ }
98
+ else {
99
+ code += `${key}: { ${childCode} }, `;
100
+ }
101
+ }
102
+ if ((_a = value.config) === null || _a === void 0 ? void 0 : _a[generationType]) {
103
+ throw new Error("Field has both subfields and direct initialization code, which is not supported.");
104
+ }
105
+ }
106
+ else if (value.config) {
107
+ if (value.config[generationType]) {
108
+ code += `${key}: ${value.config[generationType]}, `;
109
+ }
110
+ }
111
+ }
112
+ return code;
113
+ }
114
+ function generateInitialValues({ mode, formValuesConfig, filterByFragmentType, gqlIntrospection, gqlType, }) {
115
+ const instanceGqlType = gqlType[0].toLowerCase() + gqlType.substring(1);
116
+ const editMode = mode === "edit" || mode == "all";
117
+ const tree = formValuesConfigToTree({ formValuesConfig, gqlIntrospection, gqlType });
118
+ if (editMode) {
119
+ return `const initialValues = useMemo<Partial<FormValues>>(() => data?.${instanceGqlType}
120
+ ? {
121
+ ...filterByFragment<${filterByFragmentType}>(${instanceGqlType}FormFragment, data.${instanceGqlType}),
122
+ ${generateInitialValuesFromTree(tree, `data.${instanceGqlType}`, "initializationCode")}
123
+ }
124
+ : {
125
+ ${generateInitialValuesFromTree(tree, `data.${instanceGqlType}`, "defaultInitializationCode")}
126
+ }
127
+ , [data]);`;
128
+ }
129
+ else {
130
+ return `const initialValues = {
131
+ ${generateInitialValuesFromTree(tree, `data.${instanceGqlType}`, "defaultInitializationCode")}
132
+ };`;
133
+ }
134
+ }
135
+ function generateDestructFormValueForInputFromTree(tree, restObject) {
136
+ let code = "";
137
+ for (const [key, value] of Object.entries(tree)) {
138
+ if (Object.keys(value.children).length > 0) {
139
+ const childCode = generateDestructFormValueForInputFromTree(value.children, `${restObject}${key.substring(0, 1).toUpperCase()}${key.substring(1)}`);
140
+ if (childCode.length) {
141
+ code += `${key}: { ${childCode} }, `;
142
+ }
143
+ }
144
+ else if (value.config) {
145
+ if (value.config.destructFromFormValues) {
146
+ code += `${key}, `;
147
+ }
148
+ }
149
+ }
150
+ if (code.length) {
151
+ code += `...${restObject}Rest`;
152
+ return code;
153
+ }
154
+ else {
155
+ return "";
156
+ }
157
+ }
158
+ function generateDestructFormValueForInput({ formValuesConfig, gqlIntrospection, gqlType, }) {
159
+ const tree = formValuesConfigToTree({ formValuesConfig, gqlIntrospection, gqlType });
160
+ const code = generateDestructFormValueForInputFromTree(tree, "formValues");
161
+ return code.length ? `{ ${code} }` : "formValues";
162
+ }
163
+ function generateFormValuesToGqlInputFromTree(tree, dataObject, restObject) {
164
+ var _a, _b;
165
+ let code = "";
166
+ for (const [key, value] of Object.entries(tree)) {
167
+ if (Object.keys(value.children).length > 0) {
168
+ const childRestObject = `${restObject.replace(/Rest$/, "")}${key.substring(0, 1).toUpperCase()}${key.substring(1)}Rest`;
169
+ const hasChildDestruct = hasChildDestructTree(value.children);
170
+ let childCode = generateFormValuesToGqlInputFromTree(value.children, hasChildDestruct ? childRestObject : `${dataObject}.${key}`, childRestObject);
171
+ if (childCode.length || hasChildDestruct) {
172
+ childCode = `{ ...${hasChildDestruct ? childRestObject : `${dataObject}.${key}`}, ${childCode} }`;
173
+ if ((_a = value.config) === null || _a === void 0 ? void 0 : _a.wrapFormValueToGqlInputCode) {
174
+ childCode = value.config.wrapFormValueToGqlInputCode
175
+ .replaceAll("$fieldName", `${dataObject}.${key}`)
176
+ .replaceAll("$inner", childCode);
177
+ }
178
+ code += `${key}: ${childCode}, `;
179
+ }
180
+ if ((_b = value.config) === null || _b === void 0 ? void 0 : _b.formValueToGqlInputCode) {
181
+ throw new Error("Field has both subfields and direct formValueToGqlInputCode, which is not supported.");
182
+ }
183
+ }
184
+ else if (value.config) {
185
+ if (value.config.formValueToGqlInputCode) {
186
+ code += `${key}: ${value.config.formValueToGqlInputCode.replaceAll("$fieldName", `${dataObject}.${key}`)}, `;
187
+ }
188
+ }
189
+ }
190
+ return code;
191
+ }
192
+ function hasChildDestructTree(tree) {
193
+ return Object.values(tree).some((childValue) => {
194
+ var _a;
195
+ if ((_a = childValue.config) === null || _a === void 0 ? void 0 : _a.destructFromFormValues) {
196
+ return true;
197
+ }
198
+ if (Object.keys(childValue.children).length > 0) {
199
+ return hasChildDestructTree(childValue.children);
200
+ }
201
+ return false;
202
+ });
203
+ }
204
+ function generateFormValuesToGqlInput({ formValuesConfig, gqlIntrospection, gqlType, }) {
205
+ const tree = formValuesConfigToTree({ formValuesConfig, gqlIntrospection, gqlType });
206
+ const hasChildDestruct = hasChildDestructTree(tree);
207
+ const code = generateFormValuesToGqlInputFromTree(tree, hasChildDestruct ? "formValuesRest" : "formValues", hasChildDestruct ? "formValuesRest" : "formValues");
208
+ if (code.length) {
209
+ return `const output = { ...${hasChildDestruct ? "formValuesRest" : "formValues"}, ${code} };`;
210
+ }
211
+ else if (hasChildDestruct) {
212
+ return `const output = formValuesRest;`;
213
+ }
214
+ else {
215
+ return `const output = formValues;`;
216
+ }
217
+ }
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Helper function that generates a GraphQL fragment from form fragment fields (array of dot.separated.fields).
3
3
  *
4
- * - Fragments are supported as "foo { ...FragmentName }"
4
+ * - Fragments are supported as "foo...FragmentName"
5
5
  * - for FinalFormFileUpload and FinalFormFileUploadDownloadable the needed variable is added automatically
6
6
  */
7
7
  export declare function generateFragmentByFormFragmentFields({ formFragmentName, gqlType, formFragmentFields, }: {
@@ -1,50 +1,17 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.generateFragmentByFormFragmentFields = generateFragmentByFormFragmentFields;
7
- const object_path_1 = __importDefault(require("object-path"));
4
+ const generateGqlOperation_1 = require("../utils/generateGqlOperation");
8
5
  /**
9
6
  * Helper function that generates a GraphQL fragment from form fragment fields (array of dot.separated.fields).
10
7
  *
11
- * - Fragments are supported as "foo { ...FragmentName }"
8
+ * - Fragments are supported as "foo...FragmentName"
12
9
  * - for FinalFormFileUpload and FinalFormFileUploadDownloadable the needed variable is added automatically
13
10
  */
14
11
  function generateFragmentByFormFragmentFields({ formFragmentName, gqlType, formFragmentFields, }) {
15
- // 1. create tree out of dot separated fields
16
- const fieldsObject = formFragmentFields.reduce((acc, field) => {
17
- const fragmentMatch = field.match(/(.*)({.*?})/); // keep { ... } parts as they are, contains eg. fragments
18
- if (fragmentMatch) {
19
- object_path_1.default.set(acc, fragmentMatch[1].trim(), fragmentMatch[2]);
20
- }
21
- else {
22
- object_path_1.default.set(acc, field, true);
23
- }
24
- return acc;
25
- }, {});
26
- // 2. create fragment string out of tree
27
- const recursiveStringify = (obj) => {
28
- let ret = "";
29
- let prefixField = "";
30
- for (const key in obj) {
31
- const value = obj[key];
32
- if (typeof value === "boolean") {
33
- ret += `${prefixField}${key}`;
34
- }
35
- else if (typeof value === "string") {
36
- ret += `${prefixField}${key} ${value}`;
37
- }
38
- else {
39
- ret += `${prefixField}${key} { ${recursiveStringify(value)} }`;
40
- }
41
- prefixField = " ";
42
- }
43
- return ret;
44
- };
45
12
  let fragmentCode = `
46
13
  fragment ${formFragmentName} on ${gqlType} {
47
- ${recursiveStringify(fieldsObject)}
14
+ ${(0, generateGqlOperation_1.generateGqlQueryTreeFromFields)(formFragmentFields)}
48
15
  }
49
16
  `;
50
17
  // 3. add fragment instance variables when fragments are used
@@ -2,7 +2,7 @@ import { type IntrospectionField, type IntrospectionQuery } from "graphql";
2
2
  import { type FormFieldConfig } from "../generate-command";
3
3
  import { type Imports } from "../utils/generateImportsCode";
4
4
  import { type Prop } from "./generateForm";
5
- type GqlArg = {
5
+ export type GqlArg = {
6
6
  type: string;
7
7
  name: string;
8
8
  isInputArgSubfield: boolean;
@@ -13,7 +13,6 @@ export declare function getForwardedGqlArgs({ fields, gqlOperation, gqlIntrospec
13
13
  gqlIntrospection: IntrospectionQuery;
14
14
  }): {
15
15
  imports: Imports;
16
- props: Prop[];
17
- gqlArgs: GqlArg[];
18
- };
19
- export {};
16
+ prop: Prop;
17
+ gqlArg: GqlArg;
18
+ }[];
@@ -2,36 +2,37 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getForwardedGqlArgs = getForwardedGqlArgs;
4
4
  function getForwardedGqlArgs({ fields, gqlOperation, gqlIntrospection, }) {
5
- const imports = [];
6
- const props = [];
7
- const gqlArgs = [];
8
- const skipGqlInputArgFields = fields.map((field) => String(field.name));
5
+ const ret = [];
9
6
  getArgsIncludingInputArgSubfields(gqlOperation, gqlIntrospection).forEach((arg) => {
10
- if (arg.isInputArgSubfield && skipGqlInputArgFields.includes(arg.name))
11
- return;
7
+ if (arg.isInputArgSubfield) {
8
+ if (fields.some((field) => {
9
+ return field.name === arg.name || field.name.startsWith(`${arg.name}.`);
10
+ })) {
11
+ // there is a field (or subfield) in this form, no need to forward this arg
12
+ return;
13
+ }
14
+ }
15
+ let prop;
16
+ const imports = [];
12
17
  if (arg.type === "ID" || arg.type === "String" || arg.type === "DateTime") {
13
- props.push({ name: arg.name, optional: false, type: "string" });
18
+ prop = { name: arg.name, optional: false, type: "string" };
14
19
  }
15
20
  else if (arg.type === "Boolean") {
16
- props.push({ name: arg.name, optional: false, type: "boolean" });
21
+ prop = { name: arg.name, optional: false, type: "boolean" };
17
22
  }
18
23
  else if (arg.type === "Int" || arg.type === "Float") {
19
- props.push({ name: arg.name, optional: false, type: "number" });
24
+ prop = { name: arg.name, optional: false, type: "number" };
20
25
  }
21
26
  else if (arg.type === "JSONObject") {
22
- props.push({ name: arg.name, optional: false, type: "unknown" });
27
+ prop = { name: arg.name, optional: false, type: "unknown" };
23
28
  }
24
29
  else {
25
- props.push({ name: arg.name, optional: false, type: `GQL${arg.type}` }); // generated types contain GQL prefix
30
+ prop = { name: arg.name, optional: false, type: `GQL${arg.type}` }; // generated types contain GQL prefix
26
31
  imports.push({ name: `GQL${arg.type}`, importPath: "@src/graphql.generated" });
27
32
  }
28
- gqlArgs.push({ name: arg.name, type: arg.type, isInputArgSubfield: arg.isInputArgSubfield });
33
+ ret.push({ gqlArg: arg, prop, imports });
29
34
  });
30
- return {
31
- imports,
32
- props,
33
- gqlArgs,
34
- };
35
+ return ret;
35
36
  }
36
37
  function getArgsIncludingInputArgSubfields(gqlOperation, gqlIntrospection) {
37
38
  const nativeScalars = ["ID", "String", "Boolean", "Int", "Float", "DateTime", "JSONObject"];
@@ -18,6 +18,7 @@ const convertConfigImport_1 = require("../utils/convertConfigImport");
18
18
  const findMutationType_1 = require("../utils/findMutationType");
19
19
  const findQueryType_1 = require("../utils/findQueryType");
20
20
  const findRootBlocks_1 = require("../utils/findRootBlocks");
21
+ const generateGqlOperation_1 = require("../utils/generateGqlOperation");
21
22
  const generateImportsCode_1 = require("../utils/generateImportsCode");
22
23
  const runtimeTypeGuards_1 = require("../utils/runtimeTypeGuards");
23
24
  const findInputObjectType_1 = require("./findInputObjectType");
@@ -160,7 +161,6 @@ function generateGrid({ exportName, baseOutputFilename, targetDirectory, gqlIntr
160
161
  { name: "useDataGridRemote", importPath: "@comet/admin" },
161
162
  { name: "usePersistentColumnState", importPath: "@comet/admin" },
162
163
  { name: "BlockPreviewContent", importPath: "@comet/cms-admin" },
163
- { name: "useContentScope", importPath: "@comet/cms-admin" },
164
164
  { name: "Alert", importPath: "@mui/material" },
165
165
  { name: "Box", importPath: "@mui/material" },
166
166
  { name: "IconButton", importPath: "@mui/material" },
@@ -179,6 +179,7 @@ function generateGrid({ exportName, baseOutputFilename, targetDirectory, gqlIntr
179
179
  { name: "GridColumnHeaderTitle", importPath: "@mui/x-data-grid-pro" },
180
180
  { name: "GridToolbarQuickFilter", importPath: "@mui/x-data-grid-pro" },
181
181
  { name: "GridRowOrderChangeParams", importPath: "@mui/x-data-grid-pro" },
182
+ { name: "useMemo", importPath: "react" },
182
183
  ];
183
184
  const iconsToImport = ["Add", "Edit", "Info", "Excel"];
184
185
  const props = [];
@@ -229,9 +230,24 @@ function generateGrid({ exportName, baseOutputFilename, targetDirectory, gqlIntr
229
230
  const showCrudContextMenuInActionsColumn = allowDeleting;
230
231
  const showEditInActionsColumn = allowEditing && !forwardRowAction;
231
232
  const defaultActionsColumnWidth = getDefaultActionsColumnWidth(showCrudContextMenuInActionsColumn, showEditInActionsColumn);
232
- const { imports: forwardedGqlArgsImports, props: forwardedGqlArgsProps, gqlArgs } = (0, getForwardedGqlArgs_1.getForwardedGqlArgs)([gridQueryType]);
233
- imports.push(...forwardedGqlArgsImports);
234
- props.push(...forwardedGqlArgsProps);
233
+ let useScopeFromContext = false;
234
+ const gqlArgs = [];
235
+ {
236
+ const forwardedArgs = (0, getForwardedGqlArgs_1.getForwardedGqlArgs)([gridQueryType]);
237
+ for (const forwardedArg of forwardedArgs) {
238
+ imports.push(...forwardedArg.imports);
239
+ if (forwardedArg.gqlArg.name === "scope" && !config.scopeAsProp) {
240
+ useScopeFromContext = true;
241
+ }
242
+ else {
243
+ props.push(forwardedArg.prop);
244
+ gqlArgs.push(forwardedArg.gqlArg);
245
+ }
246
+ }
247
+ }
248
+ if (useScopeFromContext) {
249
+ imports.push({ name: "useContentScope", importPath: "@comet/cms-admin" });
250
+ }
235
251
  const renderToolbar = (_f = config.toolbar) !== null && _f !== void 0 ? _f : true;
236
252
  const filterArg = gridQueryType.args.find((arg) => arg.name === "filter");
237
253
  const hasFilter = !!filterArg && renderToolbar && !allowRowReordering;
@@ -285,7 +301,6 @@ function generateGrid({ exportName, baseOutputFilename, targetDirectory, gqlIntr
285
301
  }
286
302
  }
287
303
  const hasSearch = gridQueryType.args.some((arg) => arg.name === "search") && !allowRowReordering;
288
- const hasScope = gridQueryType.args.some((arg) => arg.name === "scope");
289
304
  const schemaEntity = gqlIntrospection.__schema.types.find((type) => type.kind === "OBJECT" && type.name === gqlType);
290
305
  if (!schemaEntity)
291
306
  throw new Error("didn't find entity in schema types");
@@ -489,7 +504,7 @@ function generateGrid({ exportName, baseOutputFilename, targetDirectory, gqlIntr
489
504
  if (forwardRowAction) {
490
505
  props.push({
491
506
  name: "rowAction",
492
- type: `(params: GridRenderCellParams<any, GQL${fragmentName}Fragment, any>) => ReactNode`,
507
+ type: `(params: GridRenderCellParams<GQL${fragmentName}Fragment>) => ReactNode`,
493
508
  optional: true,
494
509
  });
495
510
  props.push({
@@ -555,31 +570,30 @@ function generateGrid({ exportName, baseOutputFilename, targetDirectory, gqlIntr
555
570
  }
556
571
  \`;
557
572
 
558
- const ${instanceGqlTypePlural}Query = gql\`
559
- query ${gqlTypePlural}Grid(${[
560
- ...gqlArgs.filter((gqlArg) => gqlArg.queryOrMutationName === gridQueryType.name).map((gqlArg) => `$${gqlArg.name}: ${gqlArg.type}!`),
561
- ...[`$offset: Int!`, `$limit: Int!`],
562
- ...(hasSort ? [`$sort: [${gqlType}Sort!]`] : []),
563
- ...(hasSearch ? [`$search: String`] : []),
564
- ...(filterArg && (hasFilter || hasFilterProp) ? [`$filter: ${gqlType}Filter`] : []),
565
- ...(hasScope ? [`$scope: ${gqlType}ContentScopeInput!`] : []),
566
- ].join(", ")}) {
567
- ${gridQuery}(${[
568
- ...gqlArgs.filter((gqlArg) => gqlArg.queryOrMutationName === gridQueryType.name).map((gqlArg) => `${gqlArg.name}: $${gqlArg.name}`),
569
- ...[`offset: $offset`, `limit: $limit`],
570
- ...(hasSort ? [`sort: $sort`] : []),
571
- ...(hasSearch ? [`search: $search`] : []),
572
- ...(filterArg && (hasFilter || hasFilterProp) ? [`filter: $filter`] : []),
573
- ...(hasScope ? [`scope: $scope`] : []),
574
- ].join(", ")}) {
575
- nodes {
576
- ...${fragmentName}
577
- }
578
- totalCount
579
- }
580
- }
581
- \${${instanceGqlTypePlural}Fragment}
582
- \`;
573
+ const ${instanceGqlTypePlural}Query = gql\`${(0, generateGqlOperation_1.generateGqlOperation)({
574
+ type: "query",
575
+ operationName: `${gqlTypePlural}Grid`,
576
+ rootOperation: gridQuery,
577
+ fields: [`nodes...${fragmentName}`, "totalCount"],
578
+ fragmentVariables: [`\${${instanceGqlTypePlural}Fragment}`],
579
+ variables: [
580
+ ...gqlArgs
581
+ .filter((gqlArg) => gqlArg.queryOrMutationName === gridQueryType.name)
582
+ .map((gqlArg) => ({ name: gqlArg.name, type: `${gqlArg.type}!` })),
583
+ {
584
+ name: "offset",
585
+ type: "Int!",
586
+ },
587
+ {
588
+ name: "limit",
589
+ type: "Int!",
590
+ },
591
+ ...(hasSort ? [{ name: "sort", type: `[${gqlType}Sort!]` }] : []),
592
+ ...(hasSearch ? [{ name: "search", type: "String" }] : []),
593
+ ...(filterArg && (hasFilter || hasFilterProp) ? [{ name: "filter", type: `${gqlType}Filter` }] : []),
594
+ ...(useScopeFromContext ? [{ name: "scope", type: `${gqlType}ContentScopeInput!` }] : []),
595
+ ],
596
+ })}\`;
583
597
 
584
598
  ${allowRowReordering
585
599
  ? `const update${gqlType}PositionMutation = gql\`
@@ -627,12 +641,12 @@ function generateGrid({ exportName, baseOutputFilename, targetDirectory, gqlIntr
627
641
  : config.selectionProps === "singleSelect"
628
642
  ? `, rowSelectionModel, onRowSelectionModelChange, checkboxSelection: false, keepNonExistentRowsSelected: false, disableRowSelectionOnClick: false`
629
643
  : ``} };
630
- ${hasScope ? `const { scope } = useContentScope();` : ""}
644
+ ${useScopeFromContext ? `const { scope } = useContentScope();` : ""}
631
645
  ${gridNeedsTheme ? `const theme = useTheme();` : ""}
632
646
 
633
647
  ${generateHandleRowOrderChange(allowRowReordering, gqlType, instanceGqlTypePlural)}
634
648
 
635
- const columns: GridColDef<GQL${fragmentName}Fragment>[] = [
649
+ const columns: GridColDef<GQL${fragmentName}Fragment>[] = useMemo(()=>[
636
650
  ${gridColumnFields
637
651
  .map((column) => {
638
652
  const defaultMinWidth = 150;
@@ -727,7 +741,7 @@ function generateGrid({ exportName, baseOutputFilename, targetDirectory, gqlIntr
727
741
  );
728
742
  }` }))
729
743
  : ""}
730
- ];
744
+ ],[intl${gridNeedsTheme ? ", theme" : ""}${showCrudContextMenuInActionsColumn ? ", client" : ""}${forwardRowAction ? ", rowAction, actionsColumnWidth" : ""}]);
731
745
 
732
746
  ${hasFilter || hasSearch
733
747
  ? `const { ${hasFilter ? `filter: gqlFilter, ` : ""}${hasSearch ? `search: gqlSearch, ` : ""} } = muiGridFilterToGql(columns, dataGridProps.filterModel);`
@@ -737,7 +751,7 @@ function generateGrid({ exportName, baseOutputFilename, targetDirectory, gqlIntr
737
751
  variables: {
738
752
  ${[
739
753
  ...gqlArgs.filter((gqlArg) => gqlArg.queryOrMutationName === gridQueryType.name).map((arg) => arg.name),
740
- ...(hasScope ? ["scope"] : []),
754
+ ...(useScopeFromContext ? ["scope"] : []),
741
755
  ...(filterArg
742
756
  ? hasFilter && hasFilterProp
743
757
  ? ["filter: filter ? { and: [gqlFilter, filter] } : gqlFilter"]
@@ -8,6 +8,6 @@ export type GqlArg = {
8
8
  };
9
9
  export declare function getForwardedGqlArgs(gqlFields: IntrospectionField[]): {
10
10
  imports: Imports;
11
- props: Prop[];
12
- gqlArgs: GqlArg[];
13
- };
11
+ prop: Prop;
12
+ gqlArg: GqlArg;
13
+ }[];
@@ -2,34 +2,30 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getForwardedGqlArgs = getForwardedGqlArgs;
4
4
  function getForwardedGqlArgs(gqlFields) {
5
- const supportedGqlArgs = ["offset", "limit", "sort", "search", "filter", "scope", "input"]; // this arguments need to be handled differently or are already handled somewhere else
6
- const imports = [];
7
- const props = [];
8
- const gqlArgs = [];
5
+ const ret = [];
6
+ const supportedGqlArgs = ["offset", "limit", "sort", "search", "filter", "input"]; // this arguments need to be handled differently or are already handled somewhere else
9
7
  getArgs(gqlFields, supportedGqlArgs).forEach((arg) => {
8
+ let prop;
9
+ const imports = [];
10
10
  if (arg.type === "ID" || arg.type === "String" || arg.type === "DateTime") {
11
- props.push({ name: arg.name, optional: false, type: "string" });
11
+ prop = { name: arg.name, optional: false, type: "string" };
12
12
  }
13
13
  else if (arg.type === "Boolean") {
14
- props.push({ name: arg.name, optional: false, type: "boolean" });
14
+ prop = { name: arg.name, optional: false, type: "boolean" };
15
15
  }
16
16
  else if (arg.type === "Int" || arg.type === "Float") {
17
- props.push({ name: arg.name, optional: false, type: "number" });
17
+ prop = { name: arg.name, optional: false, type: "number" };
18
18
  }
19
19
  else if (arg.type === "JSONObject") {
20
- props.push({ name: arg.name, optional: false, type: "unknown" });
20
+ prop = { name: arg.name, optional: false, type: "unknown" };
21
21
  }
22
22
  else {
23
- props.push({ name: arg.name, optional: false, type: arg.type });
24
- imports.push({ name: arg.type, importPath: "@src/graphql.generated" });
23
+ prop = { name: arg.name, optional: false, type: `GQL${arg.type}` }; // generated types contain GQL prefix
24
+ imports.push({ name: `GQL${arg.type}`, importPath: "@src/graphql.generated" });
25
25
  }
26
- gqlArgs.push({ name: arg.name, type: arg.type, queryOrMutationName: arg.gqlField.name });
26
+ ret.push({ gqlArg: { name: arg.name, type: arg.type, queryOrMutationName: arg.gqlField.name }, prop, imports });
27
27
  });
28
- return {
29
- imports,
30
- props,
31
- gqlArgs,
32
- };
28
+ return ret;
33
29
  }
34
30
  function getArgs(gqlFields, skipGqlArgs) {
35
31
  return gqlFields.reduce((acc, gqlField) => {
@@ -2,8 +2,13 @@ type Prev = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
2
2
  type GqlLeaves<T, FollowArrays extends boolean = false, Depth extends number = 5> = [Depth] extends [never] ? never : T extends any ? T extends Array<infer ArrayType> ? FollowArrays extends true ? GqlLeaves<ArrayType, FollowArrays, Prev[Depth]> : never : "__typename" extends keyof T ? {
3
3
  [K in keyof T as K extends "__typename" ? never : K]-?: GqlLeaves<T[K], FollowArrays, Prev[Depth]>;
4
4
  } : never : never;
5
+ type IfExplicitAny<T, Y, N> = T extends never ? Y : N;
5
6
  type FieldNames<T> = {
6
7
  [K in keyof T]: `${Exclude<K, symbol>}${FieldNames<T[K]> extends never ? "" : `.${FieldNames<T[K]>}`}`;
7
8
  }[keyof T];
8
- export type UsableFields<T, FollowArrays extends boolean = false> = FieldNames<GqlLeaves<T, FollowArrays>>;
9
+ export type UsableFields<T, FollowArrays extends boolean = false> = IfExplicitAny<T, any, FieldNames<GqlLeaves<T, FollowArrays>>>;
10
+ type FormFieldNames<T> = {
11
+ [K in keyof T]: `${Exclude<K, symbol>}` | (FormFieldNames<T[K]> extends never ? never : `${Exclude<K, symbol>}.${FormFieldNames<T[K]>}`);
12
+ }[keyof T];
13
+ export type UsableFormFields<T> = IfExplicitAny<T, any, FormFieldNames<GqlLeaves<T, false>>>;
9
14
  export {};
@@ -2,4 +2,5 @@ import { type Imports } from "./generateImportsCode";
2
2
  export declare function convertConfigImport(imprt: {
3
3
  name: string;
4
4
  import: string;
5
+ defaultImport?: boolean;
5
6
  }): Imports[0];
@@ -10,5 +10,5 @@ function convertConfigImport(imprt) {
10
10
  else if (importPath.startsWith("./")) {
11
11
  importPath = `.${importPath}`;
12
12
  }
13
- return { name: imprt.name, importPath };
13
+ return { name: imprt.name, importPath, defaultImport: imprt.defaultImport };
14
14
  }