UNPKG

@paroicms/server

Version:
127 lines 5.87 kB
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