@webiny/api-headless-cms 0.0.0-unstable.97a151f74d → 0.0.0-unstable.aad28a72ae

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 (35) hide show
  1. package/crud/contentEntry.crud.js +56 -7
  2. package/crud/contentEntry.crud.js.map +1 -1
  3. package/crud/contentModel/validateModelFields.js +26 -22
  4. package/crud/contentModel/validateModelFields.js.map +1 -1
  5. package/crud/contentModel.crud.js +162 -139
  6. package/crud/contentModel.crud.js.map +1 -1
  7. package/crud/contentModelGroup.crud.js +33 -3
  8. package/crud/contentModelGroup.crud.js.map +1 -1
  9. package/fieldConverters/CmsModelDynamicZoneFieldConverterPlugin.d.ts +11 -0
  10. package/fieldConverters/CmsModelDynamicZoneFieldConverterPlugin.js +239 -0
  11. package/fieldConverters/CmsModelDynamicZoneFieldConverterPlugin.js.map +1 -0
  12. package/fieldConverters/index.d.ts +2 -1
  13. package/fieldConverters/index.js +3 -1
  14. package/fieldConverters/index.js.map +1 -1
  15. package/graphql/schema/contentModels.js +5 -3
  16. package/graphql/schema/contentModels.js.map +1 -1
  17. package/graphqlFields/dynamicZone/dynamicZoneField.js +26 -1
  18. package/graphqlFields/dynamicZone/dynamicZoneField.js.map +1 -1
  19. package/graphqlFields/object.js +26 -13
  20. package/graphqlFields/object.js.map +1 -1
  21. package/index.d.ts +1 -1
  22. package/package.json +23 -23
  23. package/plugins/CmsModelFieldConverterPlugin.d.ts +2 -2
  24. package/plugins/CmsModelFieldConverterPlugin.js.map +1 -1
  25. package/types.d.ts +100 -2
  26. package/types.js +39 -0
  27. package/types.js.map +1 -1
  28. package/utils/entryStorage.js +7 -8
  29. package/utils/entryStorage.js.map +1 -1
  30. package/graphql/schema/resolvers/manage/resolveRequestChanges.d.ts +0 -7
  31. package/graphql/schema/resolvers/manage/resolveRequestChanges.js +0 -21
  32. package/graphql/schema/resolvers/manage/resolveRequestChanges.js.map +0 -1
  33. package/graphql/schema/resolvers/manage/resolveRequestReview.d.ts +0 -7
  34. package/graphql/schema/resolvers/manage/resolveRequestReview.js +0 -21
  35. package/graphql/schema/resolvers/manage/resolveRequestReview.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"names":["defaultTitleFieldId","allowedTitleFieldTypes","getContentModelTitleFieldId","fields","titleFieldId","length","titleField","find","field","getBaseFieldType","multipleValues","fieldId","target","f","WebinyError","includes","type","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","baseType","plugin","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","item","reason","lockedFieldType","existingFieldType","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\";\nimport { getBaseFieldType } from \"~/utils/getBaseFieldType\";\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 getBaseFieldType(field) === \"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 baseType = getBaseFieldType(field);\n const plugin = plugins.find(plugin => plugin.fieldType === baseType);\n\n if (!plugin) {\n throw new Error(\n `Cannot update content model because of the unknown \"${baseType}\" 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 reason: `\"multipleValues\" changed`,\n field: existingField\n }\n );\n }\n\n const fieldType = getBaseFieldType(existingField);\n if (lockedField.type !== fieldType) {\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 reason: `\"type\" changed`,\n lockedFieldType: lockedField.type,\n existingFieldType: fieldType\n }\n );\n }\n\n /**\n * Check `lockedField` invariant for specific field\n */\n const lockedFieldsByType = cmsLockedFieldPlugins.filter(\n pl => pl.fieldType === getBaseFieldType(lockedField)\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","getBaseFieldType","multipleValues","fieldId","target","f","WebinyError","includes","type","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","createValidateChildFields","plugins","originalFields","validateFields","lockedFields","params","fieldIdList","storageIdList","validateChildFields","baseType","plugin","fieldType","Error","originalField","id","isLocked","some","lockedField","createFieldStorageId","push","label","validate","validateModelFields","original","fieldTypePlugins","byType","schema","createManageSDL","reduce","acc","pl","gql","cmsLockedFieldPlugins","existingField","item","reason","lockedFieldType","existingFieldType","lockedFieldsByType","filter","checkLockedField"],"sources":["validateModelFields.ts"],"sourcesContent":["import {\n CmsModel,\n CmsModelField,\n CmsModelFieldToGraphQLPlugin,\n CmsModelFieldToGraphQLPluginValidateChildFieldsValidate,\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\";\nimport { getBaseFieldType } from \"~/utils/getBaseFieldType\";\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 getBaseFieldType(field) === \"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\nconst createValidateChildFields = (\n plugins: CmsModelFieldToGraphQLPlugin[]\n): CmsModelFieldToGraphQLPluginValidateChildFieldsValidate => {\n return ({ fields, originalFields }) => {\n if (fields.length === 0) {\n return;\n }\n validateFields({\n fields,\n originalFields,\n plugins,\n lockedFields: []\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 const validateChildFields = createValidateChildFields(plugins);\n\n for (const field of fields) {\n const baseType = getBaseFieldType(field);\n const plugin = plugins.find(plugin => plugin.fieldType === baseType);\n\n if (!plugin) {\n throw new Error(\n `Cannot update content model because of the unknown \"${baseType}\" 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 * There might be some plugins which allow child fields.\n * We use this method to validate them as well.\n */\n if (!plugin.validateChildFields) {\n continue;\n }\n plugin.validateChildFields({\n field,\n originalField,\n validate: validateChildFields\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 reason: `\"multipleValues\" changed`,\n field: existingField\n }\n );\n }\n\n const fieldType = getBaseFieldType(existingField);\n if (lockedField.type !== fieldType) {\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 reason: `\"type\" changed`,\n lockedFieldType: lockedField.type,\n existingFieldType: fieldType\n }\n );\n }\n\n /**\n * Check `lockedField` invariant for specific field\n */\n const lockedFieldsByType = cmsLockedFieldPlugins.filter(\n pl => pl.fieldType === getBaseFieldType(lockedField)\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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"}
@@ -49,68 +49,15 @@ var _access = require("../utils/access");
49
49
 
50
50
  var _validateModelFields = require("./contentModel/validateModelFields");
51
51
 
52
- var _semver = _interopRequireDefault(require("semver"));
53
-
54
- /**
55
- * TODO: remove for 5.34.0
56
- * Required because of the 5.33.0 upgrade.
57
- * Until the upgrade is done, API will break because there is no storageId assigned.
58
- */
59
- const featureVersion = _semver.default.coerce("5.33.0");
60
-
61
- const attachStorageIdToFields = fields => {
62
- return fields.map(field => {
63
- var _field$settings;
64
-
65
- if ((_field$settings = field.settings) !== null && _field$settings !== void 0 && _field$settings.fields) {
66
- field.settings.fields = attachStorageIdToFields(field.settings.fields);
67
- }
68
-
69
- if (!field.storageId) {
70
- field.storageId = field.fieldId;
71
- }
72
-
73
- return field;
74
- });
75
- };
76
-
77
- const attachStorageIdToModelFields = model => {
78
- if (!model.webinyVersion) {
79
- return model.fields;
80
- }
81
-
82
- const version = _semver.default.coerce(model.webinyVersion);
83
-
84
- if (!version) {
85
- return model.fields;
86
- }
87
- /**
88
- * Unfortunately we need to check for beta and next.
89
- * TODO remove after 5.33.0
90
- */
91
-
92
-
93
- if (model.webinyVersion.match(/beta|next/)) {
94
- return attachStorageIdToFields(model.fields);
95
- }
96
-
97
- if (_semver.default.compare(version, featureVersion) >= 0) {
98
- return model.fields;
99
- }
100
-
101
- return attachStorageIdToFields(model.fields);
102
- };
103
52
  /**
104
53
  * Given a model, return an array of tags ensuring the `type` tag is set.
105
54
  */
106
-
107
-
108
55
  const ensureTypeTag = model => {
109
56
  // Let's make sure we have a `type` tag assigned.
110
- // If `type` tag is not set, set it to a default one (`contentModel`).
57
+ // If `type` tag is not set, set it to a default one (`model`).
111
58
  const tags = model.tags || [];
112
59
 
113
- if (!tags.find(tag => tag.startsWith("type:"))) {
60
+ if (!tags.some(tag => tag.startsWith("type:"))) {
114
61
  tags.push("type:model");
115
62
  }
116
63
 
@@ -136,7 +83,6 @@ const createModelsCrud = params => {
136
83
  return [models.map(model => {
137
84
  return (0, _objectSpread2.default)((0, _objectSpread2.default)({}, model), {}, {
138
85
  tags: ensureTypeTag(model),
139
- fields: attachStorageIdToModelFields(model),
140
86
  tenant: model.tenant || getTenant().id,
141
87
  locale: model.locale || getLocale().code
142
88
  });
@@ -174,13 +120,13 @@ const createModelsCrud = params => {
174
120
  */
175
121
  .filter(plugin => {
176
122
  const {
177
- tenant: t,
178
- locale: l
123
+ tenant: modelTenant,
124
+ locale: modelLocale
179
125
  } = plugin.contentModel;
180
126
 
181
- if (t && t !== tenant) {
127
+ if (modelTenant && modelTenant !== tenant) {
182
128
  return false;
183
- } else if (l && l !== locale) {
129
+ } else if (modelLocale && modelLocale !== locale) {
184
130
  return false;
185
131
  }
186
132
 
@@ -272,20 +218,40 @@ const createModelsCrud = params => {
272
218
  }
273
219
 
274
220
  return await updateManager(context, model);
275
- }; // create
221
+ };
222
+ /**
223
+ * Create
224
+ */
276
225
 
277
226
 
278
227
  const onModelBeforeCreate = (0, _pubsub.createTopic)("cms.onModelBeforeCreate");
279
- const onModelAfterCreate = (0, _pubsub.createTopic)("cms.onModelAfterCreate"); // create from
228
+ const onModelAfterCreate = (0, _pubsub.createTopic)("cms.onModelAfterCreate");
229
+ const onModelCreateError = (0, _pubsub.createTopic)("cms.onModelCreateError");
230
+ /**
231
+ * Create from / clone
232
+ */
280
233
 
281
234
  const onModelBeforeCreateFrom = (0, _pubsub.createTopic)("cms.onModelBeforeCreateFrom");
282
- const onModelAfterCreateFrom = (0, _pubsub.createTopic)("cms.onModelAfterCreateFrom"); // update
235
+ const onModelAfterCreateFrom = (0, _pubsub.createTopic)("cms.onModelAfterCreateFrom");
236
+ const onModelCreateFromError = (0, _pubsub.createTopic)("cms.onModelCreateFromError");
237
+ /**
238
+ * Update
239
+ */
283
240
 
284
241
  const onModelBeforeUpdate = (0, _pubsub.createTopic)("cms.onModelBeforeUpdate");
285
- const onModelAfterUpdate = (0, _pubsub.createTopic)("cms.onModelAfterUpdate"); // delete
242
+ const onModelAfterUpdate = (0, _pubsub.createTopic)("cms.onModelAfterUpdate");
243
+ const onModelUpdateError = (0, _pubsub.createTopic)("cms.onModelUpdateError");
244
+ /**
245
+ * Delete
246
+ */
286
247
 
287
248
  const onModelBeforeDelete = (0, _pubsub.createTopic)("cms.onModelBeforeDelete");
288
249
  const onModelAfterDelete = (0, _pubsub.createTopic)("cms.onModelAfterDelete");
250
+ const onModelDeleteError = (0, _pubsub.createTopic)("cms.onModelDeleteError");
251
+ /**
252
+ * Initialize
253
+ */
254
+
289
255
  const onModelInitialize = (0, _pubsub.createTopic)("cms.onModelInitialize");
290
256
  /**
291
257
  * We need to assign some default behaviors.
@@ -341,12 +307,16 @@ const createModelsCrud = params => {
341
307
  */
342
308
  onModelBeforeCreate,
343
309
  onModelAfterCreate,
310
+ onModelCreateError,
344
311
  onModelBeforeCreateFrom,
345
312
  onModelAfterCreateFrom,
313
+ onModelCreateFromError,
346
314
  onModelBeforeUpdate,
347
315
  onModelAfterUpdate,
316
+ onModelUpdateError,
348
317
  onModelBeforeDelete,
349
318
  onModelAfterDelete,
319
+ onModelDeleteError,
350
320
  onModelInitialize,
351
321
  clearModelsCache,
352
322
  getModel,
@@ -392,20 +362,30 @@ const createModelsCrud = params => {
392
362
  webinyVersion: context.WEBINY_VERSION
393
363
  };
394
364
  model.tags = ensureTypeTag(model);
395
- await onModelBeforeCreate.publish({
396
- input,
397
- model
398
- });
399
- const createdModel = await storageOperations.models.create({
400
- model
401
- });
402
- loaders.listModels.clearAll();
403
- await updateManager(context, model);
404
- await onModelAfterCreate.publish({
405
- input,
406
- model: createdModel
407
- });
408
- return createdModel;
365
+
366
+ try {
367
+ await onModelBeforeCreate.publish({
368
+ input,
369
+ model
370
+ });
371
+ const createdModel = await storageOperations.models.create({
372
+ model
373
+ });
374
+ loaders.listModels.clearAll();
375
+ await updateManager(context, model);
376
+ await onModelAfterCreate.publish({
377
+ input,
378
+ model: createdModel
379
+ });
380
+ return createdModel;
381
+ } catch (ex) {
382
+ await onModelCreateError.publish({
383
+ input,
384
+ model,
385
+ error: ex
386
+ });
387
+ throw ex;
388
+ }
409
389
  },
410
390
 
411
391
  /**
@@ -422,22 +402,33 @@ const createModelsCrud = params => {
422
402
  locale: initialModel.locale || getLocale().code,
423
403
  webinyVersion: context.WEBINY_VERSION
424
404
  });
425
- await onModelBeforeUpdate.publish({
426
- input: {},
427
- original,
428
- model
429
- });
430
- const resultModel = await storageOperations.models.update({
431
- model
432
- });
433
- await updateManager(context, resultModel);
434
- loaders.listModels.clearAll();
435
- await onModelAfterUpdate.publish({
436
- input: {},
437
- original,
438
- model: resultModel
439
- });
440
- return resultModel;
405
+
406
+ try {
407
+ await onModelBeforeUpdate.publish({
408
+ input: {},
409
+ original,
410
+ model
411
+ });
412
+ const resultModel = await storageOperations.models.update({
413
+ model
414
+ });
415
+ await updateManager(context, resultModel);
416
+ loaders.listModels.clearAll();
417
+ await onModelAfterUpdate.publish({
418
+ input: {},
419
+ original,
420
+ model: resultModel
421
+ });
422
+ return resultModel;
423
+ } catch (ex) {
424
+ await onModelUpdateError.publish({
425
+ input: {},
426
+ original,
427
+ model,
428
+ error: ex
429
+ });
430
+ throw ex;
431
+ }
441
432
  },
442
433
 
443
434
  async createModelFrom(modelId, data) {
@@ -496,22 +487,33 @@ const createModelsCrud = params => {
496
487
  lockedFields: [],
497
488
  webinyVersion: context.WEBINY_VERSION
498
489
  });
499
- await onModelBeforeCreateFrom.publish({
500
- input,
501
- model,
502
- original
503
- });
504
- const createdModel = await storageOperations.models.create({
505
- model
506
- });
507
- loaders.listModels.clearAll();
508
- await updateManager(context, model);
509
- await onModelAfterCreateFrom.publish({
510
- input,
511
- original,
512
- model: createdModel
513
- });
514
- return createdModel;
490
+
491
+ try {
492
+ await onModelBeforeCreateFrom.publish({
493
+ input,
494
+ model,
495
+ original
496
+ });
497
+ const createdModel = await storageOperations.models.create({
498
+ model
499
+ });
500
+ loaders.listModels.clearAll();
501
+ await updateManager(context, model);
502
+ await onModelAfterCreateFrom.publish({
503
+ input,
504
+ original,
505
+ model: createdModel
506
+ });
507
+ return createdModel;
508
+ } catch (ex) {
509
+ await onModelCreateFromError.publish({
510
+ input,
511
+ original,
512
+ model,
513
+ error: ex
514
+ });
515
+ throw ex;
516
+ }
515
517
  },
516
518
 
517
519
  async updateModel(modelId, inputData) {
@@ -561,48 +563,68 @@ const createModelsCrud = params => {
561
563
  savedOn: new Date().toISOString()
562
564
  });
563
565
  model.tags = ensureTypeTag(model);
564
- await onModelBeforeUpdate.publish({
565
- input,
566
- original,
567
- model
568
- });
569
- const resultModel = await storageOperations.models.update({
570
- model
571
- });
572
- await updateManager(context, resultModel);
573
- await onModelAfterUpdate.publish({
574
- input,
575
- original,
576
- model: resultModel
577
- });
578
- return resultModel;
566
+
567
+ try {
568
+ await onModelBeforeUpdate.publish({
569
+ input,
570
+ original,
571
+ model
572
+ });
573
+ const resultModel = await storageOperations.models.update({
574
+ model
575
+ });
576
+ await updateManager(context, resultModel);
577
+ await onModelAfterUpdate.publish({
578
+ input,
579
+ original,
580
+ model: resultModel
581
+ });
582
+ return resultModel;
583
+ } catch (ex) {
584
+ await onModelUpdateError.publish({
585
+ input,
586
+ model,
587
+ original,
588
+ error: ex
589
+ });
590
+ throw ex;
591
+ }
579
592
  },
580
593
 
581
594
  async deleteModel(modelId) {
582
595
  await checkModelPermissions("d");
583
596
  const model = await getModel(modelId);
584
- await onModelBeforeDelete.publish({
585
- model
586
- });
587
597
 
588
598
  try {
589
- await storageOperations.models.delete({
599
+ await onModelBeforeDelete.publish({
600
+ model
601
+ });
602
+
603
+ try {
604
+ await storageOperations.models.delete({
605
+ model
606
+ });
607
+ } catch (ex) {
608
+ throw new _error.default(ex.message || "Could not delete the content model", ex.code || "CONTENT_MODEL_DELETE_ERROR", {
609
+ error: ex,
610
+ modelId: model.modelId
611
+ });
612
+ }
613
+
614
+ await onModelAfterDelete.publish({
590
615
  model
591
616
  });
617
+ managers.delete(model.modelId);
592
618
  } catch (ex) {
593
- throw new _error.default(ex.message || "Could not delete the content model", ex.code || "CONTENT_MODEL_DELETE_ERROR", {
594
- error: ex,
595
- modelId: model.modelId
619
+ await onModelDeleteError.publish({
620
+ model,
621
+ error: ex
596
622
  });
623
+ throw ex;
597
624
  }
598
-
599
- await onModelAfterDelete.publish({
600
- model
601
- });
602
- managers.delete(model.modelId);
603
625
  },
604
626
 
605
- async initializeModel(modelId) {
627
+ async initializeModel(modelId, data) {
606
628
  /**
607
629
  * We require that users have write permissions to initialize models.
608
630
  * Maybe introduce another permission for it?
@@ -610,7 +632,8 @@ const createModelsCrud = params => {
610
632
  await checkModelPermissions("w");
611
633
  const model = await getModel(modelId);
612
634
  await onModelInitialize.publish({
613
- model
635
+ model,
636
+ data
614
637
  });
615
638
  return true;
616
639
  },