silverbullet/plugs/query/api.ts

71 lines
2.2 KiB
TypeScript
Raw Normal View History

import { parseQuery } from "../../plug-api/lib/parse_query.ts";
2024-07-30 23:33:33 +08:00
import type { Query } from "../../plug-api/types.ts";
import { events } from "@silverbulletmd/silverbullet/syscalls";
2024-07-30 23:33:33 +08:00
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<string, any>,
): Promise<any> {
const parsedQuery = await parseQuery(query);
return queryParsed(parsedQuery, variables);
}
/**
2024-08-15 17:26:59 +08:00
* 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<any[] | string>: a string if the query has a `render` clause, or an array of results
*/
export async function renderQuery(
parsedQuery: Query,
variables?: Record<string, any>,
): Promise<any[] | string> {
const results = await queryParsed(parsedQuery, variables);
2024-02-03 21:58:29 +08:00
if (parsedQuery.render) {
if (results.length === 0 && !parsedQuery.renderAll) {
return "No results";
}
2024-02-03 21:58:29 +08:00
// Configured a custom rendering template, let's use it!
const templatePage = resolvePath(
variables?.page?.name,
2024-05-28 02:33:41 +08:00
"/" + parsedQuery.render,
2024-02-03 21:58:29 +08:00
);
const rendered = await renderQueryTemplate(
variables?.page,
templatePage,
results,
parsedQuery.renderAll!,
);
return rendered.trim();
}
2024-02-03 21:58:29 +08:00
return results;
}
export async function queryParsed(
parsedQuery: Query,
variables?: Record<string, any>,
) {
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();
}