@paroicms/server
Version:
The ParoiCMS server
155 lines • 7.07 kB
JavaScript
import { getDocumentTypeByName } from "@paroicms/internal-anywhere-lib";
import { type } from "arktype";
import { getTypeNameOf } from "../admin-backend/node/node.queries.js";
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 { dbAnyLanguage } from "../context.js";
import { formatDocValues, querySelectDocValues } from "./doc-values.queries.js";
const CountRowAT = type({ cnt: "number", "+": "reject" });
export async function listDocValues(renderingContext, descriptor, options = {}) {
const { siteContext } = renderingContext;
const onlyPublished = options.onlyPublished !== false;
const offset = descriptor.offset ?? 0;
let d = descriptor;
if (d.descriptorName === "children" && !d.parentDocumentTypeName) {
d = {
...d,
parentDocumentTypeName: await getTypeNameOf(renderingContext.siteContext, d.parentDocumentId.nodeId),
};
}
renderingContext.addDependencyKey(d.descriptorName === "children"
? makeCacheDependencyKey({ relation: "children", documentId: d.parentDocumentId })
: makeCacheDependencyKey({ global: "all" }));
if (d.labeledWith && d.descriptorName === "children") {
renderingContext.addDependencyKey(makeCacheDependencyKey({
relation: "labeled",
termNodeId: d.labeledWith.termNodeId,
fieldName: d.labeledWith.fieldName,
}));
}
const query = buildDocListQuery(siteContext, d, { onlyPublished });
querySelectDocValues(query);
if (offset > 0)
query.offset(offset);
if (d.limit !== undefined)
query.limit(d.limit);
const rows = await query;
renderingContext.tracker.trackAccess(mainDbSchemaName, "PaDocument", "read");
const language = d.descriptorName === "children" ? d.parentDocumentId.language : d.language;
const items = rows.map((row) => formatDocValues(row, { language }));
if (!options.withTotal)
return { items };
let total;
if (d.limit === undefined || (rows.length < d.limit && (rows.length > 0 || offset === 0))) {
total = offset + rows.length;
}
else {
const countQ = buildDocListQuery(siteContext, d, {
onlyPublished,
});
const r = d.descriptorName === "children"
? await countQ.count("* as cnt").first()
: await countQ.countDistinct("n.id as cnt").first();
total = r ? CountRowAT.assert(r).cnt : 0;
}
return { items, total };
}
function buildDocListQuery(siteContext, descriptor, options) {
if (descriptor.descriptorName === "children") {
return buildChildrenListQuery(siteContext, descriptor, options);
}
return buildSearchListQuery(siteContext, descriptor, options);
}
function buildChildrenListQuery(siteContext, descriptor, { onlyPublished }) {
const { cn, siteSchema } = siteContext;
if (!descriptor.parentDocumentTypeName)
throw new Error("Missing parent document type name");
const parentDocumentType = getDocumentTypeByName(siteSchema, descriptor.parentDocumentTypeName);
const q = cn("PaNode as n")
.innerJoin("PaLNode as l", {
"l.nodeId": "n.id",
"l.language": cn.raw("?", [descriptor.parentDocumentId.language]),
})
.innerJoin("PaDocument as d", { "d.nodeId": "l.nodeId", "d.language": "l.language" })
.where("n.parentId", descriptor.parentDocumentId.nodeId);
if (onlyPublished) {
q.where("l.ready", 1).whereRaw("n.publishDate <= current_timestamp");
}
const typeNames = parentDocumentType.regularChildren ?? [];
if (typeNames.length === 0) {
q.whereRaw("1 = 0");
return q;
}
q.whereIn("n.typeName", typeNames);
applyRegularChildrenSortingOnQuery(siteContext, {
query: q,
parentDocumentType,
regularChildrenSorting: descriptor.sorting,
});
if (descriptor.labeledWith) {
applyLabeledWithFilter(q, descriptor.labeledWith);
}
return q;
}
function buildSearchListQuery(siteContext, descriptor, { onlyPublished }) {
const { cn } = siteContext;
const q = cn("PaDocument as d")
.innerJoin("PaLNode as l", { "l.nodeId": "d.nodeId", "l.language": "d.language" })
.innerJoin("PaNode as n", "l.nodeId", "n.id")
.leftJoin("PaFieldVarchar as fv", function () {
this.on("fv.nodeId", "=", "l.nodeId").andOn(function () {
this.on("fv.language", "=", "l.language").orOn("fv.language", "=", cn.raw("?", [dbAnyLanguage]));
});
})
.leftJoin("PaFieldText as ft", function () {
this.on("ft.nodeId", "=", "d.nodeId").andOn(function () {
this.on("ft.language", "=", "d.language").orOn("ft.language", "=", cn.raw("?", [dbAnyLanguage]));
});
})
.where("l.language", descriptor.language);
if (onlyPublished) {
q.where("l.ready", 1).whereRaw("n.publishDate <= current_timestamp");
}
for (let index = 0; index < descriptor.words.length; index++) {
const wordPattern = `%${descriptor.words[index]}%`;
q.andWhere(function () {
this.where("d.title", "like", wordPattern)
.orWhere("ft.val", "like", wordPattern)
.orWhere("fv.val", "like", wordPattern)
.orWhereRaw(`exists (
select 1
from PaNode n2
inner join PaPartNode p2 on p2.nodeId = n2.id
inner join PaLNode l2 on l2.nodeId = n2.id and l2.language = ?
left join PaFieldVarchar fv2 on fv2.nodeId = l2.nodeId and (fv2.language = l2.language or fv2.language = ?)
left join PaFieldText ft2 on ft2.nodeId = l2.nodeId and (ft2.language = l2.language or ft2.language = ?)
where p2.documentNodeId = n.id ${onlyPublished ? "and l2.ready = 1 and n2.publishDate <= current_timestamp" : ""} and (fv2.val like ? or ft2.val like ?)
)`, [descriptor.language, dbAnyLanguage, dbAnyLanguage, wordPattern, wordPattern]);
});
}
if (descriptor.labeledWith) {
applyLabeledWithFilter(q, descriptor.labeledWith);
}
applySearchSorting(siteContext, q, descriptor.sorting);
return q.distinct();
}
function applySearchSorting(siteContext, q, sorting) {
const rules = Array.isArray(sorting) && sorting.length
? sorting
: [{ fieldName: "publishDate", direction: "desc" }];
for (const rule of rules) {
if (rule.fieldName === "title")
q.orderBy("d.title", rule.direction);
else if (rule.fieldName === "publishDate")
q.orderBy("n.publishDate", rule.direction);
else
siteContext.logger.warn(`[search] unsupported sort field '${rule.fieldName}' (ignored)`);
}
}
function applyLabeledWithFilter(q, labeledWith) {
q.innerJoin("PaFieldLabeling as lab", "lab.nodeId", "n.id")
.where("lab.termId", labeledWith.termNodeId)
.where("lab.field", labeledWith.fieldName);
}
//# sourceMappingURL=doc-list.queries.js.map