diff --git a/cmd/lua_run.ts b/cmd/lua_run.ts new file mode 100644 index 00000000..b50f8296 --- /dev/null +++ b/cmd/lua_run.ts @@ -0,0 +1,91 @@ +import { resolve } from "@std/path"; +import assets from "../dist/plug_asset_bundle.json" with { type: "json" }; +import { determineDatabaseBackend } from "../server/db_backend.ts"; +import { DiskSpacePrimitives } from "$common/spaces/disk_space_primitives.ts"; + +import { ServerSystem } from "../server/server_system.ts"; +import { AssetBundlePlugSpacePrimitives } from "$common/spaces/asset_bundle_space_primitives.ts"; +import { LocalShell } from "../server/shell_backend.ts"; +import { DataStore } from "$lib/data/datastore.ts"; +import { DataStoreMQ } from "$lib/data/mq.datastore.ts"; +import { EventHook } from "../common/hooks/event.ts"; +import { AssetBundle } from "$lib/asset_bundle/bundle.ts"; +import { + type ConfigContainer, + defaultConfig, +} from "@silverbulletmd/silverbullet/type/config"; +import { parse } from "$common/space_lua/parse.ts"; +import { + LuaEnv, + LuaRuntimeError, + LuaStackFrame, +} from "$common/space_lua/runtime.ts"; + +import { evalStatement } from "$common/space_lua/eval.ts"; +import { luaBuildStandardEnv } from "$common/space_lua/stdlib.ts"; + +export async function luaRunCommand( + _options: any, + spacePath: string, + scriptPath: string, +) { + spacePath = resolve(spacePath); + console.log("Space path", spacePath); + console.log("Script to run:", scriptPath); + + const kvPrimitives = await determineDatabaseBackend(spacePath); + + if (!kvPrimitives) { + console.error("Cannot run plugs in databaseless mode."); + return; + } + + try { + const ds = new DataStore(kvPrimitives); + const mq = new DataStoreMQ(ds); + const eventHook = new EventHook(); + // TODO: Actually load config from the space + const configContainer: ConfigContainer = { + config: defaultConfig, + loadConfig: () => Promise.resolve(), + }; + + const serverSystem = new ServerSystem( + new AssetBundlePlugSpacePrimitives( + new DiskSpacePrimitives(spacePath), + new AssetBundle(assets), + ), + kvPrimitives, + new LocalShell(spacePath), + mq, + ds, + eventHook, + false, + true, + configContainer, + ); + await serverSystem.init(false); + console.log("Ok ready"); + // Then evaluate it + const luaFile = await Deno.readTextFile(scriptPath); + const chunk = parse(luaFile, {}); + const env = new LuaEnv(luaBuildStandardEnv()); + const sf = new LuaStackFrame(new LuaEnv(), chunk.ctx); + sf.threadLocal.setLocal("_GLOBAL", env); + + try { + await evalStatement(chunk, env, sf); + } catch (e: any) { + if (e instanceof LuaRuntimeError) { + console.error(`Error evaluating script:`, e.toPrettyString(luaFile)); + } else { + console.error(`Error evaluating script:`, e); + } + } + kvPrimitives.close(); + Deno.exit(0); + } catch (e: any) { + console.error(e.message); + Deno.exit(1); + } +} diff --git a/silverbullet.ts b/silverbullet.ts index ebcc4c86..a0e5a184 100755 --- a/silverbullet.ts +++ b/silverbullet.ts @@ -9,6 +9,7 @@ import { serveCommand } from "./cmd/server.ts"; import { plugCompileCommand } from "./cmd/plug_compile.ts"; import { plugRunCommand } from "./cmd/plug_run.ts"; import { syncCommand } from "./cmd/sync.ts"; +import { luaRunCommand } from "./cmd/lua_run.ts"; // Unhandled rejection, let's not crash globalThis.addEventListener("unhandledrejection", (event) => { @@ -84,6 +85,11 @@ await new Command() ) .option("-p, --port ", "Port to listen on") .action(plugRunCommand) + // lua:run + .command("lua:run") + .description("Run a Lua script") + .arguments(" ") + .action(luaRunCommand) // upgrade .command("upgrade") .description("Upgrade SilverBullet")