import { getPayload } from 'payload'; import { cache } from 'react'; import { getArchiveEntries, resolveRoute as resolveRouteRaw } from '../content/index.js'; import { buildRobots, buildSitemapEntries } from '../seo/index.js'; /** * 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, archive entries). * * 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, getEntries } = * createContentHelpers({ config, content: contentConfig }) * ``` * * `resolveRoute` and `getEntries` are separate on purpose: routing decides what * a URL is, fetching gets the listing. Metadata generation needs the first and * not the second, and a page component composes them in two obvious lines. */ export function createContentHelpers({ baseUrl, config, content, i18n, pagesSlug = 'pages', settingsSlug = 'site-settings' }) { const origin = baseUrl ?? process.env.NEXT_PUBLIC_SERVER_URL ?? ''; const getCachedPayload = cache(async ()=>getPayload({ config: await config })); const getConfiguredLocales = cache(async ()=>{ const c = await config; return c.localization ? c.localization.locales.map((l)=>l.code) : []; }); const getSettings = cache(async (locale)=>{ const payload = await getCachedPayload(); return payload.findGlobal({ slug: settingsSlug, depth: 2, locale: locale }); }); /** What does this URL point at? Routing only — no listing data. */ const resolveRoute = cache(async (locale, segments, page)=>{ const payload = await getCachedPayload(); return resolveRouteRaw({ content, locale, page, pagesSlug, payload, segments, settingsSlug }); }); /** One page of a collection's entries, for an archive listing. */ const getEntries = cache(async (collection, locale, page, perPage)=>{ const payload = await getCachedPayload(); return getArchiveEntries({ collection, locale, page, payload, perPage }); }); /** * Ready-made handler for Next's `app/sitemap.ts` — every page and entry with * per-URL hreflang and lastmod. Re-export it directly: * * ```ts * // app/sitemap.ts * export { sitemap as default } from '@/lib/content' * ``` */ const sitemap = cache(async ()=>{ if (!i18n) { throw new Error('[ipal] createContentHelpers: pass `i18n` to use the sitemap handler.'); } return buildSitemapEntries({ baseUrl: origin, config: i18n, content, pagesSlug, payload: await getCachedPayload(), settingsSlug }); }); /** * Ready-made handler for Next's `app/robots.ts`. Re-export directly: * * ```ts * // app/robots.ts * export { robots as default } from '@/lib/content' * ``` */ const robots = ()=>buildRobots({ baseUrl: origin }); return { getCachedPayload, getConfiguredLocales, getEntries, getSettings, resolveRoute, robots, sitemap }; } //# sourceMappingURL=createContentHelpers.js.map