UNPKG

@paroicms/server

Version:
116 lines (114 loc) 3.94 kB
import { parseSqliteDateTime } from "@paroicms/internal-server-lib"; import { isDef } from "@paroicms/public-anywhere-lib"; import { ApiError } from "@paroicms/public-server-lib"; import { type } from "arktype"; import { mainDbSchemaName } from "../../connector/db-init/db-constants.js"; const nodeAncestorsSubQueryWithOneParam = ` SELECT id, typeName, relativeId, publishDate, parentId, 0 as depth FROM PaNode WHERE id = ? UNION ALL SELECT p.id, p.typeName, p.relativeId, p.publishDate, p.parentId, na.depth + 1 as depth FROM PaNode p INNER JOIN node_ancestors na ON na.parentId = p.id WHERE p.parentId IS NOT NULL `; const NodeAncestorWithSlugRowAT = type({ id: "number", typeName: "string", relativeId: "string", parentId: "number", publishDate: "Date|string|number|null", depth: "number", ready: "number|null", slug: "string|null", "+": "reject", }).pipe((r) => ({ nodeId: String(r.id), typeName: r.typeName, relativeId: r.relativeId, parentId: String(r.parentId), publishDate: r.publishDate ? parseSqliteDateTime(r.publishDate) : undefined, ready: isDef(r.ready) ? Boolean(r.ready) : undefined, slug: r.slug ?? undefined, })); export async function getNodeAncestorsWithSlug(siteContext, tracker, { nodeId, language }) { const rows = await siteContext.cn.raw(` WITH RECURSIVE node_ancestors AS (${nodeAncestorsSubQueryWithOneParam}) SELECT na.id, na.typeName, na.relativeId, na.parentId, na.publishDate, na.depth, l.ready, d.slug FROM node_ancestors na LEFT JOIN PaLNode l ON l.nodeId = na.id AND l.language = ? LEFT JOIN PaDocument d ON d.nodeId = l.nodeId AND d.language = l.language ORDER BY na.depth ASC `, [nodeId, language]); tracker.trackAccess(mainDbSchemaName, "PaNode", "read"); if (rows.length === 0) { throw new ApiError(`cannot find node '${nodeId}'`, 404); } const result = []; for (const row of rows) { const { ready, ...ancestor } = NodeAncestorWithSlugRowAT.assert(row); if (ready === undefined) throw new Error(`missing "${language}" for node "${ancestor.nodeId}"`); result.push({ ready, ...ancestor }); } return result; } const NodeAncestorWithTitleRowAT = type({ id: "number", typeName: "string", relativeId: "string", parentId: "number", publishDate: "Date|string|number|null", depth: "number", ready: "number|null", title: "string|null", "+": "reject", }).pipe((r) => ({ nodeId: String(r.id), typeName: r.typeName, relativeId: r.relativeId, parentId: String(r.parentId), publishDate: r.publishDate ? parseSqliteDateTime(r.publishDate) : undefined, ready: isDef(r.ready) ? Boolean(r.ready) : undefined, title: r.title ?? undefined, })); export async function getNodeAncestorsForBreadcrumb(siteContext, tracker, { nodeId, language }, options = {}) { const rows = await siteContext.cn.raw(` WITH RECURSIVE node_ancestors AS (${nodeAncestorsSubQueryWithOneParam}) SELECT na.id, na.typeName, na.relativeId, na.parentId, na.publishDate, na.depth, l.ready, d.title FROM node_ancestors na INNER JOIN PaLNode l ON l.nodeId = na.id AND l.language = ? LEFT JOIN PaDocument d ON d.nodeId = l.nodeId AND d.language = l.language ORDER BY na.depth ASC `, [nodeId, language]); tracker.trackAccess(mainDbSchemaName, "PaNode", "read"); if (rows.length === 0) { throw new ApiError(`cannot find node '${nodeId}'`, 404); } const result = rows.map((row) => NodeAncestorWithTitleRowAT.assert(row)); if (options.ensurePublished) { const now = Date.now(); if (result.some(({ publishDate, ready }) => !ready || !publishDate || publishDate.getTime() > now)) { throw new ApiError(`node '${nodeId}' has an unpublished ancestor`, 404); } } return result; } //# sourceMappingURL=node-cte.queries.js.map