payload
Version:
Node, React, Headless CMS and Application Framework built on Next.js
357 lines (356 loc) • 16.4 kB
JavaScript
// @ts-strict-ignore
import { fieldAffectsData, fieldShouldBeLocalized } from '../../config/types.js';
import { getFieldPathsModified as getFieldPaths } from '../../getFieldPaths.js';
import { traverseFields } from './traverseFields.js';
export const promise = async ({ id, blockData, collection, context, doc, field, fieldIndex, overrideAccess, parentIndexPath, parentIsLocalized, parentPath, parentSchemaPath, req, siblingDoc, siblingFields })=>{
const { indexPath, path, schemaPath } = getFieldPaths({
field,
index: fieldIndex,
parentIndexPath,
parentPath,
parentSchemaPath
});
const { localization } = req.payload.config;
const pathSegments = path ? path.split('.') : [];
const schemaPathSegments = schemaPath ? schemaPath.split('.') : [];
const indexPathSegments = indexPath ? indexPath.split('-').filter(Boolean)?.map(Number) : [];
if (fieldAffectsData(field)) {
let fieldData = siblingDoc?.[field.name];
const fieldIsLocalized = localization && fieldShouldBeLocalized({
field,
parentIsLocalized
});
// Run field beforeDuplicate hooks
if (Array.isArray(field.hooks?.beforeDuplicate)) {
if (fieldIsLocalized) {
const localeData = {};
for (const locale of localization.localeCodes){
const beforeDuplicateArgs = {
blockData,
collection,
context,
data: doc,
field,
global: undefined,
indexPath: indexPathSegments,
path: pathSegments,
previousSiblingDoc: siblingDoc,
previousValue: siblingDoc[field.name]?.[locale],
req,
schemaPath: schemaPathSegments,
siblingData: siblingDoc,
siblingDocWithLocales: siblingDoc,
siblingFields,
value: siblingDoc[field.name]?.[locale]
};
let hookResult;
for (const hook of field.hooks.beforeDuplicate){
hookResult = await hook(beforeDuplicateArgs);
}
if (typeof hookResult !== 'undefined') {
localeData[locale] = hookResult;
}
}
siblingDoc[field.name] = localeData;
} else {
const beforeDuplicateArgs = {
blockData,
collection,
context,
data: doc,
field,
global: undefined,
indexPath: indexPathSegments,
path: pathSegments,
previousSiblingDoc: siblingDoc,
previousValue: siblingDoc[field.name],
req,
schemaPath: schemaPathSegments,
siblingData: siblingDoc,
siblingDocWithLocales: siblingDoc,
siblingFields,
value: siblingDoc[field.name]
};
let hookResult;
for (const hook of field.hooks.beforeDuplicate){
hookResult = await hook(beforeDuplicateArgs);
}
if (typeof hookResult !== 'undefined') {
siblingDoc[field.name] = hookResult;
}
}
}
// First, for any localized fields, we will loop over locales
// and if locale data is present, traverse the sub fields.
// There are only a few different fields where this is possible.
if (fieldIsLocalized) {
if (typeof fieldData !== 'object' || fieldData === null) {
siblingDoc[field.name] = {};
fieldData = siblingDoc[field.name];
}
const promises = [];
localization.localeCodes.forEach((locale)=>{
if (fieldData[locale]) {
switch(field.type){
case 'array':
{
const rows = fieldData[locale];
if (Array.isArray(rows)) {
const promises = [];
rows.forEach((row, rowIndex)=>{
promises.push(traverseFields({
id,
blockData,
collection,
context,
doc,
fields: field.fields,
overrideAccess,
parentIndexPath: '',
parentIsLocalized: parentIsLocalized || field.localized,
parentPath: path + '.' + rowIndex,
parentSchemaPath: schemaPath,
req,
siblingDoc: row
}));
});
}
break;
}
case 'blocks':
{
const rows = fieldData[locale];
if (Array.isArray(rows)) {
const promises = [];
rows.forEach((row, rowIndex)=>{
const blockTypeToMatch = row.blockType;
const block = req.payload.blocks[blockTypeToMatch] ?? (field.blockReferences ?? field.blocks).find((curBlock)=>typeof curBlock !== 'string' && curBlock.slug === blockTypeToMatch);
promises.push(traverseFields({
id,
blockData: row,
collection,
context,
doc,
fields: block.fields,
overrideAccess,
parentIndexPath: '',
parentIsLocalized: parentIsLocalized || field.localized,
parentPath: path + '.' + rowIndex,
parentSchemaPath: schemaPath + '.' + block.slug,
req,
siblingDoc: row
}));
});
}
break;
}
case 'group':
case 'tab':
{
promises.push(traverseFields({
id,
blockData,
collection,
context,
doc,
fields: field.fields,
overrideAccess,
parentIndexPath: '',
parentIsLocalized: parentIsLocalized || field.localized,
parentPath: path,
parentSchemaPath: schemaPath,
req,
siblingDoc: fieldData[locale]
}));
break;
}
}
}
});
await Promise.all(promises);
} else {
// If the field is not localized, but it affects data,
// we need to further traverse its children
// so the child fields can run beforeDuplicate hooks
switch(field.type){
case 'array':
{
const rows = siblingDoc[field.name];
if (Array.isArray(rows)) {
const promises = [];
rows.forEach((row, rowIndex)=>{
promises.push(traverseFields({
id,
blockData,
collection,
context,
doc,
fields: field.fields,
overrideAccess,
parentIndexPath: '',
parentIsLocalized: parentIsLocalized || field.localized,
parentPath: path + '.' + rowIndex,
parentSchemaPath: schemaPath,
req,
siblingDoc: row
}));
});
await Promise.all(promises);
}
break;
}
case 'blocks':
{
const rows = siblingDoc[field.name];
if (Array.isArray(rows)) {
const promises = [];
rows.forEach((row, rowIndex)=>{
const blockTypeToMatch = row.blockType;
const block = req.payload.blocks[blockTypeToMatch] ?? (field.blockReferences ?? field.blocks).find((curBlock)=>typeof curBlock !== 'string' && curBlock.slug === blockTypeToMatch);
if (block) {
;
row.blockType = blockTypeToMatch;
promises.push(traverseFields({
id,
blockData: row,
collection,
context,
doc,
fields: block.fields,
overrideAccess,
parentIndexPath: '',
parentIsLocalized: parentIsLocalized || field.localized,
parentPath: path + '.' + rowIndex,
parentSchemaPath: schemaPath + '.' + block.slug,
req,
siblingDoc: row
}));
}
});
await Promise.all(promises);
}
break;
}
case 'group':
{
if (typeof siblingDoc[field.name] !== 'object') {
siblingDoc[field.name] = {};
}
const groupDoc = siblingDoc[field.name];
await traverseFields({
id,
blockData,
collection,
context,
doc,
fields: field.fields,
overrideAccess,
parentIndexPath: '',
parentIsLocalized: parentIsLocalized || field.localized,
parentPath: path,
parentSchemaPath: schemaPath,
req,
siblingDoc: groupDoc
});
break;
}
case 'tab':
{
if (typeof siblingDoc[field.name] !== 'object') {
siblingDoc[field.name] = {};
}
const tabDoc = siblingDoc[field.name];
await traverseFields({
id,
blockData,
collection,
context,
doc,
fields: field.fields,
overrideAccess,
parentIndexPath: '',
parentIsLocalized: parentIsLocalized || field.localized,
parentPath: path,
parentSchemaPath: schemaPath,
req,
siblingDoc: tabDoc
});
break;
}
}
}
} else {
// Finally, we traverse fields which do not affect data here
switch(field.type){
case 'collapsible':
case 'row':
{
await traverseFields({
id,
blockData,
collection,
context,
doc,
fields: field.fields,
overrideAccess,
parentIndexPath: indexPath,
parentIsLocalized,
parentPath,
parentSchemaPath: schemaPath,
req,
siblingDoc
});
break;
}
// Unnamed Tab
// @ts-expect-error `fieldAffectsData` inferred return type doesn't account for TabAsField
case 'tab':
{
await traverseFields({
id,
blockData,
collection,
context,
doc,
// @ts-expect-error `fieldAffectsData` inferred return type doesn't account for TabAsField
fields: field.fields,
overrideAccess,
parentIndexPath: indexPath,
parentIsLocalized,
parentPath,
parentSchemaPath: schemaPath,
req,
siblingDoc
});
break;
}
case 'tabs':
{
await traverseFields({
id,
blockData,
collection,
context,
doc,
fields: field.tabs.map((tab)=>({
...tab,
type: 'tab'
})),
overrideAccess,
parentIndexPath: indexPath,
parentIsLocalized,
parentPath: path,
parentSchemaPath: schemaPath,
req,
siblingDoc
});
break;
}
default:
{
break;
}
}
}
};
//# sourceMappingURL=promise.js.map