import { parseQuery } from "../../plug-api/lib/parse_query.ts"; import type { Query } from "../../plug-api/types.ts"; import { events } from "@silverbulletmd/silverbullet/syscalls"; import type { QueryProviderEvent } from "../../plug-api/types.ts"; import { resolvePath } from "@silverbulletmd/silverbullet/lib/resolve"; import { renderQueryTemplate } from "../template/util.ts"; export async function query( query: string, variables?: Record, ): Promise { const parsedQuery = await parseQuery(query); return queryParsed(parsedQuery, variables); } /** * Renders a query either as a result array, or as a rendered template when the `render` clause is defined. * Runs on the server side (except in sync mode) * @param parsedQuery * @param variables * @returns Promise: a string if the query has a `render` clause, or an array of results */ export async function renderQuery( parsedQuery: Query, variables?: Record, ): Promise { const results = await queryParsed(parsedQuery, variables); if (parsedQuery.render) { if (results.length === 0 && !parsedQuery.renderAll) { return "No results"; } // Configured a custom rendering template, let's use it! const templatePage = resolvePath( variables?.page?.name, "/" + parsedQuery.render, ); const rendered = await renderQueryTemplate( variables?.page, templatePage, results, parsedQuery.renderAll!, ); return rendered.trim(); } return results; } export async function queryParsed( parsedQuery: Query, variables?: Record, ) { if (!parsedQuery.limit) { parsedQuery.limit = ["number", 1000]; } const eventName = `query:${parsedQuery.querySource}`; // console.log("Parsed query", parsedQuery); // Let's dispatch an event and see what happens const event: QueryProviderEvent = { query: parsedQuery }; if (variables) { event.variables = variables; } const results = await events.dispatchEvent(eventName, event, 30 * 1000); if (results.length === 0) { throw new Error(`Unsupported query source '${parsedQuery.querySource}'`); } return results.flat(); }