@paroicms/server
Version:
The ParoiCMS server
143 lines • 5.42 kB
JavaScript
import { getDocumentTypeByName } from "@paroicms/internal-anywhere-lib";
import { encodeLNodeId, } from "@paroicms/public-anywhere-lib";
import { assignLoadDescriptor } from "@paroicms/public-server-lib";
import { type } from "arktype";
import { applyRegularChildrenSortingOnQuery } from "../common/child-ordering-query.js";
import { makeCacheDependencyKey } from "../common/text-cache.js";
import { mainDbSchemaName } from "../connector/db-init/db-constants.js";
import { createLiquidDrop } from "../liquidjs-tools/liquidjs-drop.js";
export function getSiblingDocuments(renderingContext, documentId) {
const { siteContext } = renderingContext;
const renderingCacheKey = `doc:${encodeLNodeId(documentId)}:siblings`;
return createLiquidDrop(renderingContext, async () => {
const parentNode = await getParentNode(siteContext, renderingContext.tracker, documentId.nodeId);
if (!parentNode || parentNode.parentTypeName === "_site") {
return {
renderingCacheKey,
values: { previous: undefined, next: undefined },
};
}
const parentDocumentType = getDocumentTypeByName(siteContext.siteSchema, parentNode.parentTypeName);
if (!parentDocumentType.regularChildrenSorting) {
return {
renderingCacheKey,
values: { previous: undefined, next: undefined },
};
}
const { previousDocumentId, nextDocumentId } = await getSiblingDocumentIds(siteContext, renderingContext.tracker, {
parentDocumentType,
parentNodeId: parentNode.parentNodeId,
documentId,
});
renderingContext.addDependencyKey(makeCacheDependencyKey({
documentId: {
nodeId: parentNode.parentNodeId,
language: documentId.language,
},
relation: "children",
}));
return {
renderingCacheKey,
values: {
previous: previousDocumentId
? assignLoadDescriptor({}, {
load: "one",
nodeKind: "document",
descriptorName: "id",
documentId: previousDocumentId,
})
: undefined,
next: nextDocumentId
? assignLoadDescriptor({}, {
load: "one",
nodeKind: "document",
descriptorName: "id",
documentId: nextDocumentId,
})
: undefined,
},
};
});
}
const ParentNodeRowAT = type({
parentTypeName: "string",
parentId: "number",
"+": "reject",
}).pipe((r) => ({
parentTypeName: r.parentTypeName,
parentNodeId: String(r.parentId),
}));
async function getParentNode(siteContext, tracker, nodeId) {
const row = await siteContext
.cn("PaNode as n")
.select(["n2.typeName as parentTypeName", "n2.id as parentId"])
.where("n.id", nodeId)
.innerJoin("PaNode as n2", "n2.id", "n.parentId")
.first();
tracker.trackAccess(mainDbSchemaName, "PaNode", "read");
if (!row)
return;
return ParentNodeRowAT.assert(row);
}
const SiblingIdsRowAT = type({
prevId: "number|null",
nextId: "number|null",
"+": "reject",
}).pipe((data) => ({
prevNodeId: data.prevId === null ? undefined : String(data.prevId),
nextNodeId: data.nextId === null ? undefined : String(data.nextId),
}));
async function getSiblingDocumentIds(siteContext, tracker, { documentId, parentNodeId, parentDocumentType, }) {
const { language } = documentId;
const { cn } = siteContext;
const subQuery = cn("PaNode as n")
.innerJoin("PaLNode as l", {
"l.nodeId": "n.id",
"l.language": cn.raw("?", [language]),
})
.innerJoin("PaDocument as d", {
"d.nodeId": "l.nodeId",
"d.language": "l.language",
})
.where("n.parentId", parentNodeId)
.andWhere("l.ready", 1)
.andWhere("n.publishDate", "<=", cn.fn.now());
const { orderBy } = applyRegularChildrenSortingOnQuery(siteContext, {
query: subQuery,
parentDocumentType,
orderByAsString: true,
leftJoinDocument: false,
});
if (!orderBy)
return {};
subQuery.select([
"n.id as id",
cn.raw("lag(n.id) over (?) as prevId", [cn.raw("order by ?", [cn.raw(orderBy)])]),
cn.raw("lead(n.id) over (?) as nextId", [cn.raw("order by ?", [cn.raw(orderBy)])]),
]);
const query = cn
.with("ordered_nodes", subQuery)
.select(["prevId", "nextId"])
.from("ordered_nodes")
.where("id", documentId.nodeId);
const row = await query.first();
tracker.trackAccess(mainDbSchemaName, "PaNode", "read");
if (!row)
return {};
const { prevNodeId, nextNodeId } = SiblingIdsRowAT.assert(row);
return {
previousDocumentId: prevNodeId === undefined
? undefined
: {
nodeId: prevNodeId,
language,
},
nextDocumentId: nextNodeId === undefined
? undefined
: {
nodeId: nextNodeId,
language,
},
};
}
//# sourceMappingURL=get-siblings.queries.js.map