init commit for iPAL-kit plugin
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
import type { BasePayload, SanitizedConfig } from 'payload'
|
||||
|
||||
import { getPayload } from 'payload'
|
||||
import { cache } from 'react'
|
||||
|
||||
import type { ContentOption, ResolvedRoute } from '../content/index.js'
|
||||
|
||||
import { resolveRoute as resolveRouteRaw } from '../content/index.js'
|
||||
|
||||
type CreateContentHelpersArgs = {
|
||||
/**
|
||||
* The client's payload config promise (the default export of payload.config).
|
||||
* Passed in because the plugin never imports the client's config directly.
|
||||
*/
|
||||
config: Promise<SanitizedConfig> | SanitizedConfig
|
||||
/** Archive-backed collections, same value as the plugin option. */
|
||||
content?: ContentOption
|
||||
/** Pages collection slug. Defaults to 'pages'. */
|
||||
pagesSlug?: string
|
||||
/** SiteSettings global slug. Defaults to 'site-settings'. */
|
||||
settingsSlug?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Bundles the per-request data helpers a frontend needs — the same cached
|
||||
* wrappers every project was writing by hand (getPayload, settings, locale
|
||||
* list, route resolution).
|
||||
*
|
||||
* Everything is wrapped in React `cache()`, so within one request a value is
|
||||
* fetched once no matter how many times it's asked for — which matters because
|
||||
* Next runs generateMetadata and the page component separately, and both hit
|
||||
* these. Crucially the Payload instance is cached *here*, once, so every helper
|
||||
* shares it; that's why this is a factory and not loose functions importing a
|
||||
* shared module.
|
||||
*
|
||||
* ```ts
|
||||
* // src/lib/content.ts
|
||||
* import { createContentHelpers } from 'ipal-kit'
|
||||
* import config from '@/payload.config'
|
||||
* import { contentConfig } from '@/content.config'
|
||||
*
|
||||
* export const { getCachedPayload, getSettings, getConfiguredLocales, resolveRoute } =
|
||||
* createContentHelpers({ config, content: contentConfig })
|
||||
* ```
|
||||
*/
|
||||
export function createContentHelpers({
|
||||
config,
|
||||
content,
|
||||
pagesSlug = 'pages',
|
||||
settingsSlug = 'site-settings',
|
||||
}: CreateContentHelpersArgs) {
|
||||
const getCachedPayload = cache(async (): Promise<BasePayload> =>
|
||||
getPayload({ config: await config }),
|
||||
)
|
||||
|
||||
const getConfiguredLocales = cache(async (): Promise<string[]> => {
|
||||
const c = await config
|
||||
return c.localization ? c.localization.locales.map((l) => l.code) : []
|
||||
})
|
||||
|
||||
const getSettings = cache(async (locale: string) => {
|
||||
const payload = await getCachedPayload()
|
||||
return payload.findGlobal({ slug: settingsSlug as never, depth: 2, locale: locale as never })
|
||||
})
|
||||
|
||||
/**
|
||||
* Resolves a URL to a page / archive / entry. Pass `withEntries` on the page
|
||||
* component (it needs the listing); omit it for metadata (it doesn't, and the
|
||||
* query would be wasted).
|
||||
*/
|
||||
const resolveRoute = cache(
|
||||
async (
|
||||
locale: string,
|
||||
segments: string[] | undefined,
|
||||
page: number,
|
||||
withEntries = false,
|
||||
): Promise<null | ResolvedRoute> => {
|
||||
const payload = await getCachedPayload()
|
||||
return resolveRouteRaw({
|
||||
content,
|
||||
locale,
|
||||
page,
|
||||
pagesSlug,
|
||||
payload,
|
||||
segments,
|
||||
settingsSlug,
|
||||
withEntries,
|
||||
})
|
||||
},
|
||||
)
|
||||
|
||||
return { getCachedPayload, getConfiguredLocales, getSettings, resolveRoute }
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export { createContentHelpers } from './createContentHelpers.js'
|
||||
Reference in New Issue
Block a user