feat(live-preview): expose requestHandler to subscribe.ts (#10947)

### What?
As described in https://github.com/payloadcms/payload/discussions/10946,
allow passing a custom `collectionPopulationRequestHandler` function to
`subscribe`, which passes it along to `handleMessage` and `mergeData`

### Why?
`mergeData` already supports a custom function for this, that
functionality however isn't exposed.
My use case so far was passing along custom Authorization headers.


### How?
Move the functions type defined in `mergeData` to a dedicated
`CollectionPopulationRequestHandler` type, reuse it across `subscribe`,
`handleMessage` and `mergeData`.

---------

Co-authored-by: Jacob Fletcher <jacobsfletch@gmail.com>
This commit is contained in:
Janus Reith
2025-04-30 21:08:53 +02:00
committed by GitHub
parent cfe8c97ab7
commit 35c0404817
5 changed files with 59 additions and 46 deletions

View File

@@ -1,6 +1,6 @@
import type { FieldSchemaJSON } from 'payload'
import type { LivePreviewMessageEvent } from './types.js'
import type { CollectionPopulationRequestHandler, LivePreviewMessageEvent } from './types.js'
import { isLivePreviewEvent } from './isLivePreviewEvent.js'
import { mergeData } from './mergeData.js'
@@ -29,9 +29,10 @@ export const handleMessage = async <T extends Record<string, any>>(args: {
depth?: number
event: LivePreviewMessageEvent<T>
initialData: T
requestHandler?: CollectionPopulationRequestHandler
serverURL: string
}): Promise<T> => {
const { apiRoute, depth, event, initialData, serverURL } = args
const { apiRoute, depth, event, initialData, requestHandler, serverURL } = args
if (isLivePreviewEvent(event, serverURL)) {
const { data, externallyUpdatedRelationship, fieldSchemaJSON, locale } = event.data
@@ -57,6 +58,7 @@ export const handleMessage = async <T extends Record<string, any>>(args: {
incomingData: data,
initialData: _payloadLivePreview?.previousData || initialData,
locale,
requestHandler,
serverURL,
})

View File

@@ -1,6 +1,6 @@
import type { DocumentEvent, FieldSchemaJSON, PaginatedDocs } from 'payload'
import type { PopulationsByCollection } from './types.js'
import type { CollectionPopulationRequestHandler, PopulationsByCollection } from './types.js'
import { traverseFields } from './traverseFields.js'
@@ -29,21 +29,17 @@ let prevLocale: string | undefined
export const mergeData = async <T extends Record<string, any>>(args: {
apiRoute?: string
collectionPopulationRequestHandler?: ({
apiPath,
endpoint,
serverURL,
}: {
apiPath: string
endpoint: string
serverURL: string
}) => Promise<Response>
/**
* @deprecated Use `requestHandler` instead
*/
collectionPopulationRequestHandler?: CollectionPopulationRequestHandler
depth?: number
externallyUpdatedRelationship?: DocumentEvent
fieldSchema: FieldSchemaJSON
incomingData: Partial<T>
initialData: T
locale?: string
requestHandler?: CollectionPopulationRequestHandler
returnNumberOfRequests?: boolean
serverURL: string
}): Promise<
@@ -81,7 +77,8 @@ export const mergeData = async <T extends Record<string, any>>(args: {
let res: PaginatedDocs
const ids = new Set(populations.map(({ id }) => id))
const requestHandler = args.collectionPopulationRequestHandler || defaultRequestHandler
const requestHandler =
args.collectionPopulationRequestHandler || args.requestHandler || defaultRequestHandler
try {
res = await requestHandler({

View File

@@ -1,3 +1,5 @@
import type { CollectionPopulationRequestHandler } from './types.js'
import { handleMessage } from './handleMessage.js'
export const subscribe = <T extends Record<string, any>>(args: {
@@ -5,9 +7,10 @@ export const subscribe = <T extends Record<string, any>>(args: {
callback: (data: T) => void
depth?: number
initialData: T
requestHandler?: CollectionPopulationRequestHandler
serverURL: string
}): ((event: MessageEvent) => Promise<void> | void) => {
const { apiRoute, callback, depth, initialData, serverURL } = args
const { apiRoute, callback, depth, initialData, requestHandler, serverURL } = args
const onMessage = async (event: MessageEvent) => {
const mergedData = await handleMessage<T>({
@@ -15,6 +18,7 @@ export const subscribe = <T extends Record<string, any>>(args: {
depth,
event,
initialData,
requestHandler,
serverURL,
})

View File

@@ -1,5 +1,15 @@
import type { DocumentEvent, FieldSchemaJSON } from 'payload'
export type CollectionPopulationRequestHandler = ({
apiPath,
endpoint,
serverURL,
}: {
apiPath: string
endpoint: string
serverURL: string
}) => Promise<Response>
export type LivePreviewArgs = {}
export type LivePreview = void

View File

@@ -13,9 +13,9 @@ import { fileURLToPath } from 'url'
import type { NextRESTClient } from '../helpers/NextRESTClient.js'
import type { Media, Page, Post, Tenant } from './payload-types.js'
import config from './config.js'
import { Pages } from './collections/Pages.js'
import config from './config.js'
import { postsSlug, tenantsSlug } from './shared.js'
const filename = fileURLToPath(import.meta.url)
@@ -28,7 +28,7 @@ let restClient: NextRESTClient
import { initPayloadInt } from '../helpers/initPayloadInt.js'
function collectionPopulationRequestHandler({ endpoint }: { endpoint: string }) {
function requestHandler({ endpoint }: { endpoint: string }) {
return restClient.GET(`/${endpoint}`)
}
@@ -170,7 +170,7 @@ describe('Collections - Live Preview', () => {
initialData,
serverURL,
returnNumberOfRequests: true,
collectionPopulationRequestHandler,
requestHandler,
})
expect(mergedData.title).toEqual('Test Page (Changed)')
@@ -198,7 +198,7 @@ describe('Collections - Live Preview', () => {
initialData,
serverURL,
returnNumberOfRequests: true,
collectionPopulationRequestHandler,
requestHandler,
})
expect(mergedData.arrayOfRelationships).toEqual([])
@@ -217,7 +217,7 @@ describe('Collections - Live Preview', () => {
initialData,
serverURL,
returnNumberOfRequests: true,
collectionPopulationRequestHandler,
requestHandler,
})
expect(mergedData2.arrayOfRelationships).toEqual([])
@@ -243,7 +243,7 @@ describe('Collections - Live Preview', () => {
initialData,
serverURL,
returnNumberOfRequests: true,
collectionPopulationRequestHandler,
requestHandler,
})
expect(mergedData.hero.media).toMatchObject(media)
@@ -262,7 +262,7 @@ describe('Collections - Live Preview', () => {
},
initialData: mergedData,
serverURL,
collectionPopulationRequestHandler,
requestHandler,
})
expect(mergedDataWithoutUpload.hero.media).toBeFalsy()
@@ -290,7 +290,7 @@ describe('Collections - Live Preview', () => {
initialData,
serverURL,
returnNumberOfRequests: true,
collectionPopulationRequestHandler,
requestHandler,
})
expect(merge1.richTextSlate).toHaveLength(1)
@@ -317,7 +317,7 @@ describe('Collections - Live Preview', () => {
initialData,
serverURL,
returnNumberOfRequests: true,
collectionPopulationRequestHandler,
requestHandler,
})
expect(merge2.richTextSlate).toHaveLength(1)
@@ -377,7 +377,7 @@ describe('Collections - Live Preview', () => {
initialData,
serverURL,
returnNumberOfRequests: true,
collectionPopulationRequestHandler,
requestHandler,
})
expect(merge1.richTextLexical.root.children).toHaveLength(2)
@@ -423,7 +423,7 @@ describe('Collections - Live Preview', () => {
initialData,
serverURL,
returnNumberOfRequests: true,
collectionPopulationRequestHandler,
requestHandler,
})
expect(merge2.richTextLexical.root.children).toHaveLength(1)
@@ -446,7 +446,7 @@ describe('Collections - Live Preview', () => {
initialData,
serverURL,
returnNumberOfRequests: true,
collectionPopulationRequestHandler,
requestHandler,
})
expect(merge1._numberOfRequests).toEqual(1)
@@ -468,7 +468,7 @@ describe('Collections - Live Preview', () => {
initialData,
serverURL,
returnNumberOfRequests: true,
collectionPopulationRequestHandler,
requestHandler,
})
expect(merge1._numberOfRequests).toEqual(1)
@@ -490,7 +490,7 @@ describe('Collections - Live Preview', () => {
initialData,
serverURL,
returnNumberOfRequests: true,
collectionPopulationRequestHandler,
requestHandler,
})
expect(merge1._numberOfRequests).toEqual(1)
@@ -515,7 +515,7 @@ describe('Collections - Live Preview', () => {
initialData,
serverURL,
returnNumberOfRequests: true,
collectionPopulationRequestHandler,
requestHandler,
})
expect(merge1._numberOfRequests).toEqual(1)
@@ -545,7 +545,7 @@ describe('Collections - Live Preview', () => {
initialData,
serverURL,
returnNumberOfRequests: true,
collectionPopulationRequestHandler,
requestHandler,
})
expect(merge2._numberOfRequests).toEqual(0)
@@ -571,7 +571,7 @@ describe('Collections - Live Preview', () => {
},
initialData,
serverURL,
collectionPopulationRequestHandler,
requestHandler,
})
expect(merge1.tab.relationshipInTab).toMatchObject(testPost)
@@ -608,7 +608,7 @@ describe('Collections - Live Preview', () => {
initialData,
serverURL,
returnNumberOfRequests: true,
collectionPopulationRequestHandler,
requestHandler,
})
expect(merge1._numberOfRequests).toEqual(1)
@@ -665,7 +665,7 @@ describe('Collections - Live Preview', () => {
initialData: merge1,
serverURL,
returnNumberOfRequests: true,
collectionPopulationRequestHandler,
requestHandler,
})
expect(merge2._numberOfRequests).toEqual(1)
@@ -741,7 +741,7 @@ describe('Collections - Live Preview', () => {
initialData,
serverURL,
returnNumberOfRequests: true,
collectionPopulationRequestHandler,
requestHandler,
})
expect(merge1._numberOfRequests).toEqual(2)
@@ -804,7 +804,7 @@ describe('Collections - Live Preview', () => {
initialData: merge1,
serverURL,
returnNumberOfRequests: true,
collectionPopulationRequestHandler,
requestHandler,
})
expect(merge2._numberOfRequests).toEqual(1)
@@ -870,7 +870,7 @@ describe('Collections - Live Preview', () => {
initialData,
serverURL,
returnNumberOfRequests: true,
collectionPopulationRequestHandler,
requestHandler,
})
expect(merge1._numberOfRequests).toEqual(2)
@@ -937,7 +937,7 @@ describe('Collections - Live Preview', () => {
initialData: merge1,
serverURL,
returnNumberOfRequests: true,
collectionPopulationRequestHandler,
requestHandler,
})
expect(merge2._numberOfRequests).toEqual(1)
@@ -991,7 +991,7 @@ describe('Collections - Live Preview', () => {
initialData,
serverURL,
returnNumberOfRequests: true,
collectionPopulationRequestHandler,
requestHandler,
})
expect(merge1._numberOfRequests).toEqual(0)
@@ -1051,7 +1051,7 @@ describe('Collections - Live Preview', () => {
initialData,
serverURL,
returnNumberOfRequests: true,
collectionPopulationRequestHandler,
requestHandler,
})
// Check that the relationship on the first has been removed
@@ -1080,7 +1080,7 @@ describe('Collections - Live Preview', () => {
initialData,
serverURL,
returnNumberOfRequests: true,
collectionPopulationRequestHandler,
requestHandler,
})
expect(merge1._numberOfRequests).toEqual(1)
@@ -1126,7 +1126,7 @@ describe('Collections - Live Preview', () => {
externallyUpdatedRelationship,
serverURL,
returnNumberOfRequests: true,
collectionPopulationRequestHandler,
requestHandler,
})
expect(merge2._numberOfRequests).toEqual(1)
@@ -1183,7 +1183,7 @@ describe('Collections - Live Preview', () => {
initialData,
serverURL,
returnNumberOfRequests: true,
collectionPopulationRequestHandler,
requestHandler,
locale: 'es',
})
@@ -1332,7 +1332,7 @@ describe('Collections - Live Preview', () => {
initialData,
serverURL,
returnNumberOfRequests: true,
collectionPopulationRequestHandler,
requestHandler,
})
// Check that the blocks have been reordered
@@ -1365,7 +1365,7 @@ describe('Collections - Live Preview', () => {
initialData,
serverURL,
returnNumberOfRequests: true,
collectionPopulationRequestHandler,
requestHandler,
})
// Check that the block has been removed
@@ -1385,7 +1385,7 @@ describe('Collections - Live Preview', () => {
initialData,
serverURL,
returnNumberOfRequests: true,
collectionPopulationRequestHandler,
requestHandler,
})
// Check that the block has been removed
@@ -1445,7 +1445,7 @@ describe('Collections - Live Preview', () => {
initialData,
serverURL,
returnNumberOfRequests: true,
collectionPopulationRequestHandler: customRequestHandler,
requestHandler: customRequestHandler,
})
expect(mergedData.relationshipPolyHasMany).toMatchObject([