@paroicms/server
Version:
The ParoiCMS server
127 lines • 5.87 kB
JavaScript
import { getDocumentTypeByName, makePreviewUrl } from "@paroicms/internal-anywhere-lib";
import { toAbsoluteUrl } from "@paroicms/internal-server-lib";
import { getNodeAncestorsWithSlug, } from "../../admin-backend/node/node-cte.queries.js";
import { makeCacheDependencyKey, makeCacheKey } from "../../common/text-cache.js";
import { shouldPrefixWithLanguage } from "../../helpers/url-helpers.js";
export function getHomeUrl(siteContext, language, options) {
const url = shouldPrefixWithLanguage(siteContext.siteSchema, language) ? `/${language}` : "/";
return options?.absoluteUrl ? toAbsoluteUrl(siteContext, url) : url;
}
export async function getUrlOfDocument(siteContext, tracker, documentId, options = {}) {
const applyAbsoluteUrl = (url) => options.absoluteUrl ? toAbsoluteUrl(siteContext, url) : url;
if (!options.forPreview) {
const cacheKey = makeCacheKey(siteContext.logger, { kind: "url", documentId });
const cacheValue = await siteContext.textCache.getCacheValue(cacheKey, tracker);
if (cacheValue) {
if (!options.returnUrlDependencyKeys)
return applyAbsoluteUrl(cacheValue.value);
return {
url: applyAbsoluteUrl(cacheValue.value),
dependencyKeys: await siteContext.textCache.getDependencyKeys(cacheKey, tracker),
};
}
}
const ancestors = await getNodeAncestorsWithSlug(siteContext, tracker, documentId);
const publishedAncestors = ensureAncestorsArePublished(ancestors);
if (publishedAncestors) {
const { language } = documentId;
publishedAncestors.reverse();
publishedAncestors.shift();
let dependencyKeys;
let url;
if (publishedAncestors.length === 0) {
url = getHomeUrl(siteContext, language);
dependencyKeys = [];
}
else {
url = makeDocumentUrl(siteContext, publishedAncestors, language);
dependencyKeys = makeUrlDependencyKeys(publishedAncestors, language);
}
if (!options.forPreview) {
const cacheKey = makeCacheKey(siteContext.logger, { kind: "url", documentId });
await siteContext.textCache.setCacheValue({
cacheKey,
value: url,
dependencyKeys,
}, tracker);
}
const finalUrl = applyAbsoluteUrl(url);
return options.returnUrlDependencyKeys ? { url: finalUrl, dependencyKeys } : finalUrl;
}
if (options.forPreview) {
const previewUrl = makePreviewUrl(siteContext.previewSecret, documentId.language, documentId.nodeId);
const finalUrl = applyAbsoluteUrl(previewUrl);
return options.returnUrlDependencyKeys
? { url: finalUrl, dependencyKeys: ["previewUrl"] }
: finalUrl;
}
if (options.returnUndef)
return;
throw new Error(`Document '${documentId.nodeId}:${documentId.language}' is not published yet`);
}
function ensureAncestorsArePublished(ancestors) {
const now = Date.now();
for (const ancestor of ancestors) {
if (!ancestor.ready ||
ancestor.publishDate === undefined ||
ancestor.publishDate.getTime() > now) {
return;
}
}
return ancestors;
}
function makeDocumentUrl(siteContext, ancestors, language) {
const { siteSchema } = siteContext;
const urlSegments = shouldPrefixWithLanguage(siteContext.siteSchema, language) ? [language] : [];
let parent = getDocumentTypeByName(siteSchema, "home");
for (const ancestor of ancestors) {
if (!parent.regularChildren?.includes(ancestor.typeName) &&
!parent.routingChildren?.includes(ancestor.typeName)) {
throw new Error(`schema and database are not compatible, '${ancestor.typeName}' should not be a child of '${parent.typeName}'`);
}
const docType = getDocumentTypeByName(siteSchema, ancestor.typeName);
if (docType.documentKind === "routing") {
const routePart = docType.route?.[language];
if (!routePart) {
throw new Error(`missing urlPath['${language}'] in document type '${docType.typeName}'`);
}
urlSegments.push(routePart);
}
else {
if (docType.route === ":relativeId-:slug") {
urlSegments.push(makeRelativeIdSlugUrlPart(ancestor));
}
else if (docType.route === ":yyyy/:mm/:dd/:relativeId-:slug") {
const { publishDate } = ancestor;
urlSegments.push(String(publishDate.getFullYear()).padStart(4, "0"));
urlSegments.push(String(publishDate.getMonth() + 1).padStart(2, "0"));
urlSegments.push(String(publishDate.getDate()).padStart(2, "0"));
urlSegments.push(makeRelativeIdSlugUrlPart(ancestor));
}
else if (docType.route === ":slug") {
if (!ancestor.slug) {
throw new Error(`missing slug in '${docType.typeName}' for route ':slug'`);
}
urlSegments.push(ancestor.slug);
}
else if (docType.route === ":relativeId") {
urlSegments.push(ancestor.relativeId);
}
else {
throw new Error(`in '${docType.typeName}', unknown value for route: '${docType.route}'`);
}
}
parent = docType;
}
return `/${urlSegments.join("/")}`;
}
function makeUrlDependencyKeys(ancestors, language) {
return ancestors.map((part) => makeCacheDependencyKey({
documentId: { language, nodeId: part.nodeId },
perimeter: "slug",
}));
}
function makeRelativeIdSlugUrlPart(part) {
return part.slug ? `${part.relativeId}-${part.slug}` : part.relativeId;
}
//# sourceMappingURL=make-url.js.map