2024-01-21 02:16:07 +08:00
|
|
|
import { FunctionMap } from "$sb/types.ts";
|
|
|
|
import { builtinFunctions } from "$sb/lib/builtin_query_functions.ts";
|
2024-02-03 02:19:07 +08:00
|
|
|
import { System } from "../plugos/system.ts";
|
|
|
|
import { Query } from "$sb/types.ts";
|
|
|
|
import { LimitedMap } from "$sb/lib/limited_map.ts";
|
2024-02-06 23:51:04 +08:00
|
|
|
import { ScriptEnvironment } from "./space_script.ts";
|
2024-01-21 02:16:07 +08:00
|
|
|
|
2024-02-03 02:19:07 +08:00
|
|
|
const pageCacheTtl = 10 * 1000; // 10s
|
|
|
|
|
2024-02-06 23:51:04 +08:00
|
|
|
export async function buildQueryFunctions(
|
2024-02-03 02:19:07 +08:00
|
|
|
allKnownPages: Set<string>,
|
|
|
|
system: System<any>,
|
2024-02-06 23:51:04 +08:00
|
|
|
enableSpaceScript: boolean,
|
|
|
|
): Promise<FunctionMap> {
|
2024-02-03 02:19:07 +08:00
|
|
|
const pageCache = new LimitedMap<string>(10);
|
2024-02-06 23:51:04 +08:00
|
|
|
const scriptEnv = new ScriptEnvironment();
|
|
|
|
if (enableSpaceScript) {
|
|
|
|
try {
|
|
|
|
await scriptEnv.loadFromSystem(system);
|
|
|
|
console.log(
|
|
|
|
"Loaded",
|
|
|
|
Object.keys(scriptEnv.functions).length,
|
|
|
|
"functions from space-script",
|
|
|
|
);
|
|
|
|
} catch (e: any) {
|
|
|
|
console.error("Error loading space-script:", e.message);
|
|
|
|
}
|
|
|
|
}
|
2024-01-21 02:16:07 +08:00
|
|
|
return {
|
|
|
|
...builtinFunctions,
|
2024-02-03 02:19:07 +08:00
|
|
|
pageExists(name: string) {
|
2024-01-21 02:16:07 +08:00
|
|
|
if (name.startsWith("!") || name.startsWith("{{")) {
|
|
|
|
// Let's assume federated pages exist, and ignore template variable ones
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return allKnownPages.has(name);
|
|
|
|
},
|
2024-02-03 02:19:07 +08:00
|
|
|
async template(template: string, obj: any) {
|
|
|
|
return (await system.invokeFunction("template.renderTemplate", [
|
|
|
|
template,
|
|
|
|
obj,
|
|
|
|
])).text;
|
|
|
|
},
|
|
|
|
// INTERNAL: Used for implementing the { query } syntax in expressions
|
|
|
|
$query(query: Query, variables: Record<string, any>) {
|
|
|
|
return system.invokeFunction("query.renderQuery", [
|
|
|
|
query,
|
|
|
|
variables,
|
|
|
|
]);
|
|
|
|
},
|
|
|
|
// INTERNAL: Used to implement resolving [[links]] in expressions
|
2024-02-06 03:05:01 +08:00
|
|
|
readPage(name: string): Promise<string> | string {
|
2024-02-03 02:19:07 +08:00
|
|
|
const cachedPage = pageCache.get(name);
|
|
|
|
if (cachedPage) {
|
|
|
|
return cachedPage;
|
|
|
|
} else {
|
|
|
|
return system.syscall({}, "space.readPage", [name]).then((page) => {
|
|
|
|
pageCache.set(name, page, pageCacheTtl);
|
|
|
|
return page;
|
|
|
|
}).catch((e: any) => {
|
|
|
|
if (e.message === "Not found") {
|
|
|
|
throw new Error(`Page not found: ${name}`);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
},
|
2024-02-06 23:51:04 +08:00
|
|
|
...scriptEnv.functions,
|
2024-01-21 02:16:07 +08:00
|
|
|
};
|
|
|
|
}
|