UNPKG

@paroicms/server

Version:
261 lines 13.9 kB
import { getDocumentTypeByName } from "@paroicms/internal-anywhere-lib"; import { toAbsoluteUrl } from "@paroicms/internal-server-lib"; import { encodeLNodeId, } from "@paroicms/public-anywhere-lib"; import { type } from "arktype"; import { getSiteFieldValue } from "../admin-backend/fields/load-fields.queries.js"; import { getHandleOfSiteField } from "../common/media-handles.helpers.js"; import { toMSourceMedia, toTpSourceMedia } from "../common/medias/to-media-values.js"; import { makeCacheDependencyKey } from "../common/text-cache.js"; import { loadRoutingClusterFromNode } from "../connector/db-init/load-routing-cluster.queries.js"; import { truncExcerptToWord } from "../helpers/excerpt.helpers.js"; import { getNodeTypeLabel } from "../helpers/label-translator.helper.js"; import { createLiquidDrop, loadOrFromRenderingCache } from "../liquidjs-tools/liquidjs-drop.js"; import { getFeaturedImageOf } from "../rendered-site/helpers/medias.helpers.js"; import { getUrlOfDocument } from "../rendered-site/page-route/make-url.js"; import { getPublicBreadcrumb } from "./breadcrumb.queries.js"; import { getClusterNodeOf, toTpClusterPayload, toTpRoutingClusterNode, } from "./cluster-payloads.js"; import { createPartDrop } from "./create-part-drop.js"; import { loadExcerpt } from "./excerpt.queries.js"; import { loadPublicFieldValues } from "./field-values.js"; import { getParentDocument } from "./get-parent.queries.js"; import { getSiblingDocuments } from "./get-siblings.queries.js"; import { makeJsonLdPayload } from "./json-ld-payload.js"; import { loadDefaultImage } from "./load-default-image.js"; import { makeImageAvailable } from "./make-image-available.js"; import { countPartsOf, formatListOfPartValues, keyOfParentPartData, loadPartsOf, } from "./parts.queries.js"; import { loadTranslationsAsDrops } from "./translations.queries.js"; const StringOrUndefinedAT = type("string|undefined"); export function createDocPayloadDrop(renderingContext, docValuesOrFn, options) { const { siteContext } = renderingContext; const { documentId } = options; return createLiquidDrop(renderingContext, async () => { const docValues = typeof docValuesOrFn === "function" ? await docValuesOrFn() : docValuesOrFn; const documentType = getDocumentTypeByName(siteContext.siteSchema, docValues.type); if (docValues.nodeId !== documentId.nodeId || docValues.language !== documentId.language) { throw new Error("Document ID mismatch"); } const typeLabel = getNodeTypeLabel(siteContext.siteSchema, { language: docValues.language, typeName: docValues.type, }); renderingContext.addDependencyKey(makeCacheDependencyKey({ documentId })); const id = encodeLNodeId(docValues); return { renderingCacheKey: `doc:${id}:${options.fieldNames?.join(",") ?? "full"}`, values: { kind: options.kind ?? (documentType.documentKind === "routing" ? "routingDocument" : "regularDocument"), get leafType() { siteContext.logger.warn("'leafType' is deprecated, use 'type' instead"); return docValues.type; }, get leafId() { siteContext.logger.warn("'leafId' is deprecated, use 'nodeId' instead"); return docValues.nodeId; }, id, ...docValues, get lang() { siteContext.logger.warn("'doc.lang' is deprecated, use 'doc.language' instead"); return docValues.language; }, languageLabel: siteContext.siteSchema.languageLabels[docValues.language], url: options.url ?? (() => loadUrlOfDocument(renderingContext, docValues)), excerpt: () => loadExcerpt(siteContext, renderingContext.tracker, { lNodeId: docValues, fieldTypes: documentType.fields ?? [], }), list: createPartsDrop(renderingContext, docValues, documentType), listSize: createPartCountDrop(renderingContext, docValues, documentType), defaultImage: async () => { const image = await loadDefaultImage(renderingContext, { fieldTypes: documentType.fields, nodeId: docValues.nodeId, language: docValues.language, }); return image ? toTpSourceMedia(renderingContext, image) : undefined; }, defaultImageId: async () => { siteContext.logger.warn("'defaultImageId' is deprecated, use 'defaultImage' instead"); const image = await loadDefaultImage(renderingContext, { fieldTypes: documentType.fields, nodeId: docValues.nodeId, language: docValues.language, }); return image?.id; }, featuredImage: async () => { const image = await getFeaturedImageOf(renderingContext, { nodeId: docValues.nodeId, documentType, }); return image ? toTpSourceMedia(renderingContext, image) : undefined; }, featuredImageId: async () => { siteContext.logger.warn("'featuredImageId' is deprecated, use 'featuredImage' instead"); const image = await getFeaturedImageOf(renderingContext, { nodeId: docValues.nodeId, documentType, }); return image?.id; }, field: () => loadPublicFieldValues(renderingContext, { typeName: docValues.type, lNodeId: docValues, fieldNames: options.fieldNames, }), fields: () => { siteContext.logger.warn("'fields' is deprecated, use 'field' instead"); return loadPublicFieldValues(renderingContext, { typeName: docValues.type, lNodeId: docValues, fieldNames: options.fieldNames, }); }, translations: () => loadTranslationsAsDrops(renderingContext, docValues), labeling: () => { siteContext.logger.warn("'labeling' no longer exists, use a labeling field instead"); }, singleLabeling: () => { siteContext.logger.warn("'singleLabeling' no longer exists, use a labeling field instead"); }, flaggedWith: () => { siteContext.logger.warn("'flaggedWith' no longer exists, use a labeling field instead"); }, flaggedWithOne: () => { siteContext.logger.warn("'flaggedWithOne' no longer exists, use a labeling field instead"); }, og: () => makeOgValuesPayload(renderingContext, documentType, docValues, options), jsonLd: () => makeJsonLdPayload(renderingContext, documentType, docValues, options), breadcrumb: () => getPublicBreadcrumb(renderingContext, docValues), parent: () => getParentDocument(renderingContext, docValues), siblings: () => getSiblingDocuments(renderingContext, docValues), typeLabel: typeLabel, urlQuery: options.urlQuery, frontendAppPath: options.frontendAppPath, routing: async () => { if (documentType.documentKind !== "routing") return; const cluster = await loadRoutingClusterFromNode(siteContext, { nodeId: docValues.nodeId, typeName: docValues.type, }); const clusterNode = getClusterNodeOf(cluster, docValues.nodeId); if (!clusterNode) throw new Error(`Node '${docValues.nodeId}' not found in cluster`); return toTpRoutingClusterNode(renderingContext, clusterNode, docValues.language); }, routingIds: async () => { siteContext.logger.warn("'routingIds' is deprecated, use 'routing' instead"); if (documentType.documentKind !== "routing") return; const cluster = await loadRoutingClusterFromNode(siteContext, { nodeId: docValues.nodeId, typeName: docValues.type, }); const clusterNode = getClusterNodeOf(cluster, docValues.nodeId); if (!clusterNode) throw new Error(`Node '${docValues.nodeId}' not found in cluster`); return toTpRoutingClusterNode(renderingContext, clusterNode, docValues.language); }, cluster: async () => { const found = await loadRoutingClusterFromNode(siteContext, { nodeId: docValues.nodeId, typeName: docValues.type, }); return toTpClusterPayload(renderingContext, docValues.language, found); }, }, }; }, { loadDescriptor: { load: "one", nodeKind: "document", descriptorName: "id", documentId, }, }); } function createPartsDrop(renderingContext, documentId, documentType) { const { siteContext } = renderingContext; return createLiquidDrop(renderingContext, { renderingCacheKey: `partsOf:${encodeLNodeId(documentId)}`, values: Object.fromEntries((documentType.lists ?? []).map((listType) => [ listType.listName, async () => { const byParent = await loadPartsOf(siteContext, renderingContext.tracker, documentId, listType); const completedItems = byParent.get(keyOfParentPartData({ listName: listType.listName, parentNodeId: documentId.nodeId })); if (!completedItems || completedItems.length === 0) return; const rawItems = formatListOfPartValues(siteContext, completedItems, listType); return rawItems.map((item) => createPartDrop(renderingContext, item, { byParent })); }, ])), }); } function createPartCountDrop(renderingContext, documentId, documentType) { const { siteContext } = renderingContext; return createLiquidDrop(renderingContext, { renderingCacheKey: `partCountersOf:${encodeLNodeId(documentId)}`, values: Object.fromEntries((documentType.lists ?? []).map((listType) => [ listType.listName, () => countPartsOf(siteContext, renderingContext.tracker, documentId, listType), ])), }); } async function loadUrlOfDocument(renderingContext, documentId) { const { siteContext } = renderingContext; const { url, dependencyKeys } = await getUrlOfDocument(siteContext, renderingContext.tracker, documentId, { returnUrlDependencyKeys: true, forPreview: renderingContext.isPreview, }); renderingContext.addDependencyKey(...dependencyKeys); return url; } async function makeOgValuesPayload(renderingContext, documentType, docValues, options) { const { siteContext } = renderingContext; const excerpt = await loadOrFromRenderingCache(renderingContext, `excerpt:${encodeLNodeId(docValues)}:full`, () => loadExcerpt(siteContext, renderingContext.tracker, { lNodeId: docValues, fieldTypes: documentType.fields ?? [], })); const url = options.url ?? (await loadOrFromRenderingCache(renderingContext, `url:${encodeLNodeId(docValues)}`, () => loadUrlOfDocument(renderingContext, docValues))); const featuredImageId = await loadOrFromRenderingCache(renderingContext, `featuredImage:${encodeLNodeId(docValues)}`, async () => (await getFeaturedImageOf(renderingContext, { nodeId: docValues.nodeId, documentType, }))?.id); const siteTitle = await loadOrFromRenderingCache(renderingContext, `siteFields:${docValues.language}:title`, async () => { const title = await getSiteFieldValue(siteContext, { fieldName: "title", language: docValues.language, publishedOnly: true, }); return StringOrUndefinedAT.assert(title); }); const description = excerpt ? truncExcerptToWord(excerpt, 130) : docValues.metaDescription ? truncExcerptToWord(docValues.metaDescription, 130) : undefined; const ogMedia = featuredImageId !== undefined ? await siteContext.mediaStorage.getMedia({ mediaId: featuredImageId }) : await siteContext.mediaStorage.getMedia({ handle: getHandleOfSiteField(siteContext, { fieldName: "ogImage" }), }); const ogImage = ogMedia?.kind === "image" ? await makeImageAvailable(renderingContext, toMSourceMedia(siteContext, ogMedia), { pixelRatio: 1, resizeRule: "1200x630", }) : undefined; return { url: toAbsoluteUrl(siteContext, url), type: documentType.ogType, image: ogImage, title: documentType.typeName === "home" ? siteTitle : docValues.title, siteName: siteTitle, description, locale: docValues.language, }; } //# sourceMappingURL=create-doc-drop.js.map