@paroicms/server
Version:
The ParoiCMS server
116 lines (114 loc) • 3.94 kB
JavaScript
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