load spaces from spaces.json, allow space function whitelist

This commit is contained in:
Shivering Ocelot committed 2026-10-02 10:24:14 -05:00
1 parent 1e35028148
commit 9cafdb02dd
3 files changed
+40 -24

No files matched your search

+5 -1
View File
@@ -1,2 +1,6 @@
node_modules
package-lock.json
.remote/
spaces/ spaces/
.remote/ spaces.json
+31 -21
View File
@@ -20,6 +20,7 @@ const DEFAULT_NAME = 'remote-center';
// Global runtime state // Global runtime state
let WORK_DIR = null; let WORK_DIR = null;
let APP_CONFIG = null; let APP_CONFIG = null;
let SPACES = null;
let HOST = null; let HOST = null;
let CENTER_NAME = null; let CENTER_NAME = null;
let HORDE = null; let HORDE = null;
@@ -29,10 +30,15 @@ let API = null;
// --- config loading --- // --- config loading ---
function loadConfig() { function loadCenter(dir) {
if (!WORK_DIR) WORK_DIR = path.resolve(process.cwd()); WORK_DIR = dir;
APP_CONFIG = loadJson('.remote', 'config.json');
SPACES = loadJson('spaces.json');
}
function loadJson (...segments) {
try { try {
return JSON.parse(fs.readFileSync(path.join(WORK_DIR, '.remote', 'config.json'), 'utf8')); return JSON.parse(fs.readFileSync(path.join(WORK_DIR, ...segments), 'utf8'));
} catch { } catch {
return {}; return {};
} }
@@ -54,18 +60,22 @@ function addSpaceRemote(spaceName, dir) {
if (remote) return remote; if (remote) return remote;
// Resolve center functions for this space // Resolve center functions for this space
let spaceConfig = APP_CONFIG.spaces?.[spaceName] || {}; let spaceConfig = SPACES?.[spaceName] || {};
let centerFunctions = spaceConfig.centerFunctions; let centerFunctions = spaceConfig.centerFunctions;
if (centerFunctions == null) { if (centerFunctions == null) {
centerFunctions = CENTER ? CENTER.spaceFunctions.names() : []; centerFunctions = CENTER ? CENTER.spaceFunctions.names() : [];
} }
let functions = new Functions(path.join(dir, '.remote', 'functions'));
if (spaceConfig.functions) {
functions.whitelist = spaceConfig.functions;
}
remote = new Remote({ remote = new Remote({
horde: HORDE, horde: HORDE,
name: remoteName, name: remoteName,
functionsDir: path.join(dir, '.remote', 'functions'),
ctx: { dir, remoteName, spaceName, api: API }, ctx: { dir, remoteName, spaceName, api: API },
centerFunctions, functions, centerFunctions,
fallback: CENTER && CENTER.spaceFunctions, fallback: CENTER && CENTER.spaceFunctions,
}); });
REMOTES.set(remoteName, remote); REMOTES.set(remoteName, remote);
@@ -91,12 +101,12 @@ async function initSpace(spaceName, dir) {
} }
// Get center function names for this space // Get center function names for this space
const spaceConfig = APP_CONFIG.spaces?.[spaceName] || {}; const spaceConfig = SPACES?.[spaceName] || {};
const centerFunctions = spaceConfig.centerFunctions || []; const centerFunctions = spaceConfig.centerFunctions || [];
// Update config with center functions // Update config with center functions
APP_CONFIG = { ...APP_CONFIG, spaces: { ...APP_CONFIG.spaces, [spaceName]: { path: absoluteDir, centerFunctions } } }; SPACES[spaceName] = { path: absoluteDir, centerFunctions };
fs.writeFileSync(path.join(WORK_DIR, '.remote', 'config.json'), JSON.stringify(APP_CONFIG, null, 2) + '\n'); fs.writeFileSync(path.join(WORK_DIR, '.spaces.json'), JSON.stringify(SPACES, null, 2) + '\n');
if (REMOTES != null) { if (REMOTES != null) {
const remote = addSpaceRemote(spaceName, absoluteDir); const remote = addSpaceRemote(spaceName, absoluteDir);
@@ -148,7 +158,7 @@ async function cloneSpace(source, newName, dir = null) {
} }
function reconcileSpaces() { function reconcileSpaces() {
const definedSpaces = APP_CONFIG.spaces || {}; const definedSpaces = SPACES || {};
const present = new Set(); const present = new Set();
for (const [spaceName, spaceConfig] of Object.entries(definedSpaces)) { for (const [spaceName, spaceConfig] of Object.entries(definedSpaces)) {
@@ -240,7 +250,7 @@ async function run() {
CENTER = new Remote({ CENTER = new Remote({
horde: HORDE, horde: HORDE,
name: CENTER_NAME, name: CENTER_NAME,
functionsDir: path.join(WORK_DIR, '.remote', 'functions'), functions: new Functions(path.join(WORK_DIR, '.remote', 'functions')),
ctx: { dir: WORK_DIR, remoteName: CENTER_NAME, spaceName: null, api: API }, ctx: { dir: WORK_DIR, remoteName: CENTER_NAME, spaceName: null, api: API },
}); });
REMOTES = new Map([[CENTER_NAME, CENTER]]); REMOTES = new Map([[CENTER_NAME, CENTER]]);
@@ -274,17 +284,8 @@ async function run() {
// --- entry point --- // --- entry point ---
async function mainPromise (p) { loadCenter(path.resolve(process.cwd()));
try {
await p;
} catch (e) {
console.error(e.stack);
process.exit(1);
}
}
WORK_DIR = path.resolve(process.cwd());
APP_CONFIG = loadConfig();
HOST = process.env.HORDE_HOST || APP_CONFIG.host || DEFAULT_HOST; HOST = process.env.HORDE_HOST || APP_CONFIG.host || DEFAULT_HOST;
CENTER_NAME = APP_CONFIG.name || DEFAULT_NAME; CENTER_NAME = APP_CONFIG.name || DEFAULT_NAME;
@@ -319,4 +320,13 @@ if (command === 'init') {
process.exit(1); process.exit(1);
} else { } else {
mainPromise(run()); mainPromise(run());
}
async function mainPromise (p) {
try {
await p;
} catch (e) {
console.error(e.stack);
process.exit(1);
}
} }
+4 -2
View File
@@ -13,6 +13,7 @@ export class Functions {
constructor(dir) { constructor(dir) {
this.dir = dir; this.dir = dir;
this.map = new Map(); // spec.name -> { spec, fn, file } this.map = new Map(); // spec.name -> { spec, fn, file }
this.whitelist = null;
} }
async scan() { async scan() {
@@ -44,6 +45,7 @@ export class Functions {
if (typeof mod.default !== 'function') { if (typeof mod.default !== 'function') {
throw new Error('module must export a default function'); throw new Error('module must export a default function');
} }
if (this.whitelist && !this.whitelist.includes(spec.name)) continue;
if (map.has(spec.name)) continue; if (map.has(spec.name)) continue;
map.set(spec.name, { spec, fn: mod.default, file }); map.set(spec.name, { spec, fn: mod.default, file });
} catch (err) { } catch (err) {
@@ -136,11 +138,11 @@ export class Watcher {
// A named collection of functions in a directory, registered on the hub. // A named collection of functions in a directory, registered on the hub.
export class Remote { export class Remote {
constructor({ horde, name, functionsDir, ctx, centerFunctions = [], fallback }) { constructor({ horde, name, functions, ctx, centerFunctions = [], fallback }) {
this.horde = horde; this.horde = horde;
this.name = name; this.name = name;
this.ctx = ctx; this.ctx = ctx;
this.functions = new Functions(functionsDir); this.functions = functions;
this.centerFunctions = centerFunctions; this.centerFunctions = centerFunctions;
this.fallback = fallback; this.fallback = fallback;
this.watcher = null; this.watcher = null;