// The apps-directory contract: web/static/apps/ holds apps and nothing else. // Every .js file there calls defineApp — one app per file — so listing the // directory lists the apps. Shared machinery an app leans on (the schema // engine + renderer, the flow engine, Eleven's scripted-conversation feel, the // Vault's lock crypto) is a sibling module in web/static/, imported as // ../.js. Helpers drifted in here once and made the directory a poor // index of what an app IS; this test keeps it honest. // node test/apps-dir.test.mjs import assert from "node:assert/strict"; import { readFileSync, readdirSync } from "node:fs"; const dir = new URL("../web/static/apps/", import.meta.url); const files = readdirSync(dir).filter((f) => f.endsWith(".js")).sort(); // A defineApp CALL, not a mention: schema-render.js documented the framework in // prose and would have passed a bare substring match. const CALLS_DEFINE_APP = /\bdefineApp\s*\(/; const notApps = files.filter((f) => !CALLS_DEFINE_APP.test(readFileSync(new URL(f, dir), "utf8"))); assert.deepStrictEqual( notApps, [], `web/static/apps/ must contain only apps, but these call no defineApp: ${notApps.join(", ")}.\n` + `Move shared machinery to web/static/ and import it as ../.js.`, ); // Guard the guard: a directory that somehow scanned empty would pass vacuously. assert.ok(files.length > 10, `expected the apps directory to hold apps, found ${files.length} .js files`); console.log(`apps-dir tests passed (${files.length} apps, all calling defineApp)`);