From d34c917ef96296aea3e2826def10ba1194369d55 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sun, 2 Aug 2026 22:30:34 -0400 Subject: [PATCH] refactor: untangle bootstrapContext into makeConsole/makeLibs/runLibrary MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the shared-mutable-state dance where each db library was run in the handler context via `context.sql = x; run; module.exports = null`. Split into three single-purpose functions: - makeConsole(structureId, routeId) — the logs-table-backed console - runLibrary(sql, source, console) — eval one library in its own context - makeLibs(structureId, console) — the require() targets map Libraries are still evaluated eagerly per request (no laziness), and still see `sql` and `console`, so behavior is preserved. Verified the prime db library's top-level console.log still fires on a live request. Co-Authored-By: Claude Opus 4.8 --- index.js | 76 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 39 insertions(+), 37 deletions(-) diff --git a/index.js b/index.js index 02704c4..9620d69 100644 --- a/index.js +++ b/index.js @@ -83,53 +83,55 @@ async function saveFile(structureId, req, uploadedFile, asset=false) { return file } -function bootstrapContext(structureId, routeId, initContext) { - const allDbInstances = {}; - function getDb(alias) { - return allDbInstances[alias]; +// A console whose log() mirrors to stdout and to the structure's logs table. +function makeConsole(structureId, routeId) { + return { + log: function (...content) { + content.forEach((c) => console.log(c)); + model.createLog(structureId, routeId, inspectArgs(content)); + }, + }; +} + +// Evaluate a db's "library" script with `sql` and `console` bound, returning +// its exports. Each library runs in its own context so nothing leaks between dbs. +function runLibrary(sql, librarySource, console) { + const libContext = vm.createContext({ sql, console, module: { exports: null } }); + vm.runInContext(librarySource, libContext); + return libContext.module.exports; +} + +// The `require(name)` targets available to a user handler. +function makeLibs(structureId, console) { + const dbs = {}; + for (let appDb of model.getDbsForStructure(structureId)) { + const sql = model.getDbInstance(appDb.id); + dbs[appDb.alias] = { library: runLibrary(sql, appDb.library, console), sql }; } + return { + eta: model.getTemplater(structureId), + db: (alias) => dbs[alias], + push: webPush, + files: { saveFile: (...args) => saveFile(structureId, ...args) }, + }; +} - // todo wrap template in data-bliss-edit-template thing since ws can't take us to the editor on a component basis?? maybe... - // for now just designing with component approach - const eta = model.getTemplater(structureId); - const structure = model.getStructure(structureId) - const __urlPrefix = structure.route_prefix; +function bootstrapContext(structureId, routeId, initContext) { + const structure = model.getStructure(structureId); + const console = makeConsole(structureId, routeId); + const libs = makeLibs(structureId, console); - const libs = { eta, db: getDb, push: webPush, files: { saveFile: (...args) => saveFile(structureId, ...args) } }; - - let dbs = model.getDbsForStructure(structureId); - let context = vm.createContext({ + return vm.createContext({ ...initContext, - require: function (str) { - return libs[str]; - }, + require: (name) => libs[name], module: { exports: null }, - console: { - log: function (...content) { - content.forEach((c) => console.log(c)); - model.createLog(structureId, routeId, inspectArgs(content)); - }, - }, + console, vapidPublicKey: vapidPublicKey, fetch: fetch, clearTimeout: clearTimeout, setTimeout: setTimeout, - route: function (url) { - return withPrefix(__urlPrefix, url); - }, + route: makeRoute(structure), }); - for (let appDb of dbs) { - let dbInstance = model.getDbInstance(appDb.id); - context.sql = dbInstance; - vm.runInContext(appDb.library, context); - allDbInstances[appDb.alias] = { - library: context.module.exports, - sql: dbInstance, - }; - context.module.exports = null; - } - - return context; } function withPrefix(prefix, url) {