@whatworks/payload-sitemap 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -131,7 +131,7 @@ sitemapPlugin({
131
131
 
132
132
  // Defaults for robots output (createRobots / generateRobotsTxt).
133
133
  robots: {
134
- isProduction: undefined, // default VERCEL_ENV/NODE_ENV
134
+ allowIndexing: undefined, // default VERCEL_ENV/NODE_ENV
135
135
  disallow: ['/drafts/'], // appended to the default rule
136
136
  rules: undefined, // replace default rules entirely
137
137
  sitemaps: undefined, // default `${siteUrl}/sitemap.xml`
@@ -1,4 +1,4 @@
1
- import { o as RobotsOptions } from "../types-j8T8euN5.js";
1
+ import { o as RobotsOptions } from "../types-BsS4pTPA.js";
2
2
  import { SanitizedConfig } from "payload";
3
3
  import { MetadataRoute } from "next";
4
4
 
@@ -1,4 +1,4 @@
1
- import { _ as getSitemapConfig, c as getChunkEntries, d as finalizeEntries, h as DEFAULT_CACHE_CONTROL, i as buildRobotsData, l as getIndexItems, n as buildUrlsetXml, t as buildSitemapIndexXml } from "../xml-DSOM2moN.js";
1
+ import { _ as getSitemapConfig, c as getChunkEntries, d as finalizeEntries, h as DEFAULT_CACHE_CONTROL, i as buildRobotsData, l as getIndexItems, n as buildUrlsetXml, t as buildSitemapIndexXml } from "../xml-nj_bfoCU.js";
2
2
  import { getPayload } from "payload";
3
3
 
4
4
  //#region src/exports/next.ts
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { _ as SitemapRoute, a as RobotsData, b as resolveSiteUrl, c as SitemapCache, d as SitemapEndpointAccess, f as SitemapEndpointsConfig, g as SitemapPluginConfig, h as SitemapPathArgs, i as ResolvedSitemapEndpoints, l as SitemapCollectionConfig, m as SitemapInvalidateArgs, n as InternalSitemapCollectionConfig, o as RobotsOptions, p as SitemapEntry, r as ResolvedSitemapConfig, s as RobotsRule, t as ChangeFrequency, u as SitemapCollections, v as SitemapRoutesFn, x as siteUrlFromRequest, y as SiteUrlContext } from "./types-j8T8euN5.js";
1
+ import { _ as SitemapRoute, a as RobotsData, b as resolveSiteUrl, c as SitemapCache, d as SitemapEndpointAccess, f as SitemapEndpointsConfig, g as SitemapPluginConfig, h as SitemapPathArgs, i as ResolvedSitemapEndpoints, l as SitemapCollectionConfig, m as SitemapInvalidateArgs, n as InternalSitemapCollectionConfig, o as RobotsOptions, p as SitemapEntry, r as ResolvedSitemapConfig, s as RobotsRule, t as ChangeFrequency, u as SitemapCollections, v as SitemapRoutesFn, x as siteUrlFromRequest, y as SiteUrlContext } from "./types-BsS4pTPA.js";
2
2
  import { Payload, PayloadRequest, Plugin, SanitizedConfig } from "payload";
3
3
 
4
4
  //#region src/core/cache.d.ts
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { C as createNextTagsCache, S as createMemoryCache, T as sitemapCacheTag, _ as getSitemapConfig, a as generateRobotsTxt, b as siteUrlFromRequest, c as getChunkEntries, d as finalizeEntries, f as formatLoc, g as ROUTES_GROUP, i as buildRobotsData, l as getIndexItems, m as getSitemapEntries, n as buildUrlsetXml, o as renderRobotsTxt, p as getGroupEntries, r as escapeXml, s as chunkFileName, t as buildSitemapIndexXml, u as matchChunkFile, v as resolveSitemapConfig, w as noopCache, x as SITEMAP_CACHE_TAG, y as resolveSiteUrl } from "./xml-DSOM2moN.js";
1
+ import { C as createNextTagsCache, S as createMemoryCache, T as sitemapCacheTag, _ as getSitemapConfig, a as generateRobotsTxt, b as siteUrlFromRequest, c as getChunkEntries, d as finalizeEntries, f as formatLoc, g as ROUTES_GROUP, i as buildRobotsData, l as getIndexItems, m as getSitemapEntries, n as buildUrlsetXml, o as renderRobotsTxt, p as getGroupEntries, r as escapeXml, s as chunkFileName, t as buildSitemapIndexXml, u as matchChunkFile, v as resolveSitemapConfig, w as noopCache, x as SITEMAP_CACHE_TAG, y as resolveSiteUrl } from "./xml-nj_bfoCU.js";
2
2
 
3
3
  //#region src/core/invalidate.ts
4
4
  /** Groups already scheduled for invalidation within one request (bulk-operation dedupe). */
@@ -176,13 +176,14 @@ type RobotsData = {
176
176
  sitemaps: string[];
177
177
  };
178
178
  type RobotsOptions = {
179
- /** Extra disallow paths appended to the default rule. Ignored when `rules` is set. */
180
- disallow?: string[];
181
179
  /**
182
- * Force production behavior. Non-production output disallows everything.
180
+ * Allow search engines to index the site. When `false`, the output disallows
181
+ * everything so non-production environments stay out of search indexes.
183
182
  * @default VERCEL_ENV === 'production', falling back to NODE_ENV === 'production'
184
183
  */
185
- isProduction?: boolean;
184
+ allowIndexing?: boolean;
185
+ /** Extra disallow paths appended to the default rule. Ignored when `rules` is set. */
186
+ disallow?: string[];
186
187
  /** Replace the default rules entirely (default: allow all, disallow admin + API routes). */
187
188
  rules?: RobotsRule[];
188
189
  /** Sitemap URL(s). @default `${siteUrl}/sitemap.xml` */
@@ -268,4 +269,4 @@ type ResolvedSitemapConfig = {
268
269
  };
269
270
  //#endregion
270
271
  export { SitemapRoute as _, RobotsData as a, resolveSiteUrl as b, SitemapCache as c, SitemapEndpointAccess as d, SitemapEndpointsConfig as f, SitemapPluginConfig as g, SitemapPathArgs as h, ResolvedSitemapEndpoints as i, SitemapCollectionConfig as l, SitemapInvalidateArgs as m, InternalSitemapCollectionConfig as n, RobotsOptions as o, SitemapEntry as p, ResolvedSitemapConfig as r, RobotsRule as s, ChangeFrequency as t, SitemapCollections as u, SitemapRoutesFn as v, siteUrlFromRequest as x, SiteUrlContext as y };
271
- //# sourceMappingURL=types-j8T8euN5.d.ts.map
272
+ //# sourceMappingURL=types-BsS4pTPA.d.ts.map
@@ -388,9 +388,9 @@ const allowSitemaps = (rules, sitemaps) => rules.map((rule) => {
388
388
  };
389
389
  });
390
390
  const buildRobotsData = ({ adminRoute = "/admin", apiRoute = "/api", options = {}, sitemaps }) => {
391
- const isProduction = options.isProduction ?? (process.env.VERCEL_ENV ? process.env.VERCEL_ENV === "production" : process.env.NODE_ENV === "production");
391
+ const allowIndexing = options.allowIndexing ?? (process.env.VERCEL_ENV ? process.env.VERCEL_ENV === "production" : process.env.NODE_ENV === "production");
392
392
  let data;
393
- if (!isProduction) data = {
393
+ if (!allowIndexing) data = {
394
394
  rules: [{
395
395
  disallow: "/",
396
396
  userAgent: "*"
@@ -484,4 +484,4 @@ const buildSitemapIndexXml = (items) => {
484
484
 
485
485
  //#endregion
486
486
  export { createNextTagsCache as C, createMemoryCache as S, sitemapCacheTag as T, getSitemapConfig as _, generateRobotsTxt as a, siteUrlFromRequest as b, getChunkEntries as c, finalizeEntries as d, formatLoc as f, ROUTES_GROUP as g, DEFAULT_CACHE_CONTROL as h, buildRobotsData as i, getIndexItems as l, getSitemapEntries as m, buildUrlsetXml as n, renderRobotsTxt as o, getGroupEntries as p, escapeXml as r, chunkFileName as s, buildSitemapIndexXml as t, matchChunkFile as u, resolveSitemapConfig as v, noopCache as w, SITEMAP_CACHE_TAG as x, resolveSiteUrl as y };
487
- //# sourceMappingURL=xml-DSOM2moN.js.map
487
+ //# sourceMappingURL=xml-nj_bfoCU.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"xml-DSOM2moN.js","names":["noopCache: SitemapCache","nextCachePromise: Promise<NextCacheModule | null> | undefined","url: URL","memoizedStaticSiteUrl: string | undefined","date: Date","collection: Payload['collections'][CollectionSlug] | undefined","conditions: Where[]","select: SelectType","entries: SitemapEntry[]","lastmod: string | undefined","result: Record<string, SitemapEntry[]>","max: string | undefined","items: Array<{ lastmod?: string; loc: string }>","data: RobotsData","XML_ESCAPES: Record<string, string>"],"sources":["../src/core/cache.ts","../src/core/siteUrl.ts","../src/core/resolved.ts","../src/core/entries.ts","../src/core/chunks.ts","../src/core/robots.ts","../src/core/xml.ts"],"sourcesContent":["import type { SitemapCache, SitemapEntry, SitemapPluginConfig } from '../types.js'\n\nexport const SITEMAP_CACHE_TAG = 'payload-sitemap'\n\nexport const sitemapCacheTag = (group: string): string => `${SITEMAP_CACHE_TAG}:${group}`\n\nexport const createMemoryCache = (): SitemapCache => {\n const store = new Map<string, SitemapEntry[]>()\n return {\n invalidate(keys) {\n for (const key of keys) {\n store.delete(key)\n }\n },\n async wrap(key, fn) {\n const cached = store.get(key)\n if (cached) {\n return cached\n }\n const entries = await fn()\n store.set(key, entries)\n return entries\n },\n }\n}\n\nexport const noopCache: SitemapCache = {\n invalidate: () => {},\n wrap: (_key, fn) => fn(),\n}\n\ntype NextCacheModule = {\n revalidateTag?: (tag: string, profile?: unknown) => void\n unstable_cache?: <T>(\n fn: () => Promise<T>,\n keyParts: string[],\n options: { revalidate: false; tags: string[] },\n ) => () => Promise<T>\n}\n\nlet nextCachePromise: Promise<NextCacheModule | null> | undefined\n\nconst loadNextCache = (): Promise<NextCacheModule | null> => {\n nextCachePromise ??= import('next/cache').then(\n (mod) => mod as NextCacheModule,\n () => null,\n )\n return nextCachePromise\n}\n\n/**\n * Caches entries in the Next.js Data Cache tagged `payload-sitemap:<group>`, so\n * invalidation is `revalidateTag` — shared across serverless instances on Vercel.\n * Degrades to uncached execution when `next/cache` is unavailable or errors\n * (standalone Payload, seed scripts, non-request contexts).\n */\nexport const createNextTagsCache = (): SitemapCache => ({\n async invalidate(keys) {\n const mod = await loadNextCache()\n if (!mod?.revalidateTag) {\n return\n }\n for (const key of keys) {\n try {\n // Next 16 requires a cache profile to expire instantly; Next 15's\n // single-argument revalidateTag ignores the extra argument.\n mod.revalidateTag(sitemapCacheTag(key), { expire: 0 })\n } catch {\n // Outside a Next request scope (scripts, workers) there is nothing to invalidate.\n }\n }\n },\n async wrap(key, fn) {\n const mod = await loadNextCache()\n if (!mod?.unstable_cache) {\n return fn()\n }\n try {\n return await mod.unstable_cache(fn, [SITEMAP_CACHE_TAG, key], {\n revalidate: false,\n tags: [SITEMAP_CACHE_TAG, sitemapCacheTag(key)],\n })()\n } catch {\n return fn()\n }\n },\n})\n\n/** Next tag cache when `next/cache` is importable, in-memory otherwise. */\nexport const createAutoCache = (): SitemapCache => {\n const memory = createMemoryCache()\n const nextTags = createNextTagsCache()\n const pick = async (): Promise<SitemapCache> => ((await loadNextCache()) ? nextTags : memory)\n return {\n invalidate: async (keys) => (await pick()).invalidate(keys),\n wrap: async (key, fn) => (await pick()).wrap(key, fn),\n }\n}\n\nexport const resolveCache = (option: SitemapPluginConfig['cache']): SitemapCache => {\n if (option === 'memory') {\n return createMemoryCache()\n }\n if (option === 'none') {\n return noopCache\n }\n if (option === 'auto' || option === undefined) {\n return createAutoCache()\n }\n return option\n}\n","/**\n * Context a site URL can be derived from when nothing is configured. `request`\n * structurally accepts a Fetch `Request`, a `PayloadRequest`, or — in contexts\n * without a request object (e.g. Next metadata routes) — a bare\n * `{ headers: await headers() }`.\n */\nexport type SiteUrlContext = {\n /** The incoming request. */\n request?: { headers?: Headers; url?: null | string }\n}\n\nconst validateSiteUrl = (raw: string, source: string): string => {\n let url: URL\n try {\n url = new URL(raw)\n } catch {\n throw new Error(\n `[payload-sitemap] Invalid siteUrl \"${raw}\" (from ${source}) — expected an absolute URL like https://example.com`,\n )\n }\n const basePath = url.pathname.replace(/\\/+$/, '')\n return `${url.origin}${basePath}`\n}\n\nconst LOCAL_HOST = /^(?:localhost|127\\.|0\\.0\\.0\\.0|\\[::1\\])/\n\n/**\n * Origin of the incoming request: proxy headers first (they carry the public host\n * when the server sits behind one), then the request URL. Host headers are\n * client-controlled: responses built from them must never be written to a shared\n * cache (entries are cached as site-relative paths for this reason).\n */\nexport const siteUrlFromRequest = (ctx: SiteUrlContext): string | undefined => {\n const headers = ctx.request?.headers\n const host = headers?.get('x-forwarded-host')?.split(',')[0]?.trim() ?? headers?.get('host')\n if (host) {\n const proto =\n headers?.get('x-forwarded-proto')?.split(',')[0]?.trim() ??\n (LOCAL_HOST.test(host) ? 'http' : 'https')\n return `${proto}://${host}`\n }\n if (ctx.request?.url) {\n try {\n return new URL(ctx.request.url).origin\n } catch {\n return undefined\n }\n }\n return undefined\n}\n\n/**\n * Resolves the site origin from explicit configuration or environment variables.\n * Returns `undefined` when neither is set (the caller may then fall back to the\n * request). Env vars win over request headers so that deployments reachable via\n * non-canonical aliases (e.g. *.vercel.app) still emit the canonical domain.\n */\nexport const resolveStaticSiteUrl = (configured?: string): string | undefined => {\n if (configured) {\n return validateSiteUrl(configured, 'the siteUrl option')\n }\n if (process.env.SITE_URL) {\n return validateSiteUrl(process.env.SITE_URL, 'SITE_URL')\n }\n if (process.env.NEXT_PUBLIC_SERVER_URL) {\n return validateSiteUrl(process.env.NEXT_PUBLIC_SERVER_URL, 'NEXT_PUBLIC_SERVER_URL')\n }\n if (process.env.VERCEL_PROJECT_PRODUCTION_URL) {\n return validateSiteUrl(\n `https://${process.env.VERCEL_PROJECT_PRODUCTION_URL}`,\n 'VERCEL_PROJECT_PRODUCTION_URL',\n )\n }\n return undefined\n}\n\n/**\n * Resolves the canonical frontend origin: explicit option → SITE_URL →\n * NEXT_PUBLIC_SERVER_URL → VERCEL_PROJECT_PRODUCTION_URL → the incoming\n * request, when available.\n */\nexport const resolveSiteUrl = (\n configured?: ((ctx: SiteUrlContext) => string) | string,\n ctx?: SiteUrlContext,\n): string => {\n if (typeof configured === 'function') {\n return validateSiteUrl(configured(ctx ?? {}), 'the siteUrl function')\n }\n\n const staticUrl = resolveStaticSiteUrl(configured)\n if (staticUrl) {\n return staticUrl\n }\n\n const fromRequest = ctx && siteUrlFromRequest(ctx)\n if (fromRequest) {\n return validateSiteUrl(fromRequest, 'the incoming request')\n }\n\n throw new Error(\n '[payload-sitemap] No siteUrl available. Set the `siteUrl` plugin option, one of the SITE_URL / NEXT_PUBLIC_SERVER_URL environment variables, or call from a context with an incoming request.',\n )\n}\n","import type { SanitizedConfig } from 'payload'\n\nimport type {\n InternalSitemapCollectionConfig,\n ResolvedSitemapConfig,\n ResolvedSitemapEndpoints,\n SitemapPluginConfig,\n} from '../types.js'\n\nimport { resolveCache } from './cache.js'\nimport { resolveSiteUrl, resolveStaticSiteUrl } from './siteUrl.js'\n\n/** Reserved group name for entries from the `routes` option. */\nexport const ROUTES_GROUP = '_routes'\n\nexport const DEFAULT_CHUNK_SIZE = 25_000\n\nexport const DEFAULT_CACHE_CONTROL = 'public, max-age=0, s-maxage=600, stale-while-revalidate=86400'\n\nexport const DEFAULT_ENDPOINTS_PATH = '/sitemap'\n\nconst resolveEndpoints = (\n option: SitemapPluginConfig['endpoints'],\n): false | ResolvedSitemapEndpoints => {\n if (!option) {\n return false\n }\n const config = option === true ? {} : option\n return {\n access: config.access,\n cacheControl: config.cacheControl ?? DEFAULT_CACHE_CONTROL,\n json: config.json\n ? {\n access:\n (config.json === true ? undefined : config.json.access) ??\n (({ req }) => Boolean(req.user)),\n }\n : false,\n origin: config.origin,\n path: config.path ?? DEFAULT_ENDPOINTS_PATH,\n }\n}\n\nexport const resolveSitemapConfig = (pluginConfig: SitemapPluginConfig): ResolvedSitemapConfig => {\n const collections = pluginConfig.collections as unknown as Record<\n string,\n InternalSitemapCollectionConfig\n >\n\n if (ROUTES_GROUP in collections) {\n throw new Error(\n `[payload-sitemap] \"${ROUTES_GROUP}\" is reserved for the \\`routes\\` option and cannot be used as a collection slug.`,\n )\n }\n\n let memoizedStaticSiteUrl: string | undefined\n\n return {\n cache: resolveCache(pluginConfig.cache),\n chunkSize: pluginConfig.chunkSize ?? DEFAULT_CHUNK_SIZE,\n collections,\n endpoints: resolveEndpoints(pluginConfig.endpoints),\n excludeFieldPath:\n pluginConfig.adminFields?.exclude !== false\n ? pluginConfig.adminFields?.group\n ? `${pluginConfig.adminFields.group}.excludeFromSitemap`\n : 'excludeFromSitemap'\n : undefined,\n groups: [...Object.keys(collections), ...(pluginConfig.routes ? [ROUTES_GROUP] : [])],\n robots: pluginConfig.robots ?? {},\n routes: pluginConfig.routes,\n siteUrl: (ctx) => {\n // A configured function gets full control on every call; only the static\n // sources (option string, env vars) are safe to memoize.\n if (typeof pluginConfig.siteUrl === 'function') {\n return resolveSiteUrl(pluginConfig.siteUrl, ctx)\n }\n return (memoizedStaticSiteUrl ??= resolveStaticSiteUrl(pluginConfig.siteUrl)) != null\n ? memoizedStaticSiteUrl\n : resolveSiteUrl(undefined, ctx)\n },\n trailingSlash: pluginConfig.trailingSlash ?? false,\n }\n}\n\n/** Reads the resolved plugin config stashed on the Payload config by `sitemapPlugin`. */\nexport const getSitemapConfig = (config: SanitizedConfig): ResolvedSitemapConfig => {\n const resolved = (config.custom as { sitemap?: ResolvedSitemapConfig } | undefined)?.sitemap\n if (!resolved) {\n throw new Error(\n '[payload-sitemap] Plugin config not found — is sitemapPlugin() installed (and not disabled) on this Payload config?',\n )\n }\n return resolved\n}\n","import type { CollectionSlug, Payload, PayloadRequest, SelectType, Where } from 'payload'\n\nimport type {\n InternalSitemapCollectionConfig,\n ResolvedSitemapConfig,\n SitemapEntry,\n} from '../types.js'\n\nimport { getSitemapConfig, ROUTES_GROUP } from './resolved.js'\n\nconst PAGE_SIZE = 1000\n\nexport const formatLoc = (path: string, siteUrl: string, trailingSlash: boolean): string => {\n if (/^https?:\\/\\//.test(path)) {\n return path\n }\n let normalized = path.startsWith('/') ? path : `/${path}`\n if (normalized !== '/') {\n normalized = trailingSlash ? normalized.replace(/\\/*$/, '/') : normalized.replace(/\\/+$/, '')\n }\n return `${siteUrl}${normalized}`\n}\n\n/**\n * Joins cached site-relative entries onto the resolved site origin. Entries are\n * cached with relative `loc` paths so cached data is host-independent — a\n * request-derived siteUrl can never leak into the shared cache.\n */\nexport const finalizeEntries = (\n entries: SitemapEntry[],\n { siteUrl, trailingSlash }: { siteUrl: string; trailingSlash: boolean },\n): SitemapEntry[] =>\n entries.map((entry) => ({ ...entry, loc: formatLoc(entry.loc, siteUrl, trailingSlash) }))\n\nconst normalizeLastMod = (value: unknown): string | undefined => {\n if (!value) {\n return undefined\n }\n let date: Date\n if (value instanceof Date) {\n date = value\n } else if (typeof value === 'string' || typeof value === 'number') {\n date = new Date(value)\n } else {\n return undefined\n }\n return Number.isNaN(date.getTime()) ? undefined : date.toISOString()\n}\n\ntype FetchArgs = {\n config: ResolvedSitemapConfig\n payload: Payload\n req?: PayloadRequest\n}\n\nconst fetchCollectionEntries = async (\n { config, payload, req }: FetchArgs,\n // Group keys come from plugin config, so they are plain strings; existence is\n // checked at runtime below.\n slug: CollectionSlug,\n collConfig: InternalSitemapCollectionConfig,\n): Promise<SitemapEntry[]> => {\n const collection: Payload['collections'][CollectionSlug] | undefined = payload.collections[slug]\n if (!collection) {\n payload.logger.warn(`[payload-sitemap] Collection \"${slug}\" does not exist — skipping.`)\n return []\n }\n\n // `_status` only exists on the schema when drafts are enabled; querying it on a\n // non-draft collection throws a QueryError.\n const draftsEnabled = Boolean(collection.config.versions?.drafts)\n\n const conditions: Where[] = []\n if (collConfig.where) {\n conditions.push(collConfig.where)\n }\n if (config.excludeFieldPath) {\n conditions.push({ [config.excludeFieldPath]: { not_equals: true } })\n }\n if (draftsEnabled) {\n conditions.push({ _status: { equals: 'published' } })\n }\n\n const select: SelectType = { ...(collConfig.select ?? { slug: true }), updatedAt: true }\n if (typeof collConfig.lastMod === 'string') {\n select[collConfig.lastMod] = true\n }\n\n const entries: SitemapEntry[] = []\n let page = 1\n\n while (true) {\n const result = await payload.find({\n collection: slug,\n depth: 0,\n limit: PAGE_SIZE,\n overrideAccess: true,\n page,\n pagination: true,\n req,\n select,\n sort: 'createdAt',\n where: conditions.length ? { and: conditions } : undefined,\n })\n\n for (const doc of result.docs) {\n const path = await collConfig.path({ doc, req })\n if (!path) {\n continue\n }\n\n let lastmod: string | undefined\n if (collConfig.lastMod !== false) {\n const raw =\n typeof collConfig.lastMod === 'function'\n ? collConfig.lastMod(doc)\n : (doc as unknown as Record<string, unknown>)[\n typeof collConfig.lastMod === 'string' ? collConfig.lastMod : 'updatedAt'\n ]\n lastmod = normalizeLastMod(raw)\n }\n\n entries.push({\n loc: path,\n ...(lastmod ? { lastmod } : {}),\n })\n }\n\n if (!result.hasNextPage) {\n break\n }\n page += 1\n }\n\n return entries\n}\n\nconst fetchRouteEntries = async ({ config, payload, req }: FetchArgs): Promise<SitemapEntry[]> => {\n const routes =\n typeof config.routes === 'function'\n ? await config.routes({ payload, req })\n : (config.routes ?? [])\n\n return routes.map((route) => {\n const lastmod = normalizeLastMod(route.lastMod)\n return {\n loc: route.path,\n ...(lastmod ? { lastmod } : {}),\n ...(route.changeFreq ? { changefreq: route.changeFreq } : {}),\n ...(route.priority !== undefined ? { priority: route.priority } : {}),\n }\n })\n}\n\n/**\n * Cached entries for one group (a collection slug or `ROUTES_GROUP`).\n * `loc` values are site-relative — pass through `finalizeEntries` before rendering.\n */\nexport const getGroupEntries = async (\n args: { group: string } & FetchArgs,\n): Promise<SitemapEntry[]> => {\n const { config, group } = args\n return config.cache.wrap(group, () => {\n if (group === ROUTES_GROUP) {\n return fetchRouteEntries(args)\n }\n const collConfig = config.collections[group]\n if (!collConfig) {\n return Promise.resolve([])\n }\n // The assertion only matters in consumer projects, where generated types\n // narrow CollectionSlug from string to a union of known slugs.\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion\n return fetchCollectionEntries(args, group as CollectionSlug, collConfig)\n })\n}\n\n/**\n * All sitemap entries with absolute URLs, keyed by group. Public API for SSG\n * frontends and custom delivery — reads the plugin config from the Payload\n * instance. Pass `req` (or `request` — a Fetch Request, or\n * `{ headers: await headers() }` in an RSC) so the site origin can be derived\n * from the request when it isn't configured statically.\n */\nexport const getSitemapEntries = async (\n payload: Payload,\n options?: {\n groups?: string[]\n req?: PayloadRequest\n request?: { headers?: Headers; url?: null | string }\n },\n): Promise<Record<string, SitemapEntry[]>> => {\n const config = getSitemapConfig(payload.config)\n const groups = options?.groups ?? config.groups\n const siteUrl = config.siteUrl({ request: options?.request ?? options?.req })\n const result: Record<string, SitemapEntry[]> = {}\n for (const group of groups) {\n const entries = await getGroupEntries({ config, group, payload, req: options?.req })\n result[group] = finalizeEntries(entries, { siteUrl, trailingSlash: config.trailingSlash })\n }\n return result\n}\n","import type { Payload, PayloadRequest } from 'payload'\n\nimport type { ResolvedSitemapConfig, SitemapEntry } from '../types.js'\n\nimport { getGroupEntries } from './entries.js'\n\nexport const chunkFileName = (group: string, index: number): string => `${group}-${index + 1}.xml`\n\n/**\n * Matches a chunk filename against the known groups by prefix, so group slugs\n * containing hyphens or digits parse unambiguously.\n */\nexport const matchChunkFile = (\n file: string,\n groups: string[],\n): { group: string; index: number } | null => {\n for (const group of groups) {\n if (!file.startsWith(`${group}-`)) {\n continue\n }\n const match = /^([1-9]\\d*)\\.xml$/.exec(file.slice(group.length + 1))\n if (match) {\n return { group, index: Number(match[1]) - 1 }\n }\n }\n return null\n}\n\nconst chunkSizeFor = (config: ResolvedSitemapConfig, group: string): number =>\n config.collections[group]?.chunkSize ?? config.chunkSize\n\nconst maxLastmod = (entries: SitemapEntry[]): string | undefined => {\n let max: string | undefined\n for (const entry of entries) {\n if (entry.lastmod && (!max || entry.lastmod > max)) {\n max = entry.lastmod\n }\n }\n return max\n}\n\ntype BaseArgs = {\n config: ResolvedSitemapConfig\n payload: Payload\n req?: PayloadRequest\n}\n\n/** Items for the `<sitemapindex>`: one per chunk of each non-empty group. */\nexport const getIndexItems = async (\n args: { chunkUrl: (file: string) => string } & BaseArgs,\n): Promise<Array<{ lastmod?: string; loc: string }>> => {\n const { chunkUrl, config } = args\n const items: Array<{ lastmod?: string; loc: string }> = []\n\n for (const group of config.groups) {\n const entries = await getGroupEntries({ ...args, group })\n if (!entries.length) {\n continue\n }\n const size = chunkSizeFor(config, group)\n for (let index = 0; index * size < entries.length; index++) {\n const chunk = entries.slice(index * size, (index + 1) * size)\n const lastmod = maxLastmod(chunk)\n items.push({ loc: chunkUrl(chunkFileName(group, index)), ...(lastmod ? { lastmod } : {}) })\n }\n }\n\n return items\n}\n\n/**\n * Entries for one chunk file, or `null` when the filename matches no group/range.\n * `loc` values are site-relative — pass through `finalizeEntries` before rendering.\n */\nexport const getChunkEntries = async (\n args: { file: string } & BaseArgs,\n): Promise<{ entries: SitemapEntry[]; group: string } | null> => {\n const { config, file } = args\n const match = matchChunkFile(file, config.groups)\n if (!match) {\n return null\n }\n\n const entries = await getGroupEntries({ ...args, group: match.group })\n const size = chunkSizeFor(config, match.group)\n const start = match.index * size\n if (match.index > 0 && start >= entries.length) {\n return null\n }\n\n return { entries: entries.slice(start, start + size), group: match.group }\n}\n","import type { SanitizedConfig } from 'payload'\n\nimport type { RobotsData, RobotsOptions, RobotsRule } from '../types.js'\nimport type { SiteUrlContext } from './siteUrl.js'\n\nimport { getSitemapConfig } from './resolved.js'\n\nconst toArray = (value: string | string[] | undefined): string[] =>\n value === undefined ? [] : Array.isArray(value) ? [value].flat() : [value]\n\nconst safePathname = (url: string): string | undefined => {\n try {\n return new URL(url).pathname\n } catch {\n return undefined\n }\n}\n\n/**\n * Adds `Allow` exceptions for sitemap URLs that fall under a disallowed prefix\n * (e.g. a sitemap served from `/api/...` while `/api/` is disallowed).\n */\nconst allowSitemaps = (rules: RobotsRule[], sitemaps: string[]): RobotsRule[] =>\n rules.map((rule) => {\n const disallow = toArray(rule.disallow)\n const allow = new Set(toArray(rule.allow))\n for (const sitemap of sitemaps) {\n const pathname = safePathname(sitemap)\n if (pathname && disallow.some((prefix) => prefix !== '/' && pathname.startsWith(prefix))) {\n allow.add(pathname)\n }\n }\n return { ...rule, ...(allow.size ? { allow: [...allow] } : {}) }\n })\n\nexport type BuildRobotsArgs = {\n /** Payload admin route, used for the default disallow list. @default '/admin' */\n adminRoute?: string\n /** Payload API route, used for the default disallow list. @default '/api' */\n apiRoute?: string\n options?: RobotsOptions\n /** Absolute sitemap URL(s) advertised in the output. */\n sitemaps: string[]\n}\n\nexport const buildRobotsData = ({\n adminRoute = '/admin',\n apiRoute = '/api',\n options = {},\n sitemaps,\n}: BuildRobotsArgs): RobotsData => {\n const isProduction =\n options.isProduction ??\n (process.env.VERCEL_ENV\n ? process.env.VERCEL_ENV === 'production'\n : process.env.NODE_ENV === 'production')\n\n let data: RobotsData\n if (!isProduction) {\n data = { rules: [{ disallow: '/', userAgent: '*' }], sitemaps: [] }\n } else {\n const sitemapUrls = options.sitemaps ?? sitemaps\n const rules = options.rules ?? [\n {\n disallow: [`${adminRoute}/`, `${apiRoute}/`, ...(options.disallow ?? [])],\n userAgent: '*',\n },\n ]\n data = { rules: allowSitemaps(rules, sitemapUrls), sitemaps: sitemapUrls }\n }\n\n return options.transform ? options.transform(data) : data\n}\n\nexport const renderRobotsTxt = (data: RobotsData): string => {\n const blocks = data.rules.map((rule) => {\n const lines = [\n ...toArray(rule.userAgent).map((agent) => `User-agent: ${agent}`),\n ...toArray(rule.allow).map((path) => `Allow: ${path}`),\n ...toArray(rule.disallow).map((path) => `Disallow: ${path}`),\n ...(rule.crawlDelay !== undefined ? [`Crawl-delay: ${rule.crawlDelay}`] : []),\n ]\n return lines.join('\\n')\n })\n\n const footer = [\n ...(data.host ? [`Host: ${data.host}`] : []),\n ...data.sitemaps.map((url) => `Sitemap: ${url}`),\n ]\n\n return [...blocks, ...(footer.length ? [footer.join('\\n')] : [])].join('\\n\\n') + '\\n'\n}\n\n/**\n * robots.txt for any delivery mechanism. Defaults come from the plugin config;\n * `overrides` win field-by-field, and `transform` gets the final say. Pass\n * `request` so the default sitemap URL can derive its origin from the incoming\n * request when `siteUrl` isn't configured statically.\n */\nexport const generateRobotsTxt = async (\n configInput: Promise<SanitizedConfig> | SanitizedConfig,\n overrides?: { request?: SiteUrlContext['request'] } & RobotsOptions,\n): Promise<string> => {\n const config = await configInput\n const sitemapConfig = getSitemapConfig(config)\n const { request, ...overrideOptions } = overrides ?? {}\n const options = { ...sitemapConfig.robots, ...overrideOptions }\n const sitemaps = options.sitemaps ?? [`${sitemapConfig.siteUrl({ request })}/sitemap.xml`]\n\n return renderRobotsTxt(\n buildRobotsData({\n adminRoute: config.routes.admin,\n apiRoute: config.routes.api,\n options,\n sitemaps,\n }),\n )\n}\n","import type { ChangeFrequency, SitemapEntry } from '../types.js'\n\nconst XML_ESCAPES: Record<string, string> = {\n '\"': '&quot;',\n '&': '&amp;',\n \"'\": '&apos;',\n '<': '&lt;',\n '>': '&gt;',\n}\n\nexport const escapeXml = (value: string): string =>\n value.replace(/[&<>\"']/g, (char) => XML_ESCAPES[char])\n\nconst clampPriority = (priority: number): string => String(Math.min(1, Math.max(0, priority)))\n\nexport const buildUrlsetXml = (\n entries: SitemapEntry[],\n defaults?: { changeFreq?: ChangeFrequency; priority?: number },\n): string => {\n const body = entries\n .map((entry) => {\n const changefreq = entry.changefreq ?? defaults?.changeFreq\n const priority = entry.priority ?? defaults?.priority\n return [\n ' <url>',\n ` <loc>${escapeXml(entry.loc)}</loc>`,\n entry.lastmod ? ` <lastmod>${escapeXml(entry.lastmod)}</lastmod>` : null,\n changefreq ? ` <changefreq>${changefreq}</changefreq>` : null,\n priority !== undefined ? ` <priority>${clampPriority(priority)}</priority>` : null,\n ' </url>',\n ]\n .filter(Boolean)\n .join('\\n')\n })\n .join('\\n')\n\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\\n${body}\\n</urlset>\\n`\n}\n\nexport const buildSitemapIndexXml = (items: Array<{ lastmod?: string; loc: string }>): string => {\n const body = items\n .map((item) =>\n [\n ' <sitemap>',\n ` <loc>${escapeXml(item.loc)}</loc>`,\n item.lastmod ? ` <lastmod>${escapeXml(item.lastmod)}</lastmod>` : null,\n ' </sitemap>',\n ]\n .filter(Boolean)\n .join('\\n'),\n )\n .join('\\n')\n\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n<sitemapindex xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\\n${body}\\n</sitemapindex>\\n`\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"xml-nj_bfoCU.js","names":["noopCache: SitemapCache","nextCachePromise: Promise<NextCacheModule | null> | undefined","url: URL","memoizedStaticSiteUrl: string | undefined","date: Date","collection: Payload['collections'][CollectionSlug] | undefined","conditions: Where[]","select: SelectType","entries: SitemapEntry[]","lastmod: string | undefined","result: Record<string, SitemapEntry[]>","max: string | undefined","items: Array<{ lastmod?: string; loc: string }>","data: RobotsData","XML_ESCAPES: Record<string, string>"],"sources":["../src/core/cache.ts","../src/core/siteUrl.ts","../src/core/resolved.ts","../src/core/entries.ts","../src/core/chunks.ts","../src/core/robots.ts","../src/core/xml.ts"],"sourcesContent":["import type { SitemapCache, SitemapEntry, SitemapPluginConfig } from '../types.js'\n\nexport const SITEMAP_CACHE_TAG = 'payload-sitemap'\n\nexport const sitemapCacheTag = (group: string): string => `${SITEMAP_CACHE_TAG}:${group}`\n\nexport const createMemoryCache = (): SitemapCache => {\n const store = new Map<string, SitemapEntry[]>()\n return {\n invalidate(keys) {\n for (const key of keys) {\n store.delete(key)\n }\n },\n async wrap(key, fn) {\n const cached = store.get(key)\n if (cached) {\n return cached\n }\n const entries = await fn()\n store.set(key, entries)\n return entries\n },\n }\n}\n\nexport const noopCache: SitemapCache = {\n invalidate: () => {},\n wrap: (_key, fn) => fn(),\n}\n\ntype NextCacheModule = {\n revalidateTag?: (tag: string, profile?: unknown) => void\n unstable_cache?: <T>(\n fn: () => Promise<T>,\n keyParts: string[],\n options: { revalidate: false; tags: string[] },\n ) => () => Promise<T>\n}\n\nlet nextCachePromise: Promise<NextCacheModule | null> | undefined\n\nconst loadNextCache = (): Promise<NextCacheModule | null> => {\n nextCachePromise ??= import('next/cache').then(\n (mod) => mod as NextCacheModule,\n () => null,\n )\n return nextCachePromise\n}\n\n/**\n * Caches entries in the Next.js Data Cache tagged `payload-sitemap:<group>`, so\n * invalidation is `revalidateTag` — shared across serverless instances on Vercel.\n * Degrades to uncached execution when `next/cache` is unavailable or errors\n * (standalone Payload, seed scripts, non-request contexts).\n */\nexport const createNextTagsCache = (): SitemapCache => ({\n async invalidate(keys) {\n const mod = await loadNextCache()\n if (!mod?.revalidateTag) {\n return\n }\n for (const key of keys) {\n try {\n // Next 16 requires a cache profile to expire instantly; Next 15's\n // single-argument revalidateTag ignores the extra argument.\n mod.revalidateTag(sitemapCacheTag(key), { expire: 0 })\n } catch {\n // Outside a Next request scope (scripts, workers) there is nothing to invalidate.\n }\n }\n },\n async wrap(key, fn) {\n const mod = await loadNextCache()\n if (!mod?.unstable_cache) {\n return fn()\n }\n try {\n return await mod.unstable_cache(fn, [SITEMAP_CACHE_TAG, key], {\n revalidate: false,\n tags: [SITEMAP_CACHE_TAG, sitemapCacheTag(key)],\n })()\n } catch {\n return fn()\n }\n },\n})\n\n/** Next tag cache when `next/cache` is importable, in-memory otherwise. */\nexport const createAutoCache = (): SitemapCache => {\n const memory = createMemoryCache()\n const nextTags = createNextTagsCache()\n const pick = async (): Promise<SitemapCache> => ((await loadNextCache()) ? nextTags : memory)\n return {\n invalidate: async (keys) => (await pick()).invalidate(keys),\n wrap: async (key, fn) => (await pick()).wrap(key, fn),\n }\n}\n\nexport const resolveCache = (option: SitemapPluginConfig['cache']): SitemapCache => {\n if (option === 'memory') {\n return createMemoryCache()\n }\n if (option === 'none') {\n return noopCache\n }\n if (option === 'auto' || option === undefined) {\n return createAutoCache()\n }\n return option\n}\n","/**\n * Context a site URL can be derived from when nothing is configured. `request`\n * structurally accepts a Fetch `Request`, a `PayloadRequest`, or — in contexts\n * without a request object (e.g. Next metadata routes) — a bare\n * `{ headers: await headers() }`.\n */\nexport type SiteUrlContext = {\n /** The incoming request. */\n request?: { headers?: Headers; url?: null | string }\n}\n\nconst validateSiteUrl = (raw: string, source: string): string => {\n let url: URL\n try {\n url = new URL(raw)\n } catch {\n throw new Error(\n `[payload-sitemap] Invalid siteUrl \"${raw}\" (from ${source}) — expected an absolute URL like https://example.com`,\n )\n }\n const basePath = url.pathname.replace(/\\/+$/, '')\n return `${url.origin}${basePath}`\n}\n\nconst LOCAL_HOST = /^(?:localhost|127\\.|0\\.0\\.0\\.0|\\[::1\\])/\n\n/**\n * Origin of the incoming request: proxy headers first (they carry the public host\n * when the server sits behind one), then the request URL. Host headers are\n * client-controlled: responses built from them must never be written to a shared\n * cache (entries are cached as site-relative paths for this reason).\n */\nexport const siteUrlFromRequest = (ctx: SiteUrlContext): string | undefined => {\n const headers = ctx.request?.headers\n const host = headers?.get('x-forwarded-host')?.split(',')[0]?.trim() ?? headers?.get('host')\n if (host) {\n const proto =\n headers?.get('x-forwarded-proto')?.split(',')[0]?.trim() ??\n (LOCAL_HOST.test(host) ? 'http' : 'https')\n return `${proto}://${host}`\n }\n if (ctx.request?.url) {\n try {\n return new URL(ctx.request.url).origin\n } catch {\n return undefined\n }\n }\n return undefined\n}\n\n/**\n * Resolves the site origin from explicit configuration or environment variables.\n * Returns `undefined` when neither is set (the caller may then fall back to the\n * request). Env vars win over request headers so that deployments reachable via\n * non-canonical aliases (e.g. *.vercel.app) still emit the canonical domain.\n */\nexport const resolveStaticSiteUrl = (configured?: string): string | undefined => {\n if (configured) {\n return validateSiteUrl(configured, 'the siteUrl option')\n }\n if (process.env.SITE_URL) {\n return validateSiteUrl(process.env.SITE_URL, 'SITE_URL')\n }\n if (process.env.NEXT_PUBLIC_SERVER_URL) {\n return validateSiteUrl(process.env.NEXT_PUBLIC_SERVER_URL, 'NEXT_PUBLIC_SERVER_URL')\n }\n if (process.env.VERCEL_PROJECT_PRODUCTION_URL) {\n return validateSiteUrl(\n `https://${process.env.VERCEL_PROJECT_PRODUCTION_URL}`,\n 'VERCEL_PROJECT_PRODUCTION_URL',\n )\n }\n return undefined\n}\n\n/**\n * Resolves the canonical frontend origin: explicit option → SITE_URL →\n * NEXT_PUBLIC_SERVER_URL → VERCEL_PROJECT_PRODUCTION_URL → the incoming\n * request, when available.\n */\nexport const resolveSiteUrl = (\n configured?: ((ctx: SiteUrlContext) => string) | string,\n ctx?: SiteUrlContext,\n): string => {\n if (typeof configured === 'function') {\n return validateSiteUrl(configured(ctx ?? {}), 'the siteUrl function')\n }\n\n const staticUrl = resolveStaticSiteUrl(configured)\n if (staticUrl) {\n return staticUrl\n }\n\n const fromRequest = ctx && siteUrlFromRequest(ctx)\n if (fromRequest) {\n return validateSiteUrl(fromRequest, 'the incoming request')\n }\n\n throw new Error(\n '[payload-sitemap] No siteUrl available. Set the `siteUrl` plugin option, one of the SITE_URL / NEXT_PUBLIC_SERVER_URL environment variables, or call from a context with an incoming request.',\n )\n}\n","import type { SanitizedConfig } from 'payload'\n\nimport type {\n InternalSitemapCollectionConfig,\n ResolvedSitemapConfig,\n ResolvedSitemapEndpoints,\n SitemapPluginConfig,\n} from '../types.js'\n\nimport { resolveCache } from './cache.js'\nimport { resolveSiteUrl, resolveStaticSiteUrl } from './siteUrl.js'\n\n/** Reserved group name for entries from the `routes` option. */\nexport const ROUTES_GROUP = '_routes'\n\nexport const DEFAULT_CHUNK_SIZE = 25_000\n\nexport const DEFAULT_CACHE_CONTROL = 'public, max-age=0, s-maxage=600, stale-while-revalidate=86400'\n\nexport const DEFAULT_ENDPOINTS_PATH = '/sitemap'\n\nconst resolveEndpoints = (\n option: SitemapPluginConfig['endpoints'],\n): false | ResolvedSitemapEndpoints => {\n if (!option) {\n return false\n }\n const config = option === true ? {} : option\n return {\n access: config.access,\n cacheControl: config.cacheControl ?? DEFAULT_CACHE_CONTROL,\n json: config.json\n ? {\n access:\n (config.json === true ? undefined : config.json.access) ??\n (({ req }) => Boolean(req.user)),\n }\n : false,\n origin: config.origin,\n path: config.path ?? DEFAULT_ENDPOINTS_PATH,\n }\n}\n\nexport const resolveSitemapConfig = (pluginConfig: SitemapPluginConfig): ResolvedSitemapConfig => {\n const collections = pluginConfig.collections as unknown as Record<\n string,\n InternalSitemapCollectionConfig\n >\n\n if (ROUTES_GROUP in collections) {\n throw new Error(\n `[payload-sitemap] \"${ROUTES_GROUP}\" is reserved for the \\`routes\\` option and cannot be used as a collection slug.`,\n )\n }\n\n let memoizedStaticSiteUrl: string | undefined\n\n return {\n cache: resolveCache(pluginConfig.cache),\n chunkSize: pluginConfig.chunkSize ?? DEFAULT_CHUNK_SIZE,\n collections,\n endpoints: resolveEndpoints(pluginConfig.endpoints),\n excludeFieldPath:\n pluginConfig.adminFields?.exclude !== false\n ? pluginConfig.adminFields?.group\n ? `${pluginConfig.adminFields.group}.excludeFromSitemap`\n : 'excludeFromSitemap'\n : undefined,\n groups: [...Object.keys(collections), ...(pluginConfig.routes ? [ROUTES_GROUP] : [])],\n robots: pluginConfig.robots ?? {},\n routes: pluginConfig.routes,\n siteUrl: (ctx) => {\n // A configured function gets full control on every call; only the static\n // sources (option string, env vars) are safe to memoize.\n if (typeof pluginConfig.siteUrl === 'function') {\n return resolveSiteUrl(pluginConfig.siteUrl, ctx)\n }\n return (memoizedStaticSiteUrl ??= resolveStaticSiteUrl(pluginConfig.siteUrl)) != null\n ? memoizedStaticSiteUrl\n : resolveSiteUrl(undefined, ctx)\n },\n trailingSlash: pluginConfig.trailingSlash ?? false,\n }\n}\n\n/** Reads the resolved plugin config stashed on the Payload config by `sitemapPlugin`. */\nexport const getSitemapConfig = (config: SanitizedConfig): ResolvedSitemapConfig => {\n const resolved = (config.custom as { sitemap?: ResolvedSitemapConfig } | undefined)?.sitemap\n if (!resolved) {\n throw new Error(\n '[payload-sitemap] Plugin config not found — is sitemapPlugin() installed (and not disabled) on this Payload config?',\n )\n }\n return resolved\n}\n","import type { CollectionSlug, Payload, PayloadRequest, SelectType, Where } from 'payload'\n\nimport type {\n InternalSitemapCollectionConfig,\n ResolvedSitemapConfig,\n SitemapEntry,\n} from '../types.js'\n\nimport { getSitemapConfig, ROUTES_GROUP } from './resolved.js'\n\nconst PAGE_SIZE = 1000\n\nexport const formatLoc = (path: string, siteUrl: string, trailingSlash: boolean): string => {\n if (/^https?:\\/\\//.test(path)) {\n return path\n }\n let normalized = path.startsWith('/') ? path : `/${path}`\n if (normalized !== '/') {\n normalized = trailingSlash ? normalized.replace(/\\/*$/, '/') : normalized.replace(/\\/+$/, '')\n }\n return `${siteUrl}${normalized}`\n}\n\n/**\n * Joins cached site-relative entries onto the resolved site origin. Entries are\n * cached with relative `loc` paths so cached data is host-independent — a\n * request-derived siteUrl can never leak into the shared cache.\n */\nexport const finalizeEntries = (\n entries: SitemapEntry[],\n { siteUrl, trailingSlash }: { siteUrl: string; trailingSlash: boolean },\n): SitemapEntry[] =>\n entries.map((entry) => ({ ...entry, loc: formatLoc(entry.loc, siteUrl, trailingSlash) }))\n\nconst normalizeLastMod = (value: unknown): string | undefined => {\n if (!value) {\n return undefined\n }\n let date: Date\n if (value instanceof Date) {\n date = value\n } else if (typeof value === 'string' || typeof value === 'number') {\n date = new Date(value)\n } else {\n return undefined\n }\n return Number.isNaN(date.getTime()) ? undefined : date.toISOString()\n}\n\ntype FetchArgs = {\n config: ResolvedSitemapConfig\n payload: Payload\n req?: PayloadRequest\n}\n\nconst fetchCollectionEntries = async (\n { config, payload, req }: FetchArgs,\n // Group keys come from plugin config, so they are plain strings; existence is\n // checked at runtime below.\n slug: CollectionSlug,\n collConfig: InternalSitemapCollectionConfig,\n): Promise<SitemapEntry[]> => {\n const collection: Payload['collections'][CollectionSlug] | undefined = payload.collections[slug]\n if (!collection) {\n payload.logger.warn(`[payload-sitemap] Collection \"${slug}\" does not exist — skipping.`)\n return []\n }\n\n // `_status` only exists on the schema when drafts are enabled; querying it on a\n // non-draft collection throws a QueryError.\n const draftsEnabled = Boolean(collection.config.versions?.drafts)\n\n const conditions: Where[] = []\n if (collConfig.where) {\n conditions.push(collConfig.where)\n }\n if (config.excludeFieldPath) {\n conditions.push({ [config.excludeFieldPath]: { not_equals: true } })\n }\n if (draftsEnabled) {\n conditions.push({ _status: { equals: 'published' } })\n }\n\n const select: SelectType = { ...(collConfig.select ?? { slug: true }), updatedAt: true }\n if (typeof collConfig.lastMod === 'string') {\n select[collConfig.lastMod] = true\n }\n\n const entries: SitemapEntry[] = []\n let page = 1\n\n while (true) {\n const result = await payload.find({\n collection: slug,\n depth: 0,\n limit: PAGE_SIZE,\n overrideAccess: true,\n page,\n pagination: true,\n req,\n select,\n sort: 'createdAt',\n where: conditions.length ? { and: conditions } : undefined,\n })\n\n for (const doc of result.docs) {\n const path = await collConfig.path({ doc, req })\n if (!path) {\n continue\n }\n\n let lastmod: string | undefined\n if (collConfig.lastMod !== false) {\n const raw =\n typeof collConfig.lastMod === 'function'\n ? collConfig.lastMod(doc)\n : (doc as unknown as Record<string, unknown>)[\n typeof collConfig.lastMod === 'string' ? collConfig.lastMod : 'updatedAt'\n ]\n lastmod = normalizeLastMod(raw)\n }\n\n entries.push({\n loc: path,\n ...(lastmod ? { lastmod } : {}),\n })\n }\n\n if (!result.hasNextPage) {\n break\n }\n page += 1\n }\n\n return entries\n}\n\nconst fetchRouteEntries = async ({ config, payload, req }: FetchArgs): Promise<SitemapEntry[]> => {\n const routes =\n typeof config.routes === 'function'\n ? await config.routes({ payload, req })\n : (config.routes ?? [])\n\n return routes.map((route) => {\n const lastmod = normalizeLastMod(route.lastMod)\n return {\n loc: route.path,\n ...(lastmod ? { lastmod } : {}),\n ...(route.changeFreq ? { changefreq: route.changeFreq } : {}),\n ...(route.priority !== undefined ? { priority: route.priority } : {}),\n }\n })\n}\n\n/**\n * Cached entries for one group (a collection slug or `ROUTES_GROUP`).\n * `loc` values are site-relative — pass through `finalizeEntries` before rendering.\n */\nexport const getGroupEntries = async (\n args: { group: string } & FetchArgs,\n): Promise<SitemapEntry[]> => {\n const { config, group } = args\n return config.cache.wrap(group, () => {\n if (group === ROUTES_GROUP) {\n return fetchRouteEntries(args)\n }\n const collConfig = config.collections[group]\n if (!collConfig) {\n return Promise.resolve([])\n }\n // The assertion only matters in consumer projects, where generated types\n // narrow CollectionSlug from string to a union of known slugs.\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion\n return fetchCollectionEntries(args, group as CollectionSlug, collConfig)\n })\n}\n\n/**\n * All sitemap entries with absolute URLs, keyed by group. Public API for SSG\n * frontends and custom delivery — reads the plugin config from the Payload\n * instance. Pass `req` (or `request` — a Fetch Request, or\n * `{ headers: await headers() }` in an RSC) so the site origin can be derived\n * from the request when it isn't configured statically.\n */\nexport const getSitemapEntries = async (\n payload: Payload,\n options?: {\n groups?: string[]\n req?: PayloadRequest\n request?: { headers?: Headers; url?: null | string }\n },\n): Promise<Record<string, SitemapEntry[]>> => {\n const config = getSitemapConfig(payload.config)\n const groups = options?.groups ?? config.groups\n const siteUrl = config.siteUrl({ request: options?.request ?? options?.req })\n const result: Record<string, SitemapEntry[]> = {}\n for (const group of groups) {\n const entries = await getGroupEntries({ config, group, payload, req: options?.req })\n result[group] = finalizeEntries(entries, { siteUrl, trailingSlash: config.trailingSlash })\n }\n return result\n}\n","import type { Payload, PayloadRequest } from 'payload'\n\nimport type { ResolvedSitemapConfig, SitemapEntry } from '../types.js'\n\nimport { getGroupEntries } from './entries.js'\n\nexport const chunkFileName = (group: string, index: number): string => `${group}-${index + 1}.xml`\n\n/**\n * Matches a chunk filename against the known groups by prefix, so group slugs\n * containing hyphens or digits parse unambiguously.\n */\nexport const matchChunkFile = (\n file: string,\n groups: string[],\n): { group: string; index: number } | null => {\n for (const group of groups) {\n if (!file.startsWith(`${group}-`)) {\n continue\n }\n const match = /^([1-9]\\d*)\\.xml$/.exec(file.slice(group.length + 1))\n if (match) {\n return { group, index: Number(match[1]) - 1 }\n }\n }\n return null\n}\n\nconst chunkSizeFor = (config: ResolvedSitemapConfig, group: string): number =>\n config.collections[group]?.chunkSize ?? config.chunkSize\n\nconst maxLastmod = (entries: SitemapEntry[]): string | undefined => {\n let max: string | undefined\n for (const entry of entries) {\n if (entry.lastmod && (!max || entry.lastmod > max)) {\n max = entry.lastmod\n }\n }\n return max\n}\n\ntype BaseArgs = {\n config: ResolvedSitemapConfig\n payload: Payload\n req?: PayloadRequest\n}\n\n/** Items for the `<sitemapindex>`: one per chunk of each non-empty group. */\nexport const getIndexItems = async (\n args: { chunkUrl: (file: string) => string } & BaseArgs,\n): Promise<Array<{ lastmod?: string; loc: string }>> => {\n const { chunkUrl, config } = args\n const items: Array<{ lastmod?: string; loc: string }> = []\n\n for (const group of config.groups) {\n const entries = await getGroupEntries({ ...args, group })\n if (!entries.length) {\n continue\n }\n const size = chunkSizeFor(config, group)\n for (let index = 0; index * size < entries.length; index++) {\n const chunk = entries.slice(index * size, (index + 1) * size)\n const lastmod = maxLastmod(chunk)\n items.push({ loc: chunkUrl(chunkFileName(group, index)), ...(lastmod ? { lastmod } : {}) })\n }\n }\n\n return items\n}\n\n/**\n * Entries for one chunk file, or `null` when the filename matches no group/range.\n * `loc` values are site-relative — pass through `finalizeEntries` before rendering.\n */\nexport const getChunkEntries = async (\n args: { file: string } & BaseArgs,\n): Promise<{ entries: SitemapEntry[]; group: string } | null> => {\n const { config, file } = args\n const match = matchChunkFile(file, config.groups)\n if (!match) {\n return null\n }\n\n const entries = await getGroupEntries({ ...args, group: match.group })\n const size = chunkSizeFor(config, match.group)\n const start = match.index * size\n if (match.index > 0 && start >= entries.length) {\n return null\n }\n\n return { entries: entries.slice(start, start + size), group: match.group }\n}\n","import type { SanitizedConfig } from 'payload'\n\nimport type { RobotsData, RobotsOptions, RobotsRule } from '../types.js'\nimport type { SiteUrlContext } from './siteUrl.js'\n\nimport { getSitemapConfig } from './resolved.js'\n\nconst toArray = (value: string | string[] | undefined): string[] =>\n value === undefined ? [] : Array.isArray(value) ? [value].flat() : [value]\n\nconst safePathname = (url: string): string | undefined => {\n try {\n return new URL(url).pathname\n } catch {\n return undefined\n }\n}\n\n/**\n * Adds `Allow` exceptions for sitemap URLs that fall under a disallowed prefix\n * (e.g. a sitemap served from `/api/...` while `/api/` is disallowed).\n */\nconst allowSitemaps = (rules: RobotsRule[], sitemaps: string[]): RobotsRule[] =>\n rules.map((rule) => {\n const disallow = toArray(rule.disallow)\n const allow = new Set(toArray(rule.allow))\n for (const sitemap of sitemaps) {\n const pathname = safePathname(sitemap)\n if (pathname && disallow.some((prefix) => prefix !== '/' && pathname.startsWith(prefix))) {\n allow.add(pathname)\n }\n }\n return { ...rule, ...(allow.size ? { allow: [...allow] } : {}) }\n })\n\nexport type BuildRobotsArgs = {\n /** Payload admin route, used for the default disallow list. @default '/admin' */\n adminRoute?: string\n /** Payload API route, used for the default disallow list. @default '/api' */\n apiRoute?: string\n options?: RobotsOptions\n /** Absolute sitemap URL(s) advertised in the output. */\n sitemaps: string[]\n}\n\nexport const buildRobotsData = ({\n adminRoute = '/admin',\n apiRoute = '/api',\n options = {},\n sitemaps,\n}: BuildRobotsArgs): RobotsData => {\n const allowIndexing =\n options.allowIndexing ??\n (process.env.VERCEL_ENV\n ? process.env.VERCEL_ENV === 'production'\n : process.env.NODE_ENV === 'production')\n\n let data: RobotsData\n if (!allowIndexing) {\n data = { rules: [{ disallow: '/', userAgent: '*' }], sitemaps: [] }\n } else {\n const sitemapUrls = options.sitemaps ?? sitemaps\n const rules = options.rules ?? [\n {\n disallow: [`${adminRoute}/`, `${apiRoute}/`, ...(options.disallow ?? [])],\n userAgent: '*',\n },\n ]\n data = { rules: allowSitemaps(rules, sitemapUrls), sitemaps: sitemapUrls }\n }\n\n return options.transform ? options.transform(data) : data\n}\n\nexport const renderRobotsTxt = (data: RobotsData): string => {\n const blocks = data.rules.map((rule) => {\n const lines = [\n ...toArray(rule.userAgent).map((agent) => `User-agent: ${agent}`),\n ...toArray(rule.allow).map((path) => `Allow: ${path}`),\n ...toArray(rule.disallow).map((path) => `Disallow: ${path}`),\n ...(rule.crawlDelay !== undefined ? [`Crawl-delay: ${rule.crawlDelay}`] : []),\n ]\n return lines.join('\\n')\n })\n\n const footer = [\n ...(data.host ? [`Host: ${data.host}`] : []),\n ...data.sitemaps.map((url) => `Sitemap: ${url}`),\n ]\n\n return [...blocks, ...(footer.length ? [footer.join('\\n')] : [])].join('\\n\\n') + '\\n'\n}\n\n/**\n * robots.txt for any delivery mechanism. Defaults come from the plugin config;\n * `overrides` win field-by-field, and `transform` gets the final say. Pass\n * `request` so the default sitemap URL can derive its origin from the incoming\n * request when `siteUrl` isn't configured statically.\n */\nexport const generateRobotsTxt = async (\n configInput: Promise<SanitizedConfig> | SanitizedConfig,\n overrides?: { request?: SiteUrlContext['request'] } & RobotsOptions,\n): Promise<string> => {\n const config = await configInput\n const sitemapConfig = getSitemapConfig(config)\n const { request, ...overrideOptions } = overrides ?? {}\n const options = { ...sitemapConfig.robots, ...overrideOptions }\n const sitemaps = options.sitemaps ?? [`${sitemapConfig.siteUrl({ request })}/sitemap.xml`]\n\n return renderRobotsTxt(\n buildRobotsData({\n adminRoute: config.routes.admin,\n apiRoute: config.routes.api,\n options,\n sitemaps,\n }),\n )\n}\n","import type { ChangeFrequency, SitemapEntry } from '../types.js'\n\nconst XML_ESCAPES: Record<string, string> = {\n '\"': '&quot;',\n '&': '&amp;',\n \"'\": '&apos;',\n '<': '&lt;',\n '>': '&gt;',\n}\n\nexport const escapeXml = (value: string): string =>\n value.replace(/[&<>\"']/g, (char) => XML_ESCAPES[char])\n\nconst clampPriority = (priority: number): string => String(Math.min(1, Math.max(0, priority)))\n\nexport const buildUrlsetXml = (\n entries: SitemapEntry[],\n defaults?: { changeFreq?: ChangeFrequency; priority?: number },\n): string => {\n const body = entries\n .map((entry) => {\n const changefreq = entry.changefreq ?? defaults?.changeFreq\n const priority = entry.priority ?? defaults?.priority\n return [\n ' <url>',\n ` <loc>${escapeXml(entry.loc)}</loc>`,\n entry.lastmod ? ` <lastmod>${escapeXml(entry.lastmod)}</lastmod>` : null,\n changefreq ? ` <changefreq>${changefreq}</changefreq>` : null,\n priority !== undefined ? ` <priority>${clampPriority(priority)}</priority>` : null,\n ' </url>',\n ]\n .filter(Boolean)\n .join('\\n')\n })\n .join('\\n')\n\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\\n${body}\\n</urlset>\\n`\n}\n\nexport const buildSitemapIndexXml = (items: Array<{ lastmod?: string; loc: string }>): string => {\n const body = items\n .map((item) =>\n [\n ' <sitemap>',\n ` <loc>${escapeXml(item.loc)}</loc>`,\n item.lastmod ? ` <lastmod>${escapeXml(item.lastmod)}</lastmod>` : null,\n ' </sitemap>',\n ]\n .filter(Boolean)\n .join('\\n'),\n )\n .join('\\n')\n\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n<sitemapindex xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\\n${body}\\n</sitemapindex>\\n`\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@whatworks/payload-sitemap",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Payload plugin that generates chunked, lazily cached XML sitemaps with hook-driven invalidation and robots.txt helpers. Next.js + Vercel work out of the box; every layer is overridable for other stacks.",
5
5
  "license": "MIT",
6
6
  "type": "module",