1
0
silverbullet/plugs/core/materialized_queries.ts
2022-03-29 17:02:28 +02:00

84 lines
2.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { syscall } from "../lib/syscall";
export const queryRegex =
/(<!--\s*#query\s+(?<table>\w+)\s*(filter\s+["'](?<filter>[^"']+)["'])?\s*(group by\s+(?<groupBy>\w+))?\s*-->)(.+?)(<!--\s*#end\s*-->)/gs;
export function whiteOutQueries(text: string): string {
return text.replaceAll(queryRegex, (match) =>
new Array(match.length + 1).join(" ")
);
}
async function replaceAsync(
str: string,
regex: RegExp,
asyncFn: (match: string, ...args: any[]) => Promise<string>
) {
const promises: Promise<string>[] = [];
str.replace(regex, (match: string, ...args: any[]): string => {
const promise = asyncFn(match, ...args);
promises.push(promise);
return "";
});
const data = await Promise.all(promises);
return str.replace(regex, () => data.shift()!);
}
export async function updateMaterializedQueriesCommand() {
await syscall(
"system.invokeFunctionOnServer",
"updateMaterializedQueriesOnPage",
await syscall("editor.getCurrentPage")
);
syscall("editor.flashNotification", "Updated materialized queries");
}
// Called from client, running on server
export async function updateMaterializedQueriesOnPage(pageName: string) {
let { text } = await syscall("space.readPage", pageName);
text = await replaceAsync(text, queryRegex, async (match, ...args) => {
let { table, filter, groupBy } = args[args.length - 1];
const startQuery = args[0];
const endQuery = args[args.length - 4];
let results = [];
switch (table) {
case "task":
for (let {
key,
page,
value: { task, complete, children },
} of await syscall("indexer.scanPrefixGlobal", "task:")) {
let [, pos] = key.split(":");
if (!filter || (filter && task.includes(filter))) {
results.push(
`* [${complete ? "x" : " "}] [[${page}@${pos}]] ${task}`
);
if (children) {
results.push(children.join("\n"));
}
}
}
return `${startQuery}\n${results.join("\n")}\n${endQuery}`;
case "item":
for (let {
key,
page,
value: { item, children },
} of await syscall("indexer.scanPrefixGlobal", "it:")) {
let [, pos] = key.split(":");
if (!filter || (filter && item.includes(filter))) {
results.push(`* [[${page}@${pos}]] ${item}`);
if (children) {
results.push(children.join("\n"));
}
}
}
return `${startQuery}\n${results.join("\n")}\n${endQuery}`;
default:
return match;
}
});
// console.log("New text", text);
await syscall("space.writePage", pageName, text);
}