@webiny/api-headless-cms 0.0.0-unstable.c2780f51fe → 0.0.0-unstable.c59b9cc5b9
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/crud/contentEntry/referenceFieldsMapping.js +34 -5
- package/crud/contentEntry/referenceFieldsMapping.js.map +1 -1
- package/crud/contentEntry.crud.d.ts +4 -4
- package/crud/contentEntry.crud.js +183 -18
- package/crud/contentEntry.crud.js.map +1 -1
- package/crud/contentModelGroup.crud.js +1 -7
- package/crud/contentModelGroup.crud.js.map +1 -1
- package/graphql/schema/baseSchema.js +15 -0
- package/graphql/schema/baseSchema.js.map +1 -1
- package/graphql/schema/createFieldResolvers.d.ts +1 -1
- package/graphql/schema/createFieldResolvers.js +6 -12
- package/graphql/schema/createFieldResolvers.js.map +1 -1
- package/graphql/schema/createFieldTypePluginRecords.d.ts +3 -0
- package/graphql/schema/createFieldTypePluginRecords.js +13 -0
- package/graphql/schema/createFieldTypePluginRecords.js.map +1 -0
- package/graphql/schema/createManageResolvers.js +4 -0
- package/graphql/schema/createManageResolvers.js.map +1 -1
- package/graphql/schema/createManageSDL.js +34 -26
- package/graphql/schema/createManageSDL.js.map +1 -1
- package/graphql/schema/createReadSDL.js +22 -19
- package/graphql/schema/createReadSDL.js.map +1 -1
- package/graphql/schema/resolvers/manage/resolveDelete.d.ts +2 -1
- package/graphql/schema/resolvers/manage/resolveDelete.js +13 -3
- package/graphql/schema/resolvers/manage/resolveDelete.js.map +1 -1
- package/graphql/schema/resolvers/manage/resolveDeleteMultiple.d.ts +7 -0
- package/graphql/schema/resolvers/manage/resolveDeleteMultiple.js +20 -0
- package/graphql/schema/resolvers/manage/resolveDeleteMultiple.js.map +1 -0
- package/graphql/schema/resolvers/manage/resolveGetUniqueFieldValues.d.ts +4 -0
- package/graphql/schema/resolvers/manage/resolveGetUniqueFieldValues.js +18 -0
- package/graphql/schema/resolvers/manage/resolveGetUniqueFieldValues.js.map +1 -0
- package/graphql/schema/schemaPlugins.js +2 -11
- package/graphql/schema/schemaPlugins.js.map +1 -1
- package/graphqlFields/dynamicZone/dynamicZoneField.js +43 -28
- package/graphqlFields/dynamicZone/dynamicZoneField.js.map +1 -1
- package/graphqlFields/object.js.map +1 -1
- package/package.json +35 -35
- package/plugins/CmsModelPlugin.d.ts +3 -1
- package/plugins/CmsModelPlugin.js.map +1 -1
- package/types.d.ts +82 -31
- package/types.js +11 -0
- package/types.js.map +1 -1
- package/utils/converters/valueKeyStorageConverter.js +5 -2
- package/utils/converters/valueKeyStorageConverter.js.map +1 -1
- package/utils/getBaseFieldType.d.ts +1 -3
- package/utils/getBaseFieldType.js.map +1 -1
- package/utils/getEntryDescription.d.ts +1 -1
- package/utils/getEntryDescription.js.map +1 -1
- package/utils/getEntryImage.d.ts +1 -1
- package/utils/getEntryImage.js.map +1 -1
- package/utils/getEntryTitle.d.ts +1 -1
- package/utils/getEntryTitle.js.map +1 -1
- package/utils/renderFields.d.ts +2 -1
- package/utils/renderFields.js +2 -1
- package/utils/renderFields.js.map +1 -1
- package/utils/renderGetFilterFields.d.ts +2 -2
- package/utils/renderGetFilterFields.js +7 -20
- package/utils/renderGetFilterFields.js.map +1 -1
- package/utils/renderInputFields.d.ts +2 -1
- package/utils/renderInputFields.js +14 -6
- package/utils/renderInputFields.js.map +1 -1
- package/utils/renderListFilterFields.d.ts +2 -1
- package/utils/renderListFilterFields.js +9 -20
- package/utils/renderListFilterFields.js.map +1 -1
- package/utils/renderSortEnum.d.ts +2 -1
- package/utils/renderSortEnum.js +2 -1
- package/utils/renderSortEnum.js.map +1 -1
- package/crud/contentModel/createFieldModels.d.ts +0 -2
- package/crud/contentModel/createFieldModels.js +0 -26
- package/crud/contentModel/createFieldModels.js.map +0 -1
- package/crud/contentModel/fieldIdValidation.d.ts +0 -1
- package/crud/contentModel/fieldIdValidation.js +0 -25
- package/crud/contentModel/fieldIdValidation.js.map +0 -1
- package/crud/contentModel/idValidation.d.ts +0 -1
- package/crud/contentModel/idValidation.js +0 -22
- package/crud/contentModel/idValidation.js.map +0 -1
- package/crud/contentModel/models.d.ts +0 -4
- package/crud/contentModel/models.js +0 -192
- package/crud/contentModel/models.js.map +0 -1
- package/crud/contentModel/systemFields.d.ts +0 -1
- package/crud/contentModel/systemFields.js +0 -8
- package/crud/contentModel/systemFields.js.map +0 -1
- package/upgrades/5.33.0/index.d.ts +0 -3
- package/upgrades/5.33.0/index.js +0 -182
- package/upgrades/5.33.0/index.js.map +0 -1
- package/upgrades/index.d.ts +0 -1
- package/upgrades/index.js +0 -12
- package/upgrades/index.js.map +0 -1
- package/utils/pluralizedTypeName.d.ts +0 -1
- package/utils/pluralizedTypeName.js +0 -26
- package/utils/pluralizedTypeName.js.map +0 -1
|
@@ -18,8 +18,8 @@ const buildReferenceFieldPaths = params => {
|
|
|
18
18
|
} = params;
|
|
19
19
|
const parentPaths = [...initialParentPaths];
|
|
20
20
|
const isMultipleValues = Array.isArray(input);
|
|
21
|
-
return fields.filter(field => ["object", "ref"].includes((0, _getBaseFieldType.getBaseFieldType)(field))).reduce((collection, field) => {
|
|
22
|
-
var _field$
|
|
21
|
+
return fields.filter(field => ["object", "ref", "dynamicZone"].includes((0, _getBaseFieldType.getBaseFieldType)(field))).reduce((collection, field) => {
|
|
22
|
+
var _field$settings3;
|
|
23
23
|
/**
|
|
24
24
|
* First we check the ref field
|
|
25
25
|
*/
|
|
@@ -47,6 +47,35 @@ const buildReferenceFieldPaths = params => {
|
|
|
47
47
|
collection.push(`${parentPathsValue}${field.fieldId}`);
|
|
48
48
|
return collection;
|
|
49
49
|
}
|
|
50
|
+
if (baseType === "dynamicZone") {
|
|
51
|
+
var _field$settings;
|
|
52
|
+
const templates = ((_field$settings = field.settings) === null || _field$settings === void 0 ? void 0 : _field$settings.templates) || [];
|
|
53
|
+
for (const template of templates) {
|
|
54
|
+
if (field.multipleValues) {
|
|
55
|
+
const inputValue = _dotProp.default.get(input, `${field.fieldId}`, []);
|
|
56
|
+
if (Array.isArray(inputValue) === false) {
|
|
57
|
+
return collection;
|
|
58
|
+
}
|
|
59
|
+
for (const key in inputValue) {
|
|
60
|
+
const result = buildReferenceFieldPaths({
|
|
61
|
+
fields: template.fields,
|
|
62
|
+
input: inputValue[key],
|
|
63
|
+
parentPaths: parentPaths.concat([field.fieldId, key, template.gqlTypeName])
|
|
64
|
+
});
|
|
65
|
+
collection.push(...result);
|
|
66
|
+
}
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
const result = buildReferenceFieldPaths({
|
|
70
|
+
fields: template.fields,
|
|
71
|
+
input,
|
|
72
|
+
parentPaths: parentPaths.concat([field.fieldId, template.gqlTypeName])
|
|
73
|
+
});
|
|
74
|
+
collection.push(...result);
|
|
75
|
+
}
|
|
76
|
+
return collection;
|
|
77
|
+
}
|
|
78
|
+
|
|
50
79
|
/**
|
|
51
80
|
* Then we move onto the object field
|
|
52
81
|
*/
|
|
@@ -72,9 +101,9 @@ const buildReferenceFieldPaths = params => {
|
|
|
72
101
|
return collection;
|
|
73
102
|
}
|
|
74
103
|
for (const key in objFieldInputValue) {
|
|
75
|
-
var _field$
|
|
104
|
+
var _field$settings2;
|
|
76
105
|
const result = buildReferenceFieldPaths({
|
|
77
|
-
fields: ((_field$
|
|
106
|
+
fields: ((_field$settings2 = field.settings) === null || _field$settings2 === void 0 ? void 0 : _field$settings2.fields) || [],
|
|
78
107
|
input: objFieldInputValue[key],
|
|
79
108
|
parentPaths: parentPaths.concat([field.fieldId, key])
|
|
80
109
|
});
|
|
@@ -87,7 +116,7 @@ const buildReferenceFieldPaths = params => {
|
|
|
87
116
|
* Single value reference field.
|
|
88
117
|
*/
|
|
89
118
|
const results = buildReferenceFieldPaths({
|
|
90
|
-
fields: ((_field$
|
|
119
|
+
fields: ((_field$settings3 = field.settings) === null || _field$settings3 === void 0 ? void 0 : _field$settings3.fields) || [],
|
|
91
120
|
input: objFieldInputValue,
|
|
92
121
|
parentPaths: parentPaths.concat([field.fieldId])
|
|
93
122
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["buildReferenceFieldPaths","params","fields","parentPaths","initialParentPaths","input","isMultipleValues","Array","isArray","filter","field","includes","getBaseFieldType","reduce","collection","baseType","parentPathsValue","length","join","multipleValues","inputValue","dotProp","get","fieldId","key","path","push","objFieldPath","objFieldInputValue","result","settings","concat","results","getReferenceFieldValue","ref","id","modelId","entryId","trim","referenceFieldsMapping","context","model","validateEntries","output","referenceFieldPaths","referencesByModel","pathsByReferenceId","Object","keys","models","cms","listModels","entries","promises","map","getEntriesByIds","Promise","all","records","entry","WebinyError","parseIdentifier","paths","set"],"sources":["referenceFieldsMapping.ts"],"sourcesContent":["import { CmsContext, CmsModel, CmsModelField } from \"~/types\";\nimport WebinyError from \"@webiny/error\";\nimport dotProp from \"dot-prop\";\nimport { parseIdentifier } from \"@webiny/utils\";\nimport { getBaseFieldType } from \"~/utils/getBaseFieldType\";\n\ninterface CmsRefEntry {\n id: string;\n entryId: string;\n modelId: string;\n}\n\ninterface ReferenceObject {\n id: string;\n modelId: string;\n}\n\ninterface Params {\n context: CmsContext;\n model: CmsModel;\n input: Record<string, ReferenceObject | ReferenceObject[]>;\n validateEntries?: boolean;\n}\n\ninterface BuildReferenceFieldPaths {\n fields: CmsModelField[];\n parentPaths: string[];\n input: Record<string, any>;\n}\n\nconst buildReferenceFieldPaths = (params: BuildReferenceFieldPaths): string[] => {\n const { fields, parentPaths: initialParentPaths, input } = params;\n\n const parentPaths = [...initialParentPaths];\n\n const isMultipleValues = Array.isArray(input);\n\n return fields\n .filter(field => [\"object\", \"ref\"].includes(getBaseFieldType(field)))\n .reduce((collection, field) => {\n /**\n * First we check the ref field\n */\n const baseType = getBaseFieldType(field);\n if (baseType === \"ref\") {\n const parentPathsValue = parentPaths.length > 0 ? `${parentPaths.join(\".\")}.` : \"\";\n if (field.multipleValues) {\n const inputValue = dotProp.get(input, `${field.fieldId}`, []);\n if (Array.isArray(inputValue) === false) {\n return collection;\n }\n for (const key in inputValue) {\n const path = `${parentPathsValue}${field.fieldId}.${key}`;\n collection.push(path);\n }\n return collection;\n }\n\n if (isMultipleValues) {\n for (const key in input) {\n const path = `${parentPathsValue}${key}.${field.fieldId}`;\n collection.push(path);\n }\n return collection;\n }\n\n collection.push(`${parentPathsValue}${field.fieldId}`);\n\n return collection;\n }\n /**\n * Then we move onto the object field\n */\n const parentPathsValue = parentPaths.length > 0 ? `${parentPaths.join(\".\")}.` : \"\";\n /**\n * This is if received input is array. We need to map key with fieldId at this point.\n */\n if (isMultipleValues) {\n for (const key in input) {\n const path = `${parentPathsValue}${key}.${field.fieldId}`;\n collection.push(path);\n }\n return collection;\n }\n\n const objFieldPath = `${field.fieldId}`;\n const objFieldInputValue = dotProp.get(input, objFieldPath, []);\n\n /**\n * If field is multiple values one, we need to go through the input and use the existing keys.\n */\n if (field.multipleValues) {\n if (Array.isArray(objFieldInputValue) === false) {\n return collection;\n }\n for (const key in objFieldInputValue) {\n const result = buildReferenceFieldPaths({\n fields: field.settings?.fields || [],\n input: objFieldInputValue[key],\n parentPaths: parentPaths.concat([field.fieldId, key])\n });\n collection.push(...result);\n }\n\n return collection;\n }\n\n /**\n * Single value reference field.\n */\n const results = buildReferenceFieldPaths({\n fields: field.settings?.fields || [],\n input: objFieldInputValue,\n parentPaths: parentPaths.concat([field.fieldId])\n });\n\n return collection.concat(results);\n }, [] as string[]);\n};\n\nconst getReferenceFieldValue = (ref: any): { id: string | null; modelId: string | null } => {\n if (!ref) {\n return {\n id: null,\n modelId: null\n };\n }\n return {\n id: (ref.id || ref.entryId || \"\").trim() || null,\n modelId: (ref.modelId || \"\").trim() || null\n };\n};\n\nexport const referenceFieldsMapping = async (params: Params): Promise<Record<string, any>> => {\n const { context, model, input, validateEntries = false } = params;\n\n let output: Record<string, any> = {\n ...input\n };\n\n const referenceFieldPaths = buildReferenceFieldPaths({\n fields: model.fields,\n input,\n parentPaths: []\n });\n if (referenceFieldPaths.length === 0) {\n return output;\n }\n\n const referencesByModel: Record<string, string[]> = {};\n const pathsByReferenceId: Record<string, string[]> = {};\n\n for (const path of referenceFieldPaths) {\n const ref = dotProp.get(output, path) as ReferenceObject | any;\n\n const { id, modelId } = getReferenceFieldValue(ref);\n\n if (!id || !modelId) {\n continue;\n }\n if (!referencesByModel[modelId]) {\n referencesByModel[modelId] = [];\n }\n referencesByModel[modelId].push(id);\n if (!pathsByReferenceId[id]) {\n pathsByReferenceId[id] = [];\n }\n pathsByReferenceId[id].push(path);\n }\n\n /**\n * Again, no point in going further.\n */\n if (Object.keys(referencesByModel).length === 0) {\n return output;\n }\n /**\n * Load all models and use only those that are used in reference.\n */\n const models = (await context.cms.listModels()).filter(model => {\n const entries = referencesByModel[model.modelId];\n if (!Array.isArray(entries) || entries.length === 0) {\n return false;\n }\n return true;\n });\n /**\n * Check for any model existence, just in case.\n */\n if (models.length === 0) {\n return output;\n }\n\n /**\n * Load all the entries by their ID\n */\n const promises = models.map(model => {\n return context.cms.getEntriesByIds(model, referencesByModel[model.modelId]);\n });\n\n const results = await Promise.all(promises);\n\n const records: Record<string, CmsRefEntry> = results.reduce((collection, entries) => {\n for (const entry of entries) {\n collection[entry.id] = {\n id: entry.id,\n entryId: entry.entryId,\n modelId: entry.modelId\n };\n }\n return collection;\n }, {} as Record<string, CmsRefEntry>);\n /**\n * Verify that all referenced entries actually exist.\n */\n for (const modelId in referencesByModel) {\n const entries = referencesByModel[modelId];\n for (const id of entries) {\n if (records[id]) {\n continue;\n } else if (validateEntries) {\n throw new WebinyError(\n `Missing referenced entry with id \"${id}\" in model \"${modelId}\".`,\n \"ENTRY_NOT_FOUND\",\n {\n id,\n model: modelId\n }\n );\n }\n const { id: entryId } = parseIdentifier(id);\n records[id] = {\n id,\n entryId,\n modelId\n };\n }\n }\n\n /**\n * In the end, assign the entryId, id and model values to the output.\n */\n for (const id in pathsByReferenceId) {\n const entry = records[id];\n const paths = pathsByReferenceId[id];\n if (!entry) {\n if (validateEntries) {\n throw new WebinyError(\"Missing entry in records.\", \"ENTRY_ERROR\", {\n id,\n paths\n });\n }\n continue;\n }\n for (const path of paths) {\n output = dotProp.set(output, path, {\n id: entry.id,\n entryId: entry.entryId,\n modelId: entry.modelId\n });\n }\n }\n\n return output;\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"names":["buildReferenceFieldPaths","params","fields","parentPaths","initialParentPaths","input","isMultipleValues","Array","isArray","filter","field","includes","getBaseFieldType","reduce","collection","baseType","parentPathsValue","length","join","multipleValues","inputValue","dotProp","get","fieldId","key","path","push","templates","settings","template","result","concat","gqlTypeName","objFieldPath","objFieldInputValue","results","getReferenceFieldValue","ref","id","modelId","entryId","trim","referenceFieldsMapping","context","model","validateEntries","output","referenceFieldPaths","referencesByModel","pathsByReferenceId","Object","keys","models","cms","listModels","entries","promises","map","getEntriesByIds","Promise","all","records","entry","WebinyError","parseIdentifier","paths","set"],"sources":["referenceFieldsMapping.ts"],"sourcesContent":["import { CmsContext, CmsDynamicZoneTemplate, CmsModel, CmsModelField } from \"~/types\";\nimport WebinyError from \"@webiny/error\";\nimport dotProp from \"dot-prop\";\nimport { parseIdentifier } from \"@webiny/utils\";\nimport { getBaseFieldType } from \"~/utils/getBaseFieldType\";\n\ninterface CmsRefEntry {\n id: string;\n entryId: string;\n modelId: string;\n}\n\ninterface ReferenceObject {\n id: string;\n modelId: string;\n}\n\ninterface Params {\n context: CmsContext;\n model: CmsModel;\n input: Record<string, ReferenceObject | ReferenceObject[]>;\n validateEntries?: boolean;\n}\n\ninterface BuildReferenceFieldPaths {\n fields: CmsModelField[];\n parentPaths: string[];\n input: Record<string, any>;\n}\n\nconst buildReferenceFieldPaths = (params: BuildReferenceFieldPaths): string[] => {\n const { fields, parentPaths: initialParentPaths, input } = params;\n\n const parentPaths = [...initialParentPaths];\n\n const isMultipleValues = Array.isArray(input);\n\n return fields\n .filter(field => [\"object\", \"ref\", \"dynamicZone\"].includes(getBaseFieldType(field)))\n .reduce((collection, field) => {\n /**\n * First we check the ref field\n */\n const baseType = getBaseFieldType(field);\n if (baseType === \"ref\") {\n const parentPathsValue = parentPaths.length > 0 ? `${parentPaths.join(\".\")}.` : \"\";\n if (field.multipleValues) {\n const inputValue = dotProp.get(input, `${field.fieldId}`, []);\n if (Array.isArray(inputValue) === false) {\n return collection;\n }\n for (const key in inputValue) {\n const path = `${parentPathsValue}${field.fieldId}.${key}`;\n collection.push(path);\n }\n return collection;\n }\n\n if (isMultipleValues) {\n for (const key in input) {\n const path = `${parentPathsValue}${key}.${field.fieldId}`;\n collection.push(path);\n }\n return collection;\n }\n\n collection.push(`${parentPathsValue}${field.fieldId}`);\n\n return collection;\n }\n\n if (baseType === \"dynamicZone\") {\n const templates: CmsDynamicZoneTemplate[] = field.settings?.templates || [];\n for (const template of templates) {\n if (field.multipleValues) {\n const inputValue = dotProp.get(input, `${field.fieldId}`, []);\n if (Array.isArray(inputValue) === false) {\n return collection;\n }\n\n for (const key in inputValue) {\n const result = buildReferenceFieldPaths({\n fields: template.fields,\n input: inputValue[key],\n parentPaths: parentPaths.concat([\n field.fieldId,\n key,\n template.gqlTypeName\n ])\n });\n collection.push(...result);\n }\n continue;\n }\n\n const result = buildReferenceFieldPaths({\n fields: template.fields,\n input,\n parentPaths: parentPaths.concat([field.fieldId, template.gqlTypeName])\n });\n collection.push(...result);\n }\n\n return collection;\n }\n\n /**\n * Then we move onto the object field\n */\n const parentPathsValue = parentPaths.length > 0 ? `${parentPaths.join(\".\")}.` : \"\";\n /**\n * This is if received input is array. We need to map key with fieldId at this point.\n */\n if (isMultipleValues) {\n for (const key in input) {\n const path = `${parentPathsValue}${key}.${field.fieldId}`;\n collection.push(path);\n }\n return collection;\n }\n\n const objFieldPath = `${field.fieldId}`;\n const objFieldInputValue = dotProp.get(input, objFieldPath, []);\n\n /**\n * If field is multiple values one, we need to go through the input and use the existing keys.\n */\n if (field.multipleValues) {\n if (Array.isArray(objFieldInputValue) === false) {\n return collection;\n }\n for (const key in objFieldInputValue) {\n const result = buildReferenceFieldPaths({\n fields: field.settings?.fields || [],\n input: objFieldInputValue[key],\n parentPaths: parentPaths.concat([field.fieldId, key])\n });\n collection.push(...result);\n }\n\n return collection;\n }\n\n /**\n * Single value reference field.\n */\n const results = buildReferenceFieldPaths({\n fields: field.settings?.fields || [],\n input: objFieldInputValue,\n parentPaths: parentPaths.concat([field.fieldId])\n });\n\n return collection.concat(results);\n }, [] as string[]);\n};\n\nconst getReferenceFieldValue = (ref: any): { id: string | null; modelId: string | null } => {\n if (!ref) {\n return {\n id: null,\n modelId: null\n };\n }\n return {\n id: (ref.id || ref.entryId || \"\").trim() || null,\n modelId: (ref.modelId || \"\").trim() || null\n };\n};\n\nexport const referenceFieldsMapping = async (params: Params): Promise<Record<string, any>> => {\n const { context, model, input, validateEntries = false } = params;\n\n let output: Record<string, any> = {\n ...input\n };\n\n const referenceFieldPaths = buildReferenceFieldPaths({\n fields: model.fields,\n input,\n parentPaths: []\n });\n if (referenceFieldPaths.length === 0) {\n return output;\n }\n\n const referencesByModel: Record<string, string[]> = {};\n const pathsByReferenceId: Record<string, string[]> = {};\n\n for (const path of referenceFieldPaths) {\n const ref = dotProp.get(output, path) as ReferenceObject | any;\n\n const { id, modelId } = getReferenceFieldValue(ref);\n\n if (!id || !modelId) {\n continue;\n }\n if (!referencesByModel[modelId]) {\n referencesByModel[modelId] = [];\n }\n referencesByModel[modelId].push(id);\n if (!pathsByReferenceId[id]) {\n pathsByReferenceId[id] = [];\n }\n pathsByReferenceId[id].push(path);\n }\n\n /**\n * Again, no point in going further.\n */\n if (Object.keys(referencesByModel).length === 0) {\n return output;\n }\n /**\n * Load all models and use only those that are used in reference.\n */\n const models = (await context.cms.listModels()).filter(model => {\n const entries = referencesByModel[model.modelId];\n if (!Array.isArray(entries) || entries.length === 0) {\n return false;\n }\n return true;\n });\n /**\n * Check for any model existence, just in case.\n */\n if (models.length === 0) {\n return output;\n }\n\n /**\n * Load all the entries by their ID\n */\n const promises = models.map(model => {\n return context.cms.getEntriesByIds(model, referencesByModel[model.modelId]);\n });\n\n const results = await Promise.all(promises);\n\n const records: Record<string, CmsRefEntry> = results.reduce((collection, entries) => {\n for (const entry of entries) {\n collection[entry.id] = {\n id: entry.id,\n entryId: entry.entryId,\n modelId: entry.modelId\n };\n }\n return collection;\n }, {} as Record<string, CmsRefEntry>);\n /**\n * Verify that all referenced entries actually exist.\n */\n for (const modelId in referencesByModel) {\n const entries = referencesByModel[modelId];\n for (const id of entries) {\n if (records[id]) {\n continue;\n } else if (validateEntries) {\n throw new WebinyError(\n `Missing referenced entry with id \"${id}\" in model \"${modelId}\".`,\n \"ENTRY_NOT_FOUND\",\n {\n id,\n model: modelId\n }\n );\n }\n const { id: entryId } = parseIdentifier(id);\n records[id] = {\n id,\n entryId,\n modelId\n };\n }\n }\n\n /**\n * In the end, assign the entryId, id and model values to the output.\n */\n for (const id in pathsByReferenceId) {\n const entry = records[id];\n const paths = pathsByReferenceId[id];\n if (!entry) {\n if (validateEntries) {\n throw new WebinyError(\"Missing entry in records.\", \"ENTRY_ERROR\", {\n id,\n paths\n });\n }\n continue;\n }\n for (const path of paths) {\n output = dotProp.set(output, path, {\n id: entry.id,\n entryId: entry.entryId,\n modelId: entry.modelId\n });\n }\n }\n\n return output;\n};\n"],"mappings":"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"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { CmsContext, CmsEntryContext, HeadlessCmsStorageOperations } from "../types";
|
|
1
|
+
import { CmsContext, CmsEntryContext, CONTENT_ENTRY_STATUS, HeadlessCmsStorageOperations } from "../types";
|
|
2
2
|
import { SecurityIdentity } from "@webiny/api-security/types";
|
|
3
3
|
import { Tenant } from "@webiny/api-tenancy/types";
|
|
4
4
|
import { I18NLocale } from "@webiny/api-i18n/types";
|
|
5
|
-
export declare const STATUS_DRAFT =
|
|
6
|
-
export declare const STATUS_PUBLISHED =
|
|
7
|
-
export declare const STATUS_UNPUBLISHED =
|
|
5
|
+
export declare const STATUS_DRAFT = CONTENT_ENTRY_STATUS.DRAFT;
|
|
6
|
+
export declare const STATUS_PUBLISHED = CONTENT_ENTRY_STATUS.PUBLISHED;
|
|
7
|
+
export declare const STATUS_UNPUBLISHED = CONTENT_ENTRY_STATUS.UNPUBLISHED;
|
|
8
8
|
interface CreateContentEntryCrudParams {
|
|
9
9
|
storageOperations: HeadlessCmsStorageOperations;
|
|
10
10
|
context: CmsContext;
|
|
@@ -7,14 +7,14 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
7
7
|
exports.createContentEntryCrud = exports.STATUS_UNPUBLISHED = exports.STATUS_PUBLISHED = exports.STATUS_DRAFT = void 0;
|
|
8
8
|
var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
|
|
9
9
|
var _merge = _interopRequireDefault(require("lodash/merge"));
|
|
10
|
-
var
|
|
10
|
+
var _utils = require("@webiny/utils");
|
|
11
11
|
var _error = _interopRequireDefault(require("@webiny/error"));
|
|
12
12
|
var _handlerGraphql = require("@webiny/handler-graphql");
|
|
13
|
+
var _types = require("../types");
|
|
13
14
|
var _entryDataValidation = require("./contentEntry/entryDataValidation");
|
|
14
15
|
var _pubsub = require("@webiny/pubsub");
|
|
15
16
|
var _beforeCreate = require("./contentEntry/beforeCreate");
|
|
16
17
|
var _beforeUpdate = require("./contentEntry/beforeUpdate");
|
|
17
|
-
var _utils = require("@webiny/utils");
|
|
18
18
|
var _afterDelete = require("./contentEntry/afterDelete");
|
|
19
19
|
var _referenceFieldsMapping = require("./contentEntry/referenceFieldsMapping");
|
|
20
20
|
var _permissions = require("../utils/permissions");
|
|
@@ -22,16 +22,12 @@ var _access = require("../utils/access");
|
|
|
22
22
|
var _ownership = require("../utils/ownership");
|
|
23
23
|
var _entryStorage = require("../utils/entryStorage");
|
|
24
24
|
var _searchableFields = require("./contentEntry/searchableFields");
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
*/
|
|
28
|
-
// @ts-ignore
|
|
29
|
-
|
|
30
|
-
const STATUS_DRAFT = "draft";
|
|
25
|
+
var _filterAsync = require("../utils/filterAsync");
|
|
26
|
+
const STATUS_DRAFT = _types.CONTENT_ENTRY_STATUS.DRAFT;
|
|
31
27
|
exports.STATUS_DRAFT = STATUS_DRAFT;
|
|
32
|
-
const STATUS_PUBLISHED =
|
|
28
|
+
const STATUS_PUBLISHED = _types.CONTENT_ENTRY_STATUS.PUBLISHED;
|
|
33
29
|
exports.STATUS_PUBLISHED = STATUS_PUBLISHED;
|
|
34
|
-
const STATUS_UNPUBLISHED =
|
|
30
|
+
const STATUS_UNPUBLISHED = _types.CONTENT_ENTRY_STATUS.UNPUBLISHED;
|
|
35
31
|
exports.STATUS_UNPUBLISHED = STATUS_UNPUBLISHED;
|
|
36
32
|
/**
|
|
37
33
|
* Used for some fields to convert their values.
|
|
@@ -133,7 +129,7 @@ const createEntryMeta = (input, original) => {
|
|
|
133
129
|
return (0, _utils.removeUndefinedValues)((0, _utils.removeNullValues)(meta));
|
|
134
130
|
};
|
|
135
131
|
const createEntryId = input => {
|
|
136
|
-
let entryId = (0,
|
|
132
|
+
let entryId = (0, _utils.mdbid)();
|
|
137
133
|
if (input.id) {
|
|
138
134
|
if (input.id.match(/^([a-zA-Z0-9])([a-zA-Z0-9\-]+)([a-zA-Z0-9])$/) === null) {
|
|
139
135
|
throw new _error.default("The provided ID is not valid. It must be a string which can be A-Z, a-z, 0-9, - and it cannot start or end with a -.", "INVALID_ID", {
|
|
@@ -247,6 +243,12 @@ const createContentEntryCrud = params => {
|
|
|
247
243
|
const onEntryRevisionBeforeDelete = (0, _pubsub.createTopic)("cms.onEntryRevisionBeforeDelete");
|
|
248
244
|
const onEntryRevisionAfterDelete = (0, _pubsub.createTopic)("cms.onEntryRevisionAfterDelete");
|
|
249
245
|
const onEntryRevisionDeleteError = (0, _pubsub.createTopic)("cms.onEntryRevisionDeleteError");
|
|
246
|
+
/**
|
|
247
|
+
* Delete multiple entries
|
|
248
|
+
*/
|
|
249
|
+
const onEntryBeforeDeleteMultiple = (0, _pubsub.createTopic)("cms.onEntryBeforeDeleteMultiple");
|
|
250
|
+
const onEntryAfterDeleteMultiple = (0, _pubsub.createTopic)("cms.onEntryAfterDeleteMultiple");
|
|
251
|
+
const onEntryDeleteMultipleError = (0, _pubsub.createTopic)("cms.onEntryDeleteMultipleError");
|
|
250
252
|
|
|
251
253
|
/**
|
|
252
254
|
* Get entry
|
|
@@ -397,9 +399,6 @@ const createContentEntryCrud = params => {
|
|
|
397
399
|
limit: initialLimit
|
|
398
400
|
} = params;
|
|
399
401
|
const limit = initialLimit && initialLimit > 0 ? initialLimit : 50;
|
|
400
|
-
/**
|
|
401
|
-
* We always assign tenant and locale because we do not allow one model to have content through multiple tenants.
|
|
402
|
-
*/
|
|
403
402
|
const where = (0, _objectSpread2.default)({}, initialWhere);
|
|
404
403
|
/**
|
|
405
404
|
* Possibly only get records which are owned by current user.
|
|
@@ -894,16 +893,110 @@ const createContentEntryCrud = params => {
|
|
|
894
893
|
});
|
|
895
894
|
}
|
|
896
895
|
};
|
|
897
|
-
const
|
|
896
|
+
const deleteMultipleEntries = async (model, params) => {
|
|
897
|
+
const {
|
|
898
|
+
entries: input
|
|
899
|
+
} = params;
|
|
900
|
+
const maxDeletableEntries = 50;
|
|
901
|
+
const entryIdList = new Set();
|
|
902
|
+
for (const id of input) {
|
|
903
|
+
const {
|
|
904
|
+
id: entryId
|
|
905
|
+
} = (0, _utils.parseIdentifier)(id);
|
|
906
|
+
entryIdList.add(entryId);
|
|
907
|
+
}
|
|
908
|
+
const ids = Array.from(entryIdList);
|
|
909
|
+
if (ids.length > maxDeletableEntries) {
|
|
910
|
+
throw new _error.default("Cannot delete more than 50 entries at once.", "DELETE_ENTRIES_MAX", {
|
|
911
|
+
entries: ids
|
|
912
|
+
});
|
|
913
|
+
}
|
|
914
|
+
const permission = await checkEntryPermissions({
|
|
915
|
+
rwd: "d"
|
|
916
|
+
});
|
|
917
|
+
await (0, _access.checkModelAccess)(context, model);
|
|
918
|
+
const {
|
|
919
|
+
items: entries
|
|
920
|
+
} = await storageOperations.entries.list(model, {
|
|
921
|
+
where: {
|
|
922
|
+
latest: true,
|
|
923
|
+
entryId_in: ids
|
|
924
|
+
},
|
|
925
|
+
limit: maxDeletableEntries + 1
|
|
926
|
+
});
|
|
927
|
+
/**
|
|
928
|
+
* We do not want to allow deleting entries that user does not own or cannot access.
|
|
929
|
+
*/
|
|
930
|
+
const items = (await (0, _filterAsync.filterAsync)(entries, async entry => {
|
|
931
|
+
return (0, _ownership.validateOwnership)(context, permission, entry);
|
|
932
|
+
})).map(entry => entry.id);
|
|
933
|
+
try {
|
|
934
|
+
await onEntryBeforeDeleteMultiple.publish({
|
|
935
|
+
entries,
|
|
936
|
+
ids,
|
|
937
|
+
model
|
|
938
|
+
});
|
|
939
|
+
await storageOperations.entries.deleteMultipleEntries(model, {
|
|
940
|
+
entries: items
|
|
941
|
+
});
|
|
942
|
+
await onEntryAfterDeleteMultiple.publish({
|
|
943
|
+
entries,
|
|
944
|
+
ids,
|
|
945
|
+
model
|
|
946
|
+
});
|
|
947
|
+
return items.map(id => {
|
|
948
|
+
return {
|
|
949
|
+
id
|
|
950
|
+
};
|
|
951
|
+
});
|
|
952
|
+
} catch (ex) {
|
|
953
|
+
await onEntryDeleteMultipleError.publish({
|
|
954
|
+
entries,
|
|
955
|
+
ids,
|
|
956
|
+
model,
|
|
957
|
+
error: ex
|
|
958
|
+
});
|
|
959
|
+
throw new _error.default(ex.message, ex.code || "DELETE_ENTRIES_MULTIPLE_ERROR", {
|
|
960
|
+
error: ex,
|
|
961
|
+
entries
|
|
962
|
+
});
|
|
963
|
+
}
|
|
964
|
+
};
|
|
965
|
+
const deleteEntry = async (model, id, options) => {
|
|
898
966
|
const permission = await checkEntryPermissions({
|
|
899
967
|
rwd: "d"
|
|
900
968
|
});
|
|
901
969
|
await (0, _access.checkModelAccess)(context, model);
|
|
970
|
+
const {
|
|
971
|
+
force
|
|
972
|
+
} = options || {};
|
|
902
973
|
const storageEntry = await storageOperations.entries.getLatestRevisionByEntryId(model, {
|
|
903
|
-
id
|
|
974
|
+
id
|
|
904
975
|
});
|
|
905
|
-
|
|
906
|
-
|
|
976
|
+
/**
|
|
977
|
+
* If there is no entry, and we do not force the deletion, just throw an error.
|
|
978
|
+
*/
|
|
979
|
+
if (!storageEntry && !force) {
|
|
980
|
+
throw new _handlerGraphql.NotFoundError(`Entry "${id}" was not found!`);
|
|
981
|
+
}
|
|
982
|
+
/**
|
|
983
|
+
* In the case we are forcing the deletion, we do not need the storageEntry to exist as it might be an error when loading single database record.
|
|
984
|
+
*
|
|
985
|
+
* This happens, sometimes, in the Elasticsearch system as the entry might get deleted from the DynamoDB but not from the Elasticsearch.
|
|
986
|
+
* This is due to high load on the Elasticsearch at the time of the deletion.
|
|
987
|
+
*/
|
|
988
|
+
//
|
|
989
|
+
else if (!storageEntry && force) {
|
|
990
|
+
const {
|
|
991
|
+
id: entryId
|
|
992
|
+
} = (0, _utils.parseIdentifier)(id);
|
|
993
|
+
return await deleteEntryHelper({
|
|
994
|
+
model,
|
|
995
|
+
entry: {
|
|
996
|
+
id,
|
|
997
|
+
entryId
|
|
998
|
+
}
|
|
999
|
+
});
|
|
907
1000
|
}
|
|
908
1001
|
(0, _ownership.checkOwnership)(context, permission, storageEntry);
|
|
909
1002
|
const entry = await (0, _entryStorage.entryFromStorageTransform)(context, model, storageEntry);
|
|
@@ -1018,6 +1111,68 @@ const createContentEntryCrud = params => {
|
|
|
1018
1111
|
});
|
|
1019
1112
|
}
|
|
1020
1113
|
};
|
|
1114
|
+
const getUniqueFieldValues = async (model, params) => {
|
|
1115
|
+
const permission = await checkEntryPermissions({
|
|
1116
|
+
rwd: "r"
|
|
1117
|
+
});
|
|
1118
|
+
await (0, _access.checkModelAccess)(context, model);
|
|
1119
|
+
const {
|
|
1120
|
+
where: initialWhere,
|
|
1121
|
+
fieldId
|
|
1122
|
+
} = params;
|
|
1123
|
+
const where = (0, _objectSpread2.default)({}, initialWhere);
|
|
1124
|
+
/**
|
|
1125
|
+
* Possibly only get records which are owned by current user.
|
|
1126
|
+
* Or if searching for the owner set that value - in the case that user can see other entries than their own.
|
|
1127
|
+
*/
|
|
1128
|
+
const ownedBy = permission.own ? getIdentity().id : where.ownedBy;
|
|
1129
|
+
if (ownedBy !== undefined) {
|
|
1130
|
+
where.ownedBy = ownedBy;
|
|
1131
|
+
}
|
|
1132
|
+
/**
|
|
1133
|
+
* Where must contain either latest or published keys.
|
|
1134
|
+
* We cannot list entries without one of those
|
|
1135
|
+
*/
|
|
1136
|
+
if (where.latest && where.published) {
|
|
1137
|
+
throw new _error.default("Cannot list entries that are both published and latest.", "LIST_ENTRIES_ERROR", {
|
|
1138
|
+
where
|
|
1139
|
+
});
|
|
1140
|
+
} else if (!where.latest && !where.published) {
|
|
1141
|
+
throw new _error.default("Cannot list entries if we do not have latest or published defined.", "LIST_ENTRIES_ERROR", {
|
|
1142
|
+
where
|
|
1143
|
+
});
|
|
1144
|
+
}
|
|
1145
|
+
/**
|
|
1146
|
+
* We need to verify that the field in question is searchable.
|
|
1147
|
+
*/
|
|
1148
|
+
const fields = (0, _searchableFields.getSearchableFields)({
|
|
1149
|
+
fields: model.fields,
|
|
1150
|
+
plugins: context.plugins,
|
|
1151
|
+
input: []
|
|
1152
|
+
});
|
|
1153
|
+
if (fields.includes(fieldId) === false) {
|
|
1154
|
+
throw new _error.default("Cannot list unique entry field values if the field is not searchable.", "LIST_UNIQUE_ENTRY_VALUES_ERROR", {
|
|
1155
|
+
fieldId
|
|
1156
|
+
});
|
|
1157
|
+
}
|
|
1158
|
+
try {
|
|
1159
|
+
return await storageOperations.entries.getUniqueFieldValues(model, {
|
|
1160
|
+
where,
|
|
1161
|
+
fieldId
|
|
1162
|
+
});
|
|
1163
|
+
} catch (ex) {
|
|
1164
|
+
throw new _error.default("Error while fetching unique entry values from storage.", "LIST_UNIQUE_ENTRY_VALUES_ERROR", {
|
|
1165
|
+
error: {
|
|
1166
|
+
message: ex.message,
|
|
1167
|
+
code: ex.code,
|
|
1168
|
+
data: ex.data
|
|
1169
|
+
},
|
|
1170
|
+
model,
|
|
1171
|
+
where,
|
|
1172
|
+
fieldId
|
|
1173
|
+
});
|
|
1174
|
+
}
|
|
1175
|
+
};
|
|
1021
1176
|
return {
|
|
1022
1177
|
/**
|
|
1023
1178
|
* Deprecated - will be removed in 5.35.0
|
|
@@ -1197,6 +1352,11 @@ const createContentEntryCrud = params => {
|
|
|
1197
1352
|
return deleteEntry(model, entryId);
|
|
1198
1353
|
});
|
|
1199
1354
|
},
|
|
1355
|
+
async deleteMultipleEntries(model, ids) {
|
|
1356
|
+
return context.benchmark.measure("headlessCms.crud.entries.deleteMultipleEntries", async () => {
|
|
1357
|
+
return deleteMultipleEntries(model, ids);
|
|
1358
|
+
});
|
|
1359
|
+
},
|
|
1200
1360
|
async publishEntry(model, id) {
|
|
1201
1361
|
return context.benchmark.measure("headlessCms.crud.entries.publishEntry", async () => {
|
|
1202
1362
|
return publishEntry(model, id);
|
|
@@ -1206,6 +1366,11 @@ const createContentEntryCrud = params => {
|
|
|
1206
1366
|
return context.benchmark.measure("headlessCms.crud.entries.unpublishEntry", async () => {
|
|
1207
1367
|
return unpublishEntry(model, id);
|
|
1208
1368
|
});
|
|
1369
|
+
},
|
|
1370
|
+
async getUniqueFieldValues(model, params) {
|
|
1371
|
+
return context.benchmark.measure("headlessCms.crud.entries.getUniqueFieldValues", async () => {
|
|
1372
|
+
return getUniqueFieldValues(model, params);
|
|
1373
|
+
});
|
|
1209
1374
|
}
|
|
1210
1375
|
};
|
|
1211
1376
|
};
|