UNPKG

@paroicms/server

Version:
155 lines 7.07 kB
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