payload-plugin-urls 0.9.2 → 0.9.3

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
@@ -81,10 +81,10 @@ which are merged into the generated relationship field. Collection `rootPage` va
81
81
  ### Root-pages global (`overrides`)
82
82
 
83
83
  `overrides` is an optional `Partial<GlobalConfig>` merged into the generated `root-pages` global
84
- after the plugin's defaults. Use it for **`label`**, **`access`**, extra **`hooks`**, **`admin`**, and
85
- other global options. Hook arrays are **concatenated**: the plugin's hooks run first, then yours.
86
- The **`fields`** key in `overrides` is ignored so the plugin keeps control of the relationship
87
- fields; customize those per field with `rootPages.fields[fieldName].overrides` instead.
84
+ after the plugin's defaults. Use it for **`label`**, **`access`**, extra **`hooks`**, **`admin`**,
85
+ and other global options. Hook arrays are **concatenated**: the plugin's hooks run first, then
86
+ yours. The **`fields`** key in `overrides` is ignored so the plugin keeps control of the
87
+ relationship fields; customize those per field with `rootPages.fields[fieldName].overrides` instead.
88
88
 
89
89
  ### Other options
90
90
 
@@ -106,7 +106,9 @@ when page, category, or root page relationships change.
106
106
  ## Exports
107
107
 
108
108
  The package default export is the same function as `payloadPluginUrls`. Import runtime helpers and
109
- TypeScript types from `payload-plugin-urls`.
109
+ TypeScript types from `payload-plugin-urls`. Import the Next.js App Router client `CmsLink` from the
110
+ [`payload-plugin-urls/next`](#nextjs-exports-payload-plugin-urlsnext) submodule (optional peer dependency on `next`
111
+ and React).
110
112
 
111
113
  ### `payloadPluginUrls`
112
114
 
@@ -170,8 +172,8 @@ interface ResolvePopulatedUrlArgs {
170
172
 
171
173
  ### `getDocumentLink`
172
174
 
173
- Builds a site path from a populated relationship. Reads `populatedUrl` from the related document when
174
- present; otherwise derives segments from plugin options and document shape. Throws if
175
+ Builds a site path from a populated relationship. Reads `populatedUrl` from the related document
176
+ when present; otherwise derives segments from plugin options and document shape. Throws if
175
177
  `reference.value` is a plain id string instead of an expanded doc.
176
178
 
177
179
  ```ts
@@ -209,6 +211,63 @@ interface GetDocumentLink {
209
211
  }
210
212
  ```
211
213
 
214
+ ### Next.js exports (`payload-plugin-urls/next`)
215
+
216
+ Client `CmsLink` for Payload-style link fields: resolves internal paths with
217
+ [`getDocumentLink`](#getdocumentlink), highlights the active destination with `usePathname`, handles
218
+ same-document `#hash` targets with configurable scroll offset (`hashScrollYOffset`), resets scroll near the viewport top on
219
+ client navigations (unless opening a new tab or modifier-click), and renders **`disabled`** links as
220
+ plain `span` elements instead of anchors.
221
+
222
+ Requires optional peer dependencies `next`, `react`, and `react-dom`.
223
+
224
+ ```tsx
225
+ "use client"
226
+
227
+ import type { ReactNode } from "react"
228
+ import type { PayloadPluginUrlsOptions, UrlDoc } from "payload-plugin-urls"
229
+ import { CmsLink } from "payload-plugin-urls/next"
230
+
231
+ const urlPluginOptions = {} satisfies PayloadPluginUrlsOptions
232
+
233
+ interface CmsRelationship {
234
+ relationTo: string
235
+ value: UrlDoc | string
236
+ }
237
+
238
+ export function NavLinkDemo(props: {
239
+ locale: string
240
+ siteUrl: string
241
+ type?: string | null
242
+ url?: string | null
243
+ reference?: CmsRelationship | null
244
+ newTab?: boolean | null
245
+ /** Resolve localized labels yourself; pass the result as children. */
246
+ children: ReactNode
247
+ }) {
248
+ const { locale, siteUrl, type, url, reference, newTab, children } = props
249
+
250
+ return (
251
+ <CmsLink
252
+ siteUrl={siteUrl}
253
+ urls={{ locale, options: urlPluginOptions }}
254
+ className="text-primary underline"
255
+ type={type ?? undefined}
256
+ url={url ?? undefined}
257
+ reference={reference && typeof reference.value === "object" ? reference : undefined}
258
+ newTab={newTab ?? undefined}
259
+ >
260
+ {children}
261
+ </CmsLink>
262
+ )
263
+ }
264
+ ```
265
+
266
+ - **`siteUrl`** — Public site base (`https://example.com`-style origin is enough); used with `URL`
267
+ and `usePathname` for same-origin and active-route checks.
268
+ - **`urls`** — `locale`, `options` (your plugin config), optional `baseUrl`, optional
269
+ `urlPrefixStrategy` (same meanings as [`getDocumentLink`](#getdocumentlink)).
270
+
212
271
  ### `getDocumentLinkBySlugs`
213
272
 
214
273
  Joins URL segments with an optional locale or `baseUrl` prefix. Lower-level helper used when you
@@ -270,7 +329,11 @@ the root-pages global changes. Used internally and available for custom workflow
270
329
 
271
330
  ```ts
272
331
  interface GetRootPageChangeSources {
273
- (current: RootPagesDoc, previous: RootPagesDoc | undefined, options: PayloadPluginUrlsOptions): UrlUpdateSource[]
332
+ (
333
+ current: RootPagesDoc,
334
+ previous: RootPagesDoc | undefined,
335
+ options: PayloadPluginUrlsOptions,
336
+ ): UrlUpdateSource[]
274
337
  }
275
338
  ```
276
339
 
@@ -0,0 +1,2 @@
1
+ var l=e=>e.replace(/\/$/,"").replace(/^\/?/,"/");function c(e){return(e?.at(-1)?.url??"").replace(/(^\/)|(\/$)/g,"")}function b(e,t){return{...t||{},...p(e)}}function x(e){let{populatedUrl:t,...n}=e;return n}function L(e){if(!(!e||typeof e!="object"||!("id"in e)))return typeof e.id=="string"?e.id:void 0}function C(e){if(typeof e=="string")return e;if(!(!e||typeof e!="object"||!("id"in e)))return typeof e.id=="string"?e.id:void 0}function k(e){return l(`/${e??""}`.replace(/\/+/g,"/"))}function w(e,t){if(!e||typeof e!="object"||!(t in e))return;let n=e;return typeof n[t]=="string"?n[t]:void 0}function D(e){return e._status==="draft"}function T(e){return e&&typeof e=="object"&&!Array.isArray(e)?e:{}}function h(e){let t=new Set;return e.filter(n=>{let o=f(n);return t.has(o)?!1:(t.add(o),!0)})}function f(e){switch(e.type){case"category":case"collection":case"page":return`${e.type}:${e.collection}:${e.id??""}`;case"rootPages":return`rootPages:${JSON.stringify(e.current)}:${JSON.stringify(e.previous)}`}}function p(e){return Object.fromEntries(Object.entries(e).filter(([,t])=>t!==void 0))}function i(e,t){let r={...y(t)??{defaultLocale:"en",locales:["en"]},...e.locales};return{...e,field:{name:"populatedUrl",...e.field},locales:{defaultLocale:r.defaultLocale??r.locales[0]??"en",locales:r.locales.length?r.locales:[r.defaultLocale??"en"]},rootPages:{slug:"root-pages",...e.rootPages,fields:e.rootPages?.fields??{indexPage:{isHomepage:!0,relationTo:"pages"}}}}}function u(e,t){return e.collections[t]}function P(e){return Object.entries(e.collections)}function S(e,t){return P(e).filter(([,n])=>n.category?.collection===t).map(([n])=>n)}function R(e){let t=i(e);return Object.keys(t.rootPages.fields)}function $(e){let t=i(e).rootPages.fields;return(Object.entries(t).find(([,o])=>o.isHomepage)??Object.entries(t).find(([o])=>o==="indexPage"))?.[0]??Object.keys(t)[0]??"indexPage"}function z(e,t){return i(e).rootPages.fields[t]}function y(e){let t=e?.localization||void 0,n=t?.locales?.map(o=>typeof o=="string"?o:o.code).filter(o=>!!o);if(n?.length)return{defaultLocale:t?.defaultLocale??n[0]??"en",locales:n}}function I(e,{baseUrl:t,locale:n,options:o,urlPrefixStrategy:r}){if(typeof e.value=="string")throw new Error("Reference value is a string");if(e.value.populatedUrl)return l(e.value.populatedUrl);let a=i(o),s=u(a,e.relationTo),g=s?.routeCollection??e.relationTo,d=U(s,e.value,r??s?.prefixStrategy);return m(d,{baseUrl:t,collection:g,locale:n,options:a})}function m(e,{baseUrl:t,locale:n,options:o}){let r=i(o),s=[...(t||(n===r.locales?.defaultLocale?"":n)).split("/"),...e].filter(Boolean);return l(`/${s.join("/")}`)}function E(e,t,n){let o=i(n).locales?.defaultLocale;return t===o?l(e):l(`/${t}${e}`)}function U(e,t,n){return e?.category?n==="rootPage"?[t.slug??""]:[O(t),t.slug??""]:e?.breadcrumbs?[c(t.breadcrumbs)||t.slug||""]:[t.slug??""]}function O(e){let t=e.categories;if(!Array.isArray(t)||t.length===0)return"";let o=t[0];if(!o||typeof o!="object"||typeof o=="string")return"";let r=o;return c(r.breadcrumbs)||(r.slug??"").replace(/(^\/)|(\/$)/g,"")}export{l as a,c as b,b as c,x as d,L as e,C as f,k as g,w as h,D as i,T as j,h as k,i as l,u as m,P as n,S as o,R as p,$ as q,z as r,I as s,m as t,E as u};
2
+ //# sourceMappingURL=chunk-OKNQKSNQ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils.ts","../src/options.ts","../src/link.ts"],"sourcesContent":["import type { Breadcrumb, UrlDoc, UrlUpdateSource } from \"./types\"\n\nconst withoutTrailingSlash = (path: string) => path.replace(/\\/$/, \"\").replace(/^\\/?/, \"/\")\n\nfunction getBreadcrumbsUrl(breadcrumbs: Breadcrumb[] | null | undefined) {\n const lastItem = breadcrumbs?.at(-1)\n const url = lastItem?.url ?? \"\"\n return url.replace(/(^\\/)|(\\/$)/g, \"\")\n}\n\nfunction mergeDoc<T extends object>(data: Partial<T>, originalDoc?: Partial<T>) {\n return {\n ...(originalDoc || {}),\n ...withoutUndefinedValues(data),\n } as T\n}\n\nfunction withoutPopulatedUrl<T extends object>(doc: T) {\n const { populatedUrl: _populatedUrl, ...rest } = doc as T & { populatedUrl?: unknown }\n return rest\n}\n\nfunction getDocumentId(doc: unknown) {\n if (!doc || typeof doc !== \"object\" || !(\"id\" in doc)) {\n return undefined\n }\n\n return typeof doc.id === \"string\" ? doc.id : undefined\n}\n\nfunction getRelationId(value: unknown) {\n if (typeof value === \"string\") {\n return value\n }\n\n if (!value || typeof value !== \"object\" || !(\"id\" in value)) {\n return undefined\n }\n\n return typeof value.id === \"string\" ? value.id : undefined\n}\n\nfunction normalizePath(path: string | undefined) {\n return withoutTrailingSlash(`/${path ?? \"\"}`.replace(/\\/+/g, \"/\"))\n}\n\nfunction getStringValue(value: unknown, key: \"populatedUrl\" | \"slug\") {\n if (!value || typeof value !== \"object\" || !(key in value)) {\n return undefined\n }\n\n const record = value as Record<\"populatedUrl\" | \"slug\", unknown>\n return typeof record[key] === \"string\" ? record[key] : undefined\n}\n\nfunction isDraftDoc(doc: UrlDoc) {\n return doc._status === \"draft\"\n}\n\nfunction getRecord(value: unknown) {\n return value && typeof value === \"object\" && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : {}\n}\n\nfunction dedupeSources<T extends UrlUpdateSource>(sources: T[]) {\n const seen = new Set<string>()\n\n return sources.filter((source) => {\n const key = sourceKey(source)\n if (seen.has(key)) {\n return false\n }\n seen.add(key)\n return true\n })\n}\n\nfunction sourceKey(source: UrlUpdateSource) {\n switch (source.type) {\n case \"category\":\n case \"collection\":\n case \"page\":\n return `${source.type}:${source.collection}:${source.id ?? \"\"}`\n case \"rootPages\":\n return `rootPages:${JSON.stringify(source.current)}:${JSON.stringify(source.previous)}`\n }\n}\n\nfunction withoutUndefinedValues<T extends object>(value: Partial<T>) {\n return Object.fromEntries(\n Object.entries(value).filter(([, entry]) => entry !== undefined),\n ) as Partial<T>\n}\n\nexport {\n getBreadcrumbsUrl,\n getRecord,\n dedupeSources,\n isDraftDoc,\n getStringValue,\n normalizePath,\n getRelationId,\n getDocumentId,\n withoutPopulatedUrl,\n mergeDoc,\n withoutTrailingSlash,\n}\n","import type {\n PayloadPluginConfig,\n PayloadPluginUrlsOptions,\n RootPageFieldOptions,\n UrlCollectionOptions,\n} from \"./types\"\n\nexport type NormalizedPayloadPluginUrlsOptions = PayloadPluginUrlsOptions & {\n collections: Record<string, UrlCollectionOptions>\n locales: {\n defaultLocale: string\n locales: string[]\n }\n rootPages: {\n slug: string\n label?: unknown\n fields: Record<string, RootPageFieldOptions>\n }\n}\n\nexport function normalizeOptions(\n options: PayloadPluginUrlsOptions,\n config?: PayloadPluginConfig,\n): NormalizedPayloadPluginUrlsOptions {\n const configLocales = getConfigLocales(config)\n const fallbackLocales = configLocales ?? { defaultLocale: \"en\", locales: [\"en\"] }\n const locales = {\n ...fallbackLocales,\n ...options.locales,\n }\n\n return {\n ...options,\n field: {\n name: \"populatedUrl\",\n ...options.field,\n },\n locales: {\n defaultLocale: locales.defaultLocale ?? locales.locales[0] ?? \"en\",\n locales: locales.locales.length ? locales.locales : [locales.defaultLocale ?? \"en\"],\n },\n rootPages: {\n slug: \"root-pages\",\n ...options.rootPages,\n fields: options.rootPages?.fields ?? {\n indexPage: {\n isHomepage: true,\n relationTo: \"pages\",\n },\n },\n },\n }\n}\n\nexport function getCollectionOptions(options: PayloadPluginUrlsOptions, collection: string) {\n return options.collections[collection]\n}\n\nexport function getCollectionEntries(options: PayloadPluginUrlsOptions) {\n return Object.entries(options.collections)\n}\n\nexport function getCollectionsForCategory(\n options: PayloadPluginUrlsOptions,\n categoryCollection: string,\n) {\n return getCollectionEntries(options)\n .filter(\n ([, collectionOptions]) => collectionOptions.category?.collection === categoryCollection,\n )\n .map(([collection]) => collection)\n}\n\nexport function getRootPageFieldNames(options: PayloadPluginUrlsOptions) {\n const normalizedOptions = normalizeOptions(options)\n return Object.keys(normalizedOptions.rootPages.fields)\n}\n\nexport function getHomepageRootPageField(options: PayloadPluginUrlsOptions) {\n const fields = normalizeOptions(options).rootPages.fields\n const homepageEntry =\n Object.entries(fields).find(([, field]) => field.isHomepage) ??\n Object.entries(fields).find(([fieldName]) => fieldName === \"indexPage\")\n\n return homepageEntry?.[0] ?? Object.keys(fields)[0] ?? \"indexPage\"\n}\n\nexport function getRootPageFieldOptions(options: PayloadPluginUrlsOptions, fieldName: string) {\n return normalizeOptions(options).rootPages.fields[fieldName]\n}\n\nfunction getConfigLocales(config: PayloadPluginConfig | undefined) {\n const localization = config?.localization || undefined\n const locales = localization?.locales\n ?.map((locale) => (typeof locale === \"string\" ? locale : locale.code))\n .filter((locale): locale is string => Boolean(locale))\n\n if (!locales?.length) {\n return undefined\n }\n\n return {\n defaultLocale: localization?.defaultLocale ?? locales[0] ?? \"en\",\n locales,\n }\n}\n","import { getCollectionOptions, normalizeOptions } from \"./options\"\nimport { getBreadcrumbsUrl, withoutTrailingSlash } from \"./utils\"\n\nimport type {\n GetDocumentLinkArgs,\n GetDocumentLinkContext,\n Locale,\n PayloadPluginUrlsOptions,\n UrlCollectionOptions,\n UrlDoc,\n UrlPrefixStrategy,\n} from \"./types\"\n\nexport function getDocumentLink(\n reference: GetDocumentLinkArgs,\n { baseUrl, locale, options, urlPrefixStrategy }: GetDocumentLinkContext,\n) {\n if (typeof reference.value === \"string\") {\n throw new Error(\"Reference value is a string\")\n }\n\n if (reference.value.populatedUrl) {\n return withoutTrailingSlash(reference.value.populatedUrl)\n }\n\n const normalizedOptions = normalizeOptions(options)\n const collectionOptions = getCollectionOptions(normalizedOptions, reference.relationTo)\n const routeCollection = collectionOptions?.routeCollection ?? reference.relationTo\n const slugs = getSlugsForCollection(\n collectionOptions,\n reference.value,\n urlPrefixStrategy ?? collectionOptions?.prefixStrategy,\n )\n\n return getDocumentLinkBySlugs(slugs, {\n baseUrl,\n collection: routeCollection,\n locale,\n options: normalizedOptions,\n })\n}\n\nexport function getDocumentLinkBySlugs(\n slugs: string[],\n {\n baseUrl,\n locale,\n options,\n }: {\n baseUrl?: string\n collection: string\n locale: Locale\n options: PayloadPluginUrlsOptions\n },\n) {\n const normalizedOptions = normalizeOptions(options)\n const prefix = baseUrl || (locale === normalizedOptions.locales?.defaultLocale ? \"\" : locale)\n const segments = [...prefix.split(\"/\"), ...slugs].filter(Boolean)\n return withoutTrailingSlash(`/${segments.join(\"/\")}`)\n}\n\nexport function withLocalePrefix(path: string, locale: Locale, options: PayloadPluginUrlsOptions) {\n const defaultLocale = normalizeOptions(options).locales?.defaultLocale\n if (locale === defaultLocale) {\n return withoutTrailingSlash(path)\n }\n return withoutTrailingSlash(`/${locale}${path}`)\n}\n\nfunction getSlugsForCollection(\n collectionOptions: UrlCollectionOptions | undefined,\n doc: UrlDoc,\n strategy?: UrlPrefixStrategy,\n) {\n if (collectionOptions?.category) {\n return strategy === \"rootPage\"\n ? [doc.slug ?? \"\"]\n : [firstRelatedCategoryPath(doc), doc.slug ?? \"\"]\n }\n\n if (collectionOptions?.breadcrumbs) {\n return [getBreadcrumbsUrl(doc.breadcrumbs) || doc.slug || \"\"]\n }\n\n return [doc.slug ?? \"\"]\n}\n\nfunction firstRelatedCategoryPath(doc: UrlDoc) {\n const categories = doc.categories\n if (!Array.isArray(categories) || categories.length === 0) {\n return \"\"\n }\n\n const categoryItems = categories as unknown[]\n const first = categoryItems[0]\n if (!first || typeof first !== \"object\" || typeof first === \"string\") {\n return \"\"\n }\n\n const categoryDoc = first as UrlDoc\n return (\n getBreadcrumbsUrl(categoryDoc.breadcrumbs) ||\n (categoryDoc.slug ?? \"\").replace(/(^\\/)|(\\/$)/g, \"\")\n )\n}\n"],"mappings":"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","names":["withoutTrailingSlash","path","getBreadcrumbsUrl","breadcrumbs","mergeDoc","data","originalDoc","withoutUndefinedValues","withoutPopulatedUrl","doc","_populatedUrl","rest","getDocumentId","getRelationId","value","normalizePath","getStringValue","key","record","isDraftDoc","getRecord","dedupeSources","sources","seen","source","sourceKey","entry","normalizeOptions","options","config","locales","getConfigLocales","getCollectionOptions","collection","getCollectionEntries","getCollectionsForCategory","categoryCollection","collectionOptions","getRootPageFieldNames","normalizedOptions","getHomepageRootPageField","fields","field","fieldName","getRootPageFieldOptions","localization","locale","getDocumentLink","reference","baseUrl","locale","options","urlPrefixStrategy","withoutTrailingSlash","normalizedOptions","normalizeOptions","collectionOptions","getCollectionOptions","routeCollection","slugs","getSlugsForCollection","getDocumentLinkBySlugs","segments","withLocalePrefix","path","defaultLocale","doc","strategy","firstRelatedCategoryPath","getBreadcrumbsUrl","categories","first","categoryDoc"]}
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- var f=o=>o.replace(/\/$/,"").replace(/^\/?/,"/");function P(o){return(o?.at(-1)?.url??"").replace(/(^\/)|(\/$)/g,"")}function v(o,e){return{...e||{},...oo(o)}}function S(o){let{populatedUrl:e,...t}=o;return t}function z(o){if(!(!o||typeof o!="object"||!("id"in o)))return typeof o.id=="string"?o.id:void 0}function U(o){if(typeof o=="string")return o;if(!(!o||typeof o!="object"||!("id"in o)))return typeof o.id=="string"?o.id:void 0}function h(o){return f(`/${o??""}`.replace(/\/+/g,"/"))}function k(o,e){if(!o||typeof o!="object"||!(e in o))return;let t=o;return typeof t[e]=="string"?t[e]:void 0}function w(o){return o._status==="draft"}function I(o){return o&&typeof o=="object"&&!Array.isArray(o)?o:{}}function $(o){let e=new Set;return o.filter(t=>{let n=q(t);return e.has(n)?!1:(e.add(n),!0)})}function q(o){switch(o.type){case"category":case"collection":case"page":return`${o.type}:${o.collection}:${o.id??""}`;case"rootPages":return`rootPages:${JSON.stringify(o.current)}:${JSON.stringify(o.previous)}`}}function oo(o){return Object.fromEntries(Object.entries(o).filter(([,e])=>e!==void 0))}function A(o={collections:{}}){return{name:o.field?.name??"populatedUrl",type:"text",label:!1,localized:!0,...o.field?.overrides??{},admin:{hidden:!0,...I(o.field?.overrides?.admin)}}}function c(o,e){let r={...eo(e)??{defaultLocale:"en",locales:["en"]},...o.locales};return{...o,field:{name:"populatedUrl",...o.field},locales:{defaultLocale:r.defaultLocale??r.locales[0]??"en",locales:r.locales.length?r.locales:[r.defaultLocale??"en"]},rootPages:{slug:"root-pages",...o.rootPages,fields:o.rootPages?.fields??{indexPage:{isHomepage:!0,relationTo:"pages"}}}}}function d(o,e){return o.collections[e]}function H(o){return Object.entries(o.collections)}function L(o,e){return H(o).filter(([,t])=>t.category?.collection===e).map(([t])=>t)}function R(o){let e=c(o);return Object.keys(e.rootPages.fields)}function D(o){let e=c(o).rootPages.fields;return(Object.entries(e).find(([,n])=>n.isHomepage)??Object.entries(e).find(([n])=>n==="indexPage"))?.[0]??Object.keys(e)[0]??"indexPage"}function y(o,e){return c(o).rootPages.fields[e]}function eo(o){let e=o?.localization||void 0,t=e?.locales?.map(n=>typeof n=="string"?n:n.code).filter(n=>!!n);if(t?.length)return{defaultLocale:e?.defaultLocale??t[0]??"en",locales:t}}function O(o,{baseUrl:e,locale:t,options:n,urlPrefixStrategy:r}){if(typeof o.value=="string")throw new Error("Reference value is a string");if(o.value.populatedUrl)return f(o.value.populatedUrl);let l=c(n),a=d(l,o.relationTo),i=a?.routeCollection??o.relationTo,s=to(a,o.value,r??a?.prefixStrategy);return B(s,{baseUrl:e,collection:i,locale:t,options:l})}function B(o,{baseUrl:e,locale:t,options:n}){let r=c(n),a=[...(e||(t===r.locales?.defaultLocale?"":t)).split("/"),...o].filter(Boolean);return f(`/${a.join("/")}`)}function C(o,e,t){let n=c(t).locales?.defaultLocale;return e===n?f(o):f(`/${e}${o}`)}function to(o,e,t){return o?.category?t==="rootPage"?[e.slug??""]:[no(e),e.slug??""]:o?.breadcrumbs?[P(e.breadcrumbs)||e.slug||""]:[e.slug??""]}function no(o){let e=o.categories;if(!Array.isArray(e)||e.length===0)return"";let n=e[0];if(!n||typeof n!="object"||typeof n=="string")return"";let r=n;return P(r.breadcrumbs)||(r.slug??"").replace(/(^\/)|(\/$)/g,"")}async function m({collection:o,data:e,locale:t,options:n,originalDoc:r,payload:l,rootPages:a}){let i=c(n),s=d(i,o);if(!s)return;let u=v(e,r),g=D(i);if(s.breadcrumbs&&!s.rootPage){let p=await _({field:g,locale:t,payload:l,rootPages:a}),Y=z(p);if(u.id&&Y===u.id)return C("/",t,i);let x=h(P(u.breadcrumbs)),F=h(P(p?.breadcrumbs)),Z=F&&x.startsWith(`${F}/`)?h(x.slice(F.length)):x;return C(Z||`/${u.slug??""}`,t,i)}let b=await ro({collectionOptions:s,locale:t,options:i,payload:l,rootPages:a});if(s.category){let p=await lo({categories:u[s.category.field??"categories"],collection:s.category.collection,locale:t,payload:l});return O({relationTo:o,value:{...S(u),[s.category.field??"categories"]:p,categories:p}},{baseUrl:b,locale:t,options:i})}return O({relationTo:o,value:S(u)},{baseUrl:b,locale:t,options:i})}async function ro({collectionOptions:o,locale:e,options:t,payload:n,rootPages:r}){if(!o.rootPage)return;let l=o.rootPage,i=y(t,l)?.relationTo??"pages",s=await _({collection:i,field:l,locale:e,payload:n,rootPages:r});if(s)return typeof s.populatedUrl=="string"&&s.populatedUrl?N(s.populatedUrl,e,t):i!=="pages"?N(O({relationTo:i,value:s},{locale:e,options:t}),e,t):m({collection:i,data:{},locale:e,options:t,originalDoc:s,payload:n,rootPages:r})}function N(o,e,t){let n=c(t);return e===n.locales.defaultLocale||o===`/${e}`||o.startsWith(`/${e}/`)?o:C(o,e,n)}async function _({collection:o="pages",field:e,locale:t,payload:n,rootPages:r}){let l=r[e];return l?typeof l!="string"?l:await n?.findByID?.({collection:o,id:l,depth:0,locale:t,select:{id:!0,slug:!0,populatedUrl:!0,breadcrumbs:!0}}):void 0}async function lo({categories:o,collection:e,locale:t,payload:n}){return Array.isArray(o)?Promise.all(o.map(r=>typeof r!="string"?Promise.resolve(r):n?.findByID?.({collection:e,id:r,depth:2,locale:t})??Promise.resolve(r))):[]}function E(o){return async({job:e,req:t})=>{let n=c(o),r=e.input?.sources??[];for(let l of n.locales?.locales??[]){let a=await t.payload.findGlobal?.({slug:n.rootPages?.slug??"root-pages",depth:2,locale:l});if(a)for(let i of io(r,n))switch(i.type){case"category":await T({collection:i.collection,locale:l,options:n,payload:t.payload,rootPages:a});for(let s of L(n,i.collection))await T({collection:s,locale:l,options:n,payload:t.payload,rootPages:a});break;case"collection":case"page":await T({collection:i.collection,locale:l,options:n,payload:t.payload,rootPages:a});break;case"rootPages":break}}}}function j(o,e){let t=k(o,"populatedUrl"),n=k(e,"populatedUrl");return t&&n?t!==n:k(o,"slug")!==k(e,"slug")}function V(o,e,t){let n=c(t),r=[],l=D(n),a=y(n,l)?.relationTo??"pages",i=U(o[l]),s=U(e?.[l]);i!==s&&(i&&r.push({type:"page",collection:a,id:i}),s&&r.push({type:"page",collection:a,id:s}));for(let[u,g]of H(n)){if(!g.rootPage)continue;let b=U(o[g.rootPage]),p=U(e?.[g.rootPage]);b!==p&&r.push({type:"collection",collection:u})}return $(r)}function G(o,e){let t={};for(let n of R(e))t[n]=o?.[n];return t}function io(o,e){return o.flatMap(t=>t.type!=="rootPages"?[t]:V(t.current,t.previous,e))}async function T({collection:o,locale:e,options:t,payload:n,rootPages:r}){let l=1;for(;;){let a=await n.find?.({collection:o,depth:2,draft:!1,limit:100,locale:e,overrideAccess:!0,page:l,pagination:!0});if(!a)return;for(let i of a.docs){let s=i;if(!s.id||w(s))continue;let u=await m({collection:o,data:{},locale:e,options:t,originalDoc:s,payload:n,rootPages:r});!u||s.populatedUrl===u||await n.update?.({collection:o,id:s.id,locale:e,overrideAccess:!0,data:{[t.field?.name??"populatedUrl"]:u},context:{disablePopulateUrl:!0,disableUrlUpdates:!0}})}if(!a.nextPage)return;l=a.nextPage}}function W(o){return async({collection:e,context:t,data:n={},originalDoc:r,req:l})=>{let a=l.locale;if(!a||a==="all"||t?.disablePopulateUrl||l.context?.disablePopulateUrl)return n;let i=await l.payload.findGlobal?.({slug:c(o).rootPages?.slug??"root-pages",depth:2,locale:a});if(!i)return n;let s=await m({collection:e?.slug??"",data:n,locale:a,options:o,originalDoc:r,payload:l.payload,rootPages:i});return s&&(n[o.field?.name??"populatedUrl"]=s),n}}function M(o){return async({collection:e,doc:t,previousDoc:n,req:r})=>{let l=t,a=n;if(r.context?.disableUrlUpdates||!l||w(l)||!j(l,a))return l;let i=d(o,e?.slug??"");if(!i)return l;let s=e?.slug??"",g=L(o,s).length>0?{type:"category",collection:s,id:l.id}:{type:i.breadcrumbs&&!i.rootPage?"page":"collection",collection:s,id:l.id};return await r.payload.jobs?.queue?.({workflow:"update-urls",input:{sources:[g]}}),l}}function J(o){return async({doc:e,previousDoc:t,req:n})=>{let r=e,l=t;return n.context?.disableUrlUpdates||await n.payload.jobs?.queue?.({workflow:"update-urls",input:{sources:[{type:"rootPages",current:G(r,o),previous:G(l,o)}]}}),r}}var X=o=>o?e=>{let t=c(o,e),n=(e.collections??[]).map(r=>ao(r,t));return{...e,collections:n,globals:[...e.globals??[],so(t)],jobs:{...e.jobs??{},workflows:[...e.jobs?.workflows??[],{slug:"update-urls",handler:E(t)}]}}}:e=>e;function ao(o,e){if(!d(e,o.slug))return o;let n=e.field?.name??"populatedUrl",r=o.fields.some(a=>"name"in a&&a.name===n)?o.fields:[...o.fields,A(e)],l=o.hooks??{};return{...o,defaultPopulate:{...o.defaultPopulate??{},[n]:!0},fields:r,hooks:{...l,beforeChange:[...l.beforeChange??[],W(e)],afterChange:[...l.afterChange??[],M(e)]}}}function so(o){let e=c(o).rootPages,t={slug:e?.slug??"root-pages",label:e?.label??"Root pages",fields:R(o).map(r=>co(r,o)),hooks:{afterChange:[J(o)]}},n=o.overrides;return n?go(t,n):t}function co(o,e){let t=y(e,o),n=t?.overrides??{},{name:r,type:l,hasMany:a,relationTo:i,...s}=n;return{name:o,type:"relationship",relationTo:t?.relationTo??"pages",hasMany:!1,admin:{width:"50%"},...s}}function K(o){if(!Array.isArray(o))return[];let e=[];for(let t of o)e.push(t);return e}function uo(o,e){if(!e)return o;if(!o)return e;let t=o,n=e,r={...t};for(let l of Object.keys(n)){let a=t[l],i=n[l];Array.isArray(a)||Array.isArray(i)?r[l]=[...K(a),...K(i)]:i!==void 0&&(r[l]=i)}return r}function Q(o,e){return e?o?{...o,...e}:e:o}function go(o,e){let{hooks:t,access:n,admin:r,fields:l,...a}=e,i={...o,...a};return n&&(i.access=Q(o.access,n)),r&&(i.admin=Q(o.admin,r)),(t||o.hooks)&&(i.hooks=uo(o.hooks,t)),i}export{X as default,P as getBreadcrumbsUrl,O as getDocumentLink,B as getDocumentLinkBySlugs,V as getRootPageChangeSources,j as hasUrlPathChanged,X as payloadPluginUrls,A as populatedUrlField,m as resolvePopulatedUrl,C as withLocalePrefix,f as withoutTrailingSlash};
1
+ import{a as Y,b as C,c as S,d as v,e as I,f as m,g as b,h as y,i as R,j as z,k as T,l as d,m as g,n as B,o as O,p as w,q as D,r as f,s as U,t as Z,u as k}from"./chunk-OKNQKSNQ.js";function F(o={collections:{}}){return{name:o.field?.name??"populatedUrl",type:"text",label:!1,localized:!0,...o.field?.overrides??{},admin:{hidden:!0,...z(o.field?.overrides?.admin)}}}async function P({collection:o,data:e,locale:t,options:r,originalDoc:a,payload:n,rootPages:s}){let l=d(r),i=g(l,o);if(!i)return;let c=S(e,a),u=D(l);if(i.breadcrumbs&&!i.rootPage){let p=await N({field:u,locale:t,payload:n,rootPages:s}),Q=I(p);if(c.id&&Q===c.id)return k("/",t,l);let L=b(C(c.breadcrumbs)),x=b(C(p?.breadcrumbs)),X=x&&L.startsWith(`${x}/`)?b(L.slice(x.length)):L;return k(X||`/${c.slug??""}`,t,l)}let h=await q({collectionOptions:i,locale:t,options:l,payload:n,rootPages:s});if(i.category){let p=await oo({categories:c[i.category.field??"categories"],collection:i.category.collection,locale:t,payload:n});return U({relationTo:o,value:{...v(c),[i.category.field??"categories"]:p,categories:p}},{baseUrl:h,locale:t,options:l})}return U({relationTo:o,value:v(c)},{baseUrl:h,locale:t,options:l})}async function q({collectionOptions:o,locale:e,options:t,payload:r,rootPages:a}){if(!o.rootPage)return;let n=o.rootPage,l=f(t,n)?.relationTo??"pages",i=await N({collection:l,field:n,locale:e,payload:r,rootPages:a});if(i)return typeof i.populatedUrl=="string"&&i.populatedUrl?j(i.populatedUrl,e,t):l!=="pages"?j(U({relationTo:l,value:i},{locale:e,options:t}),e,t):P({collection:l,data:{},locale:e,options:t,originalDoc:i,payload:r,rootPages:a})}function j(o,e,t){let r=d(t);return e===r.locales.defaultLocale||o===`/${e}`||o.startsWith(`/${e}/`)?o:k(o,e,r)}async function N({collection:o="pages",field:e,locale:t,payload:r,rootPages:a}){let n=a[e];return n?typeof n!="string"?n:await r?.findByID?.({collection:o,id:n,depth:0,locale:t,select:{id:!0,slug:!0,populatedUrl:!0,breadcrumbs:!0}}):void 0}async function oo({categories:o,collection:e,locale:t,payload:r}){return Array.isArray(o)?Promise.all(o.map(a=>typeof a!="string"?Promise.resolve(a):r?.findByID?.({collection:e,id:a,depth:2,locale:t})??Promise.resolve(a))):[]}function W(o){return async({job:e,req:t})=>{let r=d(o),a=e.input?.sources??[];for(let n of r.locales?.locales??[]){let s=await t.payload.findGlobal?.({slug:r.rootPages?.slug??"root-pages",depth:2,locale:n});if(s)for(let l of eo(a,r))switch(l.type){case"category":await H({collection:l.collection,locale:n,options:r,payload:t.payload,rootPages:s});for(let i of O(r,l.collection))await H({collection:i,locale:n,options:r,payload:t.payload,rootPages:s});break;case"collection":case"page":await H({collection:l.collection,locale:n,options:r,payload:t.payload,rootPages:s});break;case"rootPages":break}}}}function A(o,e){let t=y(o,"populatedUrl"),r=y(e,"populatedUrl");return t&&r?t!==r:y(o,"slug")!==y(e,"slug")}function _(o,e,t){let r=d(t),a=[],n=D(r),s=f(r,n)?.relationTo??"pages",l=m(o[n]),i=m(e?.[n]);l!==i&&(l&&a.push({type:"page",collection:s,id:l}),i&&a.push({type:"page",collection:s,id:i}));for(let[c,u]of B(r)){if(!u.rootPage)continue;let h=m(o[u.rootPage]),p=m(e?.[u.rootPage]);h!==p&&a.push({type:"collection",collection:c})}return T(a)}function G(o,e){let t={};for(let r of w(e))t[r]=o?.[r];return t}function eo(o,e){return o.flatMap(t=>t.type!=="rootPages"?[t]:_(t.current,t.previous,e))}async function H({collection:o,locale:e,options:t,payload:r,rootPages:a}){let n=1;for(;;){let s=await r.find?.({collection:o,depth:2,draft:!1,limit:100,locale:e,overrideAccess:!0,page:n,pagination:!0});if(!s)return;for(let l of s.docs){let i=l;if(!i.id||R(i))continue;let c=await P({collection:o,data:{},locale:e,options:t,originalDoc:i,payload:r,rootPages:a});!c||i.populatedUrl===c||await r.update?.({collection:o,id:i.id,locale:e,overrideAccess:!0,data:{[t.field?.name??"populatedUrl"]:c},context:{disablePopulateUrl:!0,disableUrlUpdates:!0}})}if(!s.nextPage)return;n=s.nextPage}}function M(o){return async({collection:e,context:t,data:r={},originalDoc:a,req:n})=>{let s=n.locale;if(!s||s==="all"||t?.disablePopulateUrl||n.context?.disablePopulateUrl)return r;let l=await n.payload.findGlobal?.({slug:d(o).rootPages?.slug??"root-pages",depth:2,locale:s});if(!l)return r;let i=await P({collection:e?.slug??"",data:r,locale:s,options:o,originalDoc:a,payload:n.payload,rootPages:l});return i&&(r[o.field?.name??"populatedUrl"]=i),r}}function $(o){return async({collection:e,doc:t,previousDoc:r,req:a})=>{let n=t,s=r;if(a.context?.disableUrlUpdates||!n||R(n)||!A(n,s))return n;let l=g(o,e?.slug??"");if(!l)return n;let i=e?.slug??"",u=O(o,i).length>0?{type:"category",collection:i,id:n.id}:{type:l.breadcrumbs&&!l.rootPage?"page":"collection",collection:i,id:n.id};return await a.payload.jobs?.queue?.({workflow:"update-urls",input:{sources:[u]}}),n}}function V(o){return async({doc:e,previousDoc:t,req:r})=>{let a=e,n=t;return r.context?.disableUrlUpdates||await r.payload.jobs?.queue?.({workflow:"update-urls",input:{sources:[{type:"rootPages",current:G(a,o),previous:G(n,o)}]}}),a}}var K=o=>o?e=>{let t=d(o,e),r=(e.collections??[]).map(a=>to(a,t));return{...e,collections:r,globals:[...e.globals??[],ro(t)],jobs:{...e.jobs??{},workflows:[...e.jobs?.workflows??[],{slug:"update-urls",handler:W(t)}]}}}:e=>e;function to(o,e){if(!g(e,o.slug))return o;let r=e.field?.name??"populatedUrl",a=o.fields.some(s=>"name"in s&&s.name===r)?o.fields:[...o.fields,F(e)],n=o.hooks??{};return{...o,defaultPopulate:{...o.defaultPopulate??{},[r]:!0},fields:a,hooks:{...n,beforeChange:[...n.beforeChange??[],M(e)],afterChange:[...n.afterChange??[],$(e)]}}}function ro(o){let e=d(o).rootPages,t={slug:e?.slug??"root-pages",label:e?.label??"Root pages",fields:w(o).map(a=>no(a,o)),hooks:{afterChange:[V(o)]}},r=o.overrides;return r?lo(t,r):t}function no(o,e){let t=f(e,o),r=t?.overrides??{},{name:a,type:n,hasMany:s,relationTo:l,...i}=r;return{name:o,type:"relationship",relationTo:t?.relationTo??"pages",hasMany:!1,admin:{width:"50%"},...i}}function E(o){if(!Array.isArray(o))return[];let e=[];for(let t of o)e.push(t);return e}function ao(o,e){if(!e)return o;if(!o)return e;let t=o,r=e,a={...t};for(let n of Object.keys(r)){let s=t[n],l=r[n];Array.isArray(s)||Array.isArray(l)?a[n]=[...E(s),...E(l)]:l!==void 0&&(a[n]=l)}return a}function J(o,e){return e?o?{...o,...e}:e:o}function lo(o,e){let{hooks:t,access:r,admin:a,fields:n,...s}=e,l={...o,...s};return r&&(l.access=J(o.access,r)),a&&(l.admin=J(o.admin,a)),(t||o.hooks)&&(l.hooks=ao(o.hooks,t)),l}export{K as default,C as getBreadcrumbsUrl,U as getDocumentLink,Z as getDocumentLinkBySlugs,_ as getRootPageChangeSources,A as hasUrlPathChanged,K as payloadPluginUrls,F as populatedUrlField,P as resolvePopulatedUrl,k as withLocalePrefix,Y as withoutTrailingSlash};
2
2
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils.ts","../src/field.ts","../src/options.ts","../src/link.ts","../src/resolver.ts","../src/update-urls.ts","../src/hooks.ts","../src/plugin.ts"],"sourcesContent":["import type { Breadcrumb, UrlDoc, UrlUpdateSource } from \"./types\"\n\nconst withoutTrailingSlash = (path: string) => path.replace(/\\/$/, \"\").replace(/^\\/?/, \"/\")\n\nfunction getBreadcrumbsUrl(breadcrumbs: Breadcrumb[] | null | undefined) {\n const lastItem = breadcrumbs?.at(-1)\n const url = lastItem?.url ?? \"\"\n return url.replace(/(^\\/)|(\\/$)/g, \"\")\n}\n\nfunction mergeDoc<T extends object>(data: Partial<T>, originalDoc?: Partial<T>) {\n return {\n ...(originalDoc || {}),\n ...withoutUndefinedValues(data),\n } as T\n}\n\nfunction withoutPopulatedUrl<T extends object>(doc: T) {\n const { populatedUrl: _populatedUrl, ...rest } = doc as T & { populatedUrl?: unknown }\n return rest\n}\n\nfunction getDocumentId(doc: unknown) {\n if (!doc || typeof doc !== \"object\" || !(\"id\" in doc)) {\n return undefined\n }\n\n return typeof doc.id === \"string\" ? doc.id : undefined\n}\n\nfunction getRelationId(value: unknown) {\n if (typeof value === \"string\") {\n return value\n }\n\n if (!value || typeof value !== \"object\" || !(\"id\" in value)) {\n return undefined\n }\n\n return typeof value.id === \"string\" ? value.id : undefined\n}\n\nfunction normalizePath(path: string | undefined) {\n return withoutTrailingSlash(`/${path ?? \"\"}`.replace(/\\/+/g, \"/\"))\n}\n\nfunction getStringValue(value: unknown, key: \"populatedUrl\" | \"slug\") {\n if (!value || typeof value !== \"object\" || !(key in value)) {\n return undefined\n }\n\n const record = value as Record<\"populatedUrl\" | \"slug\", unknown>\n return typeof record[key] === \"string\" ? record[key] : undefined\n}\n\nfunction isDraftDoc(doc: UrlDoc) {\n return doc._status === \"draft\"\n}\n\nfunction getRecord(value: unknown) {\n return value && typeof value === \"object\" && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : {}\n}\n\nfunction dedupeSources<T extends UrlUpdateSource>(sources: T[]) {\n const seen = new Set<string>()\n\n return sources.filter((source) => {\n const key = sourceKey(source)\n if (seen.has(key)) {\n return false\n }\n seen.add(key)\n return true\n })\n}\n\nfunction sourceKey(source: UrlUpdateSource) {\n switch (source.type) {\n case \"category\":\n case \"collection\":\n case \"page\":\n return `${source.type}:${source.collection}:${source.id ?? \"\"}`\n case \"rootPages\":\n return `rootPages:${JSON.stringify(source.current)}:${JSON.stringify(source.previous)}`\n }\n}\n\nfunction withoutUndefinedValues<T extends object>(value: Partial<T>) {\n return Object.fromEntries(\n Object.entries(value).filter(([, entry]) => entry !== undefined),\n ) as Partial<T>\n}\n\nexport {\n getBreadcrumbsUrl,\n getRecord,\n dedupeSources,\n isDraftDoc,\n getStringValue,\n normalizePath,\n getRelationId,\n getDocumentId,\n withoutPopulatedUrl,\n mergeDoc,\n withoutTrailingSlash,\n}\n","import { getRecord } from \"./utils\"\n\nimport type { PayloadPluginUrlsOptions } from \"./types\"\nimport type { Field } from \"payload\"\n\nexport function populatedUrlField(options: PayloadPluginUrlsOptions = { collections: {} }): Field {\n const fieldName = options.field?.name ?? \"populatedUrl\"\n\n return {\n name: fieldName,\n type: \"text\",\n label: false,\n localized: true,\n ...(options.field?.overrides ?? {}),\n admin: {\n hidden: true,\n ...getRecord(options.field?.overrides?.admin),\n },\n } as Field\n}\n","import type {\n PayloadPluginConfig,\n PayloadPluginUrlsOptions,\n RootPageFieldOptions,\n UrlCollectionOptions,\n} from \"./types\"\n\nexport type NormalizedPayloadPluginUrlsOptions = PayloadPluginUrlsOptions & {\n collections: Record<string, UrlCollectionOptions>\n locales: {\n defaultLocale: string\n locales: string[]\n }\n rootPages: {\n slug: string\n label?: unknown\n fields: Record<string, RootPageFieldOptions>\n }\n}\n\nexport function normalizeOptions(\n options: PayloadPluginUrlsOptions,\n config?: PayloadPluginConfig,\n): NormalizedPayloadPluginUrlsOptions {\n const configLocales = getConfigLocales(config)\n const fallbackLocales = configLocales ?? { defaultLocale: \"en\", locales: [\"en\"] }\n const locales = {\n ...fallbackLocales,\n ...options.locales,\n }\n\n return {\n ...options,\n field: {\n name: \"populatedUrl\",\n ...options.field,\n },\n locales: {\n defaultLocale: locales.defaultLocale ?? locales.locales[0] ?? \"en\",\n locales: locales.locales.length ? locales.locales : [locales.defaultLocale ?? \"en\"],\n },\n rootPages: {\n slug: \"root-pages\",\n ...options.rootPages,\n fields: options.rootPages?.fields ?? {\n indexPage: {\n isHomepage: true,\n relationTo: \"pages\",\n },\n },\n },\n }\n}\n\nexport function getCollectionOptions(options: PayloadPluginUrlsOptions, collection: string) {\n return options.collections[collection]\n}\n\nexport function getCollectionEntries(options: PayloadPluginUrlsOptions) {\n return Object.entries(options.collections)\n}\n\nexport function getCollectionsForCategory(\n options: PayloadPluginUrlsOptions,\n categoryCollection: string,\n) {\n return getCollectionEntries(options)\n .filter(\n ([, collectionOptions]) => collectionOptions.category?.collection === categoryCollection,\n )\n .map(([collection]) => collection)\n}\n\nexport function getRootPageFieldNames(options: PayloadPluginUrlsOptions) {\n const normalizedOptions = normalizeOptions(options)\n return Object.keys(normalizedOptions.rootPages.fields)\n}\n\nexport function getHomepageRootPageField(options: PayloadPluginUrlsOptions) {\n const fields = normalizeOptions(options).rootPages.fields\n const homepageEntry =\n Object.entries(fields).find(([, field]) => field.isHomepage) ??\n Object.entries(fields).find(([fieldName]) => fieldName === \"indexPage\")\n\n return homepageEntry?.[0] ?? Object.keys(fields)[0] ?? \"indexPage\"\n}\n\nexport function getRootPageFieldOptions(options: PayloadPluginUrlsOptions, fieldName: string) {\n return normalizeOptions(options).rootPages.fields[fieldName]\n}\n\nfunction getConfigLocales(config: PayloadPluginConfig | undefined) {\n const localization = config?.localization || undefined\n const locales = localization?.locales\n ?.map((locale) => (typeof locale === \"string\" ? locale : locale.code))\n .filter((locale): locale is string => Boolean(locale))\n\n if (!locales?.length) {\n return undefined\n }\n\n return {\n defaultLocale: localization?.defaultLocale ?? locales[0] ?? \"en\",\n locales,\n }\n}\n","import { getCollectionOptions, normalizeOptions } from \"./options\"\nimport { getBreadcrumbsUrl, withoutTrailingSlash } from \"./utils\"\n\nimport type {\n GetDocumentLinkArgs,\n GetDocumentLinkContext,\n Locale,\n PayloadPluginUrlsOptions,\n UrlCollectionOptions,\n UrlDoc,\n UrlPrefixStrategy,\n} from \"./types\"\n\nexport function getDocumentLink(\n reference: GetDocumentLinkArgs,\n { baseUrl, locale, options, urlPrefixStrategy }: GetDocumentLinkContext,\n) {\n if (typeof reference.value === \"string\") {\n throw new Error(\"Reference value is a string\")\n }\n\n if (reference.value.populatedUrl) {\n return withoutTrailingSlash(reference.value.populatedUrl)\n }\n\n const normalizedOptions = normalizeOptions(options)\n const collectionOptions = getCollectionOptions(normalizedOptions, reference.relationTo)\n const routeCollection = collectionOptions?.routeCollection ?? reference.relationTo\n const slugs = getSlugsForCollection(\n collectionOptions,\n reference.value,\n urlPrefixStrategy ?? collectionOptions?.prefixStrategy,\n )\n\n return getDocumentLinkBySlugs(slugs, {\n baseUrl,\n collection: routeCollection,\n locale,\n options: normalizedOptions,\n })\n}\n\nexport function getDocumentLinkBySlugs(\n slugs: string[],\n {\n baseUrl,\n locale,\n options,\n }: {\n baseUrl?: string\n collection: string\n locale: Locale\n options: PayloadPluginUrlsOptions\n },\n) {\n const normalizedOptions = normalizeOptions(options)\n const prefix = baseUrl || (locale === normalizedOptions.locales?.defaultLocale ? \"\" : locale)\n const segments = [...prefix.split(\"/\"), ...slugs].filter(Boolean)\n return withoutTrailingSlash(`/${segments.join(\"/\")}`)\n}\n\nexport function withLocalePrefix(path: string, locale: Locale, options: PayloadPluginUrlsOptions) {\n const defaultLocale = normalizeOptions(options).locales?.defaultLocale\n if (locale === defaultLocale) {\n return withoutTrailingSlash(path)\n }\n return withoutTrailingSlash(`/${locale}${path}`)\n}\n\nfunction getSlugsForCollection(\n collectionOptions: UrlCollectionOptions | undefined,\n doc: UrlDoc,\n strategy?: UrlPrefixStrategy,\n) {\n if (collectionOptions?.category) {\n return strategy === \"rootPage\"\n ? [doc.slug ?? \"\"]\n : [firstRelatedCategoryPath(doc), doc.slug ?? \"\"]\n }\n\n if (collectionOptions?.breadcrumbs) {\n return [getBreadcrumbsUrl(doc.breadcrumbs) || doc.slug || \"\"]\n }\n\n return [doc.slug ?? \"\"]\n}\n\nfunction firstRelatedCategoryPath(doc: UrlDoc) {\n const categories = doc.categories\n if (!Array.isArray(categories) || categories.length === 0) {\n return \"\"\n }\n\n const categoryItems = categories as unknown[]\n const first = categoryItems[0]\n if (!first || typeof first !== \"object\" || typeof first === \"string\") {\n return \"\"\n }\n\n const categoryDoc = first as UrlDoc\n return (\n getBreadcrumbsUrl(categoryDoc.breadcrumbs) ||\n (categoryDoc.slug ?? \"\").replace(/(^\\/)|(\\/$)/g, \"\")\n )\n}\n","import { getDocumentLink, withLocalePrefix } from \"./link\"\nimport {\n getCollectionOptions,\n getHomepageRootPageField,\n getRootPageFieldOptions,\n normalizeOptions,\n} from \"./options\"\nimport {\n getBreadcrumbsUrl,\n getDocumentId,\n mergeDoc,\n normalizePath,\n withoutPopulatedUrl,\n} from \"./utils\"\n\nimport type {\n Locale,\n PayloadLike,\n PayloadPluginUrlsOptions,\n ResolvePopulatedUrlArgs,\n RootPagesDoc,\n UrlCollectionOptions,\n UrlDoc,\n} from \"./types\"\n\nexport async function resolvePopulatedUrl({\n collection,\n data,\n locale,\n options,\n originalDoc,\n payload,\n rootPages,\n}: ResolvePopulatedUrlArgs): Promise<string | undefined> {\n const normalizedOptions = normalizeOptions(options)\n const collectionOptions = getCollectionOptions(normalizedOptions, collection)\n if (!collectionOptions) {\n return undefined\n }\n\n const doc = mergeDoc(data, originalDoc)\n const homepageField = getHomepageRootPageField(normalizedOptions)\n\n if (collectionOptions.breadcrumbs && !collectionOptions.rootPage) {\n const homepage = await getRootPageDoc({\n field: homepageField,\n locale,\n payload,\n rootPages,\n })\n const homepageId = getDocumentId(homepage)\n\n if (doc.id && homepageId === doc.id) {\n return withLocalePrefix(\"/\", locale, normalizedOptions)\n }\n\n const breadcrumbsPath = normalizePath(getBreadcrumbsUrl(doc.breadcrumbs))\n const homepagePath = normalizePath(getBreadcrumbsUrl(homepage?.breadcrumbs))\n const pagePath =\n homepagePath && breadcrumbsPath.startsWith(`${homepagePath}/`)\n ? normalizePath(breadcrumbsPath.slice(homepagePath.length))\n : breadcrumbsPath\n\n return withLocalePrefix(pagePath || `/${doc.slug ?? \"\"}`, locale, normalizedOptions)\n }\n\n const rootPageUrl: string | undefined = await getRootPageUrl({\n collectionOptions,\n locale,\n options: normalizedOptions,\n payload,\n rootPages,\n })\n\n if (collectionOptions.category) {\n const categories = await resolveCategories({\n categories: doc[collectionOptions.category.field ?? \"categories\"],\n collection: collectionOptions.category.collection,\n locale,\n payload,\n })\n\n return getDocumentLink(\n {\n relationTo: collection,\n value: {\n ...withoutPopulatedUrl(doc),\n [collectionOptions.category.field ?? \"categories\"]: categories,\n categories,\n },\n },\n {\n baseUrl: rootPageUrl,\n locale,\n options: normalizedOptions,\n },\n )\n }\n\n return getDocumentLink(\n {\n relationTo: collection,\n value: withoutPopulatedUrl(doc),\n },\n {\n baseUrl: rootPageUrl,\n locale,\n options: normalizedOptions,\n },\n )\n}\n\nasync function getRootPageUrl({\n collectionOptions,\n locale,\n options,\n payload,\n rootPages,\n}: {\n collectionOptions: UrlCollectionOptions\n locale: Locale\n options: PayloadPluginUrlsOptions\n payload?: PayloadLike\n rootPages: RootPagesDoc\n}): Promise<string | undefined> {\n if (!collectionOptions.rootPage) {\n return undefined\n }\n\n const rootPageField = collectionOptions.rootPage\n const rootPageFieldOptions = getRootPageFieldOptions(options, rootPageField)\n const relationTo = rootPageFieldOptions?.relationTo ?? \"pages\"\n const rootPage = await getRootPageDoc({\n collection: relationTo,\n field: rootPageField,\n locale,\n payload,\n rootPages,\n })\n\n if (!rootPage) {\n return undefined\n }\n\n if (typeof rootPage.populatedUrl === \"string\" && rootPage.populatedUrl) {\n return withLocalePrefixIfNeeded(rootPage.populatedUrl, locale, options)\n }\n\n if (relationTo !== \"pages\") {\n return withLocalePrefixIfNeeded(\n getDocumentLink(\n {\n relationTo,\n value: rootPage,\n },\n {\n locale,\n options,\n },\n ),\n locale,\n options,\n )\n }\n\n return resolvePopulatedUrl({\n collection: relationTo,\n data: {},\n locale,\n options,\n originalDoc: rootPage,\n payload,\n rootPages,\n })\n}\n\nfunction withLocalePrefixIfNeeded(path: string, locale: Locale, options: PayloadPluginUrlsOptions) {\n const normalizedOptions = normalizeOptions(options)\n if (\n locale === normalizedOptions.locales.defaultLocale ||\n path === `/${locale}` ||\n path.startsWith(`/${locale}/`)\n ) {\n return path\n }\n\n return withLocalePrefix(path, locale, normalizedOptions)\n}\n\nasync function getRootPageDoc({\n collection = \"pages\",\n field,\n locale,\n payload,\n rootPages,\n}: {\n collection?: string\n field: string\n locale: Locale\n payload?: PayloadLike\n rootPages: RootPagesDoc\n}) {\n const page = rootPages[field]\n\n if (!page) {\n return undefined\n }\n\n if (typeof page !== \"string\") {\n return page\n }\n\n const found = await payload?.findByID?.({\n collection,\n id: page,\n depth: 0,\n locale,\n select: {\n id: true,\n slug: true,\n populatedUrl: true,\n breadcrumbs: true,\n },\n })\n return found as UrlDoc | undefined\n}\n\nasync function resolveCategories({\n categories,\n collection,\n locale,\n payload,\n}: {\n categories: unknown\n collection: string\n locale: Locale\n payload?: PayloadLike\n}) {\n if (!Array.isArray(categories)) {\n return []\n }\n\n return Promise.all(\n categories.map((category) => {\n if (typeof category !== \"string\") {\n return Promise.resolve(category)\n }\n\n return (\n payload?.findByID?.({\n collection,\n id: category,\n depth: 2,\n locale,\n }) ?? Promise.resolve(category)\n )\n }),\n )\n}\n","import {\n getCollectionEntries,\n getCollectionsForCategory,\n getHomepageRootPageField,\n getRootPageFieldNames,\n getRootPageFieldOptions,\n normalizeOptions,\n} from \"./options\"\nimport { resolvePopulatedUrl } from \"./resolver\"\nimport { dedupeSources, getRelationId, getStringValue, isDraftDoc } from \"./utils\"\n\nimport type {\n Locale,\n PayloadLike,\n PayloadPluginUrlsOptions,\n RootPagesDoc,\n UrlDoc,\n UrlUpdateSource,\n} from \"./types\"\n\nexport function createUpdateUrlsHandler(options: PayloadPluginUrlsOptions) {\n return async ({\n job,\n req,\n }: {\n job: {\n input?: {\n sources?: UrlUpdateSource[] | null\n }\n }\n req: {\n payload: PayloadLike\n }\n }) => {\n const normalizedOptions = normalizeOptions(options)\n const sources = job.input?.sources ?? []\n\n for (const locale of normalizedOptions.locales?.locales ?? []) {\n const rootPages = await req.payload.findGlobal?.({\n slug: normalizedOptions.rootPages?.slug ?? \"root-pages\",\n depth: 2,\n locale,\n })\n if (!rootPages) {\n continue\n }\n\n for (const source of expandSources(sources, normalizedOptions)) {\n switch (source.type) {\n case \"category\":\n await updateCollectionDocuments({\n collection: source.collection,\n locale,\n options: normalizedOptions,\n payload: req.payload,\n rootPages,\n })\n for (const collection of getCollectionsForCategory(\n normalizedOptions,\n source.collection,\n )) {\n await updateCollectionDocuments({\n collection,\n locale,\n options: normalizedOptions,\n payload: req.payload,\n rootPages,\n })\n }\n break\n case \"collection\":\n case \"page\":\n await updateCollectionDocuments({\n collection: source.collection,\n locale,\n options: normalizedOptions,\n payload: req.payload,\n rootPages,\n })\n break\n case \"rootPages\":\n break\n }\n }\n }\n }\n}\n\nexport function hasUrlPathChanged(doc: unknown, previousDoc: unknown) {\n const docUrl = getStringValue(doc, \"populatedUrl\")\n const previousUrl = getStringValue(previousDoc, \"populatedUrl\")\n\n if (docUrl && previousUrl) {\n return docUrl !== previousUrl\n }\n\n return getStringValue(doc, \"slug\") !== getStringValue(previousDoc, \"slug\")\n}\n\nexport function getRootPageChangeSources(\n current: RootPagesDoc,\n previous: RootPagesDoc | undefined,\n options: PayloadPluginUrlsOptions,\n): UrlUpdateSource[] {\n const normalizedOptions = normalizeOptions(options)\n const sources: UrlUpdateSource[] = []\n const indexPageField = getHomepageRootPageField(normalizedOptions)\n const indexPageCollection =\n getRootPageFieldOptions(normalizedOptions, indexPageField)?.relationTo ?? \"pages\"\n const currentIndexPageId = getRelationId(current[indexPageField])\n const previousIndexPageId = getRelationId(previous?.[indexPageField])\n\n if (currentIndexPageId !== previousIndexPageId) {\n if (currentIndexPageId) {\n sources.push({ type: \"page\", collection: indexPageCollection, id: currentIndexPageId })\n }\n if (previousIndexPageId) {\n sources.push({ type: \"page\", collection: indexPageCollection, id: previousIndexPageId })\n }\n }\n\n for (const [collection, collectionOptions] of getCollectionEntries(normalizedOptions)) {\n if (!collectionOptions.rootPage) {\n continue\n }\n\n const currentRootPageId = getRelationId(current[collectionOptions.rootPage])\n const previousRootPageId = getRelationId(previous?.[collectionOptions.rootPage])\n if (currentRootPageId !== previousRootPageId) {\n sources.push({ type: \"collection\", collection })\n }\n }\n\n return dedupeSources(sources)\n}\n\nexport function getRootPageSnapshot(\n rootPages: UrlDoc | undefined,\n options: PayloadPluginUrlsOptions,\n) {\n const snapshot: RootPagesDoc = {}\n\n for (const fieldName of getRootPageFieldNames(options)) {\n snapshot[fieldName] = rootPages?.[fieldName] as RootPagesDoc[string]\n }\n\n return snapshot\n}\n\nfunction expandSources(sources: UrlUpdateSource[], options: PayloadPluginUrlsOptions) {\n return sources.flatMap((source) => {\n if (source.type !== \"rootPages\") {\n return [source]\n }\n\n return getRootPageChangeSources(source.current, source.previous, options)\n })\n}\n\nasync function updateCollectionDocuments({\n collection,\n locale,\n options,\n payload,\n rootPages,\n}: {\n collection: string\n locale: Locale\n options: PayloadPluginUrlsOptions\n payload: PayloadLike\n rootPages: RootPagesDoc\n}) {\n let page = 1\n\n for (;;) {\n const result = await payload.find?.({\n collection,\n depth: 2,\n draft: false,\n limit: 100,\n locale,\n overrideAccess: true,\n page,\n pagination: true,\n })\n\n if (!result) {\n return\n }\n\n for (const doc of result.docs) {\n const urlDoc = doc as UrlDoc\n if (!urlDoc.id || isDraftDoc(urlDoc)) {\n continue\n }\n\n const populatedUrlValue = await resolvePopulatedUrl({\n collection,\n data: {},\n locale,\n options,\n originalDoc: urlDoc,\n payload,\n rootPages,\n })\n\n if (!populatedUrlValue || urlDoc.populatedUrl === populatedUrlValue) {\n continue\n }\n\n await payload.update?.({\n collection,\n id: urlDoc.id,\n locale,\n overrideAccess: true,\n data: {\n [options.field?.name ?? \"populatedUrl\"]: populatedUrlValue,\n },\n context: {\n disablePopulateUrl: true,\n disableUrlUpdates: true,\n },\n })\n }\n\n if (!result.nextPage) {\n return\n }\n\n page = result.nextPage\n }\n}\n","import { getCollectionOptions, getCollectionsForCategory, normalizeOptions } from \"./options\"\nimport { resolvePopulatedUrl } from \"./resolver\"\nimport { getRootPageSnapshot, hasUrlPathChanged } from \"./update-urls\"\nimport { isDraftDoc } from \"./utils\"\n\nimport type { PayloadPluginUrlsOptions, RootPagesDoc, UrlDoc } from \"./types\"\nimport type {\n CollectionAfterChangeHook,\n CollectionBeforeChangeHook,\n GlobalAfterChangeHook,\n} from \"payload\"\n\nexport function createPopulateUrlHook(\n options: PayloadPluginUrlsOptions,\n): CollectionBeforeChangeHook {\n return async ({ collection, context, data = {}, originalDoc, req }) => {\n const locale = req.locale\n if (\n !locale ||\n locale === \"all\" ||\n context?.disablePopulateUrl ||\n req.context?.disablePopulateUrl\n ) {\n return data\n }\n\n const rootPages = await req.payload.findGlobal?.({\n slug: normalizeOptions(options).rootPages?.slug ?? \"root-pages\",\n depth: 2,\n locale,\n })\n if (!rootPages) {\n return data\n }\n\n const populatedUrlValue = await resolvePopulatedUrl({\n collection: collection?.slug ?? \"\",\n data: data as UrlDoc,\n locale,\n options,\n originalDoc: originalDoc as UrlDoc | undefined,\n payload: req.payload,\n rootPages: rootPages as RootPagesDoc,\n })\n\n if (populatedUrlValue) {\n data[options.field?.name ?? \"populatedUrl\"] = populatedUrlValue\n }\n\n return data\n }\n}\n\nexport function createCollectionUrlUpdateHook(\n options: PayloadPluginUrlsOptions,\n): CollectionAfterChangeHook {\n return async ({ collection, doc, previousDoc, req }) => {\n const urlDoc = doc as UrlDoc | undefined\n const previousUrlDoc = previousDoc as UrlDoc | undefined\n if (\n req.context?.disableUrlUpdates ||\n !urlDoc ||\n isDraftDoc(urlDoc) ||\n !hasUrlPathChanged(urlDoc, previousUrlDoc)\n ) {\n return urlDoc\n }\n\n const collectionOptions = getCollectionOptions(options, collection?.slug ?? \"\")\n if (!collectionOptions) {\n return urlDoc\n }\n\n const collectionSlug = collection?.slug ?? \"\"\n const isCategoryCollection = getCollectionsForCategory(options, collectionSlug).length > 0\n const source = isCategoryCollection\n ? {\n type: \"category\",\n collection: collectionSlug,\n id: urlDoc.id,\n }\n : {\n type:\n collectionOptions.breadcrumbs && !collectionOptions.rootPage ? \"page\" : \"collection\",\n collection: collectionSlug,\n id: urlDoc.id,\n }\n\n await req.payload.jobs?.queue?.({\n workflow: \"update-urls\",\n input: {\n sources: [source],\n },\n })\n\n return urlDoc\n }\n}\n\nexport function createRootPagesUrlUpdateHook(\n options: PayloadPluginUrlsOptions,\n): GlobalAfterChangeHook {\n return async ({ doc, previousDoc, req }) => {\n const rootPagesDoc = doc as RootPagesDoc\n const previousRootPagesDoc = previousDoc as RootPagesDoc | undefined\n if (req.context?.disableUrlUpdates) {\n return rootPagesDoc\n }\n\n await req.payload.jobs?.queue?.({\n workflow: \"update-urls\",\n input: {\n sources: [\n {\n type: \"rootPages\",\n current: getRootPageSnapshot(rootPagesDoc, options),\n previous: getRootPageSnapshot(previousRootPagesDoc, options),\n },\n ],\n },\n })\n\n return rootPagesDoc\n }\n}\n","import { populatedUrlField } from \"./field\"\nimport {\n createCollectionUrlUpdateHook,\n createPopulateUrlHook,\n createRootPagesUrlUpdateHook,\n} from \"./hooks\"\nimport {\n getCollectionOptions,\n getRootPageFieldNames,\n getRootPageFieldOptions,\n normalizeOptions,\n} from \"./options\"\nimport { createUpdateUrlsHandler } from \"./update-urls\"\n\nimport type {\n CollectionConfigLike,\n FieldLike,\n GlobalConfigLike,\n PayloadPlugin,\n PayloadPluginUrlsOptions,\n WorkflowLike,\n} from \"./types\"\nimport type { GlobalConfig } from \"payload\"\n\nexport const payloadPluginUrls = (options?: PayloadPluginUrlsOptions): PayloadPlugin => {\n if (!options) {\n return (config) => config\n }\n\n return (config) => {\n const normalizedOptions = normalizeOptions(options, config)\n const collections = (config.collections ?? []).map((collection) =>\n applyUrlCollectionConfig(collection, normalizedOptions),\n )\n\n return {\n ...config,\n collections,\n globals: [...(config.globals ?? []), createRootPagesGlobal(normalizedOptions)],\n jobs: {\n ...(config.jobs ?? {}),\n workflows: [\n ...(config.jobs?.workflows ?? []),\n {\n slug: \"update-urls\",\n handler: createUpdateUrlsHandler(normalizedOptions),\n } as WorkflowLike,\n ],\n },\n } as ReturnType<PayloadPlugin>\n }\n}\n\nfunction applyUrlCollectionConfig(\n collection: CollectionConfigLike,\n options: PayloadPluginUrlsOptions,\n) {\n const collectionOptions = getCollectionOptions(options, collection.slug)\n if (!collectionOptions) {\n return collection\n }\n\n const fieldName = options.field?.name ?? \"populatedUrl\"\n const fields = collection.fields.some((field) => \"name\" in field && field.name === fieldName)\n ? collection.fields\n : [...collection.fields, populatedUrlField(options)]\n const hooks = collection.hooks ?? {}\n\n return {\n ...collection,\n defaultPopulate: {\n ...(collection.defaultPopulate ?? {}),\n [fieldName]: true,\n },\n fields,\n hooks: {\n ...hooks,\n beforeChange: [...(hooks.beforeChange ?? []), createPopulateUrlHook(options)],\n afterChange: [...(hooks.afterChange ?? []), createCollectionUrlUpdateHook(options)],\n },\n } as CollectionConfigLike\n}\n\nfunction createRootPagesGlobal(options: PayloadPluginUrlsOptions): GlobalConfigLike {\n const rootPagesOptions = normalizeOptions(options).rootPages\n\n const base = {\n slug: rootPagesOptions?.slug ?? \"root-pages\",\n label: rootPagesOptions?.label ?? \"Root pages\",\n fields: getRootPageFieldNames(options).map((fieldName) =>\n createRootPageField(fieldName, options),\n ),\n hooks: {\n afterChange: [createRootPagesUrlUpdateHook(options)],\n },\n } satisfies GlobalConfigLike\n\n const partial = options.overrides\n return partial ? mergeGlobalConfigOverride(base, partial) : base\n}\n\nfunction createRootPageField(fieldName: string, options: PayloadPluginUrlsOptions): FieldLike {\n const fieldOptions = getRootPageFieldOptions(options, fieldName)\n const overrides = (fieldOptions?.overrides ?? {}) as Record<string, unknown>\n const {\n name: _name,\n type: _type,\n hasMany: _hasMany,\n relationTo: _relationTo,\n ...override\n } = overrides\n\n return {\n name: fieldName,\n type: \"relationship\",\n relationTo: fieldOptions?.relationTo ?? \"pages\",\n hasMany: false,\n admin: {\n width: \"50%\",\n },\n ...override,\n } as FieldLike\n}\n\nfunction unknownArrayFrom(value: unknown): unknown[] {\n if (!Array.isArray(value)) {\n return []\n }\n const out: unknown[] = []\n for (const item of value) {\n out.push(item)\n }\n return out\n}\n\nfunction mergeHooks<H extends Record<string, unknown> | undefined>(base: H, extra: H): H {\n if (!extra) {\n return base\n }\n if (!base) {\n return extra\n }\n const a = base\n const b = extra\n const out = { ...a }\n for (const key of Object.keys(b)) {\n const av = a[key]\n const bv = b[key]\n if (Array.isArray(av) || Array.isArray(bv)) {\n out[key] = [...unknownArrayFrom(av), ...unknownArrayFrom(bv)]\n } else if (bv !== undefined) {\n out[key] = bv\n }\n }\n return out as H\n}\n\nfunction mergeRecord(\n base: Record<string, unknown> | undefined,\n extra: Record<string, unknown> | undefined,\n): Record<string, unknown> | undefined {\n if (!extra) {\n return base\n }\n if (!base) {\n return extra\n }\n return { ...base, ...extra }\n}\n\nfunction mergeGlobalConfigOverride(\n global: GlobalConfigLike,\n override: Partial<GlobalConfig>,\n): GlobalConfigLike {\n const { hooks: oHooks, access: oAccess, admin: oAdmin, fields: _fields, ...rest } = override\n\n const merged: GlobalConfigLike = {\n ...global,\n ...rest,\n }\n\n if (oAccess) {\n merged.access = mergeRecord(\n global.access as Record<string, unknown> | undefined,\n oAccess as Record<string, unknown>,\n ) as GlobalConfig[\"access\"]\n }\n\n if (oAdmin) {\n merged.admin = mergeRecord(\n global.admin as Record<string, unknown> | undefined,\n oAdmin as Record<string, unknown>,\n ) as GlobalConfig[\"admin\"]\n }\n\n if (oHooks || global.hooks) {\n merged.hooks = mergeHooks(global.hooks, oHooks)\n }\n\n return merged\n}\n"],"mappings":"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","names":["withoutTrailingSlash","path","getBreadcrumbsUrl","breadcrumbs","mergeDoc","data","originalDoc","withoutUndefinedValues","withoutPopulatedUrl","doc","_populatedUrl","rest","getDocumentId","getRelationId","value","normalizePath","getStringValue","key","record","isDraftDoc","getRecord","dedupeSources","sources","seen","source","sourceKey","entry","populatedUrlField","options","getRecord","normalizeOptions","options","config","locales","getConfigLocales","getCollectionOptions","collection","getCollectionEntries","getCollectionsForCategory","categoryCollection","collectionOptions","getRootPageFieldNames","normalizedOptions","getHomepageRootPageField","fields","field","fieldName","getRootPageFieldOptions","localization","locale","getDocumentLink","reference","baseUrl","locale","options","urlPrefixStrategy","withoutTrailingSlash","normalizedOptions","normalizeOptions","collectionOptions","getCollectionOptions","routeCollection","slugs","getSlugsForCollection","getDocumentLinkBySlugs","segments","withLocalePrefix","path","defaultLocale","doc","strategy","firstRelatedCategoryPath","getBreadcrumbsUrl","categories","first","categoryDoc","resolvePopulatedUrl","collection","data","locale","options","originalDoc","payload","rootPages","normalizedOptions","normalizeOptions","collectionOptions","getCollectionOptions","doc","mergeDoc","homepageField","getHomepageRootPageField","homepage","getRootPageDoc","homepageId","getDocumentId","withLocalePrefix","breadcrumbsPath","normalizePath","getBreadcrumbsUrl","homepagePath","pagePath","rootPageUrl","getRootPageUrl","categories","resolveCategories","getDocumentLink","withoutPopulatedUrl","rootPageField","relationTo","getRootPageFieldOptions","rootPage","withLocalePrefixIfNeeded","path","field","page","category","createUpdateUrlsHandler","options","job","req","normalizedOptions","normalizeOptions","sources","locale","rootPages","source","expandSources","updateCollectionDocuments","collection","getCollectionsForCategory","hasUrlPathChanged","doc","previousDoc","docUrl","getStringValue","previousUrl","getRootPageChangeSources","current","previous","indexPageField","getHomepageRootPageField","indexPageCollection","getRootPageFieldOptions","currentIndexPageId","getRelationId","previousIndexPageId","collectionOptions","getCollectionEntries","currentRootPageId","previousRootPageId","dedupeSources","getRootPageSnapshot","snapshot","fieldName","getRootPageFieldNames","payload","page","result","urlDoc","isDraftDoc","populatedUrlValue","resolvePopulatedUrl","createPopulateUrlHook","options","collection","context","data","originalDoc","req","locale","rootPages","normalizeOptions","populatedUrlValue","resolvePopulatedUrl","createCollectionUrlUpdateHook","doc","previousDoc","urlDoc","previousUrlDoc","isDraftDoc","hasUrlPathChanged","collectionOptions","getCollectionOptions","collectionSlug","source","getCollectionsForCategory","createRootPagesUrlUpdateHook","rootPagesDoc","previousRootPagesDoc","getRootPageSnapshot","payloadPluginUrls","options","config","normalizedOptions","normalizeOptions","collections","collection","applyUrlCollectionConfig","createRootPagesGlobal","createUpdateUrlsHandler","getCollectionOptions","fieldName","fields","field","populatedUrlField","hooks","createPopulateUrlHook","createCollectionUrlUpdateHook","rootPagesOptions","base","getRootPageFieldNames","createRootPageField","createRootPagesUrlUpdateHook","partial","mergeGlobalConfigOverride","fieldOptions","getRootPageFieldOptions","overrides","_name","_type","_hasMany","_relationTo","override","unknownArrayFrom","value","out","item","mergeHooks","extra","a","b","key","av","bv","mergeRecord","global","oHooks","oAccess","oAdmin","_fields","rest","merged"]}
1
+ {"version":3,"sources":["../src/field.ts","../src/resolver.ts","../src/update-urls.ts","../src/hooks.ts","../src/plugin.ts"],"sourcesContent":["import { getRecord } from \"./utils\"\n\nimport type { PayloadPluginUrlsOptions } from \"./types\"\nimport type { Field } from \"payload\"\n\nexport function populatedUrlField(options: PayloadPluginUrlsOptions = { collections: {} }): Field {\n const fieldName = options.field?.name ?? \"populatedUrl\"\n\n return {\n name: fieldName,\n type: \"text\",\n label: false,\n localized: true,\n ...(options.field?.overrides ?? {}),\n admin: {\n hidden: true,\n ...getRecord(options.field?.overrides?.admin),\n },\n } as Field\n}\n","import { getDocumentLink, withLocalePrefix } from \"./link\"\nimport {\n getCollectionOptions,\n getHomepageRootPageField,\n getRootPageFieldOptions,\n normalizeOptions,\n} from \"./options\"\nimport {\n getBreadcrumbsUrl,\n getDocumentId,\n mergeDoc,\n normalizePath,\n withoutPopulatedUrl,\n} from \"./utils\"\n\nimport type {\n Locale,\n PayloadLike,\n PayloadPluginUrlsOptions,\n ResolvePopulatedUrlArgs,\n RootPagesDoc,\n UrlCollectionOptions,\n UrlDoc,\n} from \"./types\"\n\nexport async function resolvePopulatedUrl({\n collection,\n data,\n locale,\n options,\n originalDoc,\n payload,\n rootPages,\n}: ResolvePopulatedUrlArgs): Promise<string | undefined> {\n const normalizedOptions = normalizeOptions(options)\n const collectionOptions = getCollectionOptions(normalizedOptions, collection)\n if (!collectionOptions) {\n return undefined\n }\n\n const doc = mergeDoc(data, originalDoc)\n const homepageField = getHomepageRootPageField(normalizedOptions)\n\n if (collectionOptions.breadcrumbs && !collectionOptions.rootPage) {\n const homepage = await getRootPageDoc({\n field: homepageField,\n locale,\n payload,\n rootPages,\n })\n const homepageId = getDocumentId(homepage)\n\n if (doc.id && homepageId === doc.id) {\n return withLocalePrefix(\"/\", locale, normalizedOptions)\n }\n\n const breadcrumbsPath = normalizePath(getBreadcrumbsUrl(doc.breadcrumbs))\n const homepagePath = normalizePath(getBreadcrumbsUrl(homepage?.breadcrumbs))\n const pagePath =\n homepagePath && breadcrumbsPath.startsWith(`${homepagePath}/`)\n ? normalizePath(breadcrumbsPath.slice(homepagePath.length))\n : breadcrumbsPath\n\n return withLocalePrefix(pagePath || `/${doc.slug ?? \"\"}`, locale, normalizedOptions)\n }\n\n const rootPageUrl: string | undefined = await getRootPageUrl({\n collectionOptions,\n locale,\n options: normalizedOptions,\n payload,\n rootPages,\n })\n\n if (collectionOptions.category) {\n const categories = await resolveCategories({\n categories: doc[collectionOptions.category.field ?? \"categories\"],\n collection: collectionOptions.category.collection,\n locale,\n payload,\n })\n\n return getDocumentLink(\n {\n relationTo: collection,\n value: {\n ...withoutPopulatedUrl(doc),\n [collectionOptions.category.field ?? \"categories\"]: categories,\n categories,\n },\n },\n {\n baseUrl: rootPageUrl,\n locale,\n options: normalizedOptions,\n },\n )\n }\n\n return getDocumentLink(\n {\n relationTo: collection,\n value: withoutPopulatedUrl(doc),\n },\n {\n baseUrl: rootPageUrl,\n locale,\n options: normalizedOptions,\n },\n )\n}\n\nasync function getRootPageUrl({\n collectionOptions,\n locale,\n options,\n payload,\n rootPages,\n}: {\n collectionOptions: UrlCollectionOptions\n locale: Locale\n options: PayloadPluginUrlsOptions\n payload?: PayloadLike\n rootPages: RootPagesDoc\n}): Promise<string | undefined> {\n if (!collectionOptions.rootPage) {\n return undefined\n }\n\n const rootPageField = collectionOptions.rootPage\n const rootPageFieldOptions = getRootPageFieldOptions(options, rootPageField)\n const relationTo = rootPageFieldOptions?.relationTo ?? \"pages\"\n const rootPage = await getRootPageDoc({\n collection: relationTo,\n field: rootPageField,\n locale,\n payload,\n rootPages,\n })\n\n if (!rootPage) {\n return undefined\n }\n\n if (typeof rootPage.populatedUrl === \"string\" && rootPage.populatedUrl) {\n return withLocalePrefixIfNeeded(rootPage.populatedUrl, locale, options)\n }\n\n if (relationTo !== \"pages\") {\n return withLocalePrefixIfNeeded(\n getDocumentLink(\n {\n relationTo,\n value: rootPage,\n },\n {\n locale,\n options,\n },\n ),\n locale,\n options,\n )\n }\n\n return resolvePopulatedUrl({\n collection: relationTo,\n data: {},\n locale,\n options,\n originalDoc: rootPage,\n payload,\n rootPages,\n })\n}\n\nfunction withLocalePrefixIfNeeded(path: string, locale: Locale, options: PayloadPluginUrlsOptions) {\n const normalizedOptions = normalizeOptions(options)\n if (\n locale === normalizedOptions.locales.defaultLocale ||\n path === `/${locale}` ||\n path.startsWith(`/${locale}/`)\n ) {\n return path\n }\n\n return withLocalePrefix(path, locale, normalizedOptions)\n}\n\nasync function getRootPageDoc({\n collection = \"pages\",\n field,\n locale,\n payload,\n rootPages,\n}: {\n collection?: string\n field: string\n locale: Locale\n payload?: PayloadLike\n rootPages: RootPagesDoc\n}) {\n const page = rootPages[field]\n\n if (!page) {\n return undefined\n }\n\n if (typeof page !== \"string\") {\n return page\n }\n\n const found = await payload?.findByID?.({\n collection,\n id: page,\n depth: 0,\n locale,\n select: {\n id: true,\n slug: true,\n populatedUrl: true,\n breadcrumbs: true,\n },\n })\n return found as UrlDoc | undefined\n}\n\nasync function resolveCategories({\n categories,\n collection,\n locale,\n payload,\n}: {\n categories: unknown\n collection: string\n locale: Locale\n payload?: PayloadLike\n}) {\n if (!Array.isArray(categories)) {\n return []\n }\n\n return Promise.all(\n categories.map((category) => {\n if (typeof category !== \"string\") {\n return Promise.resolve(category)\n }\n\n return (\n payload?.findByID?.({\n collection,\n id: category,\n depth: 2,\n locale,\n }) ?? Promise.resolve(category)\n )\n }),\n )\n}\n","import {\n getCollectionEntries,\n getCollectionsForCategory,\n getHomepageRootPageField,\n getRootPageFieldNames,\n getRootPageFieldOptions,\n normalizeOptions,\n} from \"./options\"\nimport { resolvePopulatedUrl } from \"./resolver\"\nimport { dedupeSources, getRelationId, getStringValue, isDraftDoc } from \"./utils\"\n\nimport type {\n Locale,\n PayloadLike,\n PayloadPluginUrlsOptions,\n RootPagesDoc,\n UrlDoc,\n UrlUpdateSource,\n} from \"./types\"\n\nexport function createUpdateUrlsHandler(options: PayloadPluginUrlsOptions) {\n return async ({\n job,\n req,\n }: {\n job: {\n input?: {\n sources?: UrlUpdateSource[] | null\n }\n }\n req: {\n payload: PayloadLike\n }\n }) => {\n const normalizedOptions = normalizeOptions(options)\n const sources = job.input?.sources ?? []\n\n for (const locale of normalizedOptions.locales?.locales ?? []) {\n const rootPages = await req.payload.findGlobal?.({\n slug: normalizedOptions.rootPages?.slug ?? \"root-pages\",\n depth: 2,\n locale,\n })\n if (!rootPages) {\n continue\n }\n\n for (const source of expandSources(sources, normalizedOptions)) {\n switch (source.type) {\n case \"category\":\n await updateCollectionDocuments({\n collection: source.collection,\n locale,\n options: normalizedOptions,\n payload: req.payload,\n rootPages,\n })\n for (const collection of getCollectionsForCategory(\n normalizedOptions,\n source.collection,\n )) {\n await updateCollectionDocuments({\n collection,\n locale,\n options: normalizedOptions,\n payload: req.payload,\n rootPages,\n })\n }\n break\n case \"collection\":\n case \"page\":\n await updateCollectionDocuments({\n collection: source.collection,\n locale,\n options: normalizedOptions,\n payload: req.payload,\n rootPages,\n })\n break\n case \"rootPages\":\n break\n }\n }\n }\n }\n}\n\nexport function hasUrlPathChanged(doc: unknown, previousDoc: unknown) {\n const docUrl = getStringValue(doc, \"populatedUrl\")\n const previousUrl = getStringValue(previousDoc, \"populatedUrl\")\n\n if (docUrl && previousUrl) {\n return docUrl !== previousUrl\n }\n\n return getStringValue(doc, \"slug\") !== getStringValue(previousDoc, \"slug\")\n}\n\nexport function getRootPageChangeSources(\n current: RootPagesDoc,\n previous: RootPagesDoc | undefined,\n options: PayloadPluginUrlsOptions,\n): UrlUpdateSource[] {\n const normalizedOptions = normalizeOptions(options)\n const sources: UrlUpdateSource[] = []\n const indexPageField = getHomepageRootPageField(normalizedOptions)\n const indexPageCollection =\n getRootPageFieldOptions(normalizedOptions, indexPageField)?.relationTo ?? \"pages\"\n const currentIndexPageId = getRelationId(current[indexPageField])\n const previousIndexPageId = getRelationId(previous?.[indexPageField])\n\n if (currentIndexPageId !== previousIndexPageId) {\n if (currentIndexPageId) {\n sources.push({ type: \"page\", collection: indexPageCollection, id: currentIndexPageId })\n }\n if (previousIndexPageId) {\n sources.push({ type: \"page\", collection: indexPageCollection, id: previousIndexPageId })\n }\n }\n\n for (const [collection, collectionOptions] of getCollectionEntries(normalizedOptions)) {\n if (!collectionOptions.rootPage) {\n continue\n }\n\n const currentRootPageId = getRelationId(current[collectionOptions.rootPage])\n const previousRootPageId = getRelationId(previous?.[collectionOptions.rootPage])\n if (currentRootPageId !== previousRootPageId) {\n sources.push({ type: \"collection\", collection })\n }\n }\n\n return dedupeSources(sources)\n}\n\nexport function getRootPageSnapshot(\n rootPages: UrlDoc | undefined,\n options: PayloadPluginUrlsOptions,\n) {\n const snapshot: RootPagesDoc = {}\n\n for (const fieldName of getRootPageFieldNames(options)) {\n snapshot[fieldName] = rootPages?.[fieldName] as RootPagesDoc[string]\n }\n\n return snapshot\n}\n\nfunction expandSources(sources: UrlUpdateSource[], options: PayloadPluginUrlsOptions) {\n return sources.flatMap((source) => {\n if (source.type !== \"rootPages\") {\n return [source]\n }\n\n return getRootPageChangeSources(source.current, source.previous, options)\n })\n}\n\nasync function updateCollectionDocuments({\n collection,\n locale,\n options,\n payload,\n rootPages,\n}: {\n collection: string\n locale: Locale\n options: PayloadPluginUrlsOptions\n payload: PayloadLike\n rootPages: RootPagesDoc\n}) {\n let page = 1\n\n for (;;) {\n const result = await payload.find?.({\n collection,\n depth: 2,\n draft: false,\n limit: 100,\n locale,\n overrideAccess: true,\n page,\n pagination: true,\n })\n\n if (!result) {\n return\n }\n\n for (const doc of result.docs) {\n const urlDoc = doc as UrlDoc\n if (!urlDoc.id || isDraftDoc(urlDoc)) {\n continue\n }\n\n const populatedUrlValue = await resolvePopulatedUrl({\n collection,\n data: {},\n locale,\n options,\n originalDoc: urlDoc,\n payload,\n rootPages,\n })\n\n if (!populatedUrlValue || urlDoc.populatedUrl === populatedUrlValue) {\n continue\n }\n\n await payload.update?.({\n collection,\n id: urlDoc.id,\n locale,\n overrideAccess: true,\n data: {\n [options.field?.name ?? \"populatedUrl\"]: populatedUrlValue,\n },\n context: {\n disablePopulateUrl: true,\n disableUrlUpdates: true,\n },\n })\n }\n\n if (!result.nextPage) {\n return\n }\n\n page = result.nextPage\n }\n}\n","import { getCollectionOptions, getCollectionsForCategory, normalizeOptions } from \"./options\"\nimport { resolvePopulatedUrl } from \"./resolver\"\nimport { getRootPageSnapshot, hasUrlPathChanged } from \"./update-urls\"\nimport { isDraftDoc } from \"./utils\"\n\nimport type { PayloadPluginUrlsOptions, RootPagesDoc, UrlDoc } from \"./types\"\nimport type {\n CollectionAfterChangeHook,\n CollectionBeforeChangeHook,\n GlobalAfterChangeHook,\n} from \"payload\"\n\nexport function createPopulateUrlHook(\n options: PayloadPluginUrlsOptions,\n): CollectionBeforeChangeHook {\n return async ({ collection, context, data = {}, originalDoc, req }) => {\n const locale = req.locale\n if (\n !locale ||\n locale === \"all\" ||\n context?.disablePopulateUrl ||\n req.context?.disablePopulateUrl\n ) {\n return data\n }\n\n const rootPages = await req.payload.findGlobal?.({\n slug: normalizeOptions(options).rootPages?.slug ?? \"root-pages\",\n depth: 2,\n locale,\n })\n if (!rootPages) {\n return data\n }\n\n const populatedUrlValue = await resolvePopulatedUrl({\n collection: collection?.slug ?? \"\",\n data: data as UrlDoc,\n locale,\n options,\n originalDoc: originalDoc as UrlDoc | undefined,\n payload: req.payload,\n rootPages: rootPages as RootPagesDoc,\n })\n\n if (populatedUrlValue) {\n data[options.field?.name ?? \"populatedUrl\"] = populatedUrlValue\n }\n\n return data\n }\n}\n\nexport function createCollectionUrlUpdateHook(\n options: PayloadPluginUrlsOptions,\n): CollectionAfterChangeHook {\n return async ({ collection, doc, previousDoc, req }) => {\n const urlDoc = doc as UrlDoc | undefined\n const previousUrlDoc = previousDoc as UrlDoc | undefined\n if (\n req.context?.disableUrlUpdates ||\n !urlDoc ||\n isDraftDoc(urlDoc) ||\n !hasUrlPathChanged(urlDoc, previousUrlDoc)\n ) {\n return urlDoc\n }\n\n const collectionOptions = getCollectionOptions(options, collection?.slug ?? \"\")\n if (!collectionOptions) {\n return urlDoc\n }\n\n const collectionSlug = collection?.slug ?? \"\"\n const isCategoryCollection = getCollectionsForCategory(options, collectionSlug).length > 0\n const source = isCategoryCollection\n ? {\n type: \"category\",\n collection: collectionSlug,\n id: urlDoc.id,\n }\n : {\n type:\n collectionOptions.breadcrumbs && !collectionOptions.rootPage ? \"page\" : \"collection\",\n collection: collectionSlug,\n id: urlDoc.id,\n }\n\n await req.payload.jobs?.queue?.({\n workflow: \"update-urls\",\n input: {\n sources: [source],\n },\n })\n\n return urlDoc\n }\n}\n\nexport function createRootPagesUrlUpdateHook(\n options: PayloadPluginUrlsOptions,\n): GlobalAfterChangeHook {\n return async ({ doc, previousDoc, req }) => {\n const rootPagesDoc = doc as RootPagesDoc\n const previousRootPagesDoc = previousDoc as RootPagesDoc | undefined\n if (req.context?.disableUrlUpdates) {\n return rootPagesDoc\n }\n\n await req.payload.jobs?.queue?.({\n workflow: \"update-urls\",\n input: {\n sources: [\n {\n type: \"rootPages\",\n current: getRootPageSnapshot(rootPagesDoc, options),\n previous: getRootPageSnapshot(previousRootPagesDoc, options),\n },\n ],\n },\n })\n\n return rootPagesDoc\n }\n}\n","import { populatedUrlField } from \"./field\"\nimport {\n createCollectionUrlUpdateHook,\n createPopulateUrlHook,\n createRootPagesUrlUpdateHook,\n} from \"./hooks\"\nimport {\n getCollectionOptions,\n getRootPageFieldNames,\n getRootPageFieldOptions,\n normalizeOptions,\n} from \"./options\"\nimport { createUpdateUrlsHandler } from \"./update-urls\"\n\nimport type {\n CollectionConfigLike,\n FieldLike,\n GlobalConfigLike,\n PayloadPlugin,\n PayloadPluginUrlsOptions,\n WorkflowLike,\n} from \"./types\"\nimport type { GlobalConfig } from \"payload\"\n\nexport const payloadPluginUrls = (options?: PayloadPluginUrlsOptions): PayloadPlugin => {\n if (!options) {\n return (config) => config\n }\n\n return (config) => {\n const normalizedOptions = normalizeOptions(options, config)\n const collections = (config.collections ?? []).map((collection) =>\n applyUrlCollectionConfig(collection, normalizedOptions),\n )\n\n return {\n ...config,\n collections,\n globals: [...(config.globals ?? []), createRootPagesGlobal(normalizedOptions)],\n jobs: {\n ...(config.jobs ?? {}),\n workflows: [\n ...(config.jobs?.workflows ?? []),\n {\n slug: \"update-urls\",\n handler: createUpdateUrlsHandler(normalizedOptions),\n } as WorkflowLike,\n ],\n },\n } as ReturnType<PayloadPlugin>\n }\n}\n\nfunction applyUrlCollectionConfig(\n collection: CollectionConfigLike,\n options: PayloadPluginUrlsOptions,\n) {\n const collectionOptions = getCollectionOptions(options, collection.slug)\n if (!collectionOptions) {\n return collection\n }\n\n const fieldName = options.field?.name ?? \"populatedUrl\"\n const fields = collection.fields.some((field) => \"name\" in field && field.name === fieldName)\n ? collection.fields\n : [...collection.fields, populatedUrlField(options)]\n const hooks = collection.hooks ?? {}\n\n return {\n ...collection,\n defaultPopulate: {\n ...(collection.defaultPopulate ?? {}),\n [fieldName]: true,\n },\n fields,\n hooks: {\n ...hooks,\n beforeChange: [...(hooks.beforeChange ?? []), createPopulateUrlHook(options)],\n afterChange: [...(hooks.afterChange ?? []), createCollectionUrlUpdateHook(options)],\n },\n } as CollectionConfigLike\n}\n\nfunction createRootPagesGlobal(options: PayloadPluginUrlsOptions): GlobalConfigLike {\n const rootPagesOptions = normalizeOptions(options).rootPages\n\n const base = {\n slug: rootPagesOptions?.slug ?? \"root-pages\",\n label: rootPagesOptions?.label ?? \"Root pages\",\n fields: getRootPageFieldNames(options).map((fieldName) =>\n createRootPageField(fieldName, options),\n ),\n hooks: {\n afterChange: [createRootPagesUrlUpdateHook(options)],\n },\n } satisfies GlobalConfigLike\n\n const partial = options.overrides\n return partial ? mergeGlobalConfigOverride(base, partial) : base\n}\n\nfunction createRootPageField(fieldName: string, options: PayloadPluginUrlsOptions): FieldLike {\n const fieldOptions = getRootPageFieldOptions(options, fieldName)\n const overrides = (fieldOptions?.overrides ?? {}) as Record<string, unknown>\n const {\n name: _name,\n type: _type,\n hasMany: _hasMany,\n relationTo: _relationTo,\n ...override\n } = overrides\n\n return {\n name: fieldName,\n type: \"relationship\",\n relationTo: fieldOptions?.relationTo ?? \"pages\",\n hasMany: false,\n admin: {\n width: \"50%\",\n },\n ...override,\n } as FieldLike\n}\n\nfunction unknownArrayFrom(value: unknown): unknown[] {\n if (!Array.isArray(value)) {\n return []\n }\n const out: unknown[] = []\n for (const item of value) {\n out.push(item)\n }\n return out\n}\n\nfunction mergeHooks<H extends Record<string, unknown> | undefined>(base: H, extra: H): H {\n if (!extra) {\n return base\n }\n if (!base) {\n return extra\n }\n const a = base\n const b = extra\n const out = { ...a }\n for (const key of Object.keys(b)) {\n const av = a[key]\n const bv = b[key]\n if (Array.isArray(av) || Array.isArray(bv)) {\n out[key] = [...unknownArrayFrom(av), ...unknownArrayFrom(bv)]\n } else if (bv !== undefined) {\n out[key] = bv\n }\n }\n return out as H\n}\n\nfunction mergeRecord(\n base: Record<string, unknown> | undefined,\n extra: Record<string, unknown> | undefined,\n): Record<string, unknown> | undefined {\n if (!extra) {\n return base\n }\n if (!base) {\n return extra\n }\n return { ...base, ...extra }\n}\n\nfunction mergeGlobalConfigOverride(\n global: GlobalConfigLike,\n override: Partial<GlobalConfig>,\n): GlobalConfigLike {\n const { hooks: oHooks, access: oAccess, admin: oAdmin, fields: _fields, ...rest } = override\n\n const merged: GlobalConfigLike = {\n ...global,\n ...rest,\n }\n\n if (oAccess) {\n merged.access = mergeRecord(\n global.access as Record<string, unknown> | undefined,\n oAccess as Record<string, unknown>,\n ) as GlobalConfig[\"access\"]\n }\n\n if (oAdmin) {\n merged.admin = mergeRecord(\n global.admin as Record<string, unknown> | undefined,\n oAdmin as Record<string, unknown>,\n ) as GlobalConfig[\"admin\"]\n }\n\n if (oHooks || global.hooks) {\n merged.hooks = mergeHooks(global.hooks, oHooks)\n }\n\n return merged\n}\n"],"mappings":"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","names":["populatedUrlField","options","getRecord","resolvePopulatedUrl","collection","data","locale","options","originalDoc","payload","rootPages","normalizedOptions","normalizeOptions","collectionOptions","getCollectionOptions","doc","mergeDoc","homepageField","getHomepageRootPageField","homepage","getRootPageDoc","homepageId","getDocumentId","withLocalePrefix","breadcrumbsPath","normalizePath","getBreadcrumbsUrl","homepagePath","pagePath","rootPageUrl","getRootPageUrl","categories","resolveCategories","getDocumentLink","withoutPopulatedUrl","rootPageField","relationTo","getRootPageFieldOptions","rootPage","withLocalePrefixIfNeeded","path","field","page","category","createUpdateUrlsHandler","options","job","req","normalizedOptions","normalizeOptions","sources","locale","rootPages","source","expandSources","updateCollectionDocuments","collection","getCollectionsForCategory","hasUrlPathChanged","doc","previousDoc","docUrl","getStringValue","previousUrl","getRootPageChangeSources","current","previous","indexPageField","getHomepageRootPageField","indexPageCollection","getRootPageFieldOptions","currentIndexPageId","getRelationId","previousIndexPageId","collectionOptions","getCollectionEntries","currentRootPageId","previousRootPageId","dedupeSources","getRootPageSnapshot","snapshot","fieldName","getRootPageFieldNames","payload","page","result","urlDoc","isDraftDoc","populatedUrlValue","resolvePopulatedUrl","createPopulateUrlHook","options","collection","context","data","originalDoc","req","locale","rootPages","normalizeOptions","populatedUrlValue","resolvePopulatedUrl","createCollectionUrlUpdateHook","doc","previousDoc","urlDoc","previousUrlDoc","isDraftDoc","hasUrlPathChanged","collectionOptions","getCollectionOptions","collectionSlug","source","getCollectionsForCategory","createRootPagesUrlUpdateHook","rootPagesDoc","previousRootPagesDoc","getRootPageSnapshot","payloadPluginUrls","options","config","normalizedOptions","normalizeOptions","collections","collection","applyUrlCollectionConfig","createRootPagesGlobal","createUpdateUrlsHandler","getCollectionOptions","fieldName","fields","field","populatedUrlField","hooks","createPopulateUrlHook","createCollectionUrlUpdateHook","rootPagesOptions","base","getRootPageFieldNames","createRootPageField","createRootPagesUrlUpdateHook","partial","mergeGlobalConfigOverride","fieldOptions","getRootPageFieldOptions","overrides","_name","_type","_hasMany","_relationTo","override","unknownArrayFrom","value","out","item","mergeHooks","extra","a","b","key","av","bv","mergeRecord","global","oHooks","oAccess","oAdmin","_fields","rest","merged"]}
@@ -0,0 +1,32 @@
1
+ import Link from "next/link";
2
+ import type { GetDocumentLinkArgs, GetDocumentLinkContext } from "../types";
3
+ import type { LinkProps } from "next/link";
4
+ import type { ComponentProps } from "react";
5
+ export interface CmsLinkUrlsContext {
6
+ locale: GetDocumentLinkContext["locale"];
7
+ options: GetDocumentLinkContext["options"];
8
+ baseUrl?: GetDocumentLinkContext["baseUrl"];
9
+ urlPrefixStrategy?: GetDocumentLinkContext["urlPrefixStrategy"];
10
+ }
11
+ export interface CmsLinkProps extends Omit<ComponentProps<typeof Link>, "href" | "type"> {
12
+ /** When true, renders a non-interactive `span` (Payload link blocks often expose this flag). */
13
+ disabled?: boolean;
14
+ /** Absolute site base URL (origin is enough, e.g. `https://example.com`) for resolving relative links and active-state matching. */
15
+ siteUrl: string;
16
+ /** Locale and plugin options passed to `getDocumentLink` for internal references. */
17
+ context: CmsLinkUrlsContext;
18
+ /** Link type from the CMS; internal resolution uses `reference` unless this is `"custom"`. */
19
+ type?: string | null;
20
+ /** Relationship value for internal links. */
21
+ reference?: GetDocumentLinkArgs | null;
22
+ /** Custom URL when `type` is `"custom"`. */
23
+ url?: string | null;
24
+ /** Explicit `href` overrides resolved relation and `url`. */
25
+ href?: LinkProps["href"];
26
+ newTab?: boolean | null;
27
+ matchType?: "exact" | "partial";
28
+ /** Extra pixels subtracted from the `#hash` target scroll offset (default `16`). */
29
+ hashScrollYOffset?: number;
30
+ }
31
+ export declare function CmsLink({ siteUrl, context, children, className, href, type, url, newTab, target, reference, disabled, matchType, hashScrollYOffset, onClick, ...props }: CmsLinkProps): import("react/jsx-runtime").JSX.Element;
32
+ //# sourceMappingURL=cms-link.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cms-link.d.ts","sourceRoot":"","sources":["../../src/next/cms-link.tsx"],"names":[],"mappings":"AAEA,OAAO,IAAI,MAAM,WAAW,CAAA;AAK5B,OAAO,KAAK,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAA;AAC3E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAC1C,OAAO,KAAK,EAAE,cAAc,EAAc,MAAM,OAAO,CAAA;AA0CvD,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,sBAAsB,CAAC,QAAQ,CAAC,CAAA;IACxC,OAAO,EAAE,sBAAsB,CAAC,SAAS,CAAC,CAAA;IAC1C,OAAO,CAAC,EAAE,sBAAsB,CAAC,SAAS,CAAC,CAAA;IAC3C,iBAAiB,CAAC,EAAE,sBAAsB,CAAC,mBAAmB,CAAC,CAAA;CAChE;AAED,MAAM,WAAW,YAAa,SAAQ,IAAI,CAAC,cAAc,CAAC,OAAO,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACtF,gGAAgG;IAChG,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,oIAAoI;IACpI,OAAO,EAAE,MAAM,CAAA;IACf,qFAAqF;IACrF,OAAO,EAAE,kBAAkB,CAAA;IAC3B,8FAA8F;IAC9F,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,6CAA6C;IAC7C,SAAS,CAAC,EAAE,mBAAmB,GAAG,IAAI,CAAA;IACtC,4CAA4C;IAC5C,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,6DAA6D;IAC7D,IAAI,CAAC,EAAE,SAAS,CAAC,MAAM,CAAC,CAAA;IACxB,MAAM,CAAC,EAAE,OAAO,GAAG,IAAI,CAAA;IACvB,SAAS,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;IAC/B,oFAAoF;IACpF,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAC3B;AAED,wBAAgB,OAAO,CAAC,EACtB,OAAO,EACP,OAAO,EACP,QAAQ,EACR,SAAS,EACT,IAAI,EACJ,IAAI,EACJ,GAAG,EACH,MAAM,EACN,MAAM,EACN,SAAS,EACT,QAAQ,EACR,SAAmB,EACnB,iBAAsB,EACtB,OAAO,EACP,GAAG,KAAK,EACT,EAAE,YAAY,2CAgEd"}
@@ -0,0 +1,2 @@
1
+ "use strict";var N=Object.create;var s=Object.defineProperty;var I=Object.getOwnPropertyDescriptor;var v=Object.getOwnPropertyNames;var M=Object.getPrototypeOf,_=Object.prototype.hasOwnProperty;var J=(t,e)=>{for(var n in e)s(t,n,{get:e[n],enumerable:!0})},h=(t,e,n,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of v(e))!_.call(t,r)&&r!==n&&s(t,r,{get:()=>e[r],enumerable:!(o=I(e,r))||o.enumerable});return t};var K=(t,e,n)=>(n=t!=null?N(M(t)):{},h(e||!t||!t.__esModule?s(n,"default",{value:t,enumerable:!0}):n,t)),V=t=>h(s({},"__esModule",{value:!0}),t);var et={};J(et,{CmsLink:()=>T});module.exports=V(et);var C=K(require("next/link"),1),w=require("next/navigation");function d(t,e){let r={...Y(e)??{defaultLocale:"en",locales:["en"]},...t.locales};return{...t,field:{name:"populatedUrl",...t.field},locales:{defaultLocale:r.defaultLocale??r.locales[0]??"en",locales:r.locales.length?r.locales:[r.defaultLocale??"en"]},rootPages:{slug:"root-pages",...t.rootPages,fields:t.rootPages?.fields??{indexPage:{isHomepage:!0,relationTo:"pages"}}}}}function b(t,e){return t.collections[e]}function Y(t){let e=t?.localization||void 0,n=e?.locales?.map(o=>typeof o=="string"?o:o.code).filter(o=>!!o);if(n?.length)return{defaultLocale:e?.defaultLocale??n[0]??"en",locales:n}}var m=t=>t.replace(/\/$/,"").replace(/^\/?/,"/");function y(t){return(t?.at(-1)?.url??"").replace(/(^\/)|(\/$)/g,"")}function O(t,{baseUrl:e,locale:n,options:o,urlPrefixStrategy:r}){if(typeof t.value=="string")throw new Error("Reference value is a string");if(t.value.populatedUrl)return m(t.value.populatedUrl);let l=d(o),i=b(l,t.relationTo),a=i?.routeCollection??t.relationTo,c=W(i,t.value,r??i?.prefixStrategy);return q(c,{baseUrl:e,collection:a,locale:n,options:l})}function q(t,{baseUrl:e,locale:n,options:o}){let r=d(o),i=[...(e||(n===r.locales?.defaultLocale?"":n)).split("/"),...t].filter(Boolean);return m(`/${i.join("/")}`)}function W(t,e,n){return t?.category?n==="rootPage"?[e.slug??""]:[Q(e),e.slug??""]:t?.breadcrumbs?[y(e.breadcrumbs)||e.slug||""]:[e.slug??""]}function Q(t){let e=t.categories;if(!Array.isArray(e)||e.length===0)return"";let o=e[0];if(!o||typeof o!="object"||typeof o=="string")return"";let r=o;return y(r.breadcrumbs)||(r.slug??"").replace(/(^\/)|(\/$)/g,"")}var P=require("react/jsx-runtime");function X(t){if(t==null)return"";if(typeof t=="string")return t.trim();if(typeof t=="object"){let e=t;return`${e.pathname??""}${e.search??""}${e.hash??""}`}return String(t).trim()}function Z(t,e){try{let n=t.trim();if(!n)return null;let o=new URL(n,e);if(o.protocol!=="http:"&&o.protocol!=="https:")return null;let r=new URL(e).origin;return o.origin!==r?null:o.pathname===""?"/":o.pathname}catch{return null}}function tt(t,e,n){return e==null?!1:n==="exact"?t===e:e==="/"?t==="/":t.startsWith(e)}function T({siteUrl:t,context:e,children:n,className:o,href:r,type:l,url:i,newTab:a,target:c,reference:u,disabled:D,matchType:S="exact",hashScrollYOffset:R=16,onClick:j,...$}){let A=(0,w.usePathname)();if(D===!0)return(0,P.jsx)("span",{className:o,children:n});let G=l!=="custom"&&u&&typeof u.value=="object"?O(u,e):null,p=!!(a||c==="_blank"),z=p?{rel:"noopener noreferrer",target:"_blank"}:{},L=r!=null&&r!==""?typeof r=="string"?r.replace("/#","#"):r:(G||i||"").replace("/#","#").trim(),U=X(L),B=g=>{let F=U.replace("/#","#"),f=new URL(F,window.location.href);if(f.hash&&f.pathname===window.location.pathname&&!p){g.preventDefault();let x=document.querySelector(f.hash);if(!x)return;let H=x.getBoundingClientRect().top+window.scrollY-R;window.scrollTo({top:H,behavior:"smooth"})}else!p&&!g.metaKey&&window.scrollTo({top:0,behavior:"instant"});j?.(g)},E=Z(U,t),k=tt(A,E,S);return(0,P.jsx)(C.default,{...$,...z,className:o,href:L,onClick:B,"data-state":k?"active":void 0,"data-active":k||void 0,children:n})}0&&(module.exports={CmsLink});
2
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/next/index.ts","../../src/next/cms-link.tsx","../../src/options.ts","../../src/utils.ts","../../src/link.ts"],"sourcesContent":["export { CmsLink } from \"./cms-link\"\n\nexport type { CmsLinkProps, CmsLinkUrlsContext } from \"./cms-link\"\n","\"use client\"\n\nimport Link from \"next/link\"\nimport { usePathname } from \"next/navigation\"\n\nimport { getDocumentLink } from \"../link\"\n\nimport type { GetDocumentLinkArgs, GetDocumentLinkContext } from \"../types\"\nimport type { LinkProps } from \"next/link\"\nimport type { ComponentProps, MouseEvent } from \"react\"\n\nfunction coerceToLocationString(href: LinkProps[\"href\"] | string | undefined | null): string {\n if (href == null) return \"\"\n if (typeof href === \"string\") return href.trim()\n if (typeof href === \"object\") {\n const o = href as { pathname?: string; search?: string; hash?: string }\n return `${o.pathname ?? \"\"}${o.search ?? \"\"}${o.hash ?? \"\"}`\n }\n return String(href).trim()\n}\n\nfunction sameSitePathnameForActiveMatch(href: string, siteUrl: string): string | null {\n try {\n const trimmed = href.trim()\n if (!trimmed) return null\n\n const resolved = new URL(trimmed, siteUrl)\n if (resolved.protocol !== \"http:\" && resolved.protocol !== \"https:\") return null\n\n const siteOrigin = new URL(siteUrl).origin\n if (resolved.origin !== siteOrigin) return null\n\n return resolved.pathname === \"\" ? \"/\" : resolved.pathname\n } catch {\n return null\n }\n}\n\nfunction isActivePathname(\n pathname: string,\n activePathname: string | null,\n matchType: \"exact\" | \"partial\",\n): boolean {\n if (activePathname == null) return false\n if (matchType === \"exact\") return pathname === activePathname\n\n if (activePathname === \"/\") return pathname === \"/\"\n\n return pathname.startsWith(activePathname)\n}\n\nexport interface CmsLinkUrlsContext {\n locale: GetDocumentLinkContext[\"locale\"]\n options: GetDocumentLinkContext[\"options\"]\n baseUrl?: GetDocumentLinkContext[\"baseUrl\"]\n urlPrefixStrategy?: GetDocumentLinkContext[\"urlPrefixStrategy\"]\n}\n\nexport interface CmsLinkProps extends Omit<ComponentProps<typeof Link>, \"href\" | \"type\"> {\n /** When true, renders a non-interactive `span` (Payload link blocks often expose this flag). */\n disabled?: boolean\n /** Absolute site base URL (origin is enough, e.g. `https://example.com`) for resolving relative links and active-state matching. */\n siteUrl: string\n /** Locale and plugin options passed to `getDocumentLink` for internal references. */\n context: CmsLinkUrlsContext\n /** Link type from the CMS; internal resolution uses `reference` unless this is `\"custom\"`. */\n type?: string | null\n /** Relationship value for internal links. */\n reference?: GetDocumentLinkArgs | null\n /** Custom URL when `type` is `\"custom\"`. */\n url?: string | null\n /** Explicit `href` overrides resolved relation and `url`. */\n href?: LinkProps[\"href\"]\n newTab?: boolean | null\n matchType?: \"exact\" | \"partial\"\n /** Extra pixels subtracted from the `#hash` target scroll offset (default `16`). */\n hashScrollYOffset?: number\n}\n\nexport function CmsLink({\n siteUrl,\n context,\n children,\n className,\n href,\n type,\n url,\n newTab,\n target,\n reference,\n disabled,\n matchType = \"exact\",\n hashScrollYOffset = 16,\n onClick,\n ...props\n}: CmsLinkProps) {\n const pathname = usePathname()\n\n if (disabled === true) {\n return <span className={className}>{children}</span>\n }\n\n const relationHref =\n type !== \"custom\" && reference && typeof reference.value === \"object\"\n ? getDocumentLink(reference, context)\n : null\n\n const shouldOpenNewTab = Boolean(newTab || target === \"_blank\")\n const newTabProps = shouldOpenNewTab\n ? { rel: \"noopener noreferrer\" as const, target: \"_blank\" as const }\n : {}\n\n const linkHrefResolved: LinkProps[\"href\"] =\n href != null && href !== \"\"\n ? typeof href === \"string\"\n ? href.replace(\"/#\", \"#\")\n : href\n : (relationHref || url || \"\").replace(\"/#\", \"#\").trim()\n\n const hrefString = coerceToLocationString(linkHrefResolved)\n\n const handleClick = (e: MouseEvent<HTMLAnchorElement>) => {\n const link = hrefString.replace(\"/#\", \"#\")\n\n const linkUrl = new URL(link, window.location.href)\n\n if (linkUrl.hash && linkUrl.pathname === window.location.pathname && !shouldOpenNewTab) {\n e.preventDefault()\n\n const hashTarget = document.querySelector<HTMLElement>(linkUrl.hash)\n\n if (!hashTarget) return\n\n const y = hashTarget.getBoundingClientRect().top + window.scrollY - hashScrollYOffset\n\n window.scrollTo({ top: y, behavior: \"smooth\" })\n } else if (!shouldOpenNewTab && !e.metaKey) {\n window.scrollTo({ top: 0, behavior: \"instant\" })\n }\n\n onClick?.(e)\n }\n\n const activePathname = sameSitePathnameForActiveMatch(hrefString, siteUrl)\n const isActiveLink = isActivePathname(pathname, activePathname, matchType)\n\n return (\n <Link\n {...props}\n {...newTabProps}\n className={className}\n href={linkHrefResolved}\n onClick={handleClick}\n data-state={isActiveLink ? \"active\" : undefined}\n data-active={isActiveLink || undefined}\n >\n {children}\n </Link>\n )\n}\n","import type {\n PayloadPluginConfig,\n PayloadPluginUrlsOptions,\n RootPageFieldOptions,\n UrlCollectionOptions,\n} from \"./types\"\n\nexport type NormalizedPayloadPluginUrlsOptions = PayloadPluginUrlsOptions & {\n collections: Record<string, UrlCollectionOptions>\n locales: {\n defaultLocale: string\n locales: string[]\n }\n rootPages: {\n slug: string\n label?: unknown\n fields: Record<string, RootPageFieldOptions>\n }\n}\n\nexport function normalizeOptions(\n options: PayloadPluginUrlsOptions,\n config?: PayloadPluginConfig,\n): NormalizedPayloadPluginUrlsOptions {\n const configLocales = getConfigLocales(config)\n const fallbackLocales = configLocales ?? { defaultLocale: \"en\", locales: [\"en\"] }\n const locales = {\n ...fallbackLocales,\n ...options.locales,\n }\n\n return {\n ...options,\n field: {\n name: \"populatedUrl\",\n ...options.field,\n },\n locales: {\n defaultLocale: locales.defaultLocale ?? locales.locales[0] ?? \"en\",\n locales: locales.locales.length ? locales.locales : [locales.defaultLocale ?? \"en\"],\n },\n rootPages: {\n slug: \"root-pages\",\n ...options.rootPages,\n fields: options.rootPages?.fields ?? {\n indexPage: {\n isHomepage: true,\n relationTo: \"pages\",\n },\n },\n },\n }\n}\n\nexport function getCollectionOptions(options: PayloadPluginUrlsOptions, collection: string) {\n return options.collections[collection]\n}\n\nexport function getCollectionEntries(options: PayloadPluginUrlsOptions) {\n return Object.entries(options.collections)\n}\n\nexport function getCollectionsForCategory(\n options: PayloadPluginUrlsOptions,\n categoryCollection: string,\n) {\n return getCollectionEntries(options)\n .filter(\n ([, collectionOptions]) => collectionOptions.category?.collection === categoryCollection,\n )\n .map(([collection]) => collection)\n}\n\nexport function getRootPageFieldNames(options: PayloadPluginUrlsOptions) {\n const normalizedOptions = normalizeOptions(options)\n return Object.keys(normalizedOptions.rootPages.fields)\n}\n\nexport function getHomepageRootPageField(options: PayloadPluginUrlsOptions) {\n const fields = normalizeOptions(options).rootPages.fields\n const homepageEntry =\n Object.entries(fields).find(([, field]) => field.isHomepage) ??\n Object.entries(fields).find(([fieldName]) => fieldName === \"indexPage\")\n\n return homepageEntry?.[0] ?? Object.keys(fields)[0] ?? \"indexPage\"\n}\n\nexport function getRootPageFieldOptions(options: PayloadPluginUrlsOptions, fieldName: string) {\n return normalizeOptions(options).rootPages.fields[fieldName]\n}\n\nfunction getConfigLocales(config: PayloadPluginConfig | undefined) {\n const localization = config?.localization || undefined\n const locales = localization?.locales\n ?.map((locale) => (typeof locale === \"string\" ? locale : locale.code))\n .filter((locale): locale is string => Boolean(locale))\n\n if (!locales?.length) {\n return undefined\n }\n\n return {\n defaultLocale: localization?.defaultLocale ?? locales[0] ?? \"en\",\n locales,\n }\n}\n","import type { Breadcrumb, UrlDoc, UrlUpdateSource } from \"./types\"\n\nconst withoutTrailingSlash = (path: string) => path.replace(/\\/$/, \"\").replace(/^\\/?/, \"/\")\n\nfunction getBreadcrumbsUrl(breadcrumbs: Breadcrumb[] | null | undefined) {\n const lastItem = breadcrumbs?.at(-1)\n const url = lastItem?.url ?? \"\"\n return url.replace(/(^\\/)|(\\/$)/g, \"\")\n}\n\nfunction mergeDoc<T extends object>(data: Partial<T>, originalDoc?: Partial<T>) {\n return {\n ...(originalDoc || {}),\n ...withoutUndefinedValues(data),\n } as T\n}\n\nfunction withoutPopulatedUrl<T extends object>(doc: T) {\n const { populatedUrl: _populatedUrl, ...rest } = doc as T & { populatedUrl?: unknown }\n return rest\n}\n\nfunction getDocumentId(doc: unknown) {\n if (!doc || typeof doc !== \"object\" || !(\"id\" in doc)) {\n return undefined\n }\n\n return typeof doc.id === \"string\" ? doc.id : undefined\n}\n\nfunction getRelationId(value: unknown) {\n if (typeof value === \"string\") {\n return value\n }\n\n if (!value || typeof value !== \"object\" || !(\"id\" in value)) {\n return undefined\n }\n\n return typeof value.id === \"string\" ? value.id : undefined\n}\n\nfunction normalizePath(path: string | undefined) {\n return withoutTrailingSlash(`/${path ?? \"\"}`.replace(/\\/+/g, \"/\"))\n}\n\nfunction getStringValue(value: unknown, key: \"populatedUrl\" | \"slug\") {\n if (!value || typeof value !== \"object\" || !(key in value)) {\n return undefined\n }\n\n const record = value as Record<\"populatedUrl\" | \"slug\", unknown>\n return typeof record[key] === \"string\" ? record[key] : undefined\n}\n\nfunction isDraftDoc(doc: UrlDoc) {\n return doc._status === \"draft\"\n}\n\nfunction getRecord(value: unknown) {\n return value && typeof value === \"object\" && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : {}\n}\n\nfunction dedupeSources<T extends UrlUpdateSource>(sources: T[]) {\n const seen = new Set<string>()\n\n return sources.filter((source) => {\n const key = sourceKey(source)\n if (seen.has(key)) {\n return false\n }\n seen.add(key)\n return true\n })\n}\n\nfunction sourceKey(source: UrlUpdateSource) {\n switch (source.type) {\n case \"category\":\n case \"collection\":\n case \"page\":\n return `${source.type}:${source.collection}:${source.id ?? \"\"}`\n case \"rootPages\":\n return `rootPages:${JSON.stringify(source.current)}:${JSON.stringify(source.previous)}`\n }\n}\n\nfunction withoutUndefinedValues<T extends object>(value: Partial<T>) {\n return Object.fromEntries(\n Object.entries(value).filter(([, entry]) => entry !== undefined),\n ) as Partial<T>\n}\n\nexport {\n getBreadcrumbsUrl,\n getRecord,\n dedupeSources,\n isDraftDoc,\n getStringValue,\n normalizePath,\n getRelationId,\n getDocumentId,\n withoutPopulatedUrl,\n mergeDoc,\n withoutTrailingSlash,\n}\n","import { getCollectionOptions, normalizeOptions } from \"./options\"\nimport { getBreadcrumbsUrl, withoutTrailingSlash } from \"./utils\"\n\nimport type {\n GetDocumentLinkArgs,\n GetDocumentLinkContext,\n Locale,\n PayloadPluginUrlsOptions,\n UrlCollectionOptions,\n UrlDoc,\n UrlPrefixStrategy,\n} from \"./types\"\n\nexport function getDocumentLink(\n reference: GetDocumentLinkArgs,\n { baseUrl, locale, options, urlPrefixStrategy }: GetDocumentLinkContext,\n) {\n if (typeof reference.value === \"string\") {\n throw new Error(\"Reference value is a string\")\n }\n\n if (reference.value.populatedUrl) {\n return withoutTrailingSlash(reference.value.populatedUrl)\n }\n\n const normalizedOptions = normalizeOptions(options)\n const collectionOptions = getCollectionOptions(normalizedOptions, reference.relationTo)\n const routeCollection = collectionOptions?.routeCollection ?? reference.relationTo\n const slugs = getSlugsForCollection(\n collectionOptions,\n reference.value,\n urlPrefixStrategy ?? collectionOptions?.prefixStrategy,\n )\n\n return getDocumentLinkBySlugs(slugs, {\n baseUrl,\n collection: routeCollection,\n locale,\n options: normalizedOptions,\n })\n}\n\nexport function getDocumentLinkBySlugs(\n slugs: string[],\n {\n baseUrl,\n locale,\n options,\n }: {\n baseUrl?: string\n collection: string\n locale: Locale\n options: PayloadPluginUrlsOptions\n },\n) {\n const normalizedOptions = normalizeOptions(options)\n const prefix = baseUrl || (locale === normalizedOptions.locales?.defaultLocale ? \"\" : locale)\n const segments = [...prefix.split(\"/\"), ...slugs].filter(Boolean)\n return withoutTrailingSlash(`/${segments.join(\"/\")}`)\n}\n\nexport function withLocalePrefix(path: string, locale: Locale, options: PayloadPluginUrlsOptions) {\n const defaultLocale = normalizeOptions(options).locales?.defaultLocale\n if (locale === defaultLocale) {\n return withoutTrailingSlash(path)\n }\n return withoutTrailingSlash(`/${locale}${path}`)\n}\n\nfunction getSlugsForCollection(\n collectionOptions: UrlCollectionOptions | undefined,\n doc: UrlDoc,\n strategy?: UrlPrefixStrategy,\n) {\n if (collectionOptions?.category) {\n return strategy === \"rootPage\"\n ? [doc.slug ?? \"\"]\n : [firstRelatedCategoryPath(doc), doc.slug ?? \"\"]\n }\n\n if (collectionOptions?.breadcrumbs) {\n return [getBreadcrumbsUrl(doc.breadcrumbs) || doc.slug || \"\"]\n }\n\n return [doc.slug ?? \"\"]\n}\n\nfunction firstRelatedCategoryPath(doc: UrlDoc) {\n const categories = doc.categories\n if (!Array.isArray(categories) || categories.length === 0) {\n return \"\"\n }\n\n const categoryItems = categories as unknown[]\n const first = categoryItems[0]\n if (!first || typeof first !== \"object\" || typeof first === \"string\") {\n return \"\"\n }\n\n const categoryDoc = first as UrlDoc\n return (\n getBreadcrumbsUrl(categoryDoc.breadcrumbs) ||\n (categoryDoc.slug ?? \"\").replace(/(^\\/)|(\\/$)/g, \"\")\n )\n}\n"],"mappings":"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","names":["next_exports","__export","CmsLink","__toCommonJS","import_link","import_navigation","normalizeOptions","options","config","locales","getConfigLocales","getCollectionOptions","collection","getConfigLocales","config","localization","locales","locale","withoutTrailingSlash","path","getBreadcrumbsUrl","breadcrumbs","getDocumentLink","reference","baseUrl","locale","options","urlPrefixStrategy","withoutTrailingSlash","normalizedOptions","normalizeOptions","collectionOptions","getCollectionOptions","routeCollection","slugs","getSlugsForCollection","getDocumentLinkBySlugs","segments","getSlugsForCollection","collectionOptions","doc","strategy","firstRelatedCategoryPath","getBreadcrumbsUrl","categories","first","categoryDoc","import_jsx_runtime","coerceToLocationString","href","o","sameSitePathnameForActiveMatch","siteUrl","trimmed","resolved","siteOrigin","isActivePathname","pathname","activePathname","matchType","CmsLink","context","children","className","type","url","newTab","target","reference","disabled","hashScrollYOffset","onClick","props","relationHref","getDocumentLink","shouldOpenNewTab","newTabProps","linkHrefResolved","hrefString","handleClick","e","link","linkUrl","hashTarget","y","isActiveLink","Link"]}
@@ -0,0 +1,3 @@
1
+ export { CmsLink } from "./cms-link";
2
+ export type { CmsLinkProps, CmsLinkUrlsContext } from "./cms-link";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/next/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AAEpC,YAAY,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA"}
@@ -0,0 +1,2 @@
1
+ import{s as f}from"../chunk-OKNQKSNQ.js";import A from"next/link";import{usePathname as M}from"next/navigation";import{jsx as k}from"react/jsx-runtime";function R(t){if(t==null)return"";if(typeof t=="string")return t.trim();if(typeof t=="object"){let n=t;return`${n.pathname??""}${n.search??""}${n.hash??""}`}return String(t).trim()}function E(t,n){try{let o=t.trim();if(!o)return null;let e=new URL(o,n);if(e.protocol!=="http:"&&e.protocol!=="https:")return null;let r=new URL(n).origin;return e.origin!==r?null:e.pathname===""?"/":e.pathname}catch{return null}}function H(t,n,o){return n==null?!1:o==="exact"?t===n:n==="/"?t==="/":t.startsWith(n)}function O({siteUrl:t,context:n,children:o,className:e,href:r,type:g,url:h,newTab:L,target:d,reference:i,disabled:x,matchType:C="exact",hashScrollYOffset:y=16,onClick:b,...w}){let P=M();if(x===!0)return k("span",{className:e,children:o});let v=g!=="custom"&&i&&typeof i.value=="object"?f(i,n):null,s=!!(L||d==="_blank"),T=s?{rel:"noopener noreferrer",target:"_blank"}:{},c=r!=null&&r!==""?typeof r=="string"?r.replace("/#","#"):r:(v||h||"").replace("/#","#").trim(),u=R(c),D=l=>{let S=u.replace("/#","#"),a=new URL(S,window.location.href);if(a.hash&&a.pathname===window.location.pathname&&!s){l.preventDefault();let m=document.querySelector(a.hash);if(!m)return;let G=m.getBoundingClientRect().top+window.scrollY-y;window.scrollTo({top:G,behavior:"smooth"})}else!s&&!l.metaKey&&window.scrollTo({top:0,behavior:"instant"});b?.(l)},U=E(u,t),p=H(P,U,C);return k(A,{...w,...T,className:e,href:c,onClick:D,"data-state":p?"active":void 0,"data-active":p||void 0,children:o})}export{O as CmsLink};
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/next/cms-link.tsx"],"sourcesContent":["\"use client\"\n\nimport Link from \"next/link\"\nimport { usePathname } from \"next/navigation\"\n\nimport { getDocumentLink } from \"../link\"\n\nimport type { GetDocumentLinkArgs, GetDocumentLinkContext } from \"../types\"\nimport type { LinkProps } from \"next/link\"\nimport type { ComponentProps, MouseEvent } from \"react\"\n\nfunction coerceToLocationString(href: LinkProps[\"href\"] | string | undefined | null): string {\n if (href == null) return \"\"\n if (typeof href === \"string\") return href.trim()\n if (typeof href === \"object\") {\n const o = href as { pathname?: string; search?: string; hash?: string }\n return `${o.pathname ?? \"\"}${o.search ?? \"\"}${o.hash ?? \"\"}`\n }\n return String(href).trim()\n}\n\nfunction sameSitePathnameForActiveMatch(href: string, siteUrl: string): string | null {\n try {\n const trimmed = href.trim()\n if (!trimmed) return null\n\n const resolved = new URL(trimmed, siteUrl)\n if (resolved.protocol !== \"http:\" && resolved.protocol !== \"https:\") return null\n\n const siteOrigin = new URL(siteUrl).origin\n if (resolved.origin !== siteOrigin) return null\n\n return resolved.pathname === \"\" ? \"/\" : resolved.pathname\n } catch {\n return null\n }\n}\n\nfunction isActivePathname(\n pathname: string,\n activePathname: string | null,\n matchType: \"exact\" | \"partial\",\n): boolean {\n if (activePathname == null) return false\n if (matchType === \"exact\") return pathname === activePathname\n\n if (activePathname === \"/\") return pathname === \"/\"\n\n return pathname.startsWith(activePathname)\n}\n\nexport interface CmsLinkUrlsContext {\n locale: GetDocumentLinkContext[\"locale\"]\n options: GetDocumentLinkContext[\"options\"]\n baseUrl?: GetDocumentLinkContext[\"baseUrl\"]\n urlPrefixStrategy?: GetDocumentLinkContext[\"urlPrefixStrategy\"]\n}\n\nexport interface CmsLinkProps extends Omit<ComponentProps<typeof Link>, \"href\" | \"type\"> {\n /** When true, renders a non-interactive `span` (Payload link blocks often expose this flag). */\n disabled?: boolean\n /** Absolute site base URL (origin is enough, e.g. `https://example.com`) for resolving relative links and active-state matching. */\n siteUrl: string\n /** Locale and plugin options passed to `getDocumentLink` for internal references. */\n context: CmsLinkUrlsContext\n /** Link type from the CMS; internal resolution uses `reference` unless this is `\"custom\"`. */\n type?: string | null\n /** Relationship value for internal links. */\n reference?: GetDocumentLinkArgs | null\n /** Custom URL when `type` is `\"custom\"`. */\n url?: string | null\n /** Explicit `href` overrides resolved relation and `url`. */\n href?: LinkProps[\"href\"]\n newTab?: boolean | null\n matchType?: \"exact\" | \"partial\"\n /** Extra pixels subtracted from the `#hash` target scroll offset (default `16`). */\n hashScrollYOffset?: number\n}\n\nexport function CmsLink({\n siteUrl,\n context,\n children,\n className,\n href,\n type,\n url,\n newTab,\n target,\n reference,\n disabled,\n matchType = \"exact\",\n hashScrollYOffset = 16,\n onClick,\n ...props\n}: CmsLinkProps) {\n const pathname = usePathname()\n\n if (disabled === true) {\n return <span className={className}>{children}</span>\n }\n\n const relationHref =\n type !== \"custom\" && reference && typeof reference.value === \"object\"\n ? getDocumentLink(reference, context)\n : null\n\n const shouldOpenNewTab = Boolean(newTab || target === \"_blank\")\n const newTabProps = shouldOpenNewTab\n ? { rel: \"noopener noreferrer\" as const, target: \"_blank\" as const }\n : {}\n\n const linkHrefResolved: LinkProps[\"href\"] =\n href != null && href !== \"\"\n ? typeof href === \"string\"\n ? href.replace(\"/#\", \"#\")\n : href\n : (relationHref || url || \"\").replace(\"/#\", \"#\").trim()\n\n const hrefString = coerceToLocationString(linkHrefResolved)\n\n const handleClick = (e: MouseEvent<HTMLAnchorElement>) => {\n const link = hrefString.replace(\"/#\", \"#\")\n\n const linkUrl = new URL(link, window.location.href)\n\n if (linkUrl.hash && linkUrl.pathname === window.location.pathname && !shouldOpenNewTab) {\n e.preventDefault()\n\n const hashTarget = document.querySelector<HTMLElement>(linkUrl.hash)\n\n if (!hashTarget) return\n\n const y = hashTarget.getBoundingClientRect().top + window.scrollY - hashScrollYOffset\n\n window.scrollTo({ top: y, behavior: \"smooth\" })\n } else if (!shouldOpenNewTab && !e.metaKey) {\n window.scrollTo({ top: 0, behavior: \"instant\" })\n }\n\n onClick?.(e)\n }\n\n const activePathname = sameSitePathnameForActiveMatch(hrefString, siteUrl)\n const isActiveLink = isActivePathname(pathname, activePathname, matchType)\n\n return (\n <Link\n {...props}\n {...newTabProps}\n className={className}\n href={linkHrefResolved}\n onClick={handleClick}\n data-state={isActiveLink ? \"active\" : undefined}\n data-active={isActiveLink || undefined}\n >\n {children}\n </Link>\n )\n}\n"],"mappings":"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","names":["Link","usePathname","jsx","coerceToLocationString","href","o","sameSitePathnameForActiveMatch","siteUrl","trimmed","resolved","siteOrigin","isActivePathname","pathname","activePathname","matchType","CmsLink","context","children","className","type","url","newTab","target","reference","disabled","hashScrollYOffset","onClick","props","usePathname","relationHref","getDocumentLink","shouldOpenNewTab","newTabProps","linkHrefResolved","hrefString","handleClick","e","link","linkUrl","hashTarget","y","isActiveLink","Link"]}
package/dist/types.d.ts CHANGED
@@ -1,38 +1,66 @@
1
1
  import type { CollectionAfterChangeHook, CollectionBeforeChangeHook, CollectionConfig, Field, GlobalAfterChangeHook, GlobalConfig, LabelFunction, Payload, Plugin, StaticLabel, WorkflowConfig } from "payload";
2
+ /** Locale code used when resolving localized URLs. */
2
3
  export type Locale = string;
4
+ /** Strategy used to prefix generated URLs for documents. */
3
5
  export type UrlPrefixStrategy = "category" | "rootPage";
6
+ /** Breadcrumb entry used to derive a document URL path. */
4
7
  export interface Breadcrumb {
8
+ /** Breadcrumb URL segment or full path supplied by Payload. */
5
9
  url?: string | null;
6
10
  }
11
+ /** Minimal document shape used by URL resolution helpers. */
7
12
  export interface UrlDoc {
13
+ /** Document id used for relationship values. */
8
14
  id?: string | number | null;
15
+ /** Slug used as the final URL segment. */
9
16
  slug?: string | null;
17
+ /** URL calculated by the plugin. */
10
18
  populatedUrl?: string | null;
19
+ /** Breadcrumbs used to derive a URL when breadcrumb mode is enabled. */
11
20
  breadcrumbs?: Breadcrumb[] | null;
21
+ /** Optional category relationship data used by category prefixing. */
12
22
  categories?: unknown;
23
+ /** Draft/published status used when deciding whether URL updates should cascade. */
13
24
  _status?: "draft" | "published" | null;
14
25
  [key: string]: unknown;
15
26
  }
27
+ /** Stored root-pages global data keyed by configured root page field names. */
16
28
  export interface RootPagesDoc {
29
+ /** Root-pages global id. */
17
30
  id?: string | null;
31
+ /** Relationship fields keyed by configured root page field name. */
18
32
  [field: string]: string | UrlDoc | null | undefined;
19
33
  }
34
+ /** URL plugin options for a single Payload collection. */
20
35
  export interface UrlCollectionOptions {
36
+ /** Whether to derive URLs from Payload breadcrumbs. */
21
37
  breadcrumbs?: boolean;
38
+ /** Prefixing strategy used for generated URLs. */
22
39
  prefixStrategy?: UrlPrefixStrategy;
40
+ /** Root page field name used when `prefixStrategy` is `"rootPage"`. */
23
41
  rootPage?: string;
42
+ /** Category relationship config used when `prefixStrategy` is `"category"`. */
24
43
  category?: {
44
+ /** Collection slug for related category documents. */
25
45
  collection: string;
46
+ /** Field name on the document that stores category relationships. */
26
47
  field?: string;
27
48
  };
49
+ /** Collection whose URL changes should trigger updates for this collection. */
28
50
  routeCollection?: string;
29
51
  }
52
+ /** Options for a generated root-pages relationship field. */
30
53
  export interface RootPageFieldOptions {
54
+ /** Marks this root page as the site homepage. */
31
55
  isHomepage?: boolean;
56
+ /** Collection slug used by the generated relationship field. */
32
57
  relationTo?: string;
58
+ /** Payload field config overrides for the generated relationship field. */
33
59
  overrides?: Partial<Field>;
34
60
  }
61
+ /** Options for configuring the Payload URLs plugin. */
35
62
  export interface PayloadPluginUrlsOptions {
63
+ /** URL options keyed by collection slug. */
36
64
  collections: Record<string, UrlCollectionOptions>;
37
65
  /**
38
66
  * Merged into the root-pages global after plugin defaults. Hook arrays are concatenated
@@ -40,69 +68,122 @@ export interface PayloadPluginUrlsOptions {
40
68
  * for relationship field tweaks.
41
69
  */
42
70
  overrides?: Partial<GlobalConfig>;
71
+ /** Config for the generated populated URL field. */
43
72
  field?: {
73
+ /** Field name for the generated populated URL field. */
44
74
  name?: string;
75
+ /** Field config overrides for the generated populated URL field. */
45
76
  overrides?: Record<string, unknown>;
46
77
  };
78
+ /** Locale config used when resolving URLs outside a localized request. */
47
79
  locales?: {
80
+ /** Fallback locale used when a request locale is missing. */
48
81
  defaultLocale?: Locale;
82
+ /** Supported locale codes for URL updates. */
49
83
  locales?: Locale[];
50
84
  };
85
+ /** Config for the root-pages global and its generated relationship fields. */
51
86
  rootPages?: {
87
+ /** Slug for the generated root-pages global. */
52
88
  slug?: string;
89
+ /** Admin label for the generated root-pages global. */
53
90
  label?: LabelFunction | StaticLabel;
91
+ /** Root page fields keyed by field name. */
54
92
  fields?: Record<string, RootPageFieldOptions>;
55
93
  };
56
94
  }
95
+ /** Payload instance type used by URL helpers. */
57
96
  export type PayloadLike = Payload;
97
+ /** Shared hook argument shape consumed by URL plugin hook utilities. */
58
98
  export interface HookArgs {
99
+ /** Collection metadata from the running Payload hook. */
59
100
  collection?: {
101
+ /** Collection slug for the hook document. */
60
102
  slug?: string;
61
103
  };
104
+ /** Payload request context object. */
62
105
  context?: Record<string, unknown>;
106
+ /** Incoming data in before-change hooks. */
63
107
  data?: UrlDoc;
108
+ /** Current document in after-change hooks. */
64
109
  doc?: UrlDoc;
110
+ /** Previous document state when Payload provides one. */
65
111
  previousDoc?: UrlDoc;
112
+ /** Original document state when Payload provides one. */
66
113
  originalDoc?: UrlDoc;
114
+ /** Payload request object. */
67
115
  req: {
116
+ /** Active request locale. */
68
117
  locale?: string;
118
+ /** Mutable request context shared across hooks. */
69
119
  context?: Record<string, unknown>;
120
+ /** Payload instance for querying related documents. */
70
121
  payload: PayloadLike;
71
122
  };
72
123
  }
124
+ /** Payload hook types used by the URL plugin. */
73
125
  export type Hook = CollectionBeforeChangeHook | CollectionAfterChangeHook | GlobalAfterChangeHook;
126
+ /** Payload config type accepted by plugin functions. */
74
127
  export type PayloadPluginConfig = Parameters<Plugin>[0];
128
+ /** Payload collection config type used by URL plugin helpers. */
75
129
  export type CollectionConfigLike = CollectionConfig;
130
+ /** Payload global config type used by URL plugin helpers. */
76
131
  export type GlobalConfigLike = GlobalConfig;
132
+ /** Payload field config type used by URL plugin helpers. */
77
133
  export type FieldLike = Field;
134
+ /** Payload workflow config type used by URL plugin helpers. */
78
135
  export type WorkflowLike = WorkflowConfig;
136
+ /** Payload plugin function type returned by this package. */
79
137
  export type PayloadPlugin = Plugin;
138
+ /** Arguments for resolving and assigning a document's populated URL. */
80
139
  export interface ResolvePopulatedUrlArgs {
140
+ /** Collection slug for the document being resolved. */
81
141
  collection: string;
142
+ /** Document data used to build the URL. */
82
143
  data: Partial<UrlDoc>;
144
+ /** Locale used for the generated URL. */
83
145
  locale: Locale;
146
+ /** Plugin options that describe collection and root page behavior. */
84
147
  options: PayloadPluginUrlsOptions;
148
+ /** Previous document state used to preserve unchanged values when needed. */
85
149
  originalDoc?: Partial<UrlDoc>;
150
+ /** Payload instance for resolving related category/root page documents. */
86
151
  payload?: PayloadLike;
152
+ /** Current root-pages global data. */
87
153
  rootPages: RootPagesDoc;
88
154
  }
155
+ /** Arguments for converting a relationship value into a document link. */
89
156
  export interface GetDocumentLinkArgs {
157
+ /** Collection slug for the relationship value. */
90
158
  relationTo: string;
159
+ /** Relationship value as an id or populated URL document. */
91
160
  value: string | UrlDoc;
92
161
  }
162
+ /** Context used when formatting a document link for a locale and URL strategy. */
93
163
  export interface GetDocumentLinkContext {
164
+ /** Optional base URL prepended to generated links. */
94
165
  baseUrl?: string;
166
+ /** Locale used for the generated link. */
95
167
  locale: Locale;
168
+ /** Plugin options used to determine URL structure. */
96
169
  options: PayloadPluginUrlsOptions;
170
+ /** Prefix strategy override for this link. */
97
171
  urlPrefixStrategy?: UrlPrefixStrategy;
98
172
  }
173
+ /** Source of a URL update triggered by a document or root-pages change. */
99
174
  export type UrlUpdateSource = {
175
+ /** Collection slug whose document changed. */
100
176
  collection: string;
177
+ /** Changed document id, when available. */
101
178
  id?: string | null;
179
+ /** Kind of document change that triggered URL updates. */
102
180
  type: "category" | "collection" | "page";
103
181
  } | {
182
+ /** Current root-pages global data. */
104
183
  current: RootPagesDoc;
184
+ /** Previous root-pages global data, when available. */
105
185
  previous?: RootPagesDoc;
186
+ /** Identifies a root-pages global update source. */
106
187
  type: "rootPages";
107
188
  };
108
189
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "payload-plugin-urls",
3
- "version": "0.9.2",
3
+ "version": "0.9.3",
4
4
  "description": "Payload CMS plugin for URL utilities.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -28,6 +28,11 @@
28
28
  "types": "./dist/index.d.ts",
29
29
  "import": "./dist/index.js",
30
30
  "require": "./dist/index.cjs"
31
+ },
32
+ "./next": {
33
+ "types": "./dist/next/index.d.ts",
34
+ "import": "./dist/next/index.js",
35
+ "require": "./dist/next/index.cjs"
31
36
  }
32
37
  },
33
38
  "files": [
@@ -38,10 +43,32 @@
38
43
  "build": "tsup --config tsup.config.ts --minify && tsc -p tsconfig.build.json --emitDeclarationOnly",
39
44
  "dev": "tsup --config tsup.config.ts --watch",
40
45
  "test": "vitest run tests/index.test.ts",
41
- "typecheck": "tsc --noEmit"
46
+ "typecheck": "tsc --noEmit",
47
+ "lint": "pnpm -w exec oxlint \"packages/${npm_package_name}\"",
48
+ "format": "pnpm exec oxfmt .",
49
+ "format:check": "pnpm exec oxfmt --check ."
42
50
  },
43
51
  "peerDependencies": {
44
- "payload": "^3.80.0"
52
+ "next": "^15.0.0 || ^16.0.0",
53
+ "payload": "^3.80.0",
54
+ "react": ">=18.0.0",
55
+ "react-dom": ">=18.0.0"
56
+ },
57
+ "peerDependenciesMeta": {
58
+ "next": {
59
+ "optional": true
60
+ },
61
+ "react": {
62
+ "optional": true
63
+ },
64
+ "react-dom": {
65
+ "optional": true
66
+ }
67
+ },
68
+ "devDependencies": {
69
+ "next": "^16.2.5",
70
+ "react": "^19.2.6",
71
+ "react-dom": "^19.2.6"
45
72
  },
46
73
  "publishConfig": {
47
74
  "access": "public"