Files
plainleaf/web/space_lua.ts
T
Zef HemelandGitHub dc2987a3f9 Sync engine rearchitecture (#1516)
* Don't require auth for .ping
* Finally introducing loggers
* Remove file list caching from disk_space_primitives
I don't think this is required anymore with the sync model
* Simplification of space primitives and more tests
* More reliable online status
* Add .zed settings
* Remove selfUpdate argument from `writeFile` no longer used
- Add `sync` config schema and document sync options
- Move sync config handling to client boot logic
- Move BootConfig type to ui_types.ts
- Remove sync env vars from server
- Update documentation for sync and architecture
* Improve sync logic and proxy routing for full sync state
* Add BoxProxy for late-bound client and improve Lua boot
- Add isMobile syscall for editor
* Add concurrency to sync process and log indexing duration
* Better service worker lifecycle management
2025-09-12 14:43:57 +02:00

98 lines
2.7 KiB
TypeScript

import type { System } from "../lib/plugos/system.ts";
import type { ScriptObject } from "../plugs/index/script.ts";
import {
LuaEnv,
LuaRuntimeError,
LuaStackFrame,
} from "../lib/space_lua/runtime.ts";
import {
parse as parseLua,
parseExpressionString,
} from "../lib/space_lua/parse.ts";
import { evalStatement } from "../lib/space_lua/eval.ts";
import {
encodeRef,
parseToRef,
type Ref,
} from "@silverbulletmd/silverbullet/lib/ref";
import type { ASTCtx } from "../lib/space_lua/ast.ts";
import { buildLuaEnv } from "./space_lua_api.ts";
import type { LuaCollectionQuery } from "../lib/space_lua/query_collection.ts";
export class SpaceLuaEnvironment {
env: LuaEnv;
constructor(private system: System<any>) {
this.env = buildLuaEnv(system);
}
/**
* Loads all Lua scripts from the database and evaluates them in a new environment
* @param system
*/
async reload() {
const allScripts: ScriptObject[] = await this.system.invokeFunction(
"index.queryLuaObjects",
["space-lua", {
objectVariable: "script",
orderBy: [{
expr: parseExpressionString("script.priority"),
desc: true,
}],
} as LuaCollectionQuery],
);
try {
this.env = buildLuaEnv(this.system);
const tl = new LuaEnv();
tl.setLocal("_GLOBAL", this.env);
for (const script of allScripts) {
try {
console.log("Now evaluating", script.ref);
const ast = parseLua(script.script, { ref: script.ref });
// We create a local scope for each script
const scriptEnv = new LuaEnv(this.env);
const sf = new LuaStackFrame(tl, ast.ctx);
await evalStatement(ast, scriptEnv, sf);
} catch (e: any) {
if (e instanceof LuaRuntimeError) {
const origin = resolveASTReference(e.sf.astCtx!);
if (origin) {
console.error(
`Error evaluating script: ${e.message} at [[${
encodeRef(origin)
}]]`,
);
continue;
}
}
console.error(
`Error evaluating script: ${e.message} for script: ${script.script}`,
);
}
}
console.log("[Lua] Loaded", allScripts.length, "scripts");
} catch (e: any) {
console.error("Error reloading Lua scripts:", e.message);
}
}
}
export function resolveASTReference(ctx?: ASTCtx): Ref | null {
if (!ctx?.ref) {
return null;
}
const ref = parseToRef(ctx.ref);
if (!ref) {
return null;
}
if (ref.details?.type === "position") {
ref.details.pos = (ref.details.pos as number) +
"```space-lua\n".length +
ctx.from!;
}
return ref;
}