import { Emitter } from "@noya-app/emitter"; import { uuid } from "@noya-app/noya-utils"; export type EvalRequest = { id: string; code: string; }; export type EvalResponse = | { id: string; type: "error"; error: string; } | { id: string; type: "result"; result: string; }; export type SafeEval = (code: string) => unknown; export class EvalManager { constructor(options: { safeEval?: SafeEval }) { this.safeEval = options.safeEval; } safeEval?: SafeEval; requestEmitter = new Emitter<[EvalRequest]>(); responseEmitter = new Emitter<[EvalResponse]>(); _evalRequests = new Map>(); async evaluate(code: string) { if (this.safeEval) { return this.safeEval(code); } const id = uuid(); const promise = new Promise((resolve, reject) => { this.responseEmitter.addListener((response) => { if (response.id === id) { if (response.type === "error") { reject(new Error(response.error)); } else { try { resolve(JSON.parse(response.result as string)); } catch (error) { reject(error); } } } }); }); this._evalRequests.set(id, promise); this.requestEmitter.emit({ id, code }); const result = await promise; this._evalRequests.delete(id); return result; } }