123 lines
4.3 KiB
JavaScript
123 lines
4.3 KiB
JavaScript
import { archiveFieldName } from './types.js';
|
|
/**
|
|
* Works out what a URL points at: the home page, an ordinary page, a
|
|
* collection's archive, or a single entry.
|
|
*
|
|
* Routing only. An archive result says which collection to list and on which
|
|
* page, but doesn't fetch the entries — that's `getArchiveEntries`, called by
|
|
* whoever actually needs them. Keeping the two apart means listing changes
|
|
* (sorting, filtering, pagination) never touch routing rules, and metadata
|
|
* generation doesn't pay for a query it would discard.
|
|
*
|
|
* The trick is that archive prefixes aren't configured anywhere — they're the
|
|
* slug of whichever page an editor assigned as that collection's archive. So
|
|
* /pl/artykuly and /en/articles come from one assignment, and renaming the page
|
|
* moves the whole section.
|
|
*
|
|
* Resolution order matters: a first segment matching an archive's slug wins
|
|
* over an ordinary page of the same name, because an archive *is* a page and
|
|
* would otherwise shadow its own entries.
|
|
*
|
|
* Depth beyond {archive}/{entry} isn't supported — categories in the path would
|
|
* make canonical and hreflang ambiguous (the same entry reachable under several
|
|
* URLs).
|
|
*/ export async function resolveRoute({ content, locale, page = 1, pagesSlug = 'pages', payload, segments, settingsSlug = 'site-settings' }) {
|
|
const settings = await payload.findGlobal({
|
|
slug: settingsSlug,
|
|
depth: 1,
|
|
locale: locale
|
|
});
|
|
// Locale root → Homepage from System Pages.
|
|
// settings.homepage is a shallow relation (depth: 1 above) — it identifies
|
|
// WHICH page is the homepage, but its nested block relations (e.g. Hero
|
|
// images) aren't populated. Re-fetch that page from the pages collection at
|
|
// the same depth as every other page, so the frontend gets one consistent
|
|
// shape. Uses pagesSlug/locale from args — no hard-coded collection or locale.
|
|
if (!segments?.length) {
|
|
const homepage = settings.homepage;
|
|
if (!homepage || typeof homepage !== 'object') {
|
|
return null;
|
|
}
|
|
const homepageId = homepage.id;
|
|
const doc = await payload.findByID({
|
|
id: homepageId,
|
|
collection: pagesSlug,
|
|
depth: 2,
|
|
locale: locale
|
|
});
|
|
return doc ? {
|
|
type: 'home',
|
|
doc: doc
|
|
} : null;
|
|
}
|
|
const [first, ...rest] = segments;
|
|
// Does the first segment name an archive page?
|
|
for (const collection of content?.collections ?? []){
|
|
const archive = settings[archiveFieldName(collection.slug)];
|
|
if (!archive || typeof archive !== 'object') {
|
|
continue;
|
|
}
|
|
const archiveDoc = archive;
|
|
if (archiveDoc.slug !== first) {
|
|
continue;
|
|
}
|
|
// /pl/artykuly → the archive page itself.
|
|
if (rest.length === 0) {
|
|
return {
|
|
type: 'archive',
|
|
collection: collection.slug,
|
|
doc: archiveDoc,
|
|
page,
|
|
perPage: collection.perPage ?? 10
|
|
};
|
|
}
|
|
// /pl/artykuly/moj-post → an entry.
|
|
if (rest.length === 1) {
|
|
const found = await payload.find({
|
|
collection: collection.slug,
|
|
depth: 2,
|
|
limit: 1,
|
|
locale: locale,
|
|
where: {
|
|
slug: {
|
|
equals: rest[0]
|
|
}
|
|
}
|
|
});
|
|
const entry = found.docs[0];
|
|
if (!entry) {
|
|
return null;
|
|
}
|
|
return {
|
|
type: 'entry',
|
|
archive: archiveDoc,
|
|
collection: collection.slug,
|
|
doc: entry
|
|
};
|
|
}
|
|
// Deeper than {archive}/{entry}.
|
|
return null;
|
|
}
|
|
// An ordinary page. Joined, so nested slugs ('a/b') keep working.
|
|
const found = await payload.find({
|
|
collection: pagesSlug,
|
|
depth: 2,
|
|
limit: 1,
|
|
locale: locale,
|
|
where: {
|
|
slug: {
|
|
equals: segments.join('/')
|
|
}
|
|
}
|
|
});
|
|
const doc = found.docs[0];
|
|
if (!doc) {
|
|
return null;
|
|
}
|
|
return {
|
|
type: 'page',
|
|
doc: doc
|
|
};
|
|
}
|
|
|
|
//# sourceMappingURL=resolveRoute.js.map
|