UNPKG

computers

Version:
127 lines (121 loc) 3.01 kB
'use strict'; // src/caller.ts async function call(api, path, args) { const paths = path.split("."); let value = api; for (const path2 of paths) { if (typeof value !== "object" || value === null) { throw new Error("Invalid path"); } if (!(path2 in value)) { throw new Error("Invalid path"); } value = value[path2]; } if (typeof value !== "function") { throw new Error("Invalid path"); } try { const result = await value(...args); return { success: true, data: result }; } catch (error) { return { success: false, message: error instanceof Error ? error.message : "Unknown error" // TODO: BAD! }; } } // src/constants.ts var SYMBOL_TRANSPORT_UNSUBSCRIBE = Symbol( "computers:transport-unsubscribe" ); // src/utils.ts function nonce() { return Math.random().toString(36).substring(2, 15); } function deferred() { let resolve; const promise = new Promise((res) => { resolve = res; }); return { promise, resolve }; } // src/transport.ts function createTransport(transport) { const pending = /* @__PURE__ */ new Map(); const unsubscribe = transport.subscribe(async (message) => { if (message.type === "response") { const resolve = pending.get(message.nonce); if (!resolve) { return; } pending.delete(message.nonce); resolve(message); } else { await transport.call(message.path, message.args).then( (result) => transport.send({ type: "response", nonce: message.nonce, ...result }), (error) => transport.send({ type: "response", nonce: message.nonce, message: error instanceof Error ? error.message : String(error), success: false }) ); } }); const handle = { unsubscribe, call: (path, args) => { const { promise, resolve } = deferred(); const id = nonce(); pending.set(id, resolve); transport.send({ type: "request", nonce: id, path, args }); return promise; } }; function proxy(path) { return new Proxy(() => { }, { get: function(_, prop) { if (prop === SYMBOL_TRANSPORT_UNSUBSCRIBE) { return handle.unsubscribe; } if (typeof prop === "symbol") { throw new Error("Symbol not supported"); } const prefix = path ? `${path}.` : ""; const newPath = `${prefix}${prop}`; return proxy(newPath); }, apply: async function(_target, _, args) { const result = await handle.call(path, args); if (!result.success) { throw new Error(result.message); } return result.data; } }); } return proxy(""); } exports.SYMBOL_TRANSPORT_UNSUBSCRIBE = SYMBOL_TRANSPORT_UNSUBSCRIBE; exports.call = call; exports.createTransport = createTransport; exports.deferred = deferred; exports.nonce = nonce;