packages/plugins holds the kind registry and the loader for in-repo plug-in modules (REQ-PLUG-1). The first two kinds are usage-source and limit-check (REQ-LIMIT-4). The business file's plugins key turns modules on per kind, through plugin-settings.mjs and step 5's write path (REQ-ROLE-3). A refused load is logged and keeps the kind's old modules. Any filesystem error other than ENOENT or ENOTDIR refuses as unreadable. The organization writer validates the bytes it writes as well as the document. stack-copy ships packages/plugins. Nothing is wired into a host process yet. Candidate 466c835f7dce79d20c7ab74c197a52b70e7fdeb0efae0456222dc6d0a633f219, Dewey packet80797a539(round 2), base0bdd573ff. Filbert approved round 2 in 28568 and Darkwing in 28570. Landing gate atf7d249634: 24 suites green, 0 failed. 14 package suites passed 1586 tests (plugins 21, business 92, bus 171, cli 195, webui 112). The 10 script suites passed. Follow-up: P19 task 293, coded writer refusals. Co-Authored-By: Claude Opus 5.5 <[email protected]>
39 lines
1.6 KiB
JavaScript
39 lines
1.6 KiB
JavaScript
// A scratch tree per test: a copy of this package's src/ under
|
|
// <root>/packages/plugins, plus fixture modules. The loader finds modules
|
|
// from its own location, so each tree's copy loads only that tree's modules.
|
|
import { cpSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
import { tmpdir } from "node:os";
|
|
import { dirname, join, resolve } from "node:path";
|
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
|
|
export const SRC = resolve(dirname(fileURLToPath(import.meta.url)), "..", "src");
|
|
|
|
export const USAGE = name => `export const interfaceVersion = 1;
|
|
export function readTurn() { return ${JSON.stringify(name)}; }
|
|
`;
|
|
export const LIMIT = name => `export const interfaceVersion = 1;
|
|
export function mayLaunch() { return ${JSON.stringify(name)}; }
|
|
export function mustStop() { return false; }
|
|
`;
|
|
|
|
export function tree(t) {
|
|
const root = mkdtempSync(join(tmpdir(), "mosaic-plugins-"));
|
|
t.after(() => rmSync(root, { recursive: true, force: true }));
|
|
const pkg = join(root, "packages", "plugins");
|
|
cpSync(SRC, join(pkg, "src"), { recursive: true });
|
|
const write = (kind, name, body) => {
|
|
const dir = join(pkg, kind, name);
|
|
mkdirSync(dir, { recursive: true });
|
|
writeFileSync(join(dir, "index.mjs"), body);
|
|
return dir;
|
|
};
|
|
const loaderUrl = pathToFileURL(join(pkg, "src", "loader.mjs")).href;
|
|
async function loader(options = {}) {
|
|
const { createLoader } = await import(loaderUrl);
|
|
const logged = [];
|
|
const instance = createLoader({ log: entry => logged.push(entry), ...options });
|
|
return { ...instance, logged };
|
|
}
|
|
return { root, pkg, write, loader, loaderUrl };
|
|
}
|