diff --git a/packages/live-preview/src/mergeData.ts b/packages/live-preview/src/mergeData.ts index b048163695..c1083f6a93 100644 --- a/packages/live-preview/src/mergeData.ts +++ b/packages/live-preview/src/mergeData.ts @@ -1,9 +1,11 @@ +import type { fieldSchemaToJSON } from 'payload/utilities' + import { traverseFields } from './traverseFields' export type MergeLiveDataArgs = { apiRoute?: string depth: number - fieldSchema: Record[] + fieldSchema: ReturnType incomingData: T initialData: T serverURL: string diff --git a/packages/live-preview/src/traverseFields.ts b/packages/live-preview/src/traverseFields.ts index 53f4ffd515..ab46a7c913 100644 --- a/packages/live-preview/src/traverseFields.ts +++ b/packages/live-preview/src/traverseFields.ts @@ -1,9 +1,11 @@ +import type { fieldSchemaToJSON } from 'payload/utilities' + import { promise } from './promise' type Args = { apiRoute?: string depth: number - fieldSchema: Record[] + fieldSchema: ReturnType incomingData: T populationPromises: Promise[] result: T @@ -19,12 +21,11 @@ export const traverseFields = ({ result, serverURL, }: Args): void => { - fieldSchema.forEach((field) => { - if ('name' in field && typeof field.name === 'string') { - // TODO: type this - const fieldName = field.name + fieldSchema.forEach((fieldJSON) => { + if ('name' in fieldJSON && typeof fieldJSON.name === 'string') { + const fieldName = fieldJSON.name - switch (field.type) { + switch (fieldJSON.type) { case 'array': if (Array.isArray(incomingData[fieldName])) { result[fieldName] = incomingData[fieldName].map((row, i) => { @@ -38,7 +39,7 @@ export const traverseFields = ({ traverseFields({ apiRoute, depth, - fieldSchema: field.fields as Record[], // TODO: type this + fieldSchema: fieldJSON.fields, incomingData: row, populationPromises, result: newRow, @@ -53,7 +54,7 @@ export const traverseFields = ({ case 'blocks': if (Array.isArray(incomingData[fieldName])) { result[fieldName] = incomingData[fieldName].map((row, i) => { - const matchedBlock = field.blocks[row.blockType] + const matchedBlock = fieldJSON.blocks[row.blockType] const hasExistingRow = Array.isArray(result[fieldName]) && @@ -70,7 +71,7 @@ export const traverseFields = ({ traverseFields({ apiRoute, depth, - fieldSchema: matchedBlock.fields as Record[], // TODO: type this + fieldSchema: matchedBlock.fields, incomingData: row, populationPromises, result: newRow, @@ -82,7 +83,7 @@ export const traverseFields = ({ } break - case 'tab': + case 'tabs': case 'group': if (!result[fieldName]) { result[fieldName] = {} @@ -91,7 +92,7 @@ export const traverseFields = ({ traverseFields({ apiRoute, depth, - fieldSchema: field.fields as Record[], // TODO: type this + fieldSchema: fieldJSON.fields, incomingData: incomingData[fieldName] || {}, populationPromises, result: result[fieldName], @@ -102,7 +103,7 @@ export const traverseFields = ({ case 'upload': case 'relationship': - if (field.hasMany && Array.isArray(incomingData[fieldName])) { + if (fieldJSON.hasMany && Array.isArray(incomingData[fieldName])) { const existingValue = Array.isArray(result[fieldName]) ? [...result[fieldName]] : [] result[fieldName] = Array.isArray(result[fieldName]) ? [...result[fieldName]].slice(0, incomingData[fieldName].length) @@ -110,7 +111,7 @@ export const traverseFields = ({ incomingData[fieldName].forEach((relation, i) => { // Handle `hasMany` polymorphic - if (Array.isArray(field.relationTo)) { + if (Array.isArray(fieldJSON.relationTo)) { const existingID = existingValue[i]?.value?.id if ( @@ -134,7 +135,7 @@ export const traverseFields = ({ ) } } else { - // Handle `hasMany` singular + // Handle `hasMany` monomorphic const existingID = existingValue[i]?.id if (existingID !== relation) { @@ -143,7 +144,7 @@ export const traverseFields = ({ id: relation, accessor: i, apiRoute, - collection: String(field.relationTo), + collection: String(fieldJSON.relationTo), depth, ref: result[fieldName], serverURL, @@ -154,7 +155,7 @@ export const traverseFields = ({ }) } else { // Handle `hasOne` polymorphic - if (Array.isArray(field.relationTo)) { + if (Array.isArray(fieldJSON.relationTo)) { const hasNewValue = typeof incomingData[fieldName] === 'object' && incomingData[fieldName] !== null const hasOldValue = @@ -190,31 +191,37 @@ export const traverseFields = ({ result[fieldName] = null } } else { - const hasNewValue = - typeof incomingData[fieldName] === 'object' && incomingData[fieldName] !== null - const hasOldValue = - typeof result[fieldName] === 'object' && result[fieldName] !== null + // Handle `hasOne` monomorphic + const newID: string = + (typeof incomingData[fieldName] === 'string' && incomingData[fieldName]) || + (typeof incomingData[fieldName] === 'object' && + incomingData[fieldName] !== null && + incomingData[fieldName].id) || + '' - const newValue = hasNewValue ? incomingData[fieldName].value : '' + const oldID: string = + (typeof result[fieldName] === 'string' && result[fieldName]) || + (typeof result[fieldName] === 'object' && + result[fieldName] !== null && + result[fieldName].id) || + '' - const oldValue = hasOldValue ? result[fieldName].value : '' - - if (newValue !== oldValue) { - if (newValue) { + if (newID !== oldID) { + if (newID) { populationPromises.push( promise({ - id: newValue, + id: newID, accessor: fieldName, apiRoute, - collection: String(field.relationTo), + collection: String(fieldJSON.relationTo), depth, ref: result as Record, serverURL, }), ) + } else { + result[fieldName] = null } - } else { - result[fieldName] = null } } } diff --git a/test/live-preview/collections/Media.ts b/test/live-preview/collections/Media.ts index 0113927507..80716b1c1f 100644 --- a/test/live-preview/collections/Media.ts +++ b/test/live-preview/collections/Media.ts @@ -5,6 +5,7 @@ export const Media: CollectionConfig = { upload: true, access: { read: () => true, + create: () => true, }, fields: [ {