Files
ipal-kit/dist/modules/content/resolveRoute.js
T

111 lines
3.7 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.
if (!segments?.length) {
const homepage = settings.homepage;
if (homepage && typeof homepage === 'object') {
return {
type: 'home',
doc: homepage
};
}
return 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