@webiny/api-headless-cms 6.0.0-rc.2 → 6.0.0-rc.4

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 (96) hide show
  1. package/crud/contentEntry/searchableFields.js +6 -2
  2. package/crud/contentEntry/searchableFields.js.map +1 -1
  3. package/crud/contentModel/validation.d.ts +9 -9
  4. package/crud/contentModel/validation.js +3 -3
  5. package/crud/contentModel/validation.js.map +1 -1
  6. package/domain/contentModel/errors.d.ts +1 -1
  7. package/domain/contentModel/errors.js.map +1 -1
  8. package/domain/contentModel/schemas.d.ts +126 -8
  9. package/domain/contentModel/schemas.js +12 -13
  10. package/domain/contentModel/schemas.js.map +1 -1
  11. package/export/graphql/index.js +1 -1
  12. package/export/graphql/index.js.map +1 -1
  13. package/features/contentEntry/GetUniqueFieldValues/GetUniqueFieldValuesUseCase.d.ts +2 -2
  14. package/features/contentEntry/GetUniqueFieldValues/GetUniqueFieldValuesUseCase.js +3 -4
  15. package/features/contentEntry/GetUniqueFieldValues/GetUniqueFieldValuesUseCase.js.map +1 -1
  16. package/features/contentModel/CreateModel/CreateModelRepository.js +4 -1
  17. package/features/contentModel/CreateModel/CreateModelRepository.js.map +1 -1
  18. package/features/contentModel/CreateModelFrom/CreateModelFromRepository.js +12 -3
  19. package/features/contentModel/CreateModelFrom/CreateModelFromRepository.js.map +1 -1
  20. package/features/contentModel/UpdateModel/UpdateModelRepository.js +8 -2
  21. package/features/contentModel/UpdateModel/UpdateModelRepository.js.map +1 -1
  22. package/features/contentModel/UpdateModel/UpdateModelUseCase.js +4 -1
  23. package/features/contentModel/UpdateModel/UpdateModelUseCase.js.map +1 -1
  24. package/features/modelBuilder/feature.js +2 -2
  25. package/features/modelBuilder/feature.js.map +1 -1
  26. package/features/modelBuilder/fields/BaseFieldBuilder.d.ts +36 -0
  27. package/features/modelBuilder/fields/BaseFieldBuilder.js +41 -0
  28. package/features/modelBuilder/fields/BaseFieldBuilder.js.map +1 -0
  29. package/features/modelBuilder/fields/DataFieldBuilder.d.ts +228 -0
  30. package/features/modelBuilder/fields/DataFieldBuilder.js +219 -0
  31. package/features/modelBuilder/fields/DataFieldBuilder.js.map +1 -0
  32. package/features/modelBuilder/fields/DynamicZoneFieldType.d.ts +2 -2
  33. package/features/modelBuilder/fields/DynamicZoneFieldType.js +6 -3
  34. package/features/modelBuilder/fields/DynamicZoneFieldType.js.map +1 -1
  35. package/features/modelBuilder/fields/FieldBuilder.d.ts +5 -228
  36. package/features/modelBuilder/fields/FieldBuilder.js +3 -231
  37. package/features/modelBuilder/fields/FieldBuilder.js.map +1 -1
  38. package/features/modelBuilder/fields/LayoutFieldBuilder.d.ts +7 -0
  39. package/features/modelBuilder/fields/LayoutFieldBuilder.js +9 -0
  40. package/features/modelBuilder/fields/LayoutFieldBuilder.js.map +1 -0
  41. package/features/modelBuilder/fields/ObjectFieldType.d.ts +4 -3
  42. package/features/modelBuilder/fields/ObjectFieldType.js +19 -4
  43. package/features/modelBuilder/fields/ObjectFieldType.js.map +1 -1
  44. package/features/modelBuilder/fields/UiAlertFieldType.d.ts +8 -4
  45. package/features/modelBuilder/fields/UiAlertFieldType.js +23 -6
  46. package/features/modelBuilder/fields/UiAlertFieldType.js.map +1 -1
  47. package/features/modelBuilder/fields/UiSeparatorFieldType.d.ts +6 -4
  48. package/features/modelBuilder/fields/UiSeparatorFieldType.js +18 -4
  49. package/features/modelBuilder/fields/UiSeparatorFieldType.js.map +1 -1
  50. package/features/modelBuilder/fields/UiTabsFieldType.d.ts +28 -0
  51. package/features/modelBuilder/fields/UiTabsFieldType.js +75 -0
  52. package/features/modelBuilder/fields/UiTabsFieldType.js.map +1 -0
  53. package/features/modelBuilder/fields/abstractions.d.ts +2 -2
  54. package/features/modelBuilder/fields/abstractions.js.map +1 -1
  55. package/features/modelBuilder/index.d.ts +2 -0
  56. package/features/modelBuilder/index.js +2 -0
  57. package/features/modelBuilder/index.js.map +1 -1
  58. package/features/modelBuilder/models/BaseModelBuilder.d.ts +8 -3
  59. package/features/modelBuilder/models/BaseModelBuilder.js +19 -0
  60. package/features/modelBuilder/models/BaseModelBuilder.js.map +1 -1
  61. package/features/modelBuilder/models/PrivateModelBuilder.js +4 -2
  62. package/features/modelBuilder/models/PrivateModelBuilder.js.map +1 -1
  63. package/features/modelBuilder/models/PublicModelBuilder.js +16 -11
  64. package/features/modelBuilder/models/PublicModelBuilder.js.map +1 -1
  65. package/graphql/schema/cms/helpers/index.d.ts +1 -0
  66. package/graphql/schema/cms/helpers/index.js +1 -0
  67. package/graphql/schema/cms/helpers/index.js.map +1 -1
  68. package/graphql/schema/cms/helpers/transformWhereToNested.d.ts +17 -0
  69. package/graphql/schema/cms/helpers/transformWhereToNested.js +54 -0
  70. package/graphql/schema/cms/helpers/transformWhereToNested.js.map +1 -0
  71. package/graphql/schema/cms/helpers.d.ts +1 -0
  72. package/graphql/schema/cms/helpers.js +1 -0
  73. package/graphql/schema/cms/helpers.js.map +1 -1
  74. package/graphql/schema/cms/listEntriesResolver.js +6 -2
  75. package/graphql/schema/cms/listEntriesResolver.js.map +1 -1
  76. package/graphql/schema/contentModels.js +21 -3
  77. package/graphql/schema/contentModels.js.map +1 -1
  78. package/graphqlFields/index.js +1 -2
  79. package/graphqlFields/index.js.map +1 -1
  80. package/package.json +20 -20
  81. package/plugins/CmsModelPlugin.js +19 -4
  82. package/plugins/CmsModelPlugin.js.map +1 -1
  83. package/types/fields/objectField.d.ts +2 -0
  84. package/types/fields/objectField.js.map +1 -1
  85. package/types/model.d.ts +32 -3
  86. package/types/model.js.map +1 -1
  87. package/types/modelField.d.ts +19 -3
  88. package/types/modelField.js.map +1 -1
  89. package/utils/createModelField.js +4 -2
  90. package/utils/createModelField.js.map +1 -1
  91. package/features/modelBuilder/fields/UiFieldType.d.ts +0 -18
  92. package/features/modelBuilder/fields/UiFieldType.js +0 -25
  93. package/features/modelBuilder/fields/UiFieldType.js.map +0 -1
  94. package/graphqlFields/ui.d.ts +0 -2
  95. package/graphqlFields/ui.js +0 -32
  96. package/graphqlFields/ui.js.map +0 -1
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Transforms a flat where object with dot-notation keys into a nested object.
3
+ * Keys without dots are passed through unchanged.
4
+ * Handles logical operators (AND, OR) recursively.
5
+ *
6
+ * @param where - Where clause object potentially containing dot-notation keys
7
+ * @returns Nested where object compatible with the GraphQL ListWhereInput type
8
+ *
9
+ * @example
10
+ * transformWhereToNested({ "values.name": "Keyboard", id: "abc" })
11
+ * // Returns: { values: { name: "Keyboard" }, id: "abc" }
12
+ *
13
+ * @example
14
+ * transformWhereToNested({ "values.price_gt": 100, "values.name_contains": "board" })
15
+ * // Returns: { values: { price_gt: 100, name_contains: "board" } }
16
+ */
17
+ export const transformWhereToNested = where => {
18
+ if (!where) {
19
+ return undefined;
20
+ }
21
+ const result = {};
22
+ for (const [key, value] of Object.entries(where)) {
23
+ // Handle logical operators recursively.
24
+ if (key === "AND" || key === "OR") {
25
+ if (Array.isArray(value)) {
26
+ result[key] = value.map(item => transformWhereToNested(item));
27
+ } else {
28
+ result[key] = value;
29
+ }
30
+ continue;
31
+ }
32
+ const dotIndex = key.indexOf(".");
33
+ if (dotIndex === -1) {
34
+ // No dot — pass through unchanged.
35
+ result[key] = value;
36
+ } else {
37
+ // Dot-notation key — expand into nested object.
38
+ const head = key.slice(0, dotIndex);
39
+ const tail = key.slice(dotIndex + 1);
40
+ if (result[head] === undefined) {
41
+ result[head] = {};
42
+ }
43
+ const nested = result[head];
44
+ // Recursively expand in case of multiple levels of nesting.
45
+ const expanded = transformWhereToNested({
46
+ [tail]: value
47
+ });
48
+ Object.assign(nested, expanded);
49
+ }
50
+ }
51
+ return result;
52
+ };
53
+
54
+ //# sourceMappingURL=transformWhereToNested.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["transformWhereToNested","where","undefined","result","key","value","Object","entries","Array","isArray","map","item","dotIndex","indexOf","head","slice","tail","nested","expanded","assign"],"sources":["transformWhereToNested.ts"],"sourcesContent":["/**\n * Transforms a flat where object with dot-notation keys into a nested object.\n * Keys without dots are passed through unchanged.\n * Handles logical operators (AND, OR) recursively.\n *\n * @param where - Where clause object potentially containing dot-notation keys\n * @returns Nested where object compatible with the GraphQL ListWhereInput type\n *\n * @example\n * transformWhereToNested({ \"values.name\": \"Keyboard\", id: \"abc\" })\n * // Returns: { values: { name: \"Keyboard\" }, id: \"abc\" }\n *\n * @example\n * transformWhereToNested({ \"values.price_gt\": 100, \"values.name_contains\": \"board\" })\n * // Returns: { values: { price_gt: 100, name_contains: \"board\" } }\n */\nexport const transformWhereToNested = (\n where?: Record<string, unknown>\n): Record<string, unknown> | undefined => {\n if (!where) {\n return undefined;\n }\n\n const result: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(where)) {\n // Handle logical operators recursively.\n if (key === \"AND\" || key === \"OR\") {\n if (Array.isArray(value)) {\n result[key] = value.map(item =>\n transformWhereToNested(item as Record<string, unknown>)\n );\n } else {\n result[key] = value;\n }\n continue;\n }\n\n const dotIndex = key.indexOf(\".\");\n if (dotIndex === -1) {\n // No dot — pass through unchanged.\n result[key] = value;\n } else {\n // Dot-notation key — expand into nested object.\n const head = key.slice(0, dotIndex);\n const tail = key.slice(dotIndex + 1);\n\n if (result[head] === undefined) {\n result[head] = {};\n }\n\n const nested = result[head] as Record<string, unknown>;\n // Recursively expand in case of multiple levels of nesting.\n const expanded = transformWhereToNested({ [tail]: value }) as Record<string, unknown>;\n Object.assign(nested, expanded);\n }\n }\n\n return result;\n};\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMA,sBAAsB,GAC/BC,KAA+B,IACO;EACtC,IAAI,CAACA,KAAK,EAAE;IACR,OAAOC,SAAS;EACpB;EAEA,MAAMC,MAA+B,GAAG,CAAC,CAAC;EAE1C,KAAK,MAAM,CAACC,GAAG,EAAEC,KAAK,CAAC,IAAIC,MAAM,CAACC,OAAO,CAACN,KAAK,CAAC,EAAE;IAC9C;IACA,IAAIG,GAAG,KAAK,KAAK,IAAIA,GAAG,KAAK,IAAI,EAAE;MAC/B,IAAII,KAAK,CAACC,OAAO,CAACJ,KAAK,CAAC,EAAE;QACtBF,MAAM,CAACC,GAAG,CAAC,GAAGC,KAAK,CAACK,GAAG,CAACC,IAAI,IACxBX,sBAAsB,CAACW,IAA+B,CAC1D,CAAC;MACL,CAAC,MAAM;QACHR,MAAM,CAACC,GAAG,CAAC,GAAGC,KAAK;MACvB;MACA;IACJ;IAEA,MAAMO,QAAQ,GAAGR,GAAG,CAACS,OAAO,CAAC,GAAG,CAAC;IACjC,IAAID,QAAQ,KAAK,CAAC,CAAC,EAAE;MACjB;MACAT,MAAM,CAACC,GAAG,CAAC,GAAGC,KAAK;IACvB,CAAC,MAAM;MACH;MACA,MAAMS,IAAI,GAAGV,GAAG,CAACW,KAAK,CAAC,CAAC,EAAEH,QAAQ,CAAC;MACnC,MAAMI,IAAI,GAAGZ,GAAG,CAACW,KAAK,CAACH,QAAQ,GAAG,CAAC,CAAC;MAEpC,IAAIT,MAAM,CAACW,IAAI,CAAC,KAAKZ,SAAS,EAAE;QAC5BC,MAAM,CAACW,IAAI,CAAC,GAAG,CAAC,CAAC;MACrB;MAEA,MAAMG,MAAM,GAAGd,MAAM,CAACW,IAAI,CAA4B;MACtD;MACA,MAAMI,QAAQ,GAAGlB,sBAAsB,CAAC;QAAE,CAACgB,IAAI,GAAGX;MAAM,CAAC,CAA4B;MACrFC,MAAM,CAACa,MAAM,CAACF,MAAM,EAAEC,QAAQ,CAAC;IACnC;EACJ;EAEA,OAAOf,MAAM;AACjB,CAAC","ignoreList":[]}
@@ -2,3 +2,4 @@ export { getErrorMessage } from "./helpers/getErrorMessage.js";
2
2
  export { getModel } from "./helpers/getModel.js";
3
3
  export { transformSortToArray } from "./helpers/transformSortToArray.js";
4
4
  export { buildFieldsSelection } from "./helpers/buildFieldsSelection.js";
5
+ export { transformWhereToNested } from "./helpers/transformWhereToNested.js";
@@ -2,5 +2,6 @@ export { getErrorMessage } from "./helpers/getErrorMessage.js";
2
2
  export { getModel } from "./helpers/getModel.js";
3
3
  export { transformSortToArray } from "./helpers/transformSortToArray.js";
4
4
  export { buildFieldsSelection } from "./helpers/buildFieldsSelection.js";
5
+ export { transformWhereToNested } from "./helpers/transformWhereToNested.js";
5
6
 
6
7
  //# sourceMappingURL=helpers.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["getErrorMessage","getModel","transformSortToArray","buildFieldsSelection"],"sources":["helpers.ts"],"sourcesContent":["export { getErrorMessage } from \"./helpers/getErrorMessage.js\";\nexport { getModel } from \"./helpers/getModel.js\";\nexport { transformSortToArray } from \"./helpers/transformSortToArray.js\";\nexport { buildFieldsSelection } from \"./helpers/buildFieldsSelection.js\";\n"],"mappings":"AAAA,SAASA,eAAe;AACxB,SAASC,QAAQ;AACjB,SAASC,oBAAoB;AAC7B,SAASC,oBAAoB","ignoreList":[]}
1
+ {"version":3,"names":["getErrorMessage","getModel","transformSortToArray","buildFieldsSelection","transformWhereToNested"],"sources":["helpers.ts"],"sourcesContent":["export { getErrorMessage } from \"./helpers/getErrorMessage.js\";\nexport { getModel } from \"./helpers/getModel.js\";\nexport { transformSortToArray } from \"./helpers/transformSortToArray.js\";\nexport { buildFieldsSelection } from \"./helpers/buildFieldsSelection.js\";\nexport { transformWhereToNested } from \"./helpers/transformWhereToNested.js\";\n"],"mappings":"AAAA,SAASA,eAAe;AACxB,SAASC,QAAQ;AACjB,SAASC,oBAAoB;AAC7B,SAASC,oBAAoB;AAC7B,SAASC,sBAAsB","ignoreList":[]}
@@ -1,4 +1,4 @@
1
- import { getModel, getErrorMessage, buildFieldsSelection, transformSortToArray } from "./helpers.js";
1
+ import { getModel, getErrorMessage, buildFieldsSelection, transformSortToArray, transformWhereToNested } from "./helpers.js";
2
2
  export const createListEntriesResolver = () => {
3
3
  return async ({
4
4
  args,
@@ -25,6 +25,10 @@ export const createListEntriesResolver = () => {
25
25
  // Transform sort to array format expected by the underlying GraphQL schema.
26
26
  // Handles both object format {createdOn: "desc"} and array format ["createdOn_DESC"].
27
27
  const transformedSort = transformSortToArray(sort);
28
+
29
+ // Transform dot-notation where keys (e.g. "values.name") into nested objects
30
+ // (e.g. { values: { name: ... } }) so they match the typed ListWhereInput.
31
+ const transformedWhere = transformWhereToNested(where);
28
32
  const query = /* GraphQL */`
29
33
  query List${model.pluralApiName}(
30
34
  $where: ${model.singularApiName}ListWhereInput
@@ -57,7 +61,7 @@ export const createListEntriesResolver = () => {
57
61
  const result = await executeSchema({
58
62
  query,
59
63
  variables: {
60
- where,
64
+ where: transformedWhere,
61
65
  sort: transformedSort,
62
66
  limit,
63
67
  after
@@ -1 +1 @@
1
- {"version":3,"names":["getModel","getErrorMessage","buildFieldsSelection","transformSortToArray","createListEntriesResolver","args","context","modelId","where","sort","limit","after","fields","preview","model","apiType","executeSchema","cms","getExecutableSchema","fieldsSelection","transformedSort","query","pluralApiName","singularApiName","result","variables","operationName","data","meta","cursor","hasMoreItems","totalCount","error","message","code"],"sources":["listEntriesResolver.ts"],"sourcesContent":["import type { CmsContext } from \"~/types/index.js\";\nimport type { ApiEndpoint } from \"~/types/index.js\";\nimport type { ExecutionResult } from \"graphql\";\nimport {\n getModel,\n getErrorMessage,\n buildFieldsSelection,\n transformSortToArray\n} from \"./helpers.js\";\n\nexport interface ListEntriesArgs {\n modelId: string;\n where?: Record<string, unknown>;\n sort?: Record<string, unknown> | string[];\n limit?: number;\n after?: string;\n fields: string[];\n preview?: boolean;\n}\n\nexport const createListEntriesResolver = () => {\n return async ({ args, context }: { args: ListEntriesArgs; context: CmsContext }) => {\n const { modelId, where, sort, limit, after, fields, preview = false } = args;\n\n try {\n const model = await getModel(context, modelId);\n\n // Determine which API to use based on the preview flag.\n // preview=true -> preview API, preview=false -> read API\n const apiType: ApiEndpoint = preview ? \"preview\" : \"read\";\n const executeSchema = await context.cms.getExecutableSchema(apiType);\n\n const fieldsSelection = buildFieldsSelection(fields);\n\n // Transform sort to array format expected by the underlying GraphQL schema.\n // Handles both object format {createdOn: \"desc\"} and array format [\"createdOn_DESC\"].\n const transformedSort = transformSortToArray(sort);\n\n const query = /* GraphQL */ `\n query List${model.pluralApiName}(\n $where: ${model.singularApiName}ListWhereInput\n $sort: [${model.singularApiName}ListSorter!]\n $limit: Int\n $after: String\n ) {\n list${model.pluralApiName}(\n where: $where\n sort: $sort\n limit: $limit\n after: $after\n ) {\n data {\n ${fieldsSelection}\n }\n meta {\n cursor\n hasMoreItems\n totalCount\n }\n error {\n message\n code\n data\n }\n }\n }\n `;\n\n const result = (await executeSchema({\n query,\n variables: { where, sort: transformedSort, limit, after }\n })) as ExecutionResult;\n\n const operationName = `list${model.pluralApiName}`;\n return (\n result.data?.[operationName] || {\n data: [],\n meta: { cursor: null, hasMoreItems: false, totalCount: 0 },\n error: null\n }\n );\n } catch (error) {\n return {\n data: [],\n meta: { cursor: null, hasMoreItems: false, totalCount: 0 },\n error: {\n message: getErrorMessage(error, \"Failed to list entries\"),\n code: \"LIST_ENTRIES_ERROR\"\n }\n };\n }\n };\n};\n"],"mappings":"AAGA,SACIA,QAAQ,EACRC,eAAe,EACfC,oBAAoB,EACpBC,oBAAoB;AAaxB,OAAO,MAAMC,yBAAyB,GAAGA,CAAA,KAAM;EAC3C,OAAO,OAAO;IAAEC,IAAI;IAAEC;EAAwD,CAAC,KAAK;IAChF,MAAM;MAAEC,OAAO;MAAEC,KAAK;MAAEC,IAAI;MAAEC,KAAK;MAAEC,KAAK;MAAEC,MAAM;MAAEC,OAAO,GAAG;IAAM,CAAC,GAAGR,IAAI;IAE5E,IAAI;MACA,MAAMS,KAAK,GAAG,MAAMd,QAAQ,CAACM,OAAO,EAAEC,OAAO,CAAC;;MAE9C;MACA;MACA,MAAMQ,OAAoB,GAAGF,OAAO,GAAG,SAAS,GAAG,MAAM;MACzD,MAAMG,aAAa,GAAG,MAAMV,OAAO,CAACW,GAAG,CAACC,mBAAmB,CAACH,OAAO,CAAC;MAEpE,MAAMI,eAAe,GAAGjB,oBAAoB,CAACU,MAAM,CAAC;;MAEpD;MACA;MACA,MAAMQ,eAAe,GAAGjB,oBAAoB,CAACM,IAAI,CAAC;MAElD,MAAMY,KAAK,GAAG,aAAc;AACxC,4BAA4BP,KAAK,CAACQ,aAAa;AAC/C,8BAA8BR,KAAK,CAACS,eAAe;AACnD,8BAA8BT,KAAK,CAACS,eAAe;AACnD;AACA;AACA;AACA,0BAA0BT,KAAK,CAACQ,aAAa;AAC7C;AACA;AACA;AACA;AACA;AACA;AACA,8BAA8BH,eAAe;AAC7C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;MAED,MAAMK,MAAM,GAAI,MAAMR,aAAa,CAAC;QAChCK,KAAK;QACLI,SAAS,EAAE;UAAEjB,KAAK;UAAEC,IAAI,EAAEW,eAAe;UAAEV,KAAK;UAAEC;QAAM;MAC5D,CAAC,CAAqB;MAEtB,MAAMe,aAAa,GAAG,OAAOZ,KAAK,CAACQ,aAAa,EAAE;MAClD,OACIE,MAAM,CAACG,IAAI,GAAGD,aAAa,CAAC,IAAI;QAC5BC,IAAI,EAAE,EAAE;QACRC,IAAI,EAAE;UAAEC,MAAM,EAAE,IAAI;UAAEC,YAAY,EAAE,KAAK;UAAEC,UAAU,EAAE;QAAE,CAAC;QAC1DC,KAAK,EAAE;MACX,CAAC;IAET,CAAC,CAAC,OAAOA,KAAK,EAAE;MACZ,OAAO;QACHL,IAAI,EAAE,EAAE;QACRC,IAAI,EAAE;UAAEC,MAAM,EAAE,IAAI;UAAEC,YAAY,EAAE,KAAK;UAAEC,UAAU,EAAE;QAAE,CAAC;QAC1DC,KAAK,EAAE;UACHC,OAAO,EAAEhC,eAAe,CAAC+B,KAAK,EAAE,wBAAwB,CAAC;UACzDE,IAAI,EAAE;QACV;MACJ,CAAC;IACL;EACJ,CAAC;AACL,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["getModel","getErrorMessage","buildFieldsSelection","transformSortToArray","transformWhereToNested","createListEntriesResolver","args","context","modelId","where","sort","limit","after","fields","preview","model","apiType","executeSchema","cms","getExecutableSchema","fieldsSelection","transformedSort","transformedWhere","query","pluralApiName","singularApiName","result","variables","operationName","data","meta","cursor","hasMoreItems","totalCount","error","message","code"],"sources":["listEntriesResolver.ts"],"sourcesContent":["import type { CmsContext } from \"~/types/index.js\";\nimport type { ApiEndpoint } from \"~/types/index.js\";\nimport type { ExecutionResult } from \"graphql\";\nimport {\n getModel,\n getErrorMessage,\n buildFieldsSelection,\n transformSortToArray,\n transformWhereToNested\n} from \"./helpers.js\";\n\nexport interface ListEntriesArgs {\n modelId: string;\n where?: Record<string, unknown>;\n sort?: Record<string, unknown> | string[];\n limit?: number;\n after?: string;\n fields: string[];\n preview?: boolean;\n}\n\nexport const createListEntriesResolver = () => {\n return async ({ args, context }: { args: ListEntriesArgs; context: CmsContext }) => {\n const { modelId, where, sort, limit, after, fields, preview = false } = args;\n\n try {\n const model = await getModel(context, modelId);\n\n // Determine which API to use based on the preview flag.\n // preview=true -> preview API, preview=false -> read API\n const apiType: ApiEndpoint = preview ? \"preview\" : \"read\";\n const executeSchema = await context.cms.getExecutableSchema(apiType);\n\n const fieldsSelection = buildFieldsSelection(fields);\n\n // Transform sort to array format expected by the underlying GraphQL schema.\n // Handles both object format {createdOn: \"desc\"} and array format [\"createdOn_DESC\"].\n const transformedSort = transformSortToArray(sort);\n\n // Transform dot-notation where keys (e.g. \"values.name\") into nested objects\n // (e.g. { values: { name: ... } }) so they match the typed ListWhereInput.\n const transformedWhere = transformWhereToNested(where);\n\n const query = /* GraphQL */ `\n query List${model.pluralApiName}(\n $where: ${model.singularApiName}ListWhereInput\n $sort: [${model.singularApiName}ListSorter!]\n $limit: Int\n $after: String\n ) {\n list${model.pluralApiName}(\n where: $where\n sort: $sort\n limit: $limit\n after: $after\n ) {\n data {\n ${fieldsSelection}\n }\n meta {\n cursor\n hasMoreItems\n totalCount\n }\n error {\n message\n code\n data\n }\n }\n }\n `;\n\n const result = (await executeSchema({\n query,\n variables: { where: transformedWhere, sort: transformedSort, limit, after }\n })) as ExecutionResult;\n\n const operationName = `list${model.pluralApiName}`;\n return (\n result.data?.[operationName] || {\n data: [],\n meta: { cursor: null, hasMoreItems: false, totalCount: 0 },\n error: null\n }\n );\n } catch (error) {\n return {\n data: [],\n meta: { cursor: null, hasMoreItems: false, totalCount: 0 },\n error: {\n message: getErrorMessage(error, \"Failed to list entries\"),\n code: \"LIST_ENTRIES_ERROR\"\n }\n };\n }\n };\n};\n"],"mappings":"AAGA,SACIA,QAAQ,EACRC,eAAe,EACfC,oBAAoB,EACpBC,oBAAoB,EACpBC,sBAAsB;AAa1B,OAAO,MAAMC,yBAAyB,GAAGA,CAAA,KAAM;EAC3C,OAAO,OAAO;IAAEC,IAAI;IAAEC;EAAwD,CAAC,KAAK;IAChF,MAAM;MAAEC,OAAO;MAAEC,KAAK;MAAEC,IAAI;MAAEC,KAAK;MAAEC,KAAK;MAAEC,MAAM;MAAEC,OAAO,GAAG;IAAM,CAAC,GAAGR,IAAI;IAE5E,IAAI;MACA,MAAMS,KAAK,GAAG,MAAMf,QAAQ,CAACO,OAAO,EAAEC,OAAO,CAAC;;MAE9C;MACA;MACA,MAAMQ,OAAoB,GAAGF,OAAO,GAAG,SAAS,GAAG,MAAM;MACzD,MAAMG,aAAa,GAAG,MAAMV,OAAO,CAACW,GAAG,CAACC,mBAAmB,CAACH,OAAO,CAAC;MAEpE,MAAMI,eAAe,GAAGlB,oBAAoB,CAACW,MAAM,CAAC;;MAEpD;MACA;MACA,MAAMQ,eAAe,GAAGlB,oBAAoB,CAACO,IAAI,CAAC;;MAElD;MACA;MACA,MAAMY,gBAAgB,GAAGlB,sBAAsB,CAACK,KAAK,CAAC;MAEtD,MAAMc,KAAK,GAAG,aAAc;AACxC,4BAA4BR,KAAK,CAACS,aAAa;AAC/C,8BAA8BT,KAAK,CAACU,eAAe;AACnD,8BAA8BV,KAAK,CAACU,eAAe;AACnD;AACA;AACA;AACA,0BAA0BV,KAAK,CAACS,aAAa;AAC7C;AACA;AACA;AACA;AACA;AACA;AACA,8BAA8BJ,eAAe;AAC7C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;MAED,MAAMM,MAAM,GAAI,MAAMT,aAAa,CAAC;QAChCM,KAAK;QACLI,SAAS,EAAE;UAAElB,KAAK,EAAEa,gBAAgB;UAAEZ,IAAI,EAAEW,eAAe;UAAEV,KAAK;UAAEC;QAAM;MAC9E,CAAC,CAAqB;MAEtB,MAAMgB,aAAa,GAAG,OAAOb,KAAK,CAACS,aAAa,EAAE;MAClD,OACIE,MAAM,CAACG,IAAI,GAAGD,aAAa,CAAC,IAAI;QAC5BC,IAAI,EAAE,EAAE;QACRC,IAAI,EAAE;UAAEC,MAAM,EAAE,IAAI;UAAEC,YAAY,EAAE,KAAK;UAAEC,UAAU,EAAE;QAAE,CAAC;QAC1DC,KAAK,EAAE;MACX,CAAC;IAET,CAAC,CAAC,OAAOA,KAAK,EAAE;MACZ,OAAO;QACHL,IAAI,EAAE,EAAE;QACRC,IAAI,EAAE;UAAEC,MAAM,EAAE,IAAI;UAAEC,YAAY,EAAE,KAAK;UAAEC,UAAU,EAAE;QAAE,CAAC;QAC1DC,KAAK,EAAE;UACHC,OAAO,EAAElC,eAAe,CAACiC,KAAK,EAAE,wBAAwB,CAAC;UACzDE,IAAI,EAAE;QACV;MACJ,CAAC;IACL;EACJ,CAAC;AACL,CAAC","ignoreList":[]}
@@ -121,6 +121,14 @@ export const createModelsSchema = ({
121
121
  settings: JSON
122
122
  }
123
123
 
124
+ input CmsFieldRuleInput {
125
+ type: String!
126
+ target: String!
127
+ operator: String!
128
+ value: JSON
129
+ action: String!
130
+ }
131
+
124
132
  input CmsContentModelFieldInput {
125
133
  id: ID!
126
134
  label: String!
@@ -140,6 +148,7 @@ export const createModelsSchema = ({
140
148
  validation: [CmsFieldValidationInput]
141
149
  listValidation: [CmsFieldValidationInput]
142
150
  settings: JSON
151
+ rules: [CmsFieldRuleInput!]
143
152
  }
144
153
 
145
154
  input CmsContentModelCreateInput {
@@ -151,7 +160,7 @@ export const createModelsSchema = ({
151
160
  icon: Icon
152
161
  singleEntry: Boolean
153
162
  description: String
154
- layout: [[ID!]!]
163
+ layout: JSON
155
164
  fields: [CmsContentModelFieldInput!]
156
165
  titleFieldId: String
157
166
  descriptionFieldId: String
@@ -177,7 +186,7 @@ export const createModelsSchema = ({
177
186
  group: String
178
187
  icon: Icon
179
188
  description: String
180
- layout: [[ID!]!]!
189
+ layout: JSON!
181
190
  fields: [CmsContentModelFieldInput!]!
182
191
  titleFieldId: String
183
192
  descriptionFieldId: String
@@ -226,6 +235,14 @@ export const createModelsSchema = ({
226
235
  values: [CmsPredefinedValue]
227
236
  }
228
237
 
238
+ type CmsFieldRule {
239
+ type: String!
240
+ target: String!
241
+ operator: String!
242
+ value: JSON
243
+ action: String!
244
+ }
245
+
229
246
  type CmsContentModelField {
230
247
  id: ID!
231
248
  # auto-generated value
@@ -245,6 +262,7 @@ export const createModelsSchema = ({
245
262
  validation: [CmsFieldValidation!]
246
263
  listValidation: [CmsFieldValidation!]
247
264
  settings: JSON
265
+ rules: [CmsFieldRule!]
248
266
  }
249
267
 
250
268
  type CmsContentModel {
@@ -259,7 +277,7 @@ export const createModelsSchema = ({
259
277
  savedOn: DateTime
260
278
  createdBy: CmsIdentity
261
279
  fields: [CmsContentModelField!]!
262
- layout: [[String!]!]!
280
+ layout: JSON!
263
281
  titleFieldId: String
264
282
  descriptionFieldId: String
265
283
  imageFieldId: String
@@ -1 +1 @@
1
- {"version":3,"names":["ErrorResponse","NotFoundError","Response","createCmsGraphQLSchemaPlugin","createModelsSchema","context","resolvers","Query","getContentModel","_","args","model","cms","getModel","modelId","e","listContentModels","models","listModels","includePrivate","includePlugins","CmsContentModelField","renderer","field","settings","tags","Array","isArray","CmsContentModel","hasType","find","tag","startsWith","plugin","isPlugin","manageSchema","MANAGE","createContentModel","createModel","data","createContentModelFrom","createModelFrom","updateContentModel","updateModel","deleteContentModel","deleteModel","typeDefs","name","type"],"sources":["contentModels.ts"],"sourcesContent":["import { ErrorResponse, NotFoundError, Response } from \"@webiny/handler-graphql\";\nimport type { CmsContext, CmsModel } from \"~/types/index.js\";\nimport type { Resolvers } from \"@webiny/handler-graphql/types.js\";\nimport type { ICmsGraphQLSchemaPlugin } from \"~/plugins/index.js\";\nimport { createCmsGraphQLSchemaPlugin } from \"~/plugins/index.js\";\nimport type { GenericRecord } from \"@webiny/api/types.js\";\n\nexport interface CreateModelsSchemaParams {\n context: CmsContext;\n}\n\nexport const createModelsSchema = ({\n context\n}: CreateModelsSchemaParams): ICmsGraphQLSchemaPlugin => {\n const resolvers: Resolvers<CmsContext> = {\n Query: {\n getContentModel: async (_: unknown, args: GenericRecord, context) => {\n try {\n const model = await context.cms.getModel(args.modelId);\n\n if (!model) {\n throw new NotFoundError(`Content model \"${args.modelId}\" was not found!`);\n }\n\n return new Response(model);\n } catch (e) {\n return new ErrorResponse(e);\n }\n },\n listContentModels: async (_: unknown, args: GenericRecord, context: CmsContext) => {\n try {\n const models = await context.cms.listModels({\n includePrivate: false,\n includePlugins: args?.includePlugins === false ? false : true\n });\n return new Response(models);\n } catch (e) {\n return new ErrorResponse(e);\n }\n }\n },\n CmsContentModelField: {\n renderer: field => {\n // Make sure `settings` is an object.\n if (field.renderer) {\n // We're using `||` here, because we want to use the fallback value for both `undefined` and `null`.\n return { ...field.renderer, settings: field.renderer.settings || {} };\n }\n\n return field.renderer;\n },\n tags(field) {\n // Make sure `tags` are always returned as an array.\n return Array.isArray(field.tags) ? field.tags : [];\n }\n },\n CmsContentModel: {\n tags(model: CmsModel) {\n // Make sure `tags` always contain a `type` tag, to differentiate between models.\n const hasType = (model.tags || []).find(tag => tag.startsWith(\"type:\"));\n\n return hasType ? model.tags : [\"type:model\", ...(model.tags || [])];\n },\n plugin: (model: CmsModel) => {\n return model.isPlugin ?? false;\n }\n }\n };\n\n let manageSchema = \"\";\n if (context.cms.MANAGE) {\n resolvers[\"Mutation\"] = {\n createContentModel: async (_: unknown, args: any, context) => {\n try {\n const model = await context.cms.createModel(args.data);\n return new Response(model);\n } catch (e) {\n return new ErrorResponse(e);\n }\n },\n createContentModelFrom: async (_: unknown, args: any, context) => {\n try {\n const model = await context.cms.createModelFrom(args.modelId, args.data);\n return new Response(model);\n } catch (e) {\n return new ErrorResponse(e);\n }\n },\n updateContentModel: async (_: unknown, args: any, context) => {\n const { modelId, data } = args;\n try {\n const model = await context.cms.updateModel(modelId, data);\n return new Response(model);\n } catch (e) {\n return new ErrorResponse(e);\n }\n },\n deleteContentModel: async (_: unknown, args: any, context) => {\n const { modelId } = args;\n try {\n await context.cms.deleteModel(modelId);\n return new Response(true);\n } catch (e) {\n return new ErrorResponse(e);\n }\n }\n };\n\n manageSchema = /* GraphQL */ `\n input CmsPredefinedValueInput {\n label: String!\n value: String!\n selected: Boolean\n }\n\n input CmsPredefinedValuesInput {\n enabled: Boolean\n values: [CmsPredefinedValueInput]\n }\n input CmsFieldRendererInput {\n name: String\n settings: JSON\n }\n\n input CmsFieldValidationInput {\n name: String!\n message: String\n settings: JSON\n }\n\n input CmsContentModelFieldInput {\n id: ID!\n label: String!\n help: String\n description: String\n note: String\n placeholder: String\n # we never use user input - this is here to the GraphQL does not break when posting from our UI\n # used for debugging purposes\n storageId: String\n fieldId: String!\n type: String!\n tags: [String!]\n list: Boolean\n predefinedValues: CmsPredefinedValuesInput\n renderer: CmsFieldRendererInput\n validation: [CmsFieldValidationInput]\n listValidation: [CmsFieldValidationInput]\n settings: JSON\n }\n\n input CmsContentModelCreateInput {\n name: String!\n singularApiName: String!\n pluralApiName: String!\n modelId: String\n group: String!\n icon: Icon\n singleEntry: Boolean\n description: String\n layout: [[ID!]!]\n fields: [CmsContentModelFieldInput!]\n titleFieldId: String\n descriptionFieldId: String\n imageFieldId: String\n tags: [String!]\n defaultFields: Boolean\n }\n\n input CmsContentModelCreateFromInput {\n name: String!\n singularApiName: String!\n pluralApiName: String!\n modelId: String\n group: String!\n icon: Icon\n description: String\n }\n\n input CmsContentModelUpdateInput {\n name: String\n singularApiName: String\n pluralApiName: String\n group: String\n icon: Icon\n description: String\n layout: [[ID!]!]!\n fields: [CmsContentModelFieldInput!]!\n titleFieldId: String\n descriptionFieldId: String\n imageFieldId: String\n tags: [String!]\n }\n\n extend type Mutation {\n createContentModel(data: CmsContentModelCreateInput!): CmsContentModelResponse\n\n createContentModelFrom(\n modelId: ID!\n data: CmsContentModelCreateFromInput!\n ): CmsContentModelResponse\n\n updateContentModel(\n modelId: ID!\n data: CmsContentModelUpdateInput!\n ): CmsContentModelResponse\n\n deleteContentModel(modelId: ID!): CmsDeleteResponse\n }\n `;\n }\n\n const plugin = createCmsGraphQLSchemaPlugin({\n typeDefs: /* GraphQL */ `\n type CmsFieldValidation {\n name: String!\n message: String\n settings: JSON\n }\n\n type CmsFieldRenderer {\n name: String\n settings: JSON\n }\n\n type CmsPredefinedValue {\n label: String\n value: String\n selected: Boolean\n }\n\n type CmsPredefinedValues {\n enabled: Boolean\n values: [CmsPredefinedValue]\n }\n\n type CmsContentModelField {\n id: ID!\n # auto-generated value\n # used for debugging purposes\n storageId: String\n fieldId: String!\n label: String!\n help: String\n description: String\n note: String\n placeholder: String\n type: String!\n tags: [String!]!\n list: Boolean\n predefinedValues: CmsPredefinedValues\n renderer: CmsFieldRenderer\n validation: [CmsFieldValidation!]\n listValidation: [CmsFieldValidation!]\n settings: JSON\n }\n\n type CmsContentModel {\n name: String!\n singularApiName: String!\n pluralApiName: String!\n modelId: String!\n description: String\n group: String!\n icon: Icon\n createdOn: DateTime\n savedOn: DateTime\n createdBy: CmsIdentity\n fields: [CmsContentModelField!]!\n layout: [[String!]!]!\n titleFieldId: String\n descriptionFieldId: String\n imageFieldId: String\n tags: [String!]!\n tenant: String!\n # Returns true if the content model is registered via a plugin.\n plugin: Boolean!\n }\n\n type CmsContentModelResponse {\n data: CmsContentModel\n error: CmsError\n }\n\n type CmsContentModelListResponse {\n data: [CmsContentModel]\n meta: CmsListMeta\n error: CmsError\n }\n\n extend type Query {\n getContentModel(modelId: ID!, where: JSON, sort: String): CmsContentModelResponse\n\n listContentModels(includePlugins: Boolean = true): CmsContentModelListResponse\n }\n\n ${manageSchema}\n `,\n resolvers\n });\n plugin.name = `headless-cms.graphql.schema.${context.cms.type}.content-models`;\n return plugin;\n};\n"],"mappings":"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MAAM;UAAES,OAAO;UAAEyB;QAAK,CAAC,GAAG7B,IAAI;QAC9B,IAAI;UACA,MAAMC,KAAK,GAAG,MAAMN,OAAO,CAACO,GAAG,CAAC+B,WAAW,CAAC7B,OAAO,EAAEyB,IAAI,CAAC;UAC1D,OAAO,IAAIrC,QAAQ,CAACS,KAAK,CAAC;QAC9B,CAAC,CAAC,OAAOI,CAAC,EAAE;UACR,OAAO,IAAIf,aAAa,CAACe,CAAC,CAAC;QAC/B;MACJ,CAAC;MACD6B,kBAAkB,EAAE,MAAAA,CAAOnC,CAAU,EAAEC,IAAS,EAAEL,OAAO,KAAK;QAC1D,MAAM;UAAES;QAAQ,CAAC,GAAGJ,IAAI;QACxB,IAAI;UACA,MAAML,OAAO,CAACO,GAAG,CAACiC,WAAW,CAAC/B,OAAO,CAAC;UACtC,OAAO,IAAIZ,QAAQ,CAAC,IAAI,CAAC;QAC7B,CAAC,CAAC,OAAOa,CAAC,EAAE;UACR,OAAO,IAAIf,aAAa,CAACe,CAAC,CAAC;QAC/B;MACJ;IACJ,CAAC;IAEDoB,YAAY,GAAG,aAAc;AACrC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;EACL;EAEA,MAAMF,MAAM,GAAG9B,4BAA4B,CAAC;IACxC2C,QAAQ,EAAE,aAAc;AAChC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAcX,YAAY;AAC1B,SAAS;IACD7B;EACJ,CAAC,CAAC;EACF2B,MAAM,CAACc,IAAI,GAAG,+BAA+B1C,OAAO,CAACO,GAAG,CAACoC,IAAI,iBAAiB;EAC9E,OAAOf,MAAM;AACjB,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["ErrorResponse","NotFoundError","Response","createCmsGraphQLSchemaPlugin","createModelsSchema","context","resolvers","Query","getContentModel","_","args","model","cms","getModel","modelId","e","listContentModels","models","listModels","includePrivate","includePlugins","CmsContentModelField","renderer","field","settings","tags","Array","isArray","CmsContentModel","hasType","find","tag","startsWith","plugin","isPlugin","manageSchema","MANAGE","createContentModel","createModel","data","createContentModelFrom","createModelFrom","updateContentModel","updateModel","deleteContentModel","deleteModel","typeDefs","name","type"],"sources":["contentModels.ts"],"sourcesContent":["import { ErrorResponse, NotFoundError, Response } from \"@webiny/handler-graphql\";\nimport type { CmsContext, CmsModel } from \"~/types/index.js\";\nimport type { Resolvers } from \"@webiny/handler-graphql/types.js\";\nimport type { ICmsGraphQLSchemaPlugin } from \"~/plugins/index.js\";\nimport { createCmsGraphQLSchemaPlugin } from \"~/plugins/index.js\";\nimport type { GenericRecord } from \"@webiny/api/types.js\";\n\nexport interface CreateModelsSchemaParams {\n context: CmsContext;\n}\n\nexport const createModelsSchema = ({\n context\n}: CreateModelsSchemaParams): ICmsGraphQLSchemaPlugin => {\n const resolvers: Resolvers<CmsContext> = {\n Query: {\n getContentModel: async (_: unknown, args: GenericRecord, context) => {\n try {\n const model = await context.cms.getModel(args.modelId);\n\n if (!model) {\n throw new NotFoundError(`Content model \"${args.modelId}\" was not found!`);\n }\n\n return new Response(model);\n } catch (e) {\n return new ErrorResponse(e);\n }\n },\n listContentModels: async (_: unknown, args: GenericRecord, context: CmsContext) => {\n try {\n const models = await context.cms.listModels({\n includePrivate: false,\n includePlugins: args?.includePlugins === false ? false : true\n });\n return new Response(models);\n } catch (e) {\n return new ErrorResponse(e);\n }\n }\n },\n CmsContentModelField: {\n renderer: field => {\n // Make sure `settings` is an object.\n if (field.renderer) {\n // We're using `||` here, because we want to use the fallback value for both `undefined` and `null`.\n return { ...field.renderer, settings: field.renderer.settings || {} };\n }\n\n return field.renderer;\n },\n tags(field) {\n // Make sure `tags` are always returned as an array.\n return Array.isArray(field.tags) ? field.tags : [];\n }\n },\n CmsContentModel: {\n tags(model: CmsModel) {\n // Make sure `tags` always contain a `type` tag, to differentiate between models.\n const hasType = (model.tags || []).find(tag => tag.startsWith(\"type:\"));\n\n return hasType ? model.tags : [\"type:model\", ...(model.tags || [])];\n },\n plugin: (model: CmsModel) => {\n return model.isPlugin ?? false;\n }\n }\n };\n\n let manageSchema = \"\";\n if (context.cms.MANAGE) {\n resolvers[\"Mutation\"] = {\n createContentModel: async (_: unknown, args: any, context) => {\n try {\n const model = await context.cms.createModel(args.data);\n return new Response(model);\n } catch (e) {\n return new ErrorResponse(e);\n }\n },\n createContentModelFrom: async (_: unknown, args: any, context) => {\n try {\n const model = await context.cms.createModelFrom(args.modelId, args.data);\n return new Response(model);\n } catch (e) {\n return new ErrorResponse(e);\n }\n },\n updateContentModel: async (_: unknown, args: any, context) => {\n const { modelId, data } = args;\n try {\n const model = await context.cms.updateModel(modelId, data);\n return new Response(model);\n } catch (e) {\n return new ErrorResponse(e);\n }\n },\n deleteContentModel: async (_: unknown, args: any, context) => {\n const { modelId } = args;\n try {\n await context.cms.deleteModel(modelId);\n return new Response(true);\n } catch (e) {\n return new ErrorResponse(e);\n }\n }\n };\n\n manageSchema = /* GraphQL */ `\n input CmsPredefinedValueInput {\n label: String!\n value: String!\n selected: Boolean\n }\n\n input CmsPredefinedValuesInput {\n enabled: Boolean\n values: [CmsPredefinedValueInput]\n }\n input CmsFieldRendererInput {\n name: String\n settings: JSON\n }\n\n input CmsFieldValidationInput {\n name: String!\n message: String\n settings: JSON\n }\n\n input CmsFieldRuleInput {\n type: String!\n target: String!\n operator: String!\n value: JSON\n action: String!\n }\n\n input CmsContentModelFieldInput {\n id: ID!\n label: String!\n help: String\n description: String\n note: String\n placeholder: String\n # we never use user input - this is here to the GraphQL does not break when posting from our UI\n # used for debugging purposes\n storageId: String\n fieldId: String!\n type: String!\n tags: [String!]\n list: Boolean\n predefinedValues: CmsPredefinedValuesInput\n renderer: CmsFieldRendererInput\n validation: [CmsFieldValidationInput]\n listValidation: [CmsFieldValidationInput]\n settings: JSON\n rules: [CmsFieldRuleInput!]\n }\n\n input CmsContentModelCreateInput {\n name: String!\n singularApiName: String!\n pluralApiName: String!\n modelId: String\n group: String!\n icon: Icon\n singleEntry: Boolean\n description: String\n layout: JSON\n fields: [CmsContentModelFieldInput!]\n titleFieldId: String\n descriptionFieldId: String\n imageFieldId: String\n tags: [String!]\n defaultFields: Boolean\n }\n\n input CmsContentModelCreateFromInput {\n name: String!\n singularApiName: String!\n pluralApiName: String!\n modelId: String\n group: String!\n icon: Icon\n description: String\n }\n\n input CmsContentModelUpdateInput {\n name: String\n singularApiName: String\n pluralApiName: String\n group: String\n icon: Icon\n description: String\n layout: JSON!\n fields: [CmsContentModelFieldInput!]!\n titleFieldId: String\n descriptionFieldId: String\n imageFieldId: String\n tags: [String!]\n }\n\n extend type Mutation {\n createContentModel(data: CmsContentModelCreateInput!): CmsContentModelResponse\n\n createContentModelFrom(\n modelId: ID!\n data: CmsContentModelCreateFromInput!\n ): CmsContentModelResponse\n\n updateContentModel(\n modelId: ID!\n data: CmsContentModelUpdateInput!\n ): CmsContentModelResponse\n\n deleteContentModel(modelId: ID!): CmsDeleteResponse\n }\n `;\n }\n\n const plugin = createCmsGraphQLSchemaPlugin({\n typeDefs: /* GraphQL */ `\n type CmsFieldValidation {\n name: String!\n message: String\n settings: JSON\n }\n\n type CmsFieldRenderer {\n name: String\n settings: JSON\n }\n\n type CmsPredefinedValue {\n label: String\n value: String\n selected: Boolean\n }\n\n type CmsPredefinedValues {\n enabled: Boolean\n values: [CmsPredefinedValue]\n }\n\n type CmsFieldRule {\n type: String!\n target: String!\n operator: String!\n value: JSON\n action: String!\n }\n\n type CmsContentModelField {\n id: ID!\n # auto-generated value\n # used for debugging purposes\n storageId: String\n fieldId: String!\n label: String!\n help: String\n description: String\n note: String\n placeholder: String\n type: String!\n tags: [String!]!\n list: Boolean\n predefinedValues: CmsPredefinedValues\n renderer: CmsFieldRenderer\n validation: [CmsFieldValidation!]\n listValidation: [CmsFieldValidation!]\n settings: JSON\n rules: [CmsFieldRule!]\n }\n\n type CmsContentModel {\n name: String!\n singularApiName: String!\n pluralApiName: String!\n modelId: String!\n description: String\n group: String!\n icon: Icon\n createdOn: DateTime\n savedOn: DateTime\n createdBy: CmsIdentity\n fields: [CmsContentModelField!]!\n layout: JSON!\n titleFieldId: String\n descriptionFieldId: String\n imageFieldId: String\n tags: [String!]!\n tenant: String!\n # Returns true if the content model is registered via a plugin.\n plugin: Boolean!\n }\n\n type CmsContentModelResponse {\n data: CmsContentModel\n error: CmsError\n }\n\n type CmsContentModelListResponse {\n data: [CmsContentModel]\n meta: CmsListMeta\n error: CmsError\n }\n\n extend type Query {\n getContentModel(modelId: ID!, where: JSON, sort: String): CmsContentModelResponse\n\n listContentModels(includePlugins: Boolean = true): CmsContentModelListResponse\n }\n\n ${manageSchema}\n `,\n resolvers\n });\n plugin.name = `headless-cms.graphql.schema.${context.cms.type}.content-models`;\n return plugin;\n};\n"],"mappings":"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MAAM;UAAES,OAAO;UAAEyB;QAAK,CAAC,GAAG7B,IAAI;QAC9B,IAAI;UACA,MAAMC,KAAK,GAAG,MAAMN,OAAO,CAACO,GAAG,CAAC+B,WAAW,CAAC7B,OAAO,EAAEyB,IAAI,CAAC;UAC1D,OAAO,IAAIrC,QAAQ,CAACS,KAAK,CAAC;QAC9B,CAAC,CAAC,OAAOI,CAAC,EAAE;UACR,OAAO,IAAIf,aAAa,CAACe,CAAC,CAAC;QAC/B;MACJ,CAAC;MACD6B,kBAAkB,EAAE,MAAAA,CAAOnC,CAAU,EAAEC,IAAS,EAAEL,OAAO,KAAK;QAC1D,MAAM;UAAES;QAAQ,CAAC,GAAGJ,IAAI;QACxB,IAAI;UACA,MAAML,OAAO,CAACO,GAAG,CAACiC,WAAW,CAAC/B,OAAO,CAAC;UACtC,OAAO,IAAIZ,QAAQ,CAAC,IAAI,CAAC;QAC7B,CAAC,CAAC,OAAOa,CAAC,EAAE;UACR,OAAO,IAAIf,aAAa,CAACe,CAAC,CAAC;QAC/B;MACJ;IACJ,CAAC;IAEDoB,YAAY,GAAG,aAAc;AACrC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;EACL;EAEA,MAAMF,MAAM,GAAG9B,4BAA4B,CAAC;IACxC2C,QAAQ,EAAE,aAAc;AAChC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAcX,YAAY;AAC1B,SAAS;IACD7B;EACJ,CAAC,CAAC;EACF2B,MAAM,CAACc,IAAI,GAAG,+BAA+B1C,OAAO,CAACO,GAAG,CAACoC,IAAI,iBAAiB;EAC9E,OAAOf,MAAM;AACjB,CAAC","ignoreList":[]}
@@ -10,7 +10,6 @@ import { createObjectField } from "./object.js";
10
10
  import { createDynamicZoneField } from "./dynamicZone/index.js";
11
11
  import { createJsonField } from "./json.js";
12
12
  import { createSearchableJsonField } from "./searchableJson.js";
13
- import { createUiField } from "./ui.js";
14
- export const createGraphQLFields = () => [createTextField(), createRefField(), createNumberField(), createDateTimeField(), createBooleanField(), createLongTextField(), createRichTextField(), createJsonField(), createSearchableJsonField(), createFileField(), createObjectField(), createDynamicZoneField(), createUiField()];
13
+ export const createGraphQLFields = () => [createTextField(), createRefField(), createNumberField(), createDateTimeField(), createBooleanField(), createLongTextField(), createRichTextField(), createJsonField(), createSearchableJsonField(), createFileField(), createObjectField(), createDynamicZoneField()];
15
14
 
16
15
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["createTextField","createLongTextField","createRefField","createNumberField","createBooleanField","createDateTimeField","createRichTextField","createFileField","createObjectField","createDynamicZoneField","createJsonField","createSearchableJsonField","createUiField","createGraphQLFields"],"sources":["index.ts"],"sourcesContent":["import { createTextField } from \"./text.js\";\nimport { createLongTextField } from \"./longText.js\";\nimport { createRefField } from \"./ref.js\";\nimport { createNumberField } from \"./number.js\";\nimport { createBooleanField } from \"./boolean.js\";\nimport { createDateTimeField } from \"./datetime.js\";\nimport { createRichTextField } from \"./richText.js\";\nimport { createFileField } from \"./file.js\";\nimport { createObjectField } from \"./object.js\";\nimport { createDynamicZoneField } from \"./dynamicZone/index.js\";\nimport type { CmsModelFieldToGraphQLPlugin } from \"~/types/index.js\";\nimport { createJsonField } from \"./json.js\";\nimport { createSearchableJsonField } from \"./searchableJson.js\";\nimport { createUiField } from \"./ui.js\";\n\nexport const createGraphQLFields = (): CmsModelFieldToGraphQLPlugin<any>[] => [\n createTextField(),\n createRefField(),\n createNumberField(),\n createDateTimeField(),\n createBooleanField(),\n createLongTextField(),\n createRichTextField(),\n createJsonField(),\n createSearchableJsonField(),\n createFileField(),\n createObjectField(),\n createDynamicZoneField(),\n createUiField()\n];\n"],"mappings":"AAAA,SAASA,eAAe;AACxB,SAASC,mBAAmB;AAC5B,SAASC,cAAc;AACvB,SAASC,iBAAiB;AAC1B,SAASC,kBAAkB;AAC3B,SAASC,mBAAmB;AAC5B,SAASC,mBAAmB;AAC5B,SAASC,eAAe;AACxB,SAASC,iBAAiB;AAC1B,SAASC,sBAAsB;AAE/B,SAASC,eAAe;AACxB,SAASC,yBAAyB;AAClC,SAASC,aAAa;AAEtB,OAAO,MAAMC,mBAAmB,GAAGA,CAAA,KAA2C,CAC1Eb,eAAe,CAAC,CAAC,EACjBE,cAAc,CAAC,CAAC,EAChBC,iBAAiB,CAAC,CAAC,EACnBE,mBAAmB,CAAC,CAAC,EACrBD,kBAAkB,CAAC,CAAC,EACpBH,mBAAmB,CAAC,CAAC,EACrBK,mBAAmB,CAAC,CAAC,EACrBI,eAAe,CAAC,CAAC,EACjBC,yBAAyB,CAAC,CAAC,EAC3BJ,eAAe,CAAC,CAAC,EACjBC,iBAAiB,CAAC,CAAC,EACnBC,sBAAsB,CAAC,CAAC,EACxBG,aAAa,CAAC,CAAC,CAClB","ignoreList":[]}
1
+ {"version":3,"names":["createTextField","createLongTextField","createRefField","createNumberField","createBooleanField","createDateTimeField","createRichTextField","createFileField","createObjectField","createDynamicZoneField","createJsonField","createSearchableJsonField","createGraphQLFields"],"sources":["index.ts"],"sourcesContent":["import { createTextField } from \"./text.js\";\nimport { createLongTextField } from \"./longText.js\";\nimport { createRefField } from \"./ref.js\";\nimport { createNumberField } from \"./number.js\";\nimport { createBooleanField } from \"./boolean.js\";\nimport { createDateTimeField } from \"./datetime.js\";\nimport { createRichTextField } from \"./richText.js\";\nimport { createFileField } from \"./file.js\";\nimport { createObjectField } from \"./object.js\";\nimport { createDynamicZoneField } from \"./dynamicZone/index.js\";\nimport type { CmsModelFieldToGraphQLPlugin } from \"~/types/index.js\";\nimport { createJsonField } from \"./json.js\";\nimport { createSearchableJsonField } from \"./searchableJson.js\";\n\nexport const createGraphQLFields = (): CmsModelFieldToGraphQLPlugin<any>[] => [\n createTextField(),\n createRefField(),\n createNumberField(),\n createDateTimeField(),\n createBooleanField(),\n createLongTextField(),\n createRichTextField(),\n createJsonField(),\n createSearchableJsonField(),\n createFileField(),\n createObjectField(),\n createDynamicZoneField()\n];\n"],"mappings":"AAAA,SAASA,eAAe;AACxB,SAASC,mBAAmB;AAC5B,SAASC,cAAc;AACvB,SAASC,iBAAiB;AAC1B,SAASC,kBAAkB;AAC3B,SAASC,mBAAmB;AAC5B,SAASC,mBAAmB;AAC5B,SAASC,eAAe;AACxB,SAASC,iBAAiB;AAC1B,SAASC,sBAAsB;AAE/B,SAASC,eAAe;AACxB,SAASC,yBAAyB;AAElC,OAAO,MAAMC,mBAAmB,GAAGA,CAAA,KAA2C,CAC1EZ,eAAe,CAAC,CAAC,EACjBE,cAAc,CAAC,CAAC,EAChBC,iBAAiB,CAAC,CAAC,EACnBE,mBAAmB,CAAC,CAAC,EACrBD,kBAAkB,CAAC,CAAC,EACpBH,mBAAmB,CAAC,CAAC,EACrBK,mBAAmB,CAAC,CAAC,EACrBI,eAAe,CAAC,CAAC,EACjBC,yBAAyB,CAAC,CAAC,EAC3BJ,eAAe,CAAC,CAAC,EACjBC,iBAAiB,CAAC,CAAC,EACnBC,sBAAsB,CAAC,CAAC,CAC3B","ignoreList":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webiny/api-headless-cms",
3
- "version": "6.0.0-rc.2",
3
+ "version": "6.0.0-rc.4",
4
4
  "type": "module",
5
5
  "main": "index.js",
6
6
  "keywords": [
@@ -22,19 +22,19 @@
22
22
  "@babel/code-frame": "7.29.0",
23
23
  "@graphql-tools/merge": "9.1.7",
24
24
  "@graphql-tools/schema": "10.0.31",
25
- "@webiny/api": "6.0.0-rc.2",
26
- "@webiny/api-core": "6.0.0-rc.2",
25
+ "@webiny/api": "6.0.0-rc.4",
26
+ "@webiny/api-core": "6.0.0-rc.4",
27
27
  "@webiny/di": "0.2.3",
28
- "@webiny/error": "6.0.0-rc.2",
29
- "@webiny/feature": "6.0.0-rc.2",
30
- "@webiny/handler": "6.0.0-rc.2",
31
- "@webiny/handler-aws": "6.0.0-rc.2",
32
- "@webiny/handler-db": "6.0.0-rc.2",
33
- "@webiny/handler-graphql": "6.0.0-rc.2",
34
- "@webiny/plugins": "6.0.0-rc.2",
35
- "@webiny/project": "6.0.0-rc.2",
36
- "@webiny/utils": "6.0.0-rc.2",
37
- "@webiny/validation": "6.0.0-rc.2",
28
+ "@webiny/error": "6.0.0-rc.4",
29
+ "@webiny/feature": "6.0.0-rc.4",
30
+ "@webiny/handler": "6.0.0-rc.4",
31
+ "@webiny/handler-aws": "6.0.0-rc.4",
32
+ "@webiny/handler-db": "6.0.0-rc.4",
33
+ "@webiny/handler-graphql": "6.0.0-rc.4",
34
+ "@webiny/plugins": "6.0.0-rc.4",
35
+ "@webiny/project": "6.0.0-rc.4",
36
+ "@webiny/utils": "6.0.0-rc.4",
37
+ "@webiny/validation": "6.0.0-rc.4",
38
38
  "dot-prop-immutable": "2.1.1",
39
39
  "graphql": "16.13.0",
40
40
  "graphql-tag": "2.12.6",
@@ -48,13 +48,13 @@
48
48
  "devDependencies": {
49
49
  "@types/babel__code-frame": "7.27.0",
50
50
  "@types/pluralize": "0.0.33",
51
- "@webiny/aws-sdk": "6.0.0-rc.2",
52
- "@webiny/build-tools": "6.0.0-rc.2",
53
- "@webiny/db-dynamodb": "6.0.0-rc.2",
51
+ "@webiny/aws-sdk": "6.0.0-rc.4",
52
+ "@webiny/build-tools": "6.0.0-rc.4",
53
+ "@webiny/db-dynamodb": "6.0.0-rc.4",
54
54
  "@webiny/handler-db": "0.0.0",
55
- "@webiny/project-utils": "6.0.0-rc.2",
56
- "@webiny/sdk": "6.0.0-rc.2",
57
- "@webiny/wcp": "6.0.0-rc.2",
55
+ "@webiny/project-utils": "6.0.0-rc.4",
56
+ "@webiny/sdk": "6.0.0-rc.4",
57
+ "@webiny/wcp": "6.0.0-rc.4",
58
58
  "apollo-graphql": "0.9.7",
59
59
  "graphql": "16.13.0",
60
60
  "prettier": "3.6.2",
@@ -67,5 +67,5 @@
67
67
  "access": "public",
68
68
  "directory": "dist"
69
69
  },
70
- "gitHead": "5facada4cbb8617cc60e3c98be0f1839f44be38e"
70
+ "gitHead": "e2758ee1cfa3b9a7152e9bb995a90ccabd33266f"
71
71
  }
@@ -168,12 +168,27 @@ export class CmsModelPlugin extends Plugin {
168
168
  if (this.options.validateLayout === false) {
169
169
  return;
170
170
  }
171
- for (const field of model.fields) {
171
+ const countFieldInLayout = (fieldId, layout) => {
172
172
  let total = 0;
173
- for (const row of model.layout) {
174
- const count = row.filter(cell => cell === field.id).length;
175
- total = total + count;
173
+ for (const row of layout) {
174
+ for (const cell of row) {
175
+ if (typeof cell === "string") {
176
+ if (cell === fieldId) {
177
+ total++;
178
+ }
179
+ } else if (cell && typeof cell === "object" && Array.isArray(cell.tabs)) {
180
+ for (const tab of cell.tabs) {
181
+ if (Array.isArray(tab.layout)) {
182
+ total += countFieldInLayout(fieldId, tab.layout);
183
+ }
184
+ }
185
+ }
186
+ }
176
187
  }
188
+ return total;
189
+ };
190
+ for (const field of model.fields) {
191
+ const total = countFieldInLayout(field.id, model.layout);
177
192
  if (total === 1) {
178
193
  continue;
179
194
  } else if (total > 1) {
@@ -1 +1 @@
1
- {"version":3,"names":["WebinyError","lodashCamelCase","camelCase","upperFirst","pluralize","Plugin","createFieldStorageId","validateStorageId","createApiName","name","createPluralApiName","CmsModelPlugin","type","constructor","contentModel","options","buildModel","input","isPrivate","singularApiName","pluralApiName","modelPlugin","group","description","fields","isPlugin","icon","layout","modelId","titleFieldId","noValidate","model","buildFields","validateLayout","inputFields","length","storageIdList","fieldIdList","fieldId","trim","field","match","includes","id","storageId","e","from","data","settings","childFields","push","total","row","count","filter","cell","createModelPlugin","createPrivateModelPlugin","authorization"],"sources":["CmsModelPlugin.ts"],"sourcesContent":["import WebinyError from \"@webiny/error\";\nimport lodashCamelCase from \"lodash/camelCase.js\";\nimport camelCase from \"lodash/camelCase.js\";\nimport upperFirst from \"lodash/upperFirst.js\";\nimport pluralize from \"pluralize\";\nimport { Plugin } from \"@webiny/plugins\";\nimport type {\n CmsModel as CmsModelBase,\n CmsModelField as CmsModelFieldBase,\n CmsModelFieldSettings as BaseCmsModelFieldSettings\n} from \"~/types/index.js\";\nimport { createFieldStorageId } from \"~/crud/contentModel/createFieldStorageId.js\";\nimport { validateStorageId } from \"~/crud/contentModel/validateStorageId.js\";\n\nconst createApiName = (name: string) => {\n return upperFirst(camelCase(name));\n};\n\nconst createPluralApiName = (name: string) => {\n return pluralize(createApiName(name));\n};\n\ninterface CmsModelFieldSettings extends Omit<BaseCmsModelFieldSettings, \"fields\"> {\n /**\n * Object field has child fields.\n */\n fields?: CmsModelFieldInput[];\n}\n\ninterface CmsModelFieldInput extends Omit<CmsModelFieldBase, \"storageId\" | \"settings\"> {\n /**\n * If defined, it must be camelCased string.\n * This is for backwards compatibility - before fields had storageId.\n *\n * This should only be populated in old model fields.\n * New ones must have this empty.\n */\n storageId?: string;\n /**\n * We must have a possibility to have a nested field defined without the storageId.\n */\n settings?: CmsModelFieldSettings;\n}\n\nexport interface CmsApiModel\n extends Omit<\n CmsModelPluginModel,\n \"isPrivate\" | \"fields\" | \"singularApiName\" | \"pluralApiName\" | \"isPlugin\"\n > {\n isPrivate?: never;\n noValidate?: boolean;\n singularApiName?: string;\n pluralApiName?: string;\n fields: CmsModelFieldInput[];\n}\n\nexport interface CmsApiModelFull extends Omit<CmsApiModel, \"fields\"> {\n fields: CmsModelFieldBase[];\n}\n\ninterface CmsPrivateModel\n extends Omit<\n CmsModelPluginModel,\n | \"isPrivate\"\n | \"singularApiName\"\n | \"pluralApiName\"\n | \"fields\"\n | \"isPlugin\"\n | \"layout\"\n | \"icon\"\n | \"titleFieldId\"\n | \"description\"\n > {\n noValidate?: boolean;\n titleFieldId?: string;\n singularApiName?: never;\n pluralApiName?: never;\n isPrivate: true;\n fields: CmsModelFieldInput[];\n}\n\nexport interface CmsPrivateModelFull\n extends Omit<CmsPrivateModel, \"fields\" | \"createdBy\" | \"createdOn\" | \"savedOn\"> {\n fields: CmsModelFieldBase[];\n}\n\nexport type CmsModelInput = CmsApiModel | CmsPrivateModel | CmsApiModelFull | CmsPrivateModelFull;\n\nexport interface CmsModelPluginModel extends Omit<CmsModelBase, \"tenant\"> {\n tenant?: string;\n}\n\ninterface CmsModelPluginOptions {\n validateLayout?: boolean;\n}\n\nexport class CmsModelPlugin extends Plugin {\n public static override readonly type: string = \"cms-content-model\";\n public readonly contentModel: CmsModelPluginModel;\n\n private readonly options: CmsModelPluginOptions;\n\n constructor(contentModel: CmsModelInput, options?: CmsModelPluginOptions) {\n super();\n this.options = options || {};\n this.contentModel = this.buildModel(contentModel);\n }\n\n private buildModel(input: CmsModelInput): CmsModelPluginModel {\n const isPrivate = input.isPrivate ?? false;\n\n const singularApiName = input.singularApiName\n ? createApiName(input.singularApiName)\n : createApiName(input.name);\n\n const pluralApiName = input.pluralApiName\n ? createApiName(input.pluralApiName)\n : createPluralApiName(input.name);\n\n const modelPlugin: CmsModelPluginModel = {\n group: input.group ?? \"ungrouped\",\n description: \"\",\n fields: [],\n isPlugin: true,\n isPrivate,\n icon: null,\n layout: [],\n modelId: input.modelId,\n name: input.name,\n pluralApiName,\n singularApiName,\n titleFieldId: \"id\"\n };\n\n if (input.noValidate) {\n /**\n * We can safely ignore this error, because we are sure noValidate is not a model field.\n */\n delete input[\"noValidate\"];\n\n return {\n ...modelPlugin,\n ...input,\n // Since `noValidate` is set, we trust the input, and cast to `CmsModelFieldBase`.\n fields: input.fields as CmsModelFieldBase[],\n pluralApiName,\n singularApiName\n };\n }\n\n const model: CmsModelPluginModel = {\n ...modelPlugin,\n ...input,\n pluralApiName,\n singularApiName,\n fields: this.buildFields(input, input.fields)\n };\n this.validateLayout(model);\n return model;\n }\n\n private buildFields(\n model: CmsModelInput,\n inputFields: CmsModelFieldInput[]\n ): CmsModelFieldBase[] {\n if (inputFields.length === 0) {\n throw new WebinyError(\n `Missing fields for the defined model \"${model.modelId}\".`,\n \"MISSING_FIELDS\",\n {\n model\n }\n );\n }\n const fields: CmsModelFieldBase[] = [];\n const storageIdList: string[] = [];\n const fieldIdList: string[] = [];\n for (const input of inputFields) {\n /**\n * Field must contain an fieldId. It is required in the graphql, but lets check it just in case\n */\n if (!(input.fieldId || \"\").trim()) {\n throw new WebinyError(\n `Field's \"storageId\" is not defined for the content model \"${model.modelId}\".`,\n \"FIELD_ID_ERROR\",\n {\n model,\n field: input\n }\n );\n }\n const fieldId = lodashCamelCase(input.fieldId);\n /**\n * FieldID must be in correct pattern.\n */\n if (fieldId.match(/^[0-9]/) !== null) {\n throw new WebinyError(\n `Field's \"fieldId\" does not match correct pattern in the content model \"${model.modelId}\" - cannot start with a number.`,\n \"FIELD_FIELD_ID_ERROR\",\n {\n model,\n field: input\n }\n );\n }\n /**\n * FieldID also must be camelCased.\n */\n if (fieldId !== input.fieldId) {\n throw new WebinyError(\n `Field's \"fieldId\" must be a camel cased string in the content model \"${model.modelId}\".`,\n \"FIELD_FIELD_ID_ERROR\",\n {\n model,\n field: input\n }\n );\n }\n /**\n * ... and fieldId must be unique.\n */\n if (fieldIdList.includes(fieldId)) {\n throw new WebinyError(\n `Field's \"fieldId\" (id: ${input.id}) is not unique in the content model \"${model.modelId}\".`,\n \"FIELD_ID_NOT_UNIQUE_ERROR\",\n {\n model,\n field: input\n }\n );\n }\n\n let storageId = input.storageId;\n if (storageId) {\n try {\n validateStorageId(storageId);\n } catch (e) {\n throw WebinyError.from(e, {\n data: { model, storageId, field: input }\n });\n }\n } else {\n storageId = createFieldStorageId(input);\n }\n\n /**\n * Fields storageId must be unique.\n */\n if (storageIdList.includes(storageId)) {\n throw new WebinyError(\n `Field's \"storageId\" is not unique in the content model \"${model.modelId}\".`,\n \"STORAGE_ID_ERROR\",\n {\n model,\n field: input\n }\n );\n }\n\n /**\n * We can safely ignore error because we are going through the fields and making sure each has storageId.\n */\n // @ts-expect-error\n let settings: BaseCmsModelFieldSettings = input.settings;\n\n const childFields = settings?.fields || [];\n if (input.type === \"object\" && childFields.length > 0) {\n settings = {\n ...(settings || {}),\n fields: this.buildFields(model, childFields)\n };\n }\n\n const field: CmsModelFieldBase = {\n ...input,\n settings,\n storageId\n };\n /**\n * Add all relevant data to arrays.\n */\n fields.push(field);\n storageIdList.push(field.storageId);\n fieldIdList.push(field.fieldId);\n }\n return fields;\n }\n\n private validateLayout(model: CmsModelPluginModel): void {\n /**\n * Only skip validation if option.validateLayout was set as false, explicitly.\n */\n if (this.options.validateLayout === false) {\n return;\n }\n for (const field of model.fields) {\n let total = 0;\n for (const row of model.layout) {\n const count = row.filter(cell => cell === field.id).length;\n total = total + count;\n }\n if (total === 1) {\n continue;\n } else if (total > 1) {\n throw new WebinyError(\n `Field \"${field.id}\" is in more than one layout cell.`,\n \"DUPLICATE_FIELD_IN_LAYOUT\",\n {\n model,\n field\n }\n );\n }\n throw new WebinyError(\n `Missing field \"${field.id}\" in layout.`,\n \"MISSING_FIELD_IN_LAYOUT\",\n {\n model,\n field\n }\n );\n }\n }\n}\n\n/**\n * IMPORTANT! This function should NOT be used outside the `api-headless-cms` package!\n * @internal\n */\nexport const createModelPlugin = (\n model: CmsModelInput,\n options?: CmsModelPluginOptions\n): CmsModelPlugin => {\n return new CmsModelPlugin(model, options);\n};\n\n/**\n * IMPORTANT! This function should NOT be used outside the `api-headless-cms` package!\n * @internal\n */\nexport const createPrivateModelPlugin = (\n input: Omit<CmsPrivateModelFull, \"group\" | \"isPrivate\">\n): CmsModelPlugin => {\n return createModelPlugin(\n {\n authorization: false,\n noValidate: true,\n isPrivate: true,\n group: \"private\",\n ...input\n },\n {\n validateLayout: false\n }\n );\n};\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["WebinyError","lodashCamelCase","camelCase","upperFirst","pluralize","Plugin","createFieldStorageId","validateStorageId","createApiName","name","createPluralApiName","CmsModelPlugin","type","constructor","contentModel","options","buildModel","input","isPrivate","singularApiName","pluralApiName","modelPlugin","group","description","fields","isPlugin","icon","layout","modelId","titleFieldId","noValidate","model","buildFields","validateLayout","inputFields","length","storageIdList","fieldIdList","fieldId","trim","field","match","includes","id","storageId","e","from","data","settings","childFields","push","countFieldInLayout","total","row","cell","Array","isArray","tabs","tab","createModelPlugin","createPrivateModelPlugin","authorization"],"sources":["CmsModelPlugin.ts"],"sourcesContent":["import WebinyError from \"@webiny/error\";\nimport lodashCamelCase from \"lodash/camelCase.js\";\nimport camelCase from \"lodash/camelCase.js\";\nimport upperFirst from \"lodash/upperFirst.js\";\nimport pluralize from \"pluralize\";\nimport { Plugin } from \"@webiny/plugins\";\nimport type {\n CmsModel as CmsModelBase,\n CmsModelField as CmsModelFieldBase,\n CmsModelFieldSettings as BaseCmsModelFieldSettings\n} from \"~/types/index.js\";\nimport { createFieldStorageId } from \"~/crud/contentModel/createFieldStorageId.js\";\nimport { validateStorageId } from \"~/crud/contentModel/validateStorageId.js\";\n\nconst createApiName = (name: string) => {\n return upperFirst(camelCase(name));\n};\n\nconst createPluralApiName = (name: string) => {\n return pluralize(createApiName(name));\n};\n\ninterface CmsModelFieldSettings extends Omit<BaseCmsModelFieldSettings, \"fields\"> {\n /**\n * Object field has child fields.\n */\n fields?: CmsModelFieldInput[];\n}\n\ninterface CmsModelFieldInput extends Omit<CmsModelFieldBase, \"storageId\" | \"settings\"> {\n /**\n * If defined, it must be camelCased string.\n * This is for backwards compatibility - before fields had storageId.\n *\n * This should only be populated in old model fields.\n * New ones must have this empty.\n */\n storageId?: string;\n /**\n * We must have a possibility to have a nested field defined without the storageId.\n */\n settings?: CmsModelFieldSettings;\n}\n\nexport interface CmsApiModel\n extends Omit<\n CmsModelPluginModel,\n \"isPrivate\" | \"fields\" | \"singularApiName\" | \"pluralApiName\" | \"isPlugin\"\n > {\n isPrivate?: never;\n noValidate?: boolean;\n singularApiName?: string;\n pluralApiName?: string;\n fields: CmsModelFieldInput[];\n}\n\nexport interface CmsApiModelFull extends Omit<CmsApiModel, \"fields\"> {\n fields: CmsModelFieldBase[];\n}\n\ninterface CmsPrivateModel\n extends Omit<\n CmsModelPluginModel,\n | \"isPrivate\"\n | \"singularApiName\"\n | \"pluralApiName\"\n | \"fields\"\n | \"isPlugin\"\n | \"layout\"\n | \"icon\"\n | \"titleFieldId\"\n | \"description\"\n > {\n noValidate?: boolean;\n titleFieldId?: string;\n singularApiName?: never;\n pluralApiName?: never;\n isPrivate: true;\n fields: CmsModelFieldInput[];\n}\n\nexport interface CmsPrivateModelFull\n extends Omit<CmsPrivateModel, \"fields\" | \"createdBy\" | \"createdOn\" | \"savedOn\"> {\n fields: CmsModelFieldBase[];\n}\n\nexport type CmsModelInput = CmsApiModel | CmsPrivateModel | CmsApiModelFull | CmsPrivateModelFull;\n\nexport interface CmsModelPluginModel extends Omit<CmsModelBase, \"tenant\"> {\n tenant?: string;\n}\n\ninterface CmsModelPluginOptions {\n validateLayout?: boolean;\n}\n\nexport class CmsModelPlugin extends Plugin {\n public static override readonly type: string = \"cms-content-model\";\n public readonly contentModel: CmsModelPluginModel;\n\n private readonly options: CmsModelPluginOptions;\n\n constructor(contentModel: CmsModelInput, options?: CmsModelPluginOptions) {\n super();\n this.options = options || {};\n this.contentModel = this.buildModel(contentModel);\n }\n\n private buildModel(input: CmsModelInput): CmsModelPluginModel {\n const isPrivate = input.isPrivate ?? false;\n\n const singularApiName = input.singularApiName\n ? createApiName(input.singularApiName)\n : createApiName(input.name);\n\n const pluralApiName = input.pluralApiName\n ? createApiName(input.pluralApiName)\n : createPluralApiName(input.name);\n\n const modelPlugin: CmsModelPluginModel = {\n group: input.group ?? \"ungrouped\",\n description: \"\",\n fields: [],\n isPlugin: true,\n isPrivate,\n icon: null,\n layout: [],\n modelId: input.modelId,\n name: input.name,\n pluralApiName,\n singularApiName,\n titleFieldId: \"id\"\n };\n\n if (input.noValidate) {\n /**\n * We can safely ignore this error, because we are sure noValidate is not a model field.\n */\n delete input[\"noValidate\"];\n\n return {\n ...modelPlugin,\n ...input,\n // Since `noValidate` is set, we trust the input, and cast to `CmsModelFieldBase`.\n fields: input.fields as CmsModelFieldBase[],\n pluralApiName,\n singularApiName\n };\n }\n\n const model: CmsModelPluginModel = {\n ...modelPlugin,\n ...input,\n pluralApiName,\n singularApiName,\n fields: this.buildFields(input, input.fields)\n };\n this.validateLayout(model);\n return model;\n }\n\n private buildFields(\n model: CmsModelInput,\n inputFields: CmsModelFieldInput[]\n ): CmsModelFieldBase[] {\n if (inputFields.length === 0) {\n throw new WebinyError(\n `Missing fields for the defined model \"${model.modelId}\".`,\n \"MISSING_FIELDS\",\n {\n model\n }\n );\n }\n const fields: CmsModelFieldBase[] = [];\n const storageIdList: string[] = [];\n const fieldIdList: string[] = [];\n for (const input of inputFields) {\n /**\n * Field must contain an fieldId. It is required in the graphql, but lets check it just in case\n */\n if (!(input.fieldId || \"\").trim()) {\n throw new WebinyError(\n `Field's \"storageId\" is not defined for the content model \"${model.modelId}\".`,\n \"FIELD_ID_ERROR\",\n {\n model,\n field: input\n }\n );\n }\n const fieldId = lodashCamelCase(input.fieldId);\n /**\n * FieldID must be in correct pattern.\n */\n if (fieldId.match(/^[0-9]/) !== null) {\n throw new WebinyError(\n `Field's \"fieldId\" does not match correct pattern in the content model \"${model.modelId}\" - cannot start with a number.`,\n \"FIELD_FIELD_ID_ERROR\",\n {\n model,\n field: input\n }\n );\n }\n /**\n * FieldID also must be camelCased.\n */\n if (fieldId !== input.fieldId) {\n throw new WebinyError(\n `Field's \"fieldId\" must be a camel cased string in the content model \"${model.modelId}\".`,\n \"FIELD_FIELD_ID_ERROR\",\n {\n model,\n field: input\n }\n );\n }\n /**\n * ... and fieldId must be unique.\n */\n if (fieldIdList.includes(fieldId)) {\n throw new WebinyError(\n `Field's \"fieldId\" (id: ${input.id}) is not unique in the content model \"${model.modelId}\".`,\n \"FIELD_ID_NOT_UNIQUE_ERROR\",\n {\n model,\n field: input\n }\n );\n }\n\n let storageId = input.storageId;\n if (storageId) {\n try {\n validateStorageId(storageId);\n } catch (e) {\n throw WebinyError.from(e, {\n data: { model, storageId, field: input }\n });\n }\n } else {\n storageId = createFieldStorageId(input);\n }\n\n /**\n * Fields storageId must be unique.\n */\n if (storageIdList.includes(storageId)) {\n throw new WebinyError(\n `Field's \"storageId\" is not unique in the content model \"${model.modelId}\".`,\n \"STORAGE_ID_ERROR\",\n {\n model,\n field: input\n }\n );\n }\n\n /**\n * We can safely ignore error because we are going through the fields and making sure each has storageId.\n */\n // @ts-expect-error\n let settings: BaseCmsModelFieldSettings = input.settings;\n\n const childFields = settings?.fields || [];\n if (input.type === \"object\" && childFields.length > 0) {\n settings = {\n ...(settings || {}),\n fields: this.buildFields(model, childFields)\n };\n }\n\n const field: CmsModelFieldBase = {\n ...input,\n settings,\n storageId\n };\n /**\n * Add all relevant data to arrays.\n */\n fields.push(field);\n storageIdList.push(field.storageId);\n fieldIdList.push(field.fieldId);\n }\n return fields;\n }\n\n private validateLayout(model: CmsModelPluginModel): void {\n /**\n * Only skip validation if option.validateLayout was set as false, explicitly.\n */\n if (this.options.validateLayout === false) {\n return;\n }\n\n const countFieldInLayout = (fieldId: string, layout: any[][]): number => {\n let total = 0;\n for (const row of layout) {\n for (const cell of row) {\n if (typeof cell === \"string\") {\n if (cell === fieldId) {\n total++;\n }\n } else if (cell && typeof cell === \"object\" && Array.isArray(cell.tabs)) {\n for (const tab of cell.tabs) {\n if (Array.isArray(tab.layout)) {\n total += countFieldInLayout(fieldId, tab.layout);\n }\n }\n }\n }\n }\n return total;\n };\n\n for (const field of model.fields) {\n const total = countFieldInLayout(field.id, model.layout);\n if (total === 1) {\n continue;\n } else if (total > 1) {\n throw new WebinyError(\n `Field \"${field.id}\" is in more than one layout cell.`,\n \"DUPLICATE_FIELD_IN_LAYOUT\",\n {\n model,\n field\n }\n );\n }\n throw new WebinyError(\n `Missing field \"${field.id}\" in layout.`,\n \"MISSING_FIELD_IN_LAYOUT\",\n {\n model,\n field\n }\n );\n }\n }\n}\n\n/**\n * IMPORTANT! This function should NOT be used outside the `api-headless-cms` package!\n * @internal\n */\nexport const createModelPlugin = (\n model: CmsModelInput,\n options?: CmsModelPluginOptions\n): CmsModelPlugin => {\n return new CmsModelPlugin(model, options);\n};\n\n/**\n * IMPORTANT! This function should NOT be used outside the `api-headless-cms` package!\n * @internal\n */\nexport const createPrivateModelPlugin = (\n input: Omit<CmsPrivateModelFull, \"group\" | \"isPrivate\">\n): CmsModelPlugin => {\n return createModelPlugin(\n {\n authorization: false,\n noValidate: true,\n isPrivate: true,\n group: \"private\",\n ...input\n },\n {\n validateLayout: false\n }\n );\n};\n"],"mappings":"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","ignoreList":[]}
@@ -1,4 +1,5 @@
1
1
  import type { CmsModelField } from "../modelField.js";
2
+ import type { CmsModelLayout } from "../../types/index.js";
2
3
  /**
3
4
  * A definition for object field to show possible type of the field in settings.
4
5
  */
@@ -8,6 +9,7 @@ export interface CmsModelObjectField extends CmsModelField {
8
9
  */
9
10
  settings: {
10
11
  fields: CmsModelField[];
12
+ layout?: CmsModelLayout;
11
13
  parents?: string[];
12
14
  };
13
15
  }
@@ -1 +1 @@
1
- {"version":3,"names":[],"sources":["objectField.ts"],"sourcesContent":["import type { CmsModelField } from \"../modelField.js\";\n\n/**\n * A definition for object field to show possible type of the field in settings.\n */\nexport interface CmsModelObjectField extends CmsModelField {\n /**\n * Settings object for the field. Contains `templates` property.\n */\n settings: {\n fields: CmsModelField[];\n parents?: string[];\n };\n}\n"],"mappings":"","ignoreList":[]}
1
+ {"version":3,"names":[],"sources":["objectField.ts"],"sourcesContent":["import type { CmsModelField } from \"../modelField.js\";\nimport type { CmsModelLayout } from \"~/types/index.js\";\n\n/**\n * A definition for object field to show possible type of the field in settings.\n */\nexport interface CmsModelObjectField extends CmsModelField {\n /**\n * Settings object for the field. Contains `templates` property.\n */\n settings: {\n fields: CmsModelField[];\n layout?: CmsModelLayout;\n parents?: string[];\n };\n}\n"],"mappings":"","ignoreList":[]}
package/types/model.d.ts CHANGED
@@ -1,6 +1,35 @@
1
1
  import type { CmsIdentity } from "./identity.js";
2
- import type { CmsModelField, CmsModelFieldInput } from "./modelField.js";
2
+ import type { CmsModelField, CmsModelFieldInput, FieldRule } from "./modelField.js";
3
3
  import type { CmsIcon } from "../types/types.js";
4
+ export interface CmsTabLayoutTab {
5
+ id: string;
6
+ label: string;
7
+ icon?: CmsIcon | null;
8
+ layout: CmsModelLayout;
9
+ rules?: FieldRule[];
10
+ }
11
+ export interface CmsTabLayoutDescriptor {
12
+ type: "tabs";
13
+ label: string;
14
+ description?: string | null;
15
+ help?: string | null;
16
+ tabs: CmsTabLayoutTab[];
17
+ rules?: FieldRule[];
18
+ }
19
+ export interface CmsSeparatorLayoutDescriptor {
20
+ type: "separator";
21
+ label: string;
22
+ description: string | null | undefined;
23
+ rules?: FieldRule[];
24
+ }
25
+ export interface CmsAlertLayoutDescriptor {
26
+ type: "alert";
27
+ label: string;
28
+ alertType: "info" | "success" | "warning" | "danger";
29
+ rules?: FieldRule[];
30
+ }
31
+ export type CmsModelLayoutCell = string | CmsTabLayoutDescriptor | CmsSeparatorLayoutDescriptor | CmsAlertLayoutDescriptor;
32
+ export type CmsModelLayout = CmsModelLayoutCell[][];
4
33
  /**
5
34
  * Base CMS Model. Should not be exported and used outside of this package.
6
35
  *
@@ -76,7 +105,7 @@ export interface CmsModel {
76
105
  * ]
77
106
  * ```
78
107
  */
79
- layout: string[][];
108
+ layout: CmsModelLayout;
80
109
  /**
81
110
  * Models can be tagged to give them contextual meaning.
82
111
  */
@@ -161,7 +190,7 @@ export interface CmsModelCreateInput {
161
190
  * ]
162
191
  * ```
163
192
  */
164
- layout?: string[][];
193
+ layout?: CmsModelLayout;
165
194
  /**
166
195
  * Models can be tagged to give them contextual meaning.
167
196
  */
@@ -1 +1 @@
1
- {"version":3,"names":[],"sources":["model.ts"],"sourcesContent":["import type { CmsIdentity } from \"./identity.js\";\nimport type { CmsModelField, CmsModelFieldInput } from \"./modelField.js\";\nimport type { CmsIcon } from \"~/types/types.js\";\n\n/**\n * Base CMS Model. Should not be exported and used outside of this package.\n *\n * @category Database model\n * @category CmsModel\n */\nexport interface CmsModel {\n /**\n * Name of the content model.\n */\n name: string;\n /**\n * Unique ID for the content model. Created from name if not defined by user.\n */\n modelId: string;\n /**\n * Name of the content model in singular form to be used in the API.\n * example:\n * - Article\n * - Fruit\n * - Vegetable\n * - Car\n */\n singularApiName: string;\n /**\n * Name of the content model in plural form to be used in the API.\n * example:\n * - Articles\n * - Fruits\n * - Vegetables\n * - Cars\n */\n pluralApiName: string;\n /**\n * Model tenant.\n */\n tenant: string;\n /**\n * Model group slug.\n */\n group: string;\n /**\n * Icon for the content model.\n */\n icon: CmsIcon | null;\n /**\n * Description for the content model.\n */\n description: string | null;\n /**\n * Date created\n */\n createdOn?: string;\n /**\n * Date saved. Changes on both save and create.\n */\n savedOn?: string;\n /**\n * CreatedBy object wrapper. Contains id, name and type of the user.\n */\n createdBy?: CmsIdentity;\n /**\n * List of fields defining entry values.\n */\n fields: CmsModelField[];\n /**\n * Admin UI field layout\n *\n * ```ts\n * layout: [\n * [field1id, field2id],\n * [field3id]\n * ]\n * ```\n */\n layout: string[][];\n /**\n * Models can be tagged to give them contextual meaning.\n */\n tags?: string[];\n /**\n * The field that is used as an entry title.\n * If not specified by the user, the system tries to assign the first available `text` field.\n */\n titleFieldId: string;\n /**\n * The field that is used as an entry description.\n * If not set by the user, the system will try to assign the first available `long-text` field.\n */\n descriptionFieldId?: string | null;\n /**\n * The field that is used as an entry image.\n * If not set by the user, the system will try to assign a `file` field which has `imagesOnly` enabled.\n */\n imageFieldId?: string | null;\n\n /**\n * Is model private?\n * This is meant to be used for some internal models - will not be visible in the schema.\n * Only available for the plugin constructed models.\n */\n isPrivate?: boolean;\n\n /**\n * Does this model require authorization to be performed?\n * Only available for models created via plugins.\n */\n authorization?: boolean | CmsModelAuthorization;\n\n /**\n * Is this model created via plugin?\n */\n isPlugin?: boolean;\n}\n\nexport interface CmsModelAuthorization {\n permissions: boolean;\n\n [key: string]: any;\n}\n\n/**\n * A GraphQL `params.data` parameter received when creating content model.\n *\n * @category GraphQL params\n * @category CmsModel\n */\nexport interface CmsModelCreateInput {\n /**\n * Name of the content model.\n */\n name: string;\n /**\n * Singular name of the content model to be used in the API.\n */\n singularApiName: string;\n /**\n * Plural name of the content model to be used in the API.\n */\n pluralApiName: string;\n /**\n * Unique ID of the content model. Created from name if not sent by the user. Cannot be changed.\n */\n modelId?: string;\n /**\n * Description of the content model.\n */\n description?: string | null;\n /**\n * Group where to put the content model in.\n */\n group: string;\n /**\n * A list of content model fields to define the entry values.\n */\n fields?: CmsModelFieldInput[];\n /**\n * Admin UI field layout\n *\n * ```ts\n * layout: [\n * [field1id, field2id],\n * [field3id]\n * ]\n * ```\n */\n layout?: string[][];\n /**\n * Models can be tagged to give them contextual meaning.\n */\n tags?: string[];\n /**\n * Fields fieldId which are picked to represent the CMS entry.\n */\n titleFieldId?: string | null;\n descriptionFieldId?: string | null;\n imageFieldId?: string | null;\n icon?: CmsIcon | null;\n}\n\n/**\n * A GraphQL `params.data` parameter received when creating content model from existing model.\n *\n * @category GraphQL params\n * @category CmsModel\n */\nexport interface CmsModelCreateFromInput extends CmsModelCreateInput {}\n"],"mappings":"","ignoreList":[]}
1
+ {"version":3,"names":[],"sources":["model.ts"],"sourcesContent":["import type { CmsIdentity } from \"./identity.js\";\nimport type { CmsModelField, CmsModelFieldInput, FieldRule } from \"./modelField.js\";\nimport type { CmsIcon } from \"~/types/types.js\";\n\nexport interface CmsTabLayoutTab {\n id: string;\n label: string;\n icon?: CmsIcon | null;\n layout: CmsModelLayout;\n rules?: FieldRule[];\n}\n\nexport interface CmsTabLayoutDescriptor {\n type: \"tabs\";\n label: string;\n description?: string | null;\n help?: string | null;\n tabs: CmsTabLayoutTab[];\n rules?: FieldRule[];\n}\n\nexport interface CmsSeparatorLayoutDescriptor {\n type: \"separator\";\n label: string;\n description: string | null | undefined;\n rules?: FieldRule[];\n}\n\nexport interface CmsAlertLayoutDescriptor {\n type: \"alert\";\n label: string;\n alertType: \"info\" | \"success\" | \"warning\" | \"danger\";\n rules?: FieldRule[];\n}\n\nexport type CmsModelLayoutCell =\n | string\n | CmsTabLayoutDescriptor\n | CmsSeparatorLayoutDescriptor\n | CmsAlertLayoutDescriptor;\nexport type CmsModelLayout = CmsModelLayoutCell[][];\n\n/**\n * Base CMS Model. Should not be exported and used outside of this package.\n *\n * @category Database model\n * @category CmsModel\n */\nexport interface CmsModel {\n /**\n * Name of the content model.\n */\n name: string;\n /**\n * Unique ID for the content model. Created from name if not defined by user.\n */\n modelId: string;\n /**\n * Name of the content model in singular form to be used in the API.\n * example:\n * - Article\n * - Fruit\n * - Vegetable\n * - Car\n */\n singularApiName: string;\n /**\n * Name of the content model in plural form to be used in the API.\n * example:\n * - Articles\n * - Fruits\n * - Vegetables\n * - Cars\n */\n pluralApiName: string;\n /**\n * Model tenant.\n */\n tenant: string;\n /**\n * Model group slug.\n */\n group: string;\n /**\n * Icon for the content model.\n */\n icon: CmsIcon | null;\n /**\n * Description for the content model.\n */\n description: string | null;\n /**\n * Date created\n */\n createdOn?: string;\n /**\n * Date saved. Changes on both save and create.\n */\n savedOn?: string;\n /**\n * CreatedBy object wrapper. Contains id, name and type of the user.\n */\n createdBy?: CmsIdentity;\n /**\n * List of fields defining entry values.\n */\n fields: CmsModelField[];\n /**\n * Admin UI field layout\n *\n * ```ts\n * layout: [\n * [field1id, field2id],\n * [field3id]\n * ]\n * ```\n */\n layout: CmsModelLayout;\n /**\n * Models can be tagged to give them contextual meaning.\n */\n tags?: string[];\n /**\n * The field that is used as an entry title.\n * If not specified by the user, the system tries to assign the first available `text` field.\n */\n titleFieldId: string;\n /**\n * The field that is used as an entry description.\n * If not set by the user, the system will try to assign the first available `long-text` field.\n */\n descriptionFieldId?: string | null;\n /**\n * The field that is used as an entry image.\n * If not set by the user, the system will try to assign a `file` field which has `imagesOnly` enabled.\n */\n imageFieldId?: string | null;\n\n /**\n * Is model private?\n * This is meant to be used for some internal models - will not be visible in the schema.\n * Only available for the plugin constructed models.\n */\n isPrivate?: boolean;\n\n /**\n * Does this model require authorization to be performed?\n * Only available for models created via plugins.\n */\n authorization?: boolean | CmsModelAuthorization;\n\n /**\n * Is this model created via plugin?\n */\n isPlugin?: boolean;\n}\n\nexport interface CmsModelAuthorization {\n permissions: boolean;\n\n [key: string]: any;\n}\n\n/**\n * A GraphQL `params.data` parameter received when creating content model.\n *\n * @category GraphQL params\n * @category CmsModel\n */\nexport interface CmsModelCreateInput {\n /**\n * Name of the content model.\n */\n name: string;\n /**\n * Singular name of the content model to be used in the API.\n */\n singularApiName: string;\n /**\n * Plural name of the content model to be used in the API.\n */\n pluralApiName: string;\n /**\n * Unique ID of the content model. Created from name if not sent by the user. Cannot be changed.\n */\n modelId?: string;\n /**\n * Description of the content model.\n */\n description?: string | null;\n /**\n * Group where to put the content model in.\n */\n group: string;\n /**\n * A list of content model fields to define the entry values.\n */\n fields?: CmsModelFieldInput[];\n /**\n * Admin UI field layout\n *\n * ```ts\n * layout: [\n * [field1id, field2id],\n * [field3id]\n * ]\n * ```\n */\n layout?: CmsModelLayout;\n /**\n * Models can be tagged to give them contextual meaning.\n */\n tags?: string[];\n /**\n * Fields fieldId which are picked to represent the CMS entry.\n */\n titleFieldId?: string | null;\n descriptionFieldId?: string | null;\n imageFieldId?: string | null;\n icon?: CmsIcon | null;\n}\n\n/**\n * A GraphQL `params.data` parameter received when creating content model from existing model.\n *\n * @category GraphQL params\n * @category CmsModel\n */\nexport interface CmsModelCreateFromInput extends CmsModelCreateInput {}\n"],"mappings":"","ignoreList":[]}