Files
ipal-kit/src/modules/hooks/trackSlugHistory.ts
T

39 lines
1.4 KiB
TypeScript

import type { CollectionBeforeChangeHook } from 'payload'
/**
* When a document's slug changes, appends the OLD slug to a `slugHistory` array
* field. The project reads slugHistory to serve a 301 redirect from old URLs to
* the current one — so changing a slug doesn't 404 the old address (a real SEO
* loss / audit finding).
*
* Requires a `slugHistory` field on the collection:
* { name: 'slugHistory', type: 'array', fields: [{ name: 'slug', type: 'text' }],
* admin: { readOnly: true } }
*
* hooks: { beforeChange: [trackSlugHistoryHook] }
*
* The project then, in resolveRoute or a redirect check, looks up slugHistory and
* 301s to the current slug. See docs/hooks.md.
*/
export const trackSlugHistoryHook: CollectionBeforeChangeHook = ({ data, originalDoc }) => {
const oldSlug = originalDoc?.slug
const newSlug = data.slug
if (
typeof oldSlug === 'string' &&
typeof newSlug === 'string' &&
oldSlug !== newSlug &&
oldSlug.length > 0
) {
const history: Array<{ slug: string }> = Array.isArray(data.slugHistory)
? data.slugHistory
: Array.isArray(originalDoc?.slugHistory)
? originalDoc.slugHistory
: []
// Avoid duplicates; don't record the new slug itself.
if (!history.some((h) => h?.slug === oldSlug)) {
data.slugHistory = [...history, { slug: oldSlug }]
}
}
return data
}