@webiny/api-headless-cms 0.0.0-unstable.6e5425ee89 → 0.0.0-unstable.78f581c1d2
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.
- package/context.js +15 -0
- package/context.js.map +1 -1
- package/crud/contentEntry/afterDelete.js +5 -0
- package/crud/contentEntry/afterDelete.js.map +1 -1
- package/crud/contentEntry/beforeCreate.js +3 -0
- package/crud/contentEntry/beforeCreate.js.map +1 -1
- package/crud/contentEntry/beforeUpdate.js +3 -0
- package/crud/contentEntry/beforeUpdate.js.map +1 -1
- package/crud/contentEntry/entryDataValidation.js +40 -1
- package/crud/contentEntry/entryDataValidation.js.map +1 -1
- package/crud/contentEntry/markLockedFields.js +25 -2
- package/crud/contentEntry/markLockedFields.js.map +1 -1
- package/crud/contentEntry/referenceFieldsMapping.js +59 -5
- package/crud/contentEntry/referenceFieldsMapping.js.map +1 -1
- package/crud/contentEntry.crud.js +145 -27
- package/crud/contentEntry.crud.js.map +1 -1
- package/crud/contentModel/afterCreate.js +2 -0
- package/crud/contentModel/afterCreate.js.map +1 -1
- package/crud/contentModel/afterCreateFrom.js +2 -0
- package/crud/contentModel/afterCreateFrom.js.map +1 -1
- package/crud/contentModel/afterDelete.js +2 -0
- package/crud/contentModel/afterDelete.js.map +1 -1
- package/crud/contentModel/afterUpdate.js +2 -0
- package/crud/contentModel/afterUpdate.js.map +1 -1
- package/crud/contentModel/beforeCreate.js +32 -4
- package/crud/contentModel/beforeCreate.js.map +1 -1
- package/crud/contentModel/beforeDelete.js +10 -0
- package/crud/contentModel/beforeDelete.js.map +1 -1
- package/crud/contentModel/beforeUpdate.js +5 -0
- package/crud/contentModel/beforeUpdate.js.map +1 -1
- package/crud/contentModel/contentModelManagerFactory.js +7 -0
- package/crud/contentModel/contentModelManagerFactory.js.map +1 -1
- package/crud/contentModel/createFieldModels.js +6 -0
- package/crud/contentModel/createFieldModels.js.map +1 -1
- package/crud/contentModel/createFieldStorageId.js +2 -0
- package/crud/contentModel/createFieldStorageId.js.map +1 -1
- package/crud/contentModel/fieldIdValidation.js +5 -0
- package/crud/contentModel/fieldIdValidation.js.map +1 -1
- package/crud/contentModel/idValidation.js +5 -0
- package/crud/contentModel/idValidation.js.map +1 -1
- package/crud/contentModel/models.js +8 -1
- package/crud/contentModel/models.js.map +1 -1
- package/crud/contentModel/systemFields.js.map +1 -1
- package/crud/contentModel/validateLayout.js +8 -0
- package/crud/contentModel/validateLayout.js.map +1 -1
- package/crud/contentModel/validateModel.js +8 -0
- package/crud/contentModel/validateModel.js.map +1 -1
- package/crud/contentModel/validateModelFields.js +60 -8
- package/crud/contentModel/validateModelFields.js.map +1 -1
- package/crud/contentModel.crud.js +96 -11
- package/crud/contentModel.crud.js.map +1 -1
- package/crud/contentModelGroup/beforeCreate.js +12 -0
- package/crud/contentModelGroup/beforeCreate.js.map +1 -1
- package/crud/contentModelGroup/beforeDelete.js +8 -0
- package/crud/contentModelGroup/beforeDelete.js.map +1 -1
- package/crud/contentModelGroup/beforeUpdate.js +5 -0
- package/crud/contentModelGroup/beforeUpdate.js.map +1 -1
- package/crud/contentModelGroup.crud.js +47 -10
- package/crud/contentModelGroup.crud.js.map +1 -1
- package/crud/index.js +16 -0
- package/crud/index.js.map +1 -1
- package/crud/settings.crud.js +12 -0
- package/crud/settings.crud.js.map +1 -1
- package/crud/system.crud.js +37 -2
- package/crud/system.crud.js.map +1 -1
- package/fieldConverters/CmsModelDefaultFieldConverterPlugin.js +13 -0
- package/fieldConverters/CmsModelDefaultFieldConverterPlugin.js.map +1 -1
- package/fieldConverters/CmsModelObjectFieldConverterPlugin.js +53 -0
- package/fieldConverters/CmsModelObjectFieldConverterPlugin.js.map +1 -1
- package/fieldConverters/index.js +4 -0
- package/fieldConverters/index.js.map +1 -1
- package/graphql/buildSchemaPlugins.js +9 -5
- package/graphql/buildSchemaPlugins.js.map +1 -1
- package/graphql/graphQLHandlerFactory.js +28 -3
- package/graphql/graphQLHandlerFactory.js.map +1 -1
- package/graphql/index.js +8 -1
- package/graphql/index.js.map +1 -1
- package/graphql/schema/baseContentSchema.js +9 -1
- package/graphql/schema/baseContentSchema.js.map +1 -1
- package/graphql/schema/contentEntries.js +42 -2
- package/graphql/schema/contentEntries.js.map +1 -1
- package/graphql/schema/contentModelGroups.js +19 -2
- package/graphql/schema/contentModelGroups.js.map +1 -1
- package/graphql/schema/contentModels.js +18 -2
- package/graphql/schema/contentModels.js.map +1 -1
- package/graphql/schema/createFieldResolvers.js +21 -3
- package/graphql/schema/createFieldResolvers.js.map +1 -1
- package/graphql/schema/createManageResolvers.js +26 -0
- package/graphql/schema/createManageResolvers.js.map +1 -1
- package/graphql/schema/createManageSDL.js +14 -1
- package/graphql/schema/createManageSDL.js.map +1 -1
- package/graphql/schema/createPreviewResolvers.js +10 -0
- package/graphql/schema/createPreviewResolvers.js.map +1 -1
- package/graphql/schema/createReadResolvers.js +10 -0
- package/graphql/schema/createReadResolvers.js.map +1 -1
- package/graphql/schema/createReadSDL.js +10 -0
- package/graphql/schema/createReadSDL.js.map +1 -1
- package/graphql/schema/resolvers/commonFieldResolvers.js +2 -0
- package/graphql/schema/resolvers/commonFieldResolvers.js.map +1 -1
- package/graphql/schema/resolvers/manage/resolveCreate.js +3 -0
- package/graphql/schema/resolvers/manage/resolveCreate.js.map +1 -1
- package/graphql/schema/resolvers/manage/resolveCreateFrom.js +3 -0
- package/graphql/schema/resolvers/manage/resolveCreateFrom.js.map +1 -1
- package/graphql/schema/resolvers/manage/resolveDelete.js +6 -0
- package/graphql/schema/resolvers/manage/resolveDelete.js.map +1 -1
- package/graphql/schema/resolvers/manage/resolveGet.js +16 -0
- package/graphql/schema/resolvers/manage/resolveGet.js.map +1 -1
- package/graphql/schema/resolvers/manage/resolveGetByIds.js +3 -0
- package/graphql/schema/resolvers/manage/resolveGetByIds.js.map +1 -1
- package/graphql/schema/resolvers/manage/resolveGetRevisions.js +3 -0
- package/graphql/schema/resolvers/manage/resolveGetRevisions.js.map +1 -1
- package/graphql/schema/resolvers/manage/resolveList.js +3 -0
- package/graphql/schema/resolvers/manage/resolveList.js.map +1 -1
- package/graphql/schema/resolvers/manage/resolvePublish.js +3 -0
- package/graphql/schema/resolvers/manage/resolvePublish.js.map +1 -1
- package/graphql/schema/resolvers/manage/resolveRepublish.js +3 -0
- package/graphql/schema/resolvers/manage/resolveRepublish.js.map +1 -1
- package/graphql/schema/resolvers/manage/resolveUnpublish.js +3 -0
- package/graphql/schema/resolvers/manage/resolveUnpublish.js.map +1 -1
- package/graphql/schema/resolvers/manage/resolveUpdate.js +3 -0
- package/graphql/schema/resolvers/manage/resolveUpdate.js.map +1 -1
- package/graphql/schema/resolvers/preview/resolveGet.js +8 -0
- package/graphql/schema/resolvers/preview/resolveGet.js.map +1 -1
- package/graphql/schema/resolvers/preview/resolveList.js +3 -0
- package/graphql/schema/resolvers/preview/resolveList.js.map +1 -1
- package/graphql/schema/resolvers/read/resolveGet.js +8 -0
- package/graphql/schema/resolvers/read/resolveGet.js.map +1 -1
- package/graphql/schema/resolvers/read/resolveList.js +3 -0
- package/graphql/schema/resolvers/read/resolveList.js.map +1 -1
- package/graphql/schema/schemaPlugins.js +19 -5
- package/graphql/schema/schemaPlugins.js.map +1 -1
- package/graphql/system.js +14 -1
- package/graphql/system.js.map +1 -1
- package/graphqlFields/boolean.js +12 -0
- package/graphqlFields/boolean.js.map +1 -1
- package/graphqlFields/datetime.js +17 -0
- package/graphqlFields/datetime.js.map +1 -1
- package/graphqlFields/file.js +8 -0
- package/graphqlFields/file.js.map +1 -1
- package/graphqlFields/helpers.js +10 -0
- package/graphqlFields/helpers.js.map +1 -1
- package/graphqlFields/index.js +11 -0
- package/graphqlFields/index.js.map +1 -1
- package/graphqlFields/longText.js +10 -0
- package/graphqlFields/longText.js.map +1 -1
- package/graphqlFields/number.js +12 -0
- package/graphqlFields/number.js.map +1 -1
- package/graphqlFields/object.js +36 -6
- package/graphqlFields/object.js.map +1 -1
- package/graphqlFields/ref.js +51 -17
- package/graphqlFields/ref.js.map +1 -1
- package/graphqlFields/richText.js +9 -0
- package/graphqlFields/richText.js.map +1 -1
- package/graphqlFields/text.js +11 -0
- package/graphqlFields/text.js.map +1 -1
- package/index.js +19 -0
- package/index.js.map +1 -1
- package/modelManager/DefaultCmsModelManager.js +16 -0
- package/modelManager/DefaultCmsModelManager.js.map +1 -1
- package/modelManager/index.js +4 -0
- package/modelManager/index.js.map +1 -1
- package/package.json +24 -24
- package/parameters/context.js +4 -0
- package/parameters/context.js.map +1 -1
- package/parameters/header.js +11 -0
- package/parameters/header.js.map +1 -1
- package/parameters/index.js +8 -0
- package/parameters/index.js.map +1 -1
- package/parameters/manual.js +8 -1
- package/parameters/manual.js.map +1 -1
- package/parameters/path.js +11 -0
- package/parameters/path.js.map +1 -1
- package/plugins/CmsGroupPlugin.js +8 -0
- package/plugins/CmsGroupPlugin.js.map +1 -1
- package/plugins/CmsModelFieldConverterPlugin.js +5 -0
- package/plugins/CmsModelFieldConverterPlugin.js.map +1 -1
- package/plugins/CmsModelPlugin.js +38 -2
- package/plugins/CmsModelPlugin.js.map +1 -1
- package/plugins/CmsParametersPlugin.js +7 -0
- package/plugins/CmsParametersPlugin.js.map +1 -1
- package/plugins/StorageTransformPlugin.js +9 -0
- package/plugins/StorageTransformPlugin.js.map +1 -1
- package/plugins/index.js +10 -0
- package/plugins/index.js.map +1 -1
- package/storage/default.js +3 -0
- package/storage/default.js.map +1 -1
- package/storage/object.js +18 -0
- package/storage/object.js.map +1 -1
- package/types.js +62 -0
- package/types.js.map +1 -1
- package/upgrades/5.33.0/index.js +26 -3
- package/upgrades/5.33.0/index.js.map +1 -1
- package/upgrades/index.js +3 -0
- package/upgrades/index.js.map +1 -1
- package/utils/access.js +25 -11
- package/utils/access.js.map +1 -1
- package/utils/converters/Converter.js +13 -0
- package/utils/converters/Converter.js.map +1 -1
- package/utils/converters/ConverterCollection.js +32 -9
- package/utils/converters/ConverterCollection.js.map +1 -1
- package/utils/converters/valueKeyStorageConverter.js +26 -0
- package/utils/converters/valueKeyStorageConverter.js.map +1 -1
- package/utils/createTypeName.js +8 -0
- package/utils/createTypeName.js.map +1 -1
- package/utils/entryStorage.js +26 -10
- package/utils/entryStorage.js.map +1 -1
- package/utils/filterAsync.js +5 -0
- package/utils/filterAsync.js.map +1 -1
- package/utils/filterModelFields.js +9 -3
- package/utils/filterModelFields.js.map +1 -1
- package/utils/getEntryTitle.js +9 -0
- package/utils/getEntryTitle.js.map +1 -1
- package/utils/getSchemaFromFieldPlugins.js +6 -2
- package/utils/getSchemaFromFieldPlugins.js.map +1 -1
- package/utils/ownership.js +8 -0
- package/utils/ownership.js.map +1 -1
- package/utils/permissions.js +23 -8
- package/utils/permissions.js.map +1 -1
- package/utils/pluralizedTypeName.js +6 -0
- package/utils/pluralizedTypeName.js.map +1 -1
- package/utils/renderFields.js +8 -0
- package/utils/renderFields.js.map +1 -1
- package/utils/renderGetFilterFields.js +11 -0
- package/utils/renderGetFilterFields.js.map +1 -1
- package/utils/renderInputFields.js +8 -0
- package/utils/renderInputFields.js.map +1 -1
- package/utils/renderListFilterFields.js +9 -1
- package/utils/renderListFilterFields.js.map +1 -1
- package/utils/renderSortEnum.js +7 -0
- package/utils/renderSortEnum.js.map +1 -1
- package/utils/toSlug.js +4 -0
- package/utils/toSlug.js.map +1 -1
- package/validators/dateGte.js +7 -0
- package/validators/dateGte.js.map +1 -1
- package/validators/dateLte.js +7 -0
- package/validators/dateLte.js.map +1 -1
- package/validators/gte.js +8 -0
- package/validators/gte.js.map +1 -1
- package/validators/in.js +8 -0
- package/validators/in.js.map +1 -1
- package/validators/index.js +15 -0
- package/validators/index.js.map +1 -1
- package/validators/lte.js +8 -0
- package/validators/lte.js.map +1 -1
- package/validators/maxLength.js +8 -0
- package/validators/maxLength.js.map +1 -1
- package/validators/minLength.js +8 -0
- package/validators/minLength.js.map +1 -1
- package/validators/pattern.js +9 -0
- package/validators/pattern.js.map +1 -1
- package/validators/patternPlugins/email.js +2 -0
- package/validators/patternPlugins/email.js.map +1 -1
- package/validators/patternPlugins/index.js +8 -0
- package/validators/patternPlugins/index.js.map +1 -1
- package/validators/patternPlugins/lowerCase.js +2 -0
- package/validators/patternPlugins/lowerCase.js.map +1 -1
- package/validators/patternPlugins/lowerCaseSpace.js +2 -0
- package/validators/patternPlugins/lowerCaseSpace.js.map +1 -1
- package/validators/patternPlugins/upperCase.js +2 -0
- package/validators/patternPlugins/upperCase.js.map +1 -1
- package/validators/patternPlugins/upperCaseSpace.js +2 -0
- package/validators/patternPlugins/upperCaseSpace.js.map +1 -1
- package/validators/patternPlugins/url.js +2 -0
- package/validators/patternPlugins/url.js.map +1 -1
- package/validators/required.js +5 -0
- package/validators/required.js.map +1 -1
- package/validators/timeGte.js +8 -0
- package/validators/timeGte.js.map +1 -1
- package/validators/timeLte.js +8 -0
- package/validators/timeLte.js.map +1 -1
- package/validators/unique.js +7 -0
- package/validators/unique.js.map +1 -1
|
@@ -4,25 +4,33 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.validateLayout = void 0;
|
|
7
|
+
|
|
7
8
|
const validateLayout = (layout, fields = []) => {
|
|
8
9
|
const flatLayoutIdList = layout.reduce((acc, id) => {
|
|
9
10
|
return acc.concat(Array.isArray(id) ? id : [id]);
|
|
10
11
|
}, []);
|
|
12
|
+
|
|
11
13
|
if (flatLayoutIdList.length !== fields.length) {
|
|
12
14
|
throw new Error(`There are ${flatLayoutIdList.length} IDs in the layout and ${fields.length} in fields, which cannot be - numbers must be the same.`);
|
|
13
15
|
}
|
|
16
|
+
|
|
14
17
|
for (const field of fields) {
|
|
15
18
|
if (flatLayoutIdList.includes(field.id)) {
|
|
16
19
|
continue;
|
|
17
20
|
}
|
|
21
|
+
|
|
18
22
|
throw new Error(`Field "${field.id}" is not defined in layout.`);
|
|
19
23
|
}
|
|
24
|
+
|
|
20
25
|
for (const id of flatLayoutIdList) {
|
|
21
26
|
const fieldFound = fields.some(f => f.id === id);
|
|
27
|
+
|
|
22
28
|
if (fieldFound) {
|
|
23
29
|
continue;
|
|
24
30
|
}
|
|
31
|
+
|
|
25
32
|
throw new Error(`Field id "${id}" is in layout but not in fields.`);
|
|
26
33
|
}
|
|
27
34
|
};
|
|
35
|
+
|
|
28
36
|
exports.validateLayout = validateLayout;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["validateLayout","layout","fields","flatLayoutIdList","reduce","acc","id","concat","Array","isArray","length","Error","field","includes","fieldFound","some","f"],"sources":["validateLayout.ts"],"sourcesContent":["import { CmsModelField, CmsModel } from \"~/types\";\n\nexport const validateLayout = (layout: CmsModel[\"layout\"], fields: CmsModelField[] = []): void => {\n const flatLayoutIdList = layout.reduce((acc, id) => {\n return acc.concat(Array.isArray(id) ? id : [id]);\n }, []);\n if (flatLayoutIdList.length !== fields.length) {\n throw new Error(\n `There are ${flatLayoutIdList.length} IDs in the layout and ${fields.length} in fields, which cannot be - numbers must be the same.`\n );\n }\n for (const field of fields) {\n if (flatLayoutIdList.includes(field.id)) {\n continue;\n }\n throw new Error(`Field \"${field.id}\" is not defined in layout.`);\n }\n for (const id of flatLayoutIdList) {\n const fieldFound = fields.some(f => f.id === id);\n if (fieldFound) {\n continue;\n }\n throw new Error(`Field id \"${id}\" is in layout but not in fields.`);\n }\n};\n"],"mappings":"
|
|
1
|
+
{"version":3,"names":["validateLayout","layout","fields","flatLayoutIdList","reduce","acc","id","concat","Array","isArray","length","Error","field","includes","fieldFound","some","f"],"sources":["validateLayout.ts"],"sourcesContent":["import { CmsModelField, CmsModel } from \"~/types\";\n\nexport const validateLayout = (layout: CmsModel[\"layout\"], fields: CmsModelField[] = []): void => {\n const flatLayoutIdList = layout.reduce((acc, id) => {\n return acc.concat(Array.isArray(id) ? id : [id]);\n }, []);\n if (flatLayoutIdList.length !== fields.length) {\n throw new Error(\n `There are ${flatLayoutIdList.length} IDs in the layout and ${fields.length} in fields, which cannot be - numbers must be the same.`\n );\n }\n for (const field of fields) {\n if (flatLayoutIdList.includes(field.id)) {\n continue;\n }\n throw new Error(`Field \"${field.id}\" is not defined in layout.`);\n }\n for (const id of flatLayoutIdList) {\n const fieldFound = fields.some(f => f.id === id);\n if (fieldFound) {\n continue;\n }\n throw new Error(`Field id \"${id}\" is in layout but not in fields.`);\n }\n};\n"],"mappings":";;;;;;;AAEO,MAAMA,cAAc,GAAG,CAACC,MAAD,EAA6BC,MAAuB,GAAG,EAAvD,KAAoE;EAC9F,MAAMC,gBAAgB,GAAGF,MAAM,CAACG,MAAP,CAAc,CAACC,GAAD,EAAMC,EAAN,KAAa;IAChD,OAAOD,GAAG,CAACE,MAAJ,CAAWC,KAAK,CAACC,OAAN,CAAcH,EAAd,IAAoBA,EAApB,GAAyB,CAACA,EAAD,CAApC,CAAP;EACH,CAFwB,EAEtB,EAFsB,CAAzB;;EAGA,IAAIH,gBAAgB,CAACO,MAAjB,KAA4BR,MAAM,CAACQ,MAAvC,EAA+C;IAC3C,MAAM,IAAIC,KAAJ,CACD,aAAYR,gBAAgB,CAACO,MAAO,0BAAyBR,MAAM,CAACQ,MAAO,yDAD1E,CAAN;EAGH;;EACD,KAAK,MAAME,KAAX,IAAoBV,MAApB,EAA4B;IACxB,IAAIC,gBAAgB,CAACU,QAAjB,CAA0BD,KAAK,CAACN,EAAhC,CAAJ,EAAyC;MACrC;IACH;;IACD,MAAM,IAAIK,KAAJ,CAAW,UAASC,KAAK,CAACN,EAAG,6BAA7B,CAAN;EACH;;EACD,KAAK,MAAMA,EAAX,IAAiBH,gBAAjB,EAAmC;IAC/B,MAAMW,UAAU,GAAGZ,MAAM,CAACa,IAAP,CAAYC,CAAC,IAAIA,CAAC,CAACV,EAAF,KAASA,EAA1B,CAAnB;;IACA,IAAIQ,UAAJ,EAAgB;MACZ;IACH;;IACD,MAAM,IAAIH,KAAJ,CAAW,aAAYL,EAAG,mCAA1B,CAAN;EACH;AACJ,CAtBM"}
|
|
@@ -1,24 +1,32 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
|
|
4
|
+
|
|
4
5
|
Object.defineProperty(exports, "__esModule", {
|
|
5
6
|
value: true
|
|
6
7
|
});
|
|
7
8
|
exports.validateModel = void 0;
|
|
9
|
+
|
|
8
10
|
var _error = _interopRequireDefault(require("@webiny/error"));
|
|
11
|
+
|
|
9
12
|
var _CmsModelPlugin = require("../../plugins/CmsModelPlugin");
|
|
13
|
+
|
|
10
14
|
var _validateModelFields = require("./validateModelFields");
|
|
15
|
+
|
|
11
16
|
const validateModel = params => {
|
|
12
17
|
const {
|
|
13
18
|
model,
|
|
14
19
|
plugins
|
|
15
20
|
} = params;
|
|
16
21
|
const modelPlugin = plugins.byType(_CmsModelPlugin.CmsModelPlugin.type).find(item => item.contentModel.modelId === model.modelId);
|
|
22
|
+
|
|
17
23
|
if (modelPlugin) {
|
|
18
24
|
throw new _error.default("Content models defined via plugins cannot be updated.", "CONTENT_MODEL_UPDATE_ERROR", {
|
|
19
25
|
modelId: model.modelId
|
|
20
26
|
});
|
|
21
27
|
}
|
|
28
|
+
|
|
22
29
|
(0, _validateModelFields.validateModelFields)(params);
|
|
23
30
|
};
|
|
31
|
+
|
|
24
32
|
exports.validateModel = validateModel;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["validateModel","params","model","plugins","modelPlugin","byType","CmsModelPlugin","type","find","item","contentModel","modelId","WebinyError","validateModelFields"],"sources":["validateModel.ts"],"sourcesContent":["import WebinyError from \"@webiny/error\";\nimport { CmsModelPlugin } from \"~/plugins/CmsModelPlugin\";\nimport { CmsModel } from \"~/types\";\nimport { PluginsContainer } from \"@webiny/plugins\";\nimport { validateModelFields } from \"~/crud/contentModel/validateModelFields\";\n\ninterface ValidateModelParams {\n model: CmsModel;\n original?: CmsModel;\n plugins: PluginsContainer;\n}\n\nexport const validateModel = (params: ValidateModelParams) => {\n const { model, plugins } = params;\n\n const modelPlugin = plugins\n .byType<CmsModelPlugin>(CmsModelPlugin.type)\n .find(item => item.contentModel.modelId === model.modelId);\n\n if (modelPlugin) {\n throw new WebinyError(\n \"Content models defined via plugins cannot be updated.\",\n \"CONTENT_MODEL_UPDATE_ERROR\",\n {\n modelId: model.modelId\n }\n );\n }\n\n validateModelFields(params);\n};\n"],"mappings":"
|
|
1
|
+
{"version":3,"names":["validateModel","params","model","plugins","modelPlugin","byType","CmsModelPlugin","type","find","item","contentModel","modelId","WebinyError","validateModelFields"],"sources":["validateModel.ts"],"sourcesContent":["import WebinyError from \"@webiny/error\";\nimport { CmsModelPlugin } from \"~/plugins/CmsModelPlugin\";\nimport { CmsModel } from \"~/types\";\nimport { PluginsContainer } from \"@webiny/plugins\";\nimport { validateModelFields } from \"~/crud/contentModel/validateModelFields\";\n\ninterface ValidateModelParams {\n model: CmsModel;\n original?: CmsModel;\n plugins: PluginsContainer;\n}\n\nexport const validateModel = (params: ValidateModelParams) => {\n const { model, plugins } = params;\n\n const modelPlugin = plugins\n .byType<CmsModelPlugin>(CmsModelPlugin.type)\n .find(item => item.contentModel.modelId === model.modelId);\n\n if (modelPlugin) {\n throw new WebinyError(\n \"Content models defined via plugins cannot be updated.\",\n \"CONTENT_MODEL_UPDATE_ERROR\",\n {\n modelId: model.modelId\n }\n );\n }\n\n validateModelFields(params);\n};\n"],"mappings":";;;;;;;;;AAAA;;AACA;;AAGA;;AAQO,MAAMA,aAAa,GAAIC,MAAD,IAAiC;EAC1D,MAAM;IAAEC,KAAF;IAASC;EAAT,IAAqBF,MAA3B;EAEA,MAAMG,WAAW,GAAGD,OAAO,CACtBE,MADe,CACQC,8BAAA,CAAeC,IADvB,EAEfC,IAFe,CAEVC,IAAI,IAAIA,IAAI,CAACC,YAAL,CAAkBC,OAAlB,KAA8BT,KAAK,CAACS,OAFlC,CAApB;;EAIA,IAAIP,WAAJ,EAAiB;IACb,MAAM,IAAIQ,cAAJ,CACF,uDADE,EAEF,4BAFE,EAGF;MACID,OAAO,EAAET,KAAK,CAACS;IADnB,CAHE,CAAN;EAOH;;EAED,IAAAE,wCAAA,EAAoBZ,MAApB;AACH,CAlBM"}
|
|
@@ -1,17 +1,25 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
|
|
4
|
+
|
|
4
5
|
Object.defineProperty(exports, "__esModule", {
|
|
5
6
|
value: true
|
|
6
7
|
});
|
|
7
8
|
exports.validateModelFields = void 0;
|
|
9
|
+
|
|
8
10
|
var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
|
|
11
|
+
|
|
9
12
|
var _error = _interopRequireDefault(require("@webiny/error"));
|
|
13
|
+
|
|
10
14
|
var _createManageSDL = require("../../graphql/schema/createManageSDL");
|
|
15
|
+
|
|
11
16
|
var _graphqlTag = _interopRequireDefault(require("graphql-tag"));
|
|
17
|
+
|
|
12
18
|
var _createFieldStorageId = require("./createFieldStorageId");
|
|
19
|
+
|
|
13
20
|
const defaultTitleFieldId = "id";
|
|
14
21
|
const allowedTitleFieldTypes = ["text", "number"];
|
|
22
|
+
|
|
15
23
|
const getContentModelTitleFieldId = (fields, titleFieldId) => {
|
|
16
24
|
/**
|
|
17
25
|
* If there are no fields defined, we will return the default field
|
|
@@ -24,6 +32,8 @@ const getContentModelTitleFieldId = (fields, titleFieldId) => {
|
|
|
24
32
|
* we will take first text field that has no multiple values enabled
|
|
25
33
|
* or if initial titleFieldId is the default one also try to find first available text field
|
|
26
34
|
*/
|
|
35
|
+
|
|
36
|
+
|
|
27
37
|
if (!titleFieldId || titleFieldId === defaultTitleFieldId) {
|
|
28
38
|
const titleField = fields.find(field => {
|
|
29
39
|
return field.type === "text" && !field.multipleValues;
|
|
@@ -35,13 +45,17 @@ const getContentModelTitleFieldId = (fields, titleFieldId) => {
|
|
|
35
45
|
* for correct type
|
|
36
46
|
* and that it is not multiple values field
|
|
37
47
|
*/
|
|
48
|
+
|
|
49
|
+
|
|
38
50
|
const target = fields.find(f => f.fieldId === titleFieldId);
|
|
51
|
+
|
|
39
52
|
if (!target) {
|
|
40
53
|
throw new _error.default(`Field selected for the title field does not exist in the model.`, "VALIDATION_ERROR", {
|
|
41
54
|
fieldId: titleFieldId,
|
|
42
55
|
fields
|
|
43
56
|
});
|
|
44
57
|
}
|
|
58
|
+
|
|
45
59
|
if (allowedTitleFieldTypes.includes(target.type) === false) {
|
|
46
60
|
throw new _error.default(`Only ${allowedTitleFieldTypes.join(", ")} and id fields can be used as an entry title.`, "ENTRY_TITLE_FIELD_TYPE", {
|
|
47
61
|
storageId: target.storageId,
|
|
@@ -49,6 +63,7 @@ const getContentModelTitleFieldId = (fields, titleFieldId) => {
|
|
|
49
63
|
type: target.type
|
|
50
64
|
});
|
|
51
65
|
}
|
|
66
|
+
|
|
52
67
|
if (target.multipleValues) {
|
|
53
68
|
throw new _error.default(`Fields that accept multiple values cannot be used as the entry title.`, "ENTRY_TITLE_FIELD_TYPE", {
|
|
54
69
|
storageId: target.storageId,
|
|
@@ -56,15 +71,18 @@ const getContentModelTitleFieldId = (fields, titleFieldId) => {
|
|
|
56
71
|
type: target.type
|
|
57
72
|
});
|
|
58
73
|
}
|
|
74
|
+
|
|
59
75
|
return target.fieldId;
|
|
60
76
|
};
|
|
77
|
+
|
|
61
78
|
const extractInvalidField = (model, err) => {
|
|
62
79
|
var _err$source;
|
|
63
|
-
const sdl = ((_err$source = err.source) === null || _err$source === void 0 ? void 0 : _err$source.body) || "";
|
|
64
80
|
|
|
81
|
+
const sdl = ((_err$source = err.source) === null || _err$source === void 0 ? void 0 : _err$source.body) || "";
|
|
65
82
|
/**
|
|
66
83
|
* Find the invalid type
|
|
67
84
|
*/
|
|
85
|
+
|
|
68
86
|
const {
|
|
69
87
|
line: lineNumber
|
|
70
88
|
} = err.locations ? err.locations[0] : {
|
|
@@ -73,25 +91,33 @@ const extractInvalidField = (model, err) => {
|
|
|
73
91
|
const sdlLines = sdl.split("\n");
|
|
74
92
|
let sdlLine;
|
|
75
93
|
let gqlType;
|
|
94
|
+
|
|
76
95
|
for (let i = lineNumber; i > 0; i--) {
|
|
77
96
|
if (sdlLine && sdlLine.includes("type ")) {
|
|
78
97
|
gqlType = sdlLine.match(/type\s+(.*?)\s+{/);
|
|
79
98
|
break;
|
|
80
99
|
}
|
|
100
|
+
|
|
81
101
|
sdlLine = sdlLines[i];
|
|
82
102
|
}
|
|
103
|
+
|
|
83
104
|
let invalidField = undefined;
|
|
105
|
+
|
|
84
106
|
if (Array.isArray(gqlType)) {
|
|
85
107
|
const fieldRegex = new RegExp(`([^\\s+].*?):\\s+\\[?${gqlType[1]}!?\\]?`);
|
|
86
108
|
const matched = sdl.match(fieldRegex);
|
|
109
|
+
|
|
87
110
|
if (matched) {
|
|
88
111
|
invalidField = matched[1];
|
|
89
112
|
}
|
|
90
113
|
}
|
|
114
|
+
|
|
91
115
|
let message = `See more details in the browser console.`;
|
|
116
|
+
|
|
92
117
|
if (invalidField) {
|
|
93
118
|
message = `Please review the definition of "${invalidField}" field.`;
|
|
94
119
|
}
|
|
120
|
+
|
|
95
121
|
return {
|
|
96
122
|
data: {
|
|
97
123
|
modelId: model.modelId,
|
|
@@ -102,6 +128,7 @@ const extractInvalidField = (model, err) => {
|
|
|
102
128
|
message: [`Model "${model.modelId}" was not saved!`, message].join("\n")
|
|
103
129
|
};
|
|
104
130
|
};
|
|
131
|
+
|
|
105
132
|
const validateFields = params => {
|
|
106
133
|
const {
|
|
107
134
|
plugins,
|
|
@@ -111,16 +138,21 @@ const validateFields = params => {
|
|
|
111
138
|
} = params;
|
|
112
139
|
const fieldIdList = [];
|
|
113
140
|
const storageIdList = [];
|
|
141
|
+
|
|
114
142
|
for (const field of fields) {
|
|
115
143
|
var _field$settings, _originalField$settin;
|
|
144
|
+
|
|
116
145
|
const plugin = plugins.find(item => item.fieldType === field.type);
|
|
146
|
+
|
|
117
147
|
if (!plugin) {
|
|
118
148
|
throw new Error(`Cannot update content model because of the unknown "${field.type}" field.`);
|
|
119
149
|
}
|
|
150
|
+
|
|
120
151
|
const originalField = originalFields.find(f => f.id === field.id);
|
|
121
152
|
/**
|
|
122
153
|
* Field MUST have an fieldId defined.
|
|
123
154
|
*/
|
|
155
|
+
|
|
124
156
|
if (!field.fieldId) {
|
|
125
157
|
throw new _error.default(`Field does not have an "fieldId" defined.`, "MISSING_FIELD_ID", {
|
|
126
158
|
field
|
|
@@ -139,9 +171,12 @@ const validateFields = params => {
|
|
|
139
171
|
* https://discuss.elastic.co/t/special-characters-in-field-names/10658/3
|
|
140
172
|
* https://discuss.elastic.co/t/illegal-characters-in-elasticsearch-field-names/17196/2
|
|
141
173
|
*/
|
|
174
|
+
|
|
175
|
+
|
|
142
176
|
const isLocked = lockedFields.some(lockedField => {
|
|
143
177
|
return lockedField.fieldId === field.storageId;
|
|
144
178
|
});
|
|
179
|
+
|
|
145
180
|
if (!field.storageId) {
|
|
146
181
|
/**
|
|
147
182
|
* In case field is locked, we must set the storageId to the fieldId value.
|
|
@@ -170,35 +205,44 @@ const validateFields = params => {
|
|
|
170
205
|
* Check the field's fieldId against existing ones.
|
|
171
206
|
* There cannot be two fields with the same fieldId - outside world identifier.
|
|
172
207
|
*/
|
|
208
|
+
|
|
209
|
+
|
|
173
210
|
if (fieldIdList.includes(field.fieldId)) {
|
|
174
211
|
throw new _error.default(`Cannot update content model because field "${field.storageId}" has fieldId "${field.fieldId}", which is already used.`);
|
|
175
212
|
}
|
|
213
|
+
|
|
176
214
|
fieldIdList.push(field.fieldId);
|
|
177
215
|
/**
|
|
178
216
|
* Check the field's storageId against the existing ones.
|
|
179
217
|
* There cannot be two fields with the same storageId.
|
|
180
218
|
*/
|
|
219
|
+
|
|
181
220
|
if (storageIdList.includes(field.storageId)) {
|
|
182
221
|
throw new _error.default(`Cannot update content model because field "${field.label}" has storageId "${field.storageId}", which is already used.`);
|
|
183
222
|
}
|
|
223
|
+
|
|
184
224
|
storageIdList.push(field.storageId);
|
|
185
225
|
/**
|
|
186
226
|
* TODO maybe make this part pluginable?
|
|
187
227
|
* We need to check the object field child fields.
|
|
188
228
|
* It must be recursive.
|
|
189
229
|
*/
|
|
230
|
+
|
|
190
231
|
if (field.type !== "object") {
|
|
191
232
|
continue;
|
|
192
233
|
}
|
|
234
|
+
|
|
193
235
|
const childFields = ((_field$settings = field.settings) === null || _field$settings === void 0 ? void 0 : _field$settings.fields) || [];
|
|
194
236
|
const originalChildFields = (originalField === null || originalField === void 0 ? void 0 : (_originalField$settin = originalField.settings) === null || _originalField$settin === void 0 ? void 0 : _originalField$settin.fields) || [];
|
|
195
237
|
/**
|
|
196
238
|
* No point in going further if there are no child fields.
|
|
197
239
|
* Code will break if child fields were removed but used in the entries.
|
|
198
240
|
*/
|
|
241
|
+
|
|
199
242
|
if (childFields.length === 0) {
|
|
200
243
|
continue;
|
|
201
244
|
}
|
|
245
|
+
|
|
202
246
|
validateFields({
|
|
203
247
|
fields: childFields,
|
|
204
248
|
originalFields: originalChildFields,
|
|
@@ -207,6 +251,7 @@ const validateFields = params => {
|
|
|
207
251
|
});
|
|
208
252
|
}
|
|
209
253
|
};
|
|
254
|
+
|
|
210
255
|
const validateModelFields = params => {
|
|
211
256
|
const {
|
|
212
257
|
model,
|
|
@@ -216,19 +261,19 @@ const validateModelFields = params => {
|
|
|
216
261
|
const {
|
|
217
262
|
titleFieldId
|
|
218
263
|
} = model;
|
|
219
|
-
|
|
220
264
|
/**
|
|
221
265
|
* There should be fields/locked fields in either model or data to be updated.
|
|
222
266
|
*/
|
|
267
|
+
|
|
223
268
|
const {
|
|
224
269
|
fields = [],
|
|
225
270
|
lockedFields = []
|
|
226
271
|
} = model;
|
|
227
|
-
|
|
228
272
|
/**
|
|
229
273
|
* Let's inspect the fields of the received content model. We prevent saving of a content model if it
|
|
230
274
|
* contains a field for which a "cms-model-field-to-graphql" plugin does not exist on the backend.
|
|
231
275
|
*/
|
|
276
|
+
|
|
232
277
|
const fieldTypePlugins = plugins.byType("cms-model-field-to-graphql");
|
|
233
278
|
validateFields({
|
|
234
279
|
fields,
|
|
@@ -236,6 +281,7 @@ const validateModelFields = params => {
|
|
|
236
281
|
lockedFields,
|
|
237
282
|
plugins: fieldTypePlugins
|
|
238
283
|
});
|
|
284
|
+
|
|
239
285
|
if (fields.length) {
|
|
240
286
|
/**
|
|
241
287
|
* Make sure that this model can be safely converted to a GraphQL SDL
|
|
@@ -246,29 +292,30 @@ const validateModelFields = params => {
|
|
|
246
292
|
[pl.fieldType]: pl
|
|
247
293
|
}), {})
|
|
248
294
|
});
|
|
295
|
+
|
|
249
296
|
try {
|
|
250
297
|
(0, _graphqlTag.default)(schema);
|
|
251
298
|
} catch (err) {
|
|
252
299
|
throw new _error.default(extractInvalidField(model, err));
|
|
253
300
|
}
|
|
254
301
|
}
|
|
302
|
+
|
|
255
303
|
model.titleFieldId = getContentModelTitleFieldId(fields, titleFieldId);
|
|
256
304
|
const cmsLockedFieldPlugins = plugins.byType("cms-model-locked-field");
|
|
257
|
-
|
|
258
305
|
/**
|
|
259
306
|
* We must not allow removal or changes in fields that are already in use in content entries.
|
|
260
307
|
* Locked fields still have fieldId (should be storageId) because of the old existing locked fields in the models.
|
|
261
308
|
*/
|
|
309
|
+
|
|
262
310
|
for (const lockedField of lockedFields) {
|
|
263
311
|
const existingField = fields.find(item => item.storageId === lockedField.fieldId);
|
|
264
|
-
|
|
265
312
|
/**
|
|
266
313
|
* Starting with 5.33.0 fields can be deleted.
|
|
267
314
|
* Our UI gives a warning upon locked field deletion, but if user is managing fields through API directly - we cannot do anything.
|
|
268
315
|
*/
|
|
316
|
+
|
|
269
317
|
if (!existingField) {
|
|
270
|
-
continue;
|
|
271
|
-
// throw new WebinyError(
|
|
318
|
+
continue; // throw new WebinyError(
|
|
272
319
|
// `Cannot remove the field "${lockedField.fieldId}" because it's already in use in created content.`,
|
|
273
320
|
// "ENTRY_FIELD_USED",
|
|
274
321
|
// {
|
|
@@ -283,20 +330,24 @@ const validateModelFields = params => {
|
|
|
283
330
|
field: existingField
|
|
284
331
|
});
|
|
285
332
|
}
|
|
333
|
+
|
|
286
334
|
if (lockedField.type !== existingField.type) {
|
|
287
335
|
throw new _error.default(`Cannot change field type for the "${lockedField.fieldId}" field because it's already in use in created content.`, "ENTRY_FIELD_USED", {
|
|
288
336
|
field: existingField
|
|
289
337
|
});
|
|
290
338
|
}
|
|
291
|
-
|
|
292
339
|
/**
|
|
293
340
|
* Check `lockedField` invariant for specific field
|
|
294
341
|
*/
|
|
342
|
+
|
|
343
|
+
|
|
295
344
|
const lockedFieldsByType = cmsLockedFieldPlugins.filter(pl => pl.fieldType === lockedField.type);
|
|
345
|
+
|
|
296
346
|
for (const plugin of lockedFieldsByType) {
|
|
297
347
|
if (typeof plugin.checkLockedField !== "function") {
|
|
298
348
|
continue;
|
|
299
349
|
}
|
|
350
|
+
|
|
300
351
|
plugin.checkLockedField({
|
|
301
352
|
lockedField,
|
|
302
353
|
field: existingField
|
|
@@ -304,4 +355,5 @@ const validateModelFields = params => {
|
|
|
304
355
|
}
|
|
305
356
|
}
|
|
306
357
|
};
|
|
358
|
+
|
|
307
359
|
exports.validateModelFields = validateModelFields;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["defaultTitleFieldId","allowedTitleFieldTypes","getContentModelTitleFieldId","fields","titleFieldId","length","titleField","find","field","type","multipleValues","fieldId","target","f","WebinyError","includes","join","storageId","extractInvalidField","model","err","sdl","source","body","line","lineNumber","locations","sdlLines","split","sdlLine","gqlType","i","match","invalidField","undefined","Array","isArray","fieldRegex","RegExp","matched","message","data","modelId","code","validateFields","params","plugins","originalFields","lockedFields","fieldIdList","storageIdList","plugin","item","fieldType","Error","originalField","id","isLocked","some","lockedField","createFieldStorageId","push","label","childFields","settings","originalChildFields","validateModelFields","original","fieldTypePlugins","byType","schema","createManageSDL","reduce","acc","pl","gql","cmsLockedFieldPlugins","existingField","lockedFieldsByType","filter","checkLockedField"],"sources":["validateModelFields.ts"],"sourcesContent":["import {\n CmsModel,\n CmsModelField,\n CmsModelFieldToGraphQLPlugin,\n CmsModelLockedFieldPlugin,\n LockedField\n} from \"~/types\";\nimport WebinyError from \"@webiny/error\";\nimport { createManageSDL } from \"~/graphql/schema/createManageSDL\";\nimport gql from \"graphql-tag\";\nimport { PluginsContainer } from \"@webiny/plugins\";\nimport { createFieldStorageId } from \"./createFieldStorageId\";\nimport { GraphQLError } from \"graphql\";\n\nconst defaultTitleFieldId = \"id\";\n\nconst allowedTitleFieldTypes = [\"text\", \"number\"];\n\nconst getContentModelTitleFieldId = (fields: CmsModelField[], titleFieldId?: string): string => {\n /**\n * If there are no fields defined, we will return the default field\n */\n if (fields.length === 0) {\n return defaultTitleFieldId;\n }\n /**\n * if there is no title field defined either in input data or existing content model data\n * we will take first text field that has no multiple values enabled\n * or if initial titleFieldId is the default one also try to find first available text field\n */\n if (!titleFieldId || titleFieldId === defaultTitleFieldId) {\n const titleField = fields.find(field => {\n return field.type === \"text\" && !field.multipleValues;\n });\n return titleField?.fieldId || defaultTitleFieldId;\n }\n /**\n * check existing titleFieldId for existence in the model\n * for correct type\n * and that it is not multiple values field\n */\n const target = fields.find(f => f.fieldId === titleFieldId);\n if (!target) {\n throw new WebinyError(\n `Field selected for the title field does not exist in the model.`,\n \"VALIDATION_ERROR\",\n {\n fieldId: titleFieldId,\n fields\n }\n );\n }\n\n if (allowedTitleFieldTypes.includes(target.type) === false) {\n throw new WebinyError(\n `Only ${allowedTitleFieldTypes.join(\n \", \"\n )} and id fields can be used as an entry title.`,\n \"ENTRY_TITLE_FIELD_TYPE\",\n {\n storageId: target.storageId,\n fieldId: target.fieldId,\n type: target.type\n }\n );\n }\n\n if (target.multipleValues) {\n throw new WebinyError(\n `Fields that accept multiple values cannot be used as the entry title.`,\n \"ENTRY_TITLE_FIELD_TYPE\",\n {\n storageId: target.storageId,\n fieldId: target.fieldId,\n type: target.type\n }\n );\n }\n\n return target.fieldId;\n};\n\nconst extractInvalidField = (model: CmsModel, err: GraphQLError) => {\n const sdl = err.source?.body || \"\";\n\n /**\n * Find the invalid type\n */\n const { line: lineNumber } = err.locations\n ? err.locations[0]\n : {\n line: 0\n };\n const sdlLines = sdl.split(\"\\n\");\n let sdlLine;\n let gqlType;\n for (let i = lineNumber; i > 0; i--) {\n if (sdlLine && sdlLine.includes(\"type \")) {\n gqlType = sdlLine.match(/type\\s+(.*?)\\s+{/);\n break;\n }\n\n sdlLine = sdlLines[i];\n }\n\n let invalidField: string | undefined = undefined;\n if (Array.isArray(gqlType)) {\n const fieldRegex = new RegExp(`([^\\\\s+].*?):\\\\s+\\\\[?${gqlType[1]}!?\\\\]?`);\n\n const matched = sdl.match(fieldRegex);\n if (matched) {\n invalidField = matched[1];\n }\n }\n\n let message = `See more details in the browser console.`;\n if (invalidField) {\n message = `Please review the definition of \"${invalidField}\" field.`;\n }\n\n return {\n data: {\n modelId: model.modelId,\n sdl,\n invalidField\n },\n code: \"INVALID_MODEL_DEFINITION\",\n message: [`Model \"${model.modelId}\" was not saved!`, message].join(\"\\n\")\n };\n};\n\ninterface ValidateFieldsParams {\n plugins: CmsModelFieldToGraphQLPlugin[];\n fields: CmsModelField[];\n originalFields: CmsModelField[];\n lockedFields: LockedField[];\n}\nconst validateFields = (params: ValidateFieldsParams) => {\n const { plugins, fields, originalFields, lockedFields } = params;\n\n const fieldIdList: string[] = [];\n\n const storageIdList: string[] = [];\n\n for (const field of fields) {\n const plugin = plugins.find(item => item.fieldType === field.type);\n if (!plugin) {\n throw new Error(\n `Cannot update content model because of the unknown \"${field.type}\" field.`\n );\n }\n const originalField = originalFields.find(f => f.id === field.id);\n /**\n * Field MUST have an fieldId defined.\n */\n if (!field.fieldId) {\n throw new WebinyError(`Field does not have an \"fieldId\" defined.`, \"MISSING_FIELD_ID\", {\n field\n });\n }\n /**\n * If storageId does not match a certain pattern, add that pattern, but only if field is not locked (used) already.\n * This is to avoid errors in the already installed systems.\n *\n * Why are we using the @?\n *\n * It is not part of special characters for the query syntax in the Lucene.\n *\n * Relevant links:\n * https://lucene.apache.org/core/3_4_0/queryparsersyntax.html\n * https://discuss.elastic.co/t/special-characters-in-field-names/10658/3\n * https://discuss.elastic.co/t/illegal-characters-in-elasticsearch-field-names/17196/2\n */\n const isLocked = lockedFields.some(lockedField => {\n return lockedField.fieldId === field.storageId;\n });\n if (!field.storageId) {\n /**\n * In case field is locked, we must set the storageId to the fieldId value.\n * This should not happen, because we upgrade all the fields in 5.33.0, but let's have a check just in case of some upgrade miss.\n */\n //\n if (isLocked) {\n field.storageId = field.fieldId;\n }\n /**\n * When having original field, just set the storageId to value from the originalField\n */\n //\n else if (originalField) {\n field.storageId = originalField.storageId;\n }\n /**\n * The last case is when no original field and not locked - so this is a completely new field.\n */\n //\n else {\n field.storageId = createFieldStorageId(field);\n }\n }\n /**\n * Check the field's fieldId against existing ones.\n * There cannot be two fields with the same fieldId - outside world identifier.\n */\n if (fieldIdList.includes(field.fieldId)) {\n throw new WebinyError(\n `Cannot update content model because field \"${field.storageId}\" has fieldId \"${field.fieldId}\", which is already used.`\n );\n }\n fieldIdList.push(field.fieldId);\n /**\n * Check the field's storageId against the existing ones.\n * There cannot be two fields with the same storageId.\n */\n if (storageIdList.includes(field.storageId)) {\n throw new WebinyError(\n `Cannot update content model because field \"${field.label}\" has storageId \"${field.storageId}\", which is already used.`\n );\n }\n storageIdList.push(field.storageId);\n /**\n * TODO maybe make this part pluginable?\n * We need to check the object field child fields.\n * It must be recursive.\n */\n if (field.type !== \"object\") {\n continue;\n }\n const childFields = field.settings?.fields || [];\n const originalChildFields = originalField?.settings?.fields || [];\n /**\n * No point in going further if there are no child fields.\n * Code will break if child fields were removed but used in the entries.\n */\n if (childFields.length === 0) {\n continue;\n }\n validateFields({\n fields: childFields,\n originalFields: originalChildFields,\n plugins,\n lockedFields: []\n });\n }\n};\n\ninterface ValidateModelFieldsParams {\n model: CmsModel;\n original?: CmsModel;\n plugins: PluginsContainer;\n}\nexport const validateModelFields = (params: ValidateModelFieldsParams) => {\n const { model, original, plugins } = params;\n const { titleFieldId } = model;\n\n /**\n * There should be fields/locked fields in either model or data to be updated.\n */\n const { fields = [], lockedFields = [] } = model;\n\n /**\n * Let's inspect the fields of the received content model. We prevent saving of a content model if it\n * contains a field for which a \"cms-model-field-to-graphql\" plugin does not exist on the backend.\n */\n const fieldTypePlugins = plugins.byType<CmsModelFieldToGraphQLPlugin>(\n \"cms-model-field-to-graphql\"\n );\n\n validateFields({\n fields,\n originalFields: original?.fields || [],\n lockedFields,\n plugins: fieldTypePlugins\n });\n\n if (fields.length) {\n /**\n * Make sure that this model can be safely converted to a GraphQL SDL\n */\n const schema = createManageSDL({\n model,\n fieldTypePlugins: fieldTypePlugins.reduce(\n (acc, pl) => ({ ...acc, [pl.fieldType]: pl }),\n {}\n )\n });\n\n try {\n gql(schema);\n } catch (err) {\n throw new WebinyError(extractInvalidField(model, err));\n }\n }\n\n model.titleFieldId = getContentModelTitleFieldId(fields, titleFieldId);\n\n const cmsLockedFieldPlugins =\n plugins.byType<CmsModelLockedFieldPlugin>(\"cms-model-locked-field\");\n\n /**\n * We must not allow removal or changes in fields that are already in use in content entries.\n * Locked fields still have fieldId (should be storageId) because of the old existing locked fields in the models.\n */\n for (const lockedField of lockedFields) {\n const existingField = fields.find(item => item.storageId === lockedField.fieldId);\n\n /**\n * Starting with 5.33.0 fields can be deleted.\n * Our UI gives a warning upon locked field deletion, but if user is managing fields through API directly - we cannot do anything.\n */\n if (!existingField) {\n continue;\n // throw new WebinyError(\n // `Cannot remove the field \"${lockedField.fieldId}\" because it's already in use in created content.`,\n // \"ENTRY_FIELD_USED\",\n // {\n // lockedField,\n // fields\n // }\n // );\n }\n\n if (lockedField.multipleValues !== existingField.multipleValues) {\n throw new WebinyError(\n `Cannot change \"multipleValues\" for the \"${lockedField.fieldId}\" field because it's already in use in created content.`,\n \"ENTRY_FIELD_USED\",\n {\n field: existingField\n }\n );\n }\n\n if (lockedField.type !== existingField.type) {\n throw new WebinyError(\n `Cannot change field type for the \"${lockedField.fieldId}\" field because it's already in use in created content.`,\n \"ENTRY_FIELD_USED\",\n {\n field: existingField\n }\n );\n }\n\n /**\n * Check `lockedField` invariant for specific field\n */\n const lockedFieldsByType = cmsLockedFieldPlugins.filter(\n pl => pl.fieldType === lockedField.type\n );\n for (const plugin of lockedFieldsByType) {\n if (typeof plugin.checkLockedField !== \"function\") {\n continue;\n }\n plugin.checkLockedField({\n lockedField,\n field: existingField\n });\n }\n }\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"names":["defaultTitleFieldId","allowedTitleFieldTypes","getContentModelTitleFieldId","fields","titleFieldId","length","titleField","find","field","type","multipleValues","fieldId","target","f","WebinyError","includes","join","storageId","extractInvalidField","model","err","sdl","source","body","line","lineNumber","locations","sdlLines","split","sdlLine","gqlType","i","match","invalidField","undefined","Array","isArray","fieldRegex","RegExp","matched","message","data","modelId","code","validateFields","params","plugins","originalFields","lockedFields","fieldIdList","storageIdList","plugin","item","fieldType","Error","originalField","id","isLocked","some","lockedField","createFieldStorageId","push","label","childFields","settings","originalChildFields","validateModelFields","original","fieldTypePlugins","byType","schema","createManageSDL","reduce","acc","pl","gql","cmsLockedFieldPlugins","existingField","lockedFieldsByType","filter","checkLockedField"],"sources":["validateModelFields.ts"],"sourcesContent":["import {\n CmsModel,\n CmsModelField,\n CmsModelFieldToGraphQLPlugin,\n CmsModelLockedFieldPlugin,\n LockedField\n} from \"~/types\";\nimport WebinyError from \"@webiny/error\";\nimport { createManageSDL } from \"~/graphql/schema/createManageSDL\";\nimport gql from \"graphql-tag\";\nimport { PluginsContainer } from \"@webiny/plugins\";\nimport { createFieldStorageId } from \"./createFieldStorageId\";\nimport { GraphQLError } from \"graphql\";\n\nconst defaultTitleFieldId = \"id\";\n\nconst allowedTitleFieldTypes = [\"text\", \"number\"];\n\nconst getContentModelTitleFieldId = (fields: CmsModelField[], titleFieldId?: string): string => {\n /**\n * If there are no fields defined, we will return the default field\n */\n if (fields.length === 0) {\n return defaultTitleFieldId;\n }\n /**\n * if there is no title field defined either in input data or existing content model data\n * we will take first text field that has no multiple values enabled\n * or if initial titleFieldId is the default one also try to find first available text field\n */\n if (!titleFieldId || titleFieldId === defaultTitleFieldId) {\n const titleField = fields.find(field => {\n return field.type === \"text\" && !field.multipleValues;\n });\n return titleField?.fieldId || defaultTitleFieldId;\n }\n /**\n * check existing titleFieldId for existence in the model\n * for correct type\n * and that it is not multiple values field\n */\n const target = fields.find(f => f.fieldId === titleFieldId);\n if (!target) {\n throw new WebinyError(\n `Field selected for the title field does not exist in the model.`,\n \"VALIDATION_ERROR\",\n {\n fieldId: titleFieldId,\n fields\n }\n );\n }\n\n if (allowedTitleFieldTypes.includes(target.type) === false) {\n throw new WebinyError(\n `Only ${allowedTitleFieldTypes.join(\n \", \"\n )} and id fields can be used as an entry title.`,\n \"ENTRY_TITLE_FIELD_TYPE\",\n {\n storageId: target.storageId,\n fieldId: target.fieldId,\n type: target.type\n }\n );\n }\n\n if (target.multipleValues) {\n throw new WebinyError(\n `Fields that accept multiple values cannot be used as the entry title.`,\n \"ENTRY_TITLE_FIELD_TYPE\",\n {\n storageId: target.storageId,\n fieldId: target.fieldId,\n type: target.type\n }\n );\n }\n\n return target.fieldId;\n};\n\nconst extractInvalidField = (model: CmsModel, err: GraphQLError) => {\n const sdl = err.source?.body || \"\";\n\n /**\n * Find the invalid type\n */\n const { line: lineNumber } = err.locations\n ? err.locations[0]\n : {\n line: 0\n };\n const sdlLines = sdl.split(\"\\n\");\n let sdlLine;\n let gqlType;\n for (let i = lineNumber; i > 0; i--) {\n if (sdlLine && sdlLine.includes(\"type \")) {\n gqlType = sdlLine.match(/type\\s+(.*?)\\s+{/);\n break;\n }\n\n sdlLine = sdlLines[i];\n }\n\n let invalidField: string | undefined = undefined;\n if (Array.isArray(gqlType)) {\n const fieldRegex = new RegExp(`([^\\\\s+].*?):\\\\s+\\\\[?${gqlType[1]}!?\\\\]?`);\n\n const matched = sdl.match(fieldRegex);\n if (matched) {\n invalidField = matched[1];\n }\n }\n\n let message = `See more details in the browser console.`;\n if (invalidField) {\n message = `Please review the definition of \"${invalidField}\" field.`;\n }\n\n return {\n data: {\n modelId: model.modelId,\n sdl,\n invalidField\n },\n code: \"INVALID_MODEL_DEFINITION\",\n message: [`Model \"${model.modelId}\" was not saved!`, message].join(\"\\n\")\n };\n};\n\ninterface ValidateFieldsParams {\n plugins: CmsModelFieldToGraphQLPlugin[];\n fields: CmsModelField[];\n originalFields: CmsModelField[];\n lockedFields: LockedField[];\n}\nconst validateFields = (params: ValidateFieldsParams) => {\n const { plugins, fields, originalFields, lockedFields } = params;\n\n const fieldIdList: string[] = [];\n\n const storageIdList: string[] = [];\n\n for (const field of fields) {\n const plugin = plugins.find(item => item.fieldType === field.type);\n if (!plugin) {\n throw new Error(\n `Cannot update content model because of the unknown \"${field.type}\" field.`\n );\n }\n const originalField = originalFields.find(f => f.id === field.id);\n /**\n * Field MUST have an fieldId defined.\n */\n if (!field.fieldId) {\n throw new WebinyError(`Field does not have an \"fieldId\" defined.`, \"MISSING_FIELD_ID\", {\n field\n });\n }\n /**\n * If storageId does not match a certain pattern, add that pattern, but only if field is not locked (used) already.\n * This is to avoid errors in the already installed systems.\n *\n * Why are we using the @?\n *\n * It is not part of special characters for the query syntax in the Lucene.\n *\n * Relevant links:\n * https://lucene.apache.org/core/3_4_0/queryparsersyntax.html\n * https://discuss.elastic.co/t/special-characters-in-field-names/10658/3\n * https://discuss.elastic.co/t/illegal-characters-in-elasticsearch-field-names/17196/2\n */\n const isLocked = lockedFields.some(lockedField => {\n return lockedField.fieldId === field.storageId;\n });\n if (!field.storageId) {\n /**\n * In case field is locked, we must set the storageId to the fieldId value.\n * This should not happen, because we upgrade all the fields in 5.33.0, but let's have a check just in case of some upgrade miss.\n */\n //\n if (isLocked) {\n field.storageId = field.fieldId;\n }\n /**\n * When having original field, just set the storageId to value from the originalField\n */\n //\n else if (originalField) {\n field.storageId = originalField.storageId;\n }\n /**\n * The last case is when no original field and not locked - so this is a completely new field.\n */\n //\n else {\n field.storageId = createFieldStorageId(field);\n }\n }\n /**\n * Check the field's fieldId against existing ones.\n * There cannot be two fields with the same fieldId - outside world identifier.\n */\n if (fieldIdList.includes(field.fieldId)) {\n throw new WebinyError(\n `Cannot update content model because field \"${field.storageId}\" has fieldId \"${field.fieldId}\", which is already used.`\n );\n }\n fieldIdList.push(field.fieldId);\n /**\n * Check the field's storageId against the existing ones.\n * There cannot be two fields with the same storageId.\n */\n if (storageIdList.includes(field.storageId)) {\n throw new WebinyError(\n `Cannot update content model because field \"${field.label}\" has storageId \"${field.storageId}\", which is already used.`\n );\n }\n storageIdList.push(field.storageId);\n /**\n * TODO maybe make this part pluginable?\n * We need to check the object field child fields.\n * It must be recursive.\n */\n if (field.type !== \"object\") {\n continue;\n }\n const childFields = field.settings?.fields || [];\n const originalChildFields = originalField?.settings?.fields || [];\n /**\n * No point in going further if there are no child fields.\n * Code will break if child fields were removed but used in the entries.\n */\n if (childFields.length === 0) {\n continue;\n }\n validateFields({\n fields: childFields,\n originalFields: originalChildFields,\n plugins,\n lockedFields: []\n });\n }\n};\n\ninterface ValidateModelFieldsParams {\n model: CmsModel;\n original?: CmsModel;\n plugins: PluginsContainer;\n}\nexport const validateModelFields = (params: ValidateModelFieldsParams) => {\n const { model, original, plugins } = params;\n const { titleFieldId } = model;\n\n /**\n * There should be fields/locked fields in either model or data to be updated.\n */\n const { fields = [], lockedFields = [] } = model;\n\n /**\n * Let's inspect the fields of the received content model. We prevent saving of a content model if it\n * contains a field for which a \"cms-model-field-to-graphql\" plugin does not exist on the backend.\n */\n const fieldTypePlugins = plugins.byType<CmsModelFieldToGraphQLPlugin>(\n \"cms-model-field-to-graphql\"\n );\n\n validateFields({\n fields,\n originalFields: original?.fields || [],\n lockedFields,\n plugins: fieldTypePlugins\n });\n\n if (fields.length) {\n /**\n * Make sure that this model can be safely converted to a GraphQL SDL\n */\n const schema = createManageSDL({\n model,\n fieldTypePlugins: fieldTypePlugins.reduce(\n (acc, pl) => ({ ...acc, [pl.fieldType]: pl }),\n {}\n )\n });\n\n try {\n gql(schema);\n } catch (err) {\n throw new WebinyError(extractInvalidField(model, err));\n }\n }\n\n model.titleFieldId = getContentModelTitleFieldId(fields, titleFieldId);\n\n const cmsLockedFieldPlugins =\n plugins.byType<CmsModelLockedFieldPlugin>(\"cms-model-locked-field\");\n\n /**\n * We must not allow removal or changes in fields that are already in use in content entries.\n * Locked fields still have fieldId (should be storageId) because of the old existing locked fields in the models.\n */\n for (const lockedField of lockedFields) {\n const existingField = fields.find(item => item.storageId === lockedField.fieldId);\n\n /**\n * Starting with 5.33.0 fields can be deleted.\n * Our UI gives a warning upon locked field deletion, but if user is managing fields through API directly - we cannot do anything.\n */\n if (!existingField) {\n continue;\n // throw new WebinyError(\n // `Cannot remove the field \"${lockedField.fieldId}\" because it's already in use in created content.`,\n // \"ENTRY_FIELD_USED\",\n // {\n // lockedField,\n // fields\n // }\n // );\n }\n\n if (lockedField.multipleValues !== existingField.multipleValues) {\n throw new WebinyError(\n `Cannot change \"multipleValues\" for the \"${lockedField.fieldId}\" field because it's already in use in created content.`,\n \"ENTRY_FIELD_USED\",\n {\n field: existingField\n }\n );\n }\n\n if (lockedField.type !== existingField.type) {\n throw new WebinyError(\n `Cannot change field type for the \"${lockedField.fieldId}\" field because it's already in use in created content.`,\n \"ENTRY_FIELD_USED\",\n {\n field: existingField\n }\n );\n }\n\n /**\n * Check `lockedField` invariant for specific field\n */\n const lockedFieldsByType = cmsLockedFieldPlugins.filter(\n pl => pl.fieldType === lockedField.type\n );\n for (const plugin of lockedFieldsByType) {\n if (typeof plugin.checkLockedField !== \"function\") {\n continue;\n }\n plugin.checkLockedField({\n lockedField,\n field: existingField\n });\n }\n }\n};\n"],"mappings":"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"}
|