Files
payload/packages/live-preview/src/handleMessage.ts
2024-03-06 14:53:54 -05:00

60 lines
1.8 KiB
TypeScript

import { mergeData } from './mergeData.js'
// For performance reasons, `fieldSchemaJSON` will only be sent once on the initial message
// We need to cache this value so that it can be used across subsequent messages
// To do this, save `fieldSchemaJSON` when it arrives as a global variable
// Send this cached value to `mergeData`, instead of `eventData.fieldSchemaJSON` directly
let payloadLivePreviewFieldSchema = undefined // TODO: type this from `fieldSchemaToJSON` return type
// Each time the data is merged, cache the result as a `previousData` variable
// This will ensure changes compound overtop of each other
let payloadLivePreviewPreviousData = undefined
export const handleMessage = async <T>(args: {
apiRoute?: string
depth?: number
event: MessageEvent
initialData: T
serverURL: string
}): Promise<T> => {
const { apiRoute, depth, event, initialData, serverURL } = args
if (
event.origin === serverURL &&
event.data &&
typeof event.data === 'object' &&
event.data.type === 'payload-live-preview'
) {
const { data, externallyUpdatedRelationship, fieldSchemaJSON } = event.data
if (!payloadLivePreviewFieldSchema && fieldSchemaJSON) {
payloadLivePreviewFieldSchema = fieldSchemaJSON
}
if (!payloadLivePreviewFieldSchema) {
// eslint-disable-next-line no-console
console.warn(
'Payload Live Preview: No `fieldSchemaJSON` was received from the parent window. Unable to merge data.',
)
return initialData
}
const mergedData = await mergeData<T>({
apiRoute,
depth,
externallyUpdatedRelationship,
fieldSchema: payloadLivePreviewFieldSchema,
incomingData: data,
initialData: payloadLivePreviewPreviousData || initialData,
serverURL,
})
payloadLivePreviewPreviousData = mergedData
return mergedData
}
return initialData
}