payload-plugin-urls 0.9.1 → 0.9.2

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
@@ -57,6 +57,16 @@ export default buildConfig({
57
57
  },
58
58
  },
59
59
  },
60
+ overrides: {
61
+ label: "Site structure",
62
+ hooks: {
63
+ afterChange: [
64
+ async () => {
65
+ /* runs after the plugin's root-pages URL hook */
66
+ },
67
+ ],
68
+ },
69
+ },
60
70
  }),
61
71
  ],
62
72
  })
@@ -68,9 +78,21 @@ default locale and `/<locale>` for other locales. Each field can set `relationTo
68
78
  which are merged into the generated relationship field. Collection `rootPage` values such as
69
79
  `recipesPage` define URL prefixes for documents in that collection.
70
80
 
71
- Locales are read from the Payload `localization` config when the plugin is installed. You can still
72
- pass `locales` to the plugin options to override that inferred value or when using exported helpers
73
- outside the plugin lifecycle.
81
+ ### Root-pages global (`overrides`)
82
+
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.
88
+
89
+ ### Other options
90
+
91
+ - **`field`** — Rename the hidden `populatedUrl` field or pass field-level `overrides` (for example
92
+ `admin` UI tweaks).
93
+ - **`locales`** — Optional. When omitted, locales are taken from Payload `localization`. Set
94
+ `defaultLocale` and `locales` explicitly to override that, or when using exported helpers outside
95
+ the normal plugin lifecycle.
74
96
 
75
97
  Categorized collections can choose how their prefix is built:
76
98
 
@@ -83,11 +105,304 @@ when page, category, or root page relationships change.
83
105
 
84
106
  ## Exports
85
107
 
86
- - `payloadPluginUrls`
87
- - `populatedUrlField`
88
- - `resolvePopulatedUrl`
89
- - `getDocumentLink`
90
- - `getDocumentLinkBySlugs`
91
- - `getRootPageChangeSources`
92
- - `withLocalePrefix`
93
- - `withoutTrailingSlash`
108
+ The package default export is the same function as `payloadPluginUrls`. Import runtime helpers and
109
+ TypeScript types from `payload-plugin-urls`.
110
+
111
+ ### `payloadPluginUrls`
112
+
113
+ Registers the `root-pages` global, URL hooks and fields on configured collections, and the
114
+ `update-urls` job workflow.
115
+
116
+ ```ts
117
+ interface PayloadPluginUrls {
118
+ (options?: PayloadPluginUrlsOptions): PayloadPlugin
119
+ }
120
+ ```
121
+
122
+ - **`options`** — Plugin configuration; see [`PayloadPluginUrlsOptions`](#payloadpluginurlsoptions).
123
+ When omitted, the plugin is a no-op and returns the Payload config unchanged.
124
+
125
+ ### `populatedUrlField`
126
+
127
+ Builds the hidden, localized `populatedUrl` text field definition (same shape the plugin injects
128
+ into collections). Use it if you register the field manually.
129
+
130
+ ```ts
131
+ interface PopulatedUrlField {
132
+ (options?: PayloadPluginUrlsOptions): Field
133
+ }
134
+ ```
135
+
136
+ - **`options`** — Same plugin options object used for `name` / `overrides` under `field`; defaults
137
+ to `{ collections: {} }` if omitted.
138
+
139
+ ### `resolvePopulatedUrl`
140
+
141
+ Async helper that computes the public URL path for a document using your plugin `options`, locale,
142
+ merged document data, and the `root-pages` global snapshot.
143
+
144
+ ```ts
145
+ interface ResolvePopulatedUrl {
146
+ (args: ResolvePopulatedUrlArgs): Promise<string | undefined>
147
+ }
148
+ ```
149
+
150
+ `ResolvePopulatedUrlArgs`:
151
+
152
+ ```ts
153
+ interface ResolvePopulatedUrlArgs {
154
+ /** Collection slug configured under `options.collections`. */
155
+ collection: string
156
+ /** Incoming payload data for the document (merged with `originalDoc` internally). */
157
+ data: Partial<UrlDoc>
158
+ /** Locale code to resolve for. */
159
+ locale: Locale
160
+ /** Full plugin options including `collections` and `locales`. */
161
+ options: PayloadPluginUrlsOptions
162
+ /** Prior revision used to fill missing fields when resolving. */
163
+ originalDoc?: Partial<UrlDoc>
164
+ /** Optional Payload instance for loading related docs when needed. */
165
+ payload?: PayloadLike
166
+ /** Loaded `root-pages` global document for this locale. */
167
+ rootPages: RootPagesDoc
168
+ }
169
+ ```
170
+
171
+ ### `getDocumentLink`
172
+
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
+ `reference.value` is a plain id string instead of an expanded doc.
176
+
177
+ ```ts
178
+ interface GetDocumentLink {
179
+ (reference: GetDocumentLinkArgs, context: GetDocumentLinkContext): string
180
+ }
181
+ ```
182
+
183
+ - **`reference`** — Which collection the relationship targets and the related `UrlDoc` (expanded).
184
+
185
+ `GetDocumentLinkArgs`:
186
+
187
+ ```ts
188
+ interface GetDocumentLinkArgs {
189
+ relationTo: string
190
+ value: string | UrlDoc
191
+ }
192
+ ```
193
+
194
+ - **`relationTo`** — Target collection slug.
195
+ - **`value`** — Related document; must be an object with `populatedUrl` / category / slug data,
196
+ not an unresolved id string.
197
+
198
+ - **`context`** — Locale, plugin options, optional public `baseUrl`, and optional
199
+ `urlPrefixStrategy` override when building category paths.
200
+
201
+ `GetDocumentLinkContext`:
202
+
203
+ ```ts
204
+ interface GetDocumentLinkContext {
205
+ baseUrl?: string
206
+ locale: Locale
207
+ options: PayloadPluginUrlsOptions
208
+ urlPrefixStrategy?: UrlPrefixStrategy
209
+ }
210
+ ```
211
+
212
+ ### `getDocumentLinkBySlugs`
213
+
214
+ Joins URL segments with an optional locale or `baseUrl` prefix. Lower-level helper used when you
215
+ already know slug segments.
216
+
217
+ ```ts
218
+ interface GetDocumentLinkBySlugs {
219
+ (slugs: string[], context: GetDocumentLinkBySlugsContext): string
220
+ }
221
+ ```
222
+
223
+ `GetDocumentLinkBySlugsContext`:
224
+
225
+ ```ts
226
+ interface GetDocumentLinkBySlugsContext {
227
+ /** When set, prefixed before segments (can include origin or path prefix). */
228
+ baseUrl?: string
229
+ /** Declares which collection the path belongs to (for consistency with call sites). */
230
+ collection: string
231
+ locale: Locale
232
+ options: PayloadPluginUrlsOptions
233
+ }
234
+ ```
235
+
236
+ - **`slugs`** — Path segments in order (for example category path + page slug).
237
+ - **`context`** — Locale and options for default-locale handling; `collection` is part of the public
238
+ signature for naming consistency with internal routing.
239
+
240
+ ### `withLocalePrefix`
241
+
242
+ Prefixes `path` with `/<locale>` when `locale` is not the configured default locale.
243
+
244
+ ```ts
245
+ interface WithLocalePrefix {
246
+ (path: string, locale: Locale, options: PayloadPluginUrlsOptions): string
247
+ }
248
+ ```
249
+
250
+ - **`path`** — Path starting with `/` (trailing slash normalized away in the result).
251
+ - **`locale`** — Active locale.
252
+ - **`options`** — Plugin options (uses normalized `locales.defaultLocale`).
253
+
254
+ ### `withoutTrailingSlash`
255
+
256
+ Normalizes a path to start with `/` and removes a trailing slash.
257
+
258
+ ```ts
259
+ interface WithoutTrailingSlash {
260
+ (path: string): string
261
+ }
262
+ ```
263
+
264
+ - **`path`** — Raw path string.
265
+
266
+ ### `getRootPageChangeSources`
267
+
268
+ Returns job input sources describing which collections and homepage pages need URL refreshes after
269
+ the root-pages global changes. Used internally and available for custom workflows.
270
+
271
+ ```ts
272
+ interface GetRootPageChangeSources {
273
+ (current: RootPagesDoc, previous: RootPagesDoc | undefined, options: PayloadPluginUrlsOptions): UrlUpdateSource[]
274
+ }
275
+ ```
276
+
277
+ - **`current`** — New root-pages field values (ids or embedded docs).
278
+ - **`previous`** — Previous root-pages snapshot, or `undefined` on first save.
279
+ - **`options`** — Plugin options determining homepage field and `rootPage` mappings.
280
+
281
+ ### `hasUrlPathChanged`
282
+
283
+ Compares `populatedUrl` on two document-like values when both exist; otherwise compares `slug`.
284
+ Handy in hooks to detect URL-relevant edits.
285
+
286
+ ```ts
287
+ interface HasUrlPathChanged {
288
+ (doc: unknown, previousDoc: unknown): boolean
289
+ }
290
+ ```
291
+
292
+ - **`doc`** — Current document or partial.
293
+ - **`previousDoc`** — Prior revision for comparison.
294
+
295
+ ---
296
+
297
+ ### Exported types
298
+
299
+ References to `GlobalConfig`, `Field`, `LabelFunction`, `StaticLabel`, and `PayloadPlugin` use the
300
+ same names as in [`payload`](https://payloadcms.com/docs/configuration/overview). The following
301
+ interfaces are exported from `payload-plugin-urls` for use in your codebase.
302
+
303
+ #### `PayloadPluginUrlsOptions`
304
+
305
+ ```ts
306
+ interface PayloadPluginUrlsOptions {
307
+ /** Collections that participate in URL generation and how each behaves. */
308
+ collections: Record<string, UrlCollectionOptions>
309
+ /** Applied to the generated `root-pages` global only; see [Root-pages global](#root-pages-global-overrides). */
310
+ overrides?: Partial<GlobalConfig>
311
+ /** Customize the hidden URL field name or field config. */
312
+ field?: {
313
+ name?: string
314
+ overrides?: Record<string, unknown>
315
+ }
316
+ /** Override inferred localization or use helpers outside Payload. */
317
+ locales?: {
318
+ defaultLocale?: Locale
319
+ locales?: Locale[]
320
+ }
321
+ /** Root global slug, label, and relationship fields. */
322
+ rootPages?: {
323
+ slug?: string
324
+ label?: LabelFunction | StaticLabel
325
+ fields?: Record<string, RootPageFieldOptions>
326
+ }
327
+ }
328
+ ```
329
+
330
+ #### `UrlCollectionOptions`
331
+
332
+ ```ts
333
+ interface UrlCollectionOptions {
334
+ /** Use breadcrumb trail for path (typical for page trees). */
335
+ breadcrumbs?: boolean
336
+ /** How category segments appear in the path. */
337
+ prefixStrategy?: UrlPrefixStrategy
338
+ /** Key in `rootPages.fields` whose page defines this collection's URL prefix. */
339
+ rootPage?: string
340
+ category?: {
341
+ collection: string
342
+ field?: string
343
+ }
344
+ routeCollection?: string
345
+ }
346
+ ```
347
+
348
+ #### `RootPageFieldOptions`
349
+
350
+ ```ts
351
+ interface RootPageFieldOptions {
352
+ /** Marks the field whose target is the locale root `/`. */
353
+ isHomepage?: boolean
354
+ relationTo?: string
355
+ overrides?: Partial<Field>
356
+ }
357
+ ```
358
+
359
+ #### `UrlDoc`, `RootPagesDoc`, `Breadcrumb`
360
+
361
+ ```ts
362
+ interface Breadcrumb {
363
+ url?: string | null
364
+ }
365
+
366
+ interface UrlDoc {
367
+ id?: string | number | null
368
+ slug?: string | null
369
+ populatedUrl?: string | null
370
+ breadcrumbs?: Breadcrumb[] | null
371
+ categories?: unknown
372
+ _status?: "draft" | "published" | null
373
+ [key: string]: unknown
374
+ }
375
+
376
+ interface RootPagesDoc {
377
+ id?: string | null
378
+ [field: string]: string | UrlDoc | null | undefined
379
+ }
380
+ ```
381
+
382
+ #### `UrlPrefixStrategy`
383
+
384
+ ```ts
385
+ type UrlPrefixStrategy = "category" | "rootPage"
386
+ ```
387
+
388
+ #### `UrlUpdateSource`
389
+
390
+ ```ts
391
+ type UrlUpdateSource =
392
+ | {
393
+ collection: string
394
+ id?: string | null
395
+ type: "category" | "collection" | "page"
396
+ }
397
+ | {
398
+ current: RootPagesDoc
399
+ previous?: RootPagesDoc
400
+ type: "rootPages"
401
+ }
402
+ ```
403
+
404
+ #### Aliases from Payload
405
+
406
+ `PayloadPlugin`, `PayloadPluginConfig`, `CollectionConfigLike`, `GlobalConfigLike`, `FieldLike`,
407
+ `WorkflowLike`, `PayloadLike`, `Hook`, and `HookArgs` match the names exported from this package and
408
+ follow Payload’s definitions. `Locale` is `string`.
package/dist/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";var j=Object.defineProperty;var Z=Object.getOwnPropertyDescriptor;var q=Object.getOwnPropertyNames;var oo=Object.prototype.hasOwnProperty;var eo=(o,e)=>{for(var t in e)j(o,t,{get:e[t],enumerable:!0})},to=(o,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of q(e))!oo.call(o,r)&&r!==t&&j(o,r,{get:()=>e[r],enumerable:!(n=Z(e,r))||n.enumerable});return o};var no=o=>to(j({},"__esModule",{value:!0}),o);var yo={};eo(yo,{default:()=>B,getBreadcrumbsUrl:()=>g,getDocumentLink:()=>U,getDocumentLinkBySlugs:()=>v,getRootPageChangeSources:()=>I,hasUrlPathChanged:()=>F,payloadPluginUrls:()=>B,populatedUrlField:()=>L,resolvePopulatedUrl:()=>y,withLocalePrefix:()=>O,withoutTrailingSlash:()=>d});module.exports=no(yo);var d=o=>o.replace(/\/$/,"").replace(/^\/?/,"/");function g(o){return(o?.at(-1)?.url??"").replace(/(^\/)|(\/$)/g,"")}function G(o,e){return{...e||{},...lo(o)}}function z(o){let{populatedUrl:e,...t}=o;return t}function N(o){if(!(!o||typeof o!="object"||!("id"in o)))return typeof o.id=="string"?o.id:void 0}function k(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 C(o){return d(`/${o??""}`.replace(/\/+/g,"/"))}function b(o,e){if(!o||typeof o!="object"||!(e in o))return;let t=o;return typeof t[e]=="string"?t[e]:void 0}function D(o){return o._status==="draft"}function E(o){return o&&typeof o=="object"&&!Array.isArray(o)?o:{}}function _(o){let e=new Set;return o.filter(t=>{let n=ro(t);return e.has(n)?!1:(e.add(n),!0)})}function ro(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 lo(o){return Object.fromEntries(Object.entries(o).filter(([,e])=>e!==void 0))}function L(o={collections:{}}){return{name:o.field?.name??"populatedUrl",type:"text",label:!1,localized:!0,...o.field?.overrides??{},admin:{hidden:!0,...E(o.field?.overrides?.admin)}}}function c(o,e){let r={...ao(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 p(o,e){return o.collections[e]}function H(o){return Object.entries(o.collections)}function x(o,e){return H(o).filter(([,t])=>t.category?.collection===e).map(([t])=>t)}function w(o){let e=c(o);return Object.keys(e.rootPages.fields)}function R(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 m(o,e){return c(o).rootPages.fields[e]}function ao(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 U(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 d(o.value.populatedUrl);let l=c(n),i=p(l,o.relationTo),s=i?.routeCollection??o.relationTo,a=io(i,o.value,r??i?.prefixStrategy);return v(a,{baseUrl:e,collection:s,locale:t,options:l})}function v(o,{baseUrl:e,locale:t,options:n}){let r=c(n),i=[...(e||(t===r.locales?.defaultLocale?"":t)).split("/"),...o].filter(Boolean);return d(`/${i.join("/")}`)}function O(o,e,t){let n=c(t).locales?.defaultLocale;return e===n?d(o):d(`/${e}${o}`)}function io(o,e,t){return o?.category?t==="rootPage"?[e.slug??""]:[so(e),e.slug??""]:o?.breadcrumbs?[g(e.breadcrumbs)||e.slug||""]:[e.slug??""]}function so(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 g(r.breadcrumbs)||(r.slug??"").replace(/(^\/)|(\/$)/g,"")}async function y({collection:o,data:e,locale:t,options:n,originalDoc:r,payload:l,rootPages:i}){let s=c(n),a=p(s,o);if(!a)return;let u=G(e,r),f=R(s);if(a.breadcrumbs&&!a.rootPage){let P=await W({field:f,locale:t,payload:l,rootPages:i}),X=N(P);if(u.id&&X===u.id)return O("/",t,s);let S=C(g(u.breadcrumbs)),T=C(g(P?.breadcrumbs)),Y=T&&S.startsWith(`${T}/`)?C(S.slice(T.length)):S;return O(Y||`/${u.slug??""}`,t,s)}let h=await co({collectionOptions:a,locale:t,options:s,payload:l,rootPages:i});if(a.category){let P=await uo({categories:u[a.category.field??"categories"],collection:a.category.collection,locale:t,payload:l});return U({relationTo:o,value:{...z(u),[a.category.field??"categories"]:P,categories:P}},{baseUrl:h,locale:t,options:s})}return U({relationTo:o,value:z(u)},{baseUrl:h,locale:t,options:s})}async function co({collectionOptions:o,locale:e,options:t,payload:n,rootPages:r}){if(!o.rootPage)return;let l=o.rootPage,s=m(t,l)?.relationTo??"pages",a=await W({collection:s,field:l,locale:e,payload:n,rootPages:r});if(a)return typeof a.populatedUrl=="string"&&a.populatedUrl?V(a.populatedUrl,e,t):s!=="pages"?V(U({relationTo:s,value:a},{locale:e,options:t}),e,t):y({collection:s,data:{},locale:e,options:t,originalDoc:a,payload:n,rootPages:r})}function V(o,e,t){let n=c(t);return e===n.locales.defaultLocale||o===`/${e}`||o.startsWith(`/${e}/`)?o:O(o,e,n)}async function W({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 uo({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 M(o){return async({job:e,req:t})=>{let n=c(o),r=e.input?.sources??[];for(let l of n.locales?.locales??[]){let i=await t.payload.findGlobal?.({slug:n.rootPages?.slug??"root-pages",depth:2,locale:l});if(i)for(let s of go(r,n))switch(s.type){case"category":await A({collection:s.collection,locale:l,options:n,payload:t.payload,rootPages:i});for(let a of x(n,s.collection))await A({collection:a,locale:l,options:n,payload:t.payload,rootPages:i});break;case"collection":case"page":await A({collection:s.collection,locale:l,options:n,payload:t.payload,rootPages:i});break;case"rootPages":break}}}}function F(o,e){let t=b(o,"populatedUrl"),n=b(e,"populatedUrl");return t&&n?t!==n:b(o,"slug")!==b(e,"slug")}function I(o,e,t){let n=c(t),r=[],l=R(n),i=m(n,l)?.relationTo??"pages",s=k(o[l]),a=k(e?.[l]);s!==a&&(s&&r.push({type:"page",collection:i,id:s}),a&&r.push({type:"page",collection:i,id:a}));for(let[u,f]of H(n)){if(!f.rootPage)continue;let h=k(o[f.rootPage]),P=k(e?.[f.rootPage]);h!==P&&r.push({type:"collection",collection:u})}return _(r)}function $(o,e){let t={};for(let n of w(e))t[n]=o?.[n];return t}function go(o,e){return o.flatMap(t=>t.type!=="rootPages"?[t]:I(t.current,t.previous,e))}async function A({collection:o,locale:e,options:t,payload:n,rootPages:r}){let l=1;for(;;){let i=await n.find?.({collection:o,depth:2,draft:!1,limit:100,locale:e,overrideAccess:!0,page:l,pagination:!0});if(!i)return;for(let s of i.docs){let a=s;if(!a.id||D(a))continue;let u=await y({collection:o,data:{},locale:e,options:t,originalDoc:a,payload:n,rootPages:r});!u||a.populatedUrl===u||await n.update?.({collection:o,id:a.id,locale:e,overrideAccess:!0,data:{[t.field?.name??"populatedUrl"]:u},context:{disablePopulateUrl:!0,disableUrlUpdates:!0}})}if(!i.nextPage)return;l=i.nextPage}}function J(o){return async({collection:e,context:t,data:n={},originalDoc:r,req:l})=>{let i=l.locale;if(!i||i==="all"||t?.disablePopulateUrl||l.context?.disablePopulateUrl)return n;let s=await l.payload.findGlobal?.({slug:c(o).rootPages?.slug??"root-pages",depth:2,locale:i});if(!s)return n;let a=await y({collection:e?.slug??"",data:n,locale:i,options:o,originalDoc:r,payload:l.payload,rootPages:s});return a&&(n[o.field?.name??"populatedUrl"]=a),n}}function K(o){return async({collection:e,doc:t,previousDoc:n,req:r})=>{let l=t,i=n;if(r.context?.disableUrlUpdates||!l||D(l)||!F(l,i))return l;let s=p(o,e?.slug??"");if(!s)return l;let a=e?.slug??"",f=x(o,a).length>0?{type:"category",collection:a,id:l.id}:{type:s.breadcrumbs&&!s.rootPage?"page":"collection",collection:a,id:l.id};return await r.payload.jobs?.queue?.({workflow:"update-urls",input:{sources:[f]}}),l}}function Q(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:$(r,o),previous:$(l,o)}]}}),r}}var B=o=>o?e=>{let t=c(o,e),n=(e.collections??[]).map(r=>po(r,t));return{...e,collections:n,globals:[...e.globals??[],fo(t)],jobs:{...e.jobs??{},workflows:[...e.jobs?.workflows??[],{slug:"update-urls",handler:M(t)}]}}}:e=>e;function po(o,e){if(!p(e,o.slug))return o;let n=e.field?.name??"populatedUrl",r=o.fields.some(i=>"name"in i&&i.name===n)?o.fields:[...o.fields,L(e)],l=o.hooks??{};return{...o,defaultPopulate:{...o.defaultPopulate??{},[n]:!0},fields:r,hooks:{...l,beforeChange:[...l.beforeChange??[],J(e)],afterChange:[...l.afterChange??[],K(e)]}}}function fo(o){let e=c(o).rootPages;return{slug:e?.slug??"root-pages",label:e?.label??"Root pages",fields:w(o).map(t=>Po(t,o)),hooks:{afterChange:[Q(o)]}}}function Po(o,e){let t=m(e,o),n=t?.overrides??{},{name:r,type:l,hasMany:i,relationTo:s,...a}=n;return{name:o,type:"relationship",relationTo:t?.relationTo??"pages",hasMany:!1,admin:{width:"50%"},...a}}0&&(module.exports={getBreadcrumbsUrl,getDocumentLink,getDocumentLinkBySlugs,getRootPageChangeSources,hasUrlPathChanged,payloadPluginUrls,populatedUrlField,resolvePopulatedUrl,withLocalePrefix,withoutTrailingSlash});
1
+ "use strict";var H=Object.defineProperty;var oo=Object.getOwnPropertyDescriptor;var eo=Object.getOwnPropertyNames;var to=Object.prototype.hasOwnProperty;var no=(o,e)=>{for(var t in e)H(o,t,{get:e[t],enumerable:!0})},ro=(o,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of eo(e))!to.call(o,r)&&r!==t&&H(o,r,{get:()=>e[r],enumerable:!(n=oo(e,r))||n.enumerable});return o};var lo=o=>ro(H({},"__esModule",{value:!0}),o);var Oo={};no(Oo,{default:()=>$,getBreadcrumbsUrl:()=>g,getDocumentLink:()=>U,getDocumentLinkBySlugs:()=>G,getRootPageChangeSources:()=>z,hasUrlPathChanged:()=>F,payloadPluginUrls:()=>$,populatedUrlField:()=>L,resolvePopulatedUrl:()=>y,withLocalePrefix:()=>k,withoutTrailingSlash:()=>d});module.exports=lo(Oo);var d=o=>o.replace(/\/$/,"").replace(/^\/?/,"/");function g(o){return(o?.at(-1)?.url??"").replace(/(^\/)|(\/$)/g,"")}function B(o,e){return{...e||{},...ao(o)}}function T(o){let{populatedUrl:e,...t}=o;return t}function N(o){if(!(!o||typeof o!="object"||!("id"in o)))return typeof o.id=="string"?o.id:void 0}function O(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 d(`/${o??""}`.replace(/\/+/g,"/"))}function C(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 _(o){return o&&typeof o=="object"&&!Array.isArray(o)?o:{}}function E(o){let e=new Set;return o.filter(t=>{let n=io(t);return e.has(n)?!1:(e.add(n),!0)})}function io(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 ao(o){return Object.fromEntries(Object.entries(o).filter(([,e])=>e!==void 0))}function L(o={collections:{}}){return{name:o.field?.name??"populatedUrl",type:"text",label:!1,localized:!0,...o.field?.overrides??{},admin:{hidden:!0,..._(o.field?.overrides?.admin)}}}function c(o,e){let r={...so(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 p(o,e){return o.collections[e]}function j(o){return Object.entries(o.collections)}function R(o,e){return j(o).filter(([,t])=>t.category?.collection===e).map(([t])=>t)}function D(o){let e=c(o);return Object.keys(e.rootPages.fields)}function x(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 m(o,e){return c(o).rootPages.fields[e]}function so(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 U(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 d(o.value.populatedUrl);let l=c(n),a=p(l,o.relationTo),i=a?.routeCollection??o.relationTo,s=co(a,o.value,r??a?.prefixStrategy);return G(s,{baseUrl:e,collection:i,locale:t,options:l})}function G(o,{baseUrl:e,locale:t,options:n}){let r=c(n),a=[...(e||(t===r.locales?.defaultLocale?"":t)).split("/"),...o].filter(Boolean);return d(`/${a.join("/")}`)}function k(o,e,t){let n=c(t).locales?.defaultLocale;return e===n?d(o):d(`/${e}${o}`)}function co(o,e,t){return o?.category?t==="rootPage"?[e.slug??""]:[uo(e),e.slug??""]:o?.breadcrumbs?[g(e.breadcrumbs)||e.slug||""]:[e.slug??""]}function uo(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 g(r.breadcrumbs)||(r.slug??"").replace(/(^\/)|(\/$)/g,"")}async function y({collection:o,data:e,locale:t,options:n,originalDoc:r,payload:l,rootPages:a}){let i=c(n),s=p(i,o);if(!s)return;let u=B(e,r),f=x(i);if(s.breadcrumbs&&!s.rootPage){let P=await W({field:f,locale:t,payload:l,rootPages:a}),Z=N(P);if(u.id&&Z===u.id)return k("/",t,i);let S=h(g(u.breadcrumbs)),A=h(g(P?.breadcrumbs)),q=A&&S.startsWith(`${A}/`)?h(S.slice(A.length)):S;return k(q||`/${u.slug??""}`,t,i)}let b=await go({collectionOptions:s,locale:t,options:i,payload:l,rootPages:a});if(s.category){let P=await po({categories:u[s.category.field??"categories"],collection:s.category.collection,locale:t,payload:l});return U({relationTo:o,value:{...T(u),[s.category.field??"categories"]:P,categories:P}},{baseUrl:b,locale:t,options:i})}return U({relationTo:o,value:T(u)},{baseUrl:b,locale:t,options:i})}async function go({collectionOptions:o,locale:e,options:t,payload:n,rootPages:r}){if(!o.rootPage)return;let l=o.rootPage,i=m(t,l)?.relationTo??"pages",s=await W({collection:i,field:l,locale:e,payload:n,rootPages:r});if(s)return typeof s.populatedUrl=="string"&&s.populatedUrl?V(s.populatedUrl,e,t):i!=="pages"?V(U({relationTo:i,value:s},{locale:e,options:t}),e,t):y({collection:i,data:{},locale:e,options:t,originalDoc:s,payload:n,rootPages:r})}function V(o,e,t){let n=c(t);return e===n.locales.defaultLocale||o===`/${e}`||o.startsWith(`/${e}/`)?o:k(o,e,n)}async function W({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 po({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 M(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 fo(r,n))switch(i.type){case"category":await v({collection:i.collection,locale:l,options:n,payload:t.payload,rootPages:a});for(let s of R(n,i.collection))await v({collection:s,locale:l,options:n,payload:t.payload,rootPages:a});break;case"collection":case"page":await v({collection:i.collection,locale:l,options:n,payload:t.payload,rootPages:a});break;case"rootPages":break}}}}function F(o,e){let t=C(o,"populatedUrl"),n=C(e,"populatedUrl");return t&&n?t!==n:C(o,"slug")!==C(e,"slug")}function z(o,e,t){let n=c(t),r=[],l=x(n),a=m(n,l)?.relationTo??"pages",i=O(o[l]),s=O(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,f]of j(n)){if(!f.rootPage)continue;let b=O(o[f.rootPage]),P=O(e?.[f.rootPage]);b!==P&&r.push({type:"collection",collection:u})}return E(r)}function I(o,e){let t={};for(let n of D(e))t[n]=o?.[n];return t}function fo(o,e){return o.flatMap(t=>t.type!=="rootPages"?[t]:z(t.current,t.previous,e))}async function v({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 y({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 J(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 y({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 K(o){return async({collection:e,doc:t,previousDoc:n,req:r})=>{let l=t,a=n;if(r.context?.disableUrlUpdates||!l||w(l)||!F(l,a))return l;let i=p(o,e?.slug??"");if(!i)return l;let s=e?.slug??"",f=R(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:[f]}}),l}}function Q(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:I(r,o),previous:I(l,o)}]}}),r}}var $=o=>o?e=>{let t=c(o,e),n=(e.collections??[]).map(r=>Po(r,t));return{...e,collections:n,globals:[...e.globals??[],yo(t)],jobs:{...e.jobs??{},workflows:[...e.jobs?.workflows??[],{slug:"update-urls",handler:M(t)}]}}}:e=>e;function Po(o,e){if(!p(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,L(e)],l=o.hooks??{};return{...o,defaultPopulate:{...o.defaultPopulate??{},[n]:!0},fields:r,hooks:{...l,beforeChange:[...l.beforeChange??[],J(e)],afterChange:[...l.afterChange??[],K(e)]}}}function yo(o){let e=c(o).rootPages,t={slug:e?.slug??"root-pages",label:e?.label??"Root pages",fields:D(o).map(r=>mo(r,o)),hooks:{afterChange:[Q(o)]}},n=o.overrides;return n?ko(t,n):t}function mo(o,e){let t=m(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 X(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]=[...X(a),...X(i)]:i!==void 0&&(r[l]=i)}return r}function Y(o,e){return e?o?{...o,...e}:e:o}function ko(o,e){let{hooks:t,access:n,admin:r,fields:l,...a}=e,i={...o,...a};return n&&(i.access=Y(o.access,n)),r&&(i.admin=Y(o.admin,r)),(t||o.hooks)&&(i.hooks=Uo(o.hooks,t)),i}0&&(module.exports={getBreadcrumbsUrl,getDocumentLink,getDocumentLinkBySlugs,getRootPageChangeSources,hasUrlPathChanged,payloadPluginUrls,populatedUrlField,resolvePopulatedUrl,withLocalePrefix,withoutTrailingSlash});
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../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":["export { populatedUrlField } from \"./field\"\nexport { getDocumentLink, getDocumentLinkBySlugs, withLocalePrefix } from \"./link\"\nexport { payloadPluginUrls } from \"./plugin\"\nexport { resolvePopulatedUrl } from \"./resolver\"\nexport { getRootPageChangeSources, hasUrlPathChanged } from \"./update-urls\"\nexport { getBreadcrumbsUrl, withoutTrailingSlash } from \"./utils\"\n\nexport type {\n Breadcrumb,\n CollectionConfigLike,\n FieldLike,\n GetDocumentLinkArgs,\n GetDocumentLinkContext,\n GlobalConfigLike,\n Hook,\n HookArgs,\n Locale,\n PayloadLike,\n PayloadPlugin,\n PayloadPluginConfig,\n PayloadPluginUrlsOptions,\n ResolvePopulatedUrlArgs,\n RootPageFieldOptions,\n RootPagesDoc,\n UrlCollectionOptions,\n UrlDoc,\n UrlPrefixStrategy,\n UrlUpdateSource,\n WorkflowLike,\n} from \"./types\"\n\nexport { payloadPluginUrls as default } from \"./plugin\"\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 { 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\"\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 return {\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 }\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"],"mappings":"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","names":["index_exports","__export","payloadPluginUrls","getBreadcrumbsUrl","getDocumentLink","getDocumentLinkBySlugs","getRootPageChangeSources","hasUrlPathChanged","populatedUrlField","resolvePopulatedUrl","withLocalePrefix","withoutTrailingSlash","__toCommonJS","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","getRootPageFieldNames","createRootPageField","createRootPagesUrlUpdateHook","fieldOptions","getRootPageFieldOptions","overrides","_name","_type","_hasMany","_relationTo","override"]}
1
+ {"version":3,"sources":["../src/index.ts","../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":["export { populatedUrlField } from \"./field\"\nexport { getDocumentLink, getDocumentLinkBySlugs, withLocalePrefix } from \"./link\"\nexport { payloadPluginUrls } from \"./plugin\"\nexport { resolvePopulatedUrl } from \"./resolver\"\nexport { getRootPageChangeSources, hasUrlPathChanged } from \"./update-urls\"\nexport { getBreadcrumbsUrl, withoutTrailingSlash } from \"./utils\"\n\nexport type {\n Breadcrumb,\n CollectionConfigLike,\n FieldLike,\n GetDocumentLinkArgs,\n GetDocumentLinkContext,\n GlobalConfigLike,\n Hook,\n HookArgs,\n Locale,\n PayloadLike,\n PayloadPlugin,\n PayloadPluginConfig,\n PayloadPluginUrlsOptions,\n ResolvePopulatedUrlArgs,\n RootPageFieldOptions,\n RootPagesDoc,\n UrlCollectionOptions,\n UrlDoc,\n UrlPrefixStrategy,\n UrlUpdateSource,\n WorkflowLike,\n} from \"./types\"\n\nexport { payloadPluginUrls as default } from \"./plugin\"\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 { 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":["index_exports","__export","payloadPluginUrls","getBreadcrumbsUrl","getDocumentLink","getDocumentLinkBySlugs","getRootPageChangeSources","hasUrlPathChanged","populatedUrlField","resolvePopulatedUrl","withLocalePrefix","withoutTrailingSlash","__toCommonJS","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"]}
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 A(o,e){return{...e||{},...Z(o)}}function S(o){let{populatedUrl:e,...t}=o;return t}function I(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 C(o){return f(`/${o??""}`.replace(/\/+/g,"/"))}function O(o,e){if(!o||typeof o!="object"||!(e in o))return;let t=o;return typeof t[e]=="string"?t[e]:void 0}function D(o){return o._status==="draft"}function $(o){return o&&typeof o=="object"&&!Array.isArray(o)?o:{}}function B(o){let e=new Set;return o.filter(t=>{let n=Y(t);return e.has(n)?!1:(e.add(n),!0)})}function Y(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 Z(o){return Object.fromEntries(Object.entries(o).filter(([,e])=>e!==void 0))}function T(o={collections:{}}){return{name:o.field?.name??"populatedUrl",type:"text",label:!1,localized:!0,...o.field?.overrides??{},admin:{hidden:!0,...$(o.field?.overrides?.admin)}}}function c(o,e){let l={...q(e)??{defaultLocale:"en",locales:["en"]},...o.locales};return{...o,field:{name:"populatedUrl",...o.field},locales:{defaultLocale:l.defaultLocale??l.locales[0]??"en",locales:l.locales.length?l.locales:[l.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 j(o){return Object.entries(o.collections)}function L(o,e){return j(o).filter(([,t])=>t.category?.collection===e).map(([t])=>t)}function x(o){let e=c(o);return Object.keys(e.rootPages.fields)}function w(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 q(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 k(o,{baseUrl:e,locale:t,options:n,urlPrefixStrategy:l}){if(typeof o.value=="string")throw new Error("Reference value is a string");if(o.value.populatedUrl)return f(o.value.populatedUrl);let r=c(n),i=d(r,o.relationTo),s=i?.routeCollection??o.relationTo,a=oo(i,o.value,l??i?.prefixStrategy);return G(a,{baseUrl:e,collection:s,locale:t,options:r})}function G(o,{baseUrl:e,locale:t,options:n}){let l=c(n),i=[...(e||(t===l.locales?.defaultLocale?"":t)).split("/"),...o].filter(Boolean);return f(`/${i.join("/")}`)}function b(o,e,t){let n=c(t).locales?.defaultLocale;return e===n?f(o):f(`/${e}${o}`)}function oo(o,e,t){return o?.category?t==="rootPage"?[e.slug??""]:[eo(e),e.slug??""]:o?.breadcrumbs?[P(e.breadcrumbs)||e.slug||""]:[e.slug??""]}function eo(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 l=n;return P(l.breadcrumbs)||(l.slug??"").replace(/(^\/)|(\/$)/g,"")}async function m({collection:o,data:e,locale:t,options:n,originalDoc:l,payload:r,rootPages:i}){let s=c(n),a=d(s,o);if(!a)return;let u=A(e,l),g=w(s);if(a.breadcrumbs&&!a.rootPage){let p=await E({field:g,locale:t,payload:r,rootPages:i}),Q=I(p);if(u.id&&Q===u.id)return b("/",t,s);let R=C(P(u.breadcrumbs)),F=C(P(p?.breadcrumbs)),X=F&&R.startsWith(`${F}/`)?C(R.slice(F.length)):R;return b(X||`/${u.slug??""}`,t,s)}let h=await to({collectionOptions:a,locale:t,options:s,payload:r,rootPages:i});if(a.category){let p=await no({categories:u[a.category.field??"categories"],collection:a.category.collection,locale:t,payload:r});return k({relationTo:o,value:{...S(u),[a.category.field??"categories"]:p,categories:p}},{baseUrl:h,locale:t,options:s})}return k({relationTo:o,value:S(u)},{baseUrl:h,locale:t,options:s})}async function to({collectionOptions:o,locale:e,options:t,payload:n,rootPages:l}){if(!o.rootPage)return;let r=o.rootPage,s=y(t,r)?.relationTo??"pages",a=await E({collection:s,field:r,locale:e,payload:n,rootPages:l});if(a)return typeof a.populatedUrl=="string"&&a.populatedUrl?N(a.populatedUrl,e,t):s!=="pages"?N(k({relationTo:s,value:a},{locale:e,options:t}),e,t):m({collection:s,data:{},locale:e,options:t,originalDoc:a,payload:n,rootPages:l})}function N(o,e,t){let n=c(t);return e===n.locales.defaultLocale||o===`/${e}`||o.startsWith(`/${e}/`)?o:b(o,e,n)}async function E({collection:o="pages",field:e,locale:t,payload:n,rootPages:l}){let r=l[e];return r?typeof r!="string"?r:await n?.findByID?.({collection:o,id:r,depth:0,locale:t,select:{id:!0,slug:!0,populatedUrl:!0,breadcrumbs:!0}}):void 0}async function no({categories:o,collection:e,locale:t,payload:n}){return Array.isArray(o)?Promise.all(o.map(l=>typeof l!="string"?Promise.resolve(l):n?.findByID?.({collection:e,id:l,depth:2,locale:t})??Promise.resolve(l))):[]}function _(o){return async({job:e,req:t})=>{let n=c(o),l=e.input?.sources??[];for(let r of n.locales?.locales??[]){let i=await t.payload.findGlobal?.({slug:n.rootPages?.slug??"root-pages",depth:2,locale:r});if(i)for(let s of ro(l,n))switch(s.type){case"category":await z({collection:s.collection,locale:r,options:n,payload:t.payload,rootPages:i});for(let a of L(n,s.collection))await z({collection:a,locale:r,options:n,payload:t.payload,rootPages:i});break;case"collection":case"page":await z({collection:s.collection,locale:r,options:n,payload:t.payload,rootPages:i});break;case"rootPages":break}}}}function H(o,e){let t=O(o,"populatedUrl"),n=O(e,"populatedUrl");return t&&n?t!==n:O(o,"slug")!==O(e,"slug")}function V(o,e,t){let n=c(t),l=[],r=w(n),i=y(n,r)?.relationTo??"pages",s=U(o[r]),a=U(e?.[r]);s!==a&&(s&&l.push({type:"page",collection:i,id:s}),a&&l.push({type:"page",collection:i,id:a}));for(let[u,g]of j(n)){if(!g.rootPage)continue;let h=U(o[g.rootPage]),p=U(e?.[g.rootPage]);h!==p&&l.push({type:"collection",collection:u})}return B(l)}function v(o,e){let t={};for(let n of x(e))t[n]=o?.[n];return t}function ro(o,e){return o.flatMap(t=>t.type!=="rootPages"?[t]:V(t.current,t.previous,e))}async function z({collection:o,locale:e,options:t,payload:n,rootPages:l}){let r=1;for(;;){let i=await n.find?.({collection:o,depth:2,draft:!1,limit:100,locale:e,overrideAccess:!0,page:r,pagination:!0});if(!i)return;for(let s of i.docs){let a=s;if(!a.id||D(a))continue;let u=await m({collection:o,data:{},locale:e,options:t,originalDoc:a,payload:n,rootPages:l});!u||a.populatedUrl===u||await n.update?.({collection:o,id:a.id,locale:e,overrideAccess:!0,data:{[t.field?.name??"populatedUrl"]:u},context:{disablePopulateUrl:!0,disableUrlUpdates:!0}})}if(!i.nextPage)return;r=i.nextPage}}function W(o){return async({collection:e,context:t,data:n={},originalDoc:l,req:r})=>{let i=r.locale;if(!i||i==="all"||t?.disablePopulateUrl||r.context?.disablePopulateUrl)return n;let s=await r.payload.findGlobal?.({slug:c(o).rootPages?.slug??"root-pages",depth:2,locale:i});if(!s)return n;let a=await m({collection:e?.slug??"",data:n,locale:i,options:o,originalDoc:l,payload:r.payload,rootPages:s});return a&&(n[o.field?.name??"populatedUrl"]=a),n}}function M(o){return async({collection:e,doc:t,previousDoc:n,req:l})=>{let r=t,i=n;if(l.context?.disableUrlUpdates||!r||D(r)||!H(r,i))return r;let s=d(o,e?.slug??"");if(!s)return r;let a=e?.slug??"",g=L(o,a).length>0?{type:"category",collection:a,id:r.id}:{type:s.breadcrumbs&&!s.rootPage?"page":"collection",collection:a,id:r.id};return await l.payload.jobs?.queue?.({workflow:"update-urls",input:{sources:[g]}}),r}}function J(o){return async({doc:e,previousDoc:t,req:n})=>{let l=e,r=t;return n.context?.disableUrlUpdates||await n.payload.jobs?.queue?.({workflow:"update-urls",input:{sources:[{type:"rootPages",current:v(l,o),previous:v(r,o)}]}}),l}}var K=o=>o?e=>{let t=c(o,e),n=(e.collections??[]).map(l=>lo(l,t));return{...e,collections:n,globals:[...e.globals??[],ao(t)],jobs:{...e.jobs??{},workflows:[...e.jobs?.workflows??[],{slug:"update-urls",handler:_(t)}]}}}:e=>e;function lo(o,e){if(!d(e,o.slug))return o;let n=e.field?.name??"populatedUrl",l=o.fields.some(i=>"name"in i&&i.name===n)?o.fields:[...o.fields,T(e)],r=o.hooks??{};return{...o,defaultPopulate:{...o.defaultPopulate??{},[n]:!0},fields:l,hooks:{...r,beforeChange:[...r.beforeChange??[],W(e)],afterChange:[...r.afterChange??[],M(e)]}}}function ao(o){let e=c(o).rootPages;return{slug:e?.slug??"root-pages",label:e?.label??"Root pages",fields:x(o).map(t=>io(t,o)),hooks:{afterChange:[J(o)]}}}function io(o,e){let t=y(e,o),n=t?.overrides??{},{name:l,type:r,hasMany:i,relationTo:s,...a}=n;return{name:o,type:"relationship",relationTo:t?.relationTo??"pages",hasMany:!1,admin:{width:"50%"},...a}}export{K as default,P as getBreadcrumbsUrl,k as getDocumentLink,G as getDocumentLinkBySlugs,V as getRootPageChangeSources,H as hasUrlPathChanged,K as payloadPluginUrls,T as populatedUrlField,m as resolvePopulatedUrl,b as withLocalePrefix,f as withoutTrailingSlash};
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};
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\"\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 return {\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 }\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"],"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","getRootPageFieldNames","createRootPageField","createRootPagesUrlUpdateHook","fieldOptions","getRootPageFieldOptions","overrides","_name","_type","_hasMany","_relationTo","override"]}
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 +1 @@
1
- {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAIV,aAAa,EACb,wBAAwB,EAEzB,MAAM,SAAS,CAAA;AAEhB,eAAO,MAAM,iBAAiB,GAAI,UAAU,wBAAwB,KAAG,aA2BtE,CAAA"}
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAIV,aAAa,EACb,wBAAwB,EAEzB,MAAM,SAAS,CAAA;AAGhB,eAAO,MAAM,iBAAiB,GAAI,UAAU,wBAAwB,KAAG,aA2BtE,CAAA"}
package/dist/types.d.ts CHANGED
@@ -34,6 +34,12 @@ export interface RootPageFieldOptions {
34
34
  }
35
35
  export interface PayloadPluginUrlsOptions {
36
36
  collections: Record<string, UrlCollectionOptions>;
37
+ /**
38
+ * Merged into the root-pages global after plugin defaults. Hook arrays are concatenated
39
+ * (plugin hooks first, then yours). `fields` is ignored; use `rootPages.fields[field].overrides`
40
+ * for relationship field tweaks.
41
+ */
42
+ overrides?: Partial<GlobalConfig>;
37
43
  field?: {
38
44
  name?: string;
39
45
  overrides?: Record<string, unknown>;
@@ -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.1",
3
+ "version": "0.9.2",
4
4
  "description": "Payload CMS plugin for URL utilities.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",