UNPKG

@tbd54566975/dwn-proxy-js

Version:

Bidirectional proxy between DWM's <> RESTful

307 lines (299 loc) 10.5 kB
var __create = Object.create; var __defProp = Object.defineProperty; var __defProps = Object.defineProperties; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropDescs = Object.getOwnPropertyDescriptors; var __getOwnPropNames = Object.getOwnPropertyNames; var __getOwnPropSymbols = Object.getOwnPropertySymbols; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __propIsEnum = Object.prototype.propertyIsEnumerable; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __spreadValues = (a, b) => { for (var prop in b ||= {}) if (__hasOwnProp.call(b, prop)) __defNormalProp(a, prop, b[prop]); if (__getOwnPropSymbols) for (var prop of __getOwnPropSymbols(b)) { if (__propIsEnum.call(b, prop)) __defNormalProp(a, prop, b[prop]); } return a; }; var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b)); var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var __accessCheck = (obj, member, msg) => { if (!member.has(obj)) throw TypeError("Cannot " + msg); }; var __privateGet = (obj, member, getter) => { __accessCheck(obj, member, "read from private field"); return getter ? getter.call(obj) : member.get(obj); }; var __privateAdd = (obj, member, value) => { if (member.has(obj)) throw TypeError("Cannot add the same private member more than once"); member instanceof WeakSet ? member.add(obj) : member.set(obj, value); }; var __privateSet = (obj, member, value, setter) => { __accessCheck(obj, member, "write to private field"); setter ? setter.call(obj, value) : member.set(obj, value); return value; }; var __forAwait = (obj, it, method) => { it = obj[Symbol.asyncIterator]; method = (key, fn) => (fn = obj[key]) && (it[key] = (arg) => new Promise((resolve, reject, done) => { arg = fn.call(obj, arg); done = arg.done; return Promise.resolve(arg.value).then((value) => resolve({ value, done }), reject); })); return it ? it.call(obj) : (obj = obj[Symbol.iterator](), it = {}, method("next"), method("return"), it); }; // src/main.ts var main_exports = {}; __export(main_exports, { DwnHttpClient: () => DwnHttpClient, DwnHttpServer: () => DwnHttpServer, DwnProxy: () => DwnProxy, createRequest: () => createRequest, createResponse: () => createResponse, parseRequest: () => parseRequest, parseResponse: () => parseResponse, readReq: () => readReq }); module.exports = __toCommonJS(main_exports); // src/dwn-http-client.ts var import_dids = require("@tbd54566975/dids"); // src/dwn-json-rpc.ts var parseRequest = (req) => { return req.params; }; var createRequest = (target, message) => { return { jsonrpc: "2.0", id: "", // TODO method: "dwn.processMessage", params: { target, message } }; }; var parseResponse = (res) => { return res.result; }; var createResponse = (res) => { return { jsonrpc: "2.0", id: "", result: { reply: res.reply } }; }; // src/dwn-http-client.ts var _resolveEndpoint; var DwnHttpClient = class { constructor() { // TODO did resolver cache member variable __privateAdd(this, _resolveEndpoint, async (did) => { var _a; const doc = (await new import_dids.DidIonApi().resolve(did)).didDocument; if (!doc) throw new Error(); const service = (_a = doc.service) == null ? void 0 : _a.find((x) => x.type === "DecentralizedWebNode"); if (!service) throw new Error(); return service.serviceEndpoint.nodes[0]; }); this.send = async (target, message, payload) => { const endpoint = await __privateGet(this, _resolveEndpoint).call(this, target); const fetchOpts = { method: "POST", headers: { "dwn-request": JSON.stringify(createRequest(target, message)) } }; if (payload) { fetchOpts.headers["content-type"] = "application/octet-stream"; fetchOpts["body"] = payload; } const res = await fetch(endpoint, fetchOpts); let dwnResponse; if (res.headers.has("dwn-response")) dwnResponse = parseResponse(JSON.parse(res.headers.get("dwn-response"))); else dwnResponse = parseResponse(JSON.parse(await res.text())); return dwnResponse; }; } }; _resolveEndpoint = new WeakMap(); // src/dwn-http-server.ts var import_express = __toESM(require("express"), 1); var import_cors = __toESM(require("cors"), 1); var readReq = async (req) => { let chunks = ""; try { for (var iter = __forAwait(req), more, temp, error; more = !(temp = await iter.next()).done; more = false) { const chunk = temp.value; chunks += chunk; } } catch (temp) { error = [temp]; } finally { try { more && (temp = iter.return) && await temp.call(iter); } finally { if (error) throw error[0]; } } if (chunks) return JSON.parse(chunks); }; var _options; var DwnHttpServer = class { constructor(options) { __privateAdd(this, _options, void 0); this.listen = (port, callback) => this.api.listen(port, callback); __privateSet(this, _options, options); this.api = (0, import_express.default)(); this.api.use((0, import_cors.default)({ exposedHeaders: "dwn-response" })); this.api.get("/health", (_, res) => res.json({ ok: true })); this.api.get("/", (_req, res) => { res.setHeader("content-type", "text/plain"); return res.send("please use a web5 client, for example: https://github.com/TBD54566975/web5-js "); }); this.api.post("/", async (req, res) => { try { let dwnRequest; try { dwnRequest = parseRequest(JSON.parse(req.headers["dwn-request"])); if (!dwnRequest.payload) { const contentLength = req.headers["content-length"]; const transferEncoding = req.headers["transfer-encoding"]; const requestDataStream = parseInt(contentLength) > 0 || transferEncoding !== void 0 ? req : void 0; dwnRequest.payload = requestDataStream; } } catch (err) { console.error("Failed to parse client request", err); res.status(400).end(err.message); return; } const dwnResponse = __privateGet(this, _options).handler ? await __privateGet(this, _options).handler(dwnRequest) : void 0; if (!dwnResponse) { const reply = await __privateGet(this, _options).dwn.processMessage(dwnRequest.target, dwnRequest.message, dwnRequest.payload); res.json(reply); } else if (dwnResponse.payload) { res.setHeader("content-type", "application/octet-stream"); res.setHeader("dwn-response", JSON.stringify(createResponse(dwnResponse))); dwnResponse.payload.pipe(res); } else { res.json(createResponse(dwnResponse)); } } catch (err) { console.error("Failed to process message", err); res.status(500).end(err.message); return; } }); } }; _options = new WeakMap(); // src/dwn-did.ts var import_dids2 = require("@tbd54566975/dids"); var generateDidState = async (endpoint) => { const didState = await new import_dids2.DidIonApi().create({ services: [{ id: "dwn", type: "DecentralizedWebNode", serviceEndpoint: { nodes: [endpoint] } }] }); console.log(`Created DID & hosting service endpoint at ${endpoint}`); console.log(didState.id); const { keys } = didState; const [key] = keys; const { privateKeyJwk } = key; const kidFragment = privateKeyJwk.kid || key.id; const kid = `${didState.id}#${kidFragment}`; return __spreadProps(__spreadValues({}, didState), { signatureInput: { privateJwk: privateKeyJwk, protectedHeader: { alg: privateKeyJwk.crv, kid } } }); }; // src/dwn-proxy.ts var import_dwn_sdk_js = require("@tbd54566975/dwn-sdk-js"); var _handlers, _inbound; var DwnProxy = class { constructor(options) { __privateAdd(this, _handlers, []); __privateAdd(this, _inbound, async (request) => { for (const { match, handler } of __privateGet(this, _handlers)) { const isMatch = match(request); if (isMatch) { if (request.payload) request.payload = await readReq(request.payload); return await handler(request); } } throw new Error("Unable to find middleware"); }); this.addHandler = (match, handler) => __privateGet(this, _handlers).push({ match, handler }); this.options = options; } async listen(port) { var _a; if (!this.options.didState) this.options.didState = await generateDidState((_a = this.options.serviceEndpoint) != null ? _a : `http://0.0.0.0:${port}`); this.dwn = await import_dwn_sdk_js.Dwn.create(); this.server = new DwnHttpServer({ dwn: this.dwn, handler: __privateGet(this, _inbound) }); this.server.listen(port, () => { console.log(`server listening on port ${port}`); }); this.client = new DwnHttpClient(); } }; _handlers = new WeakMap(); _inbound = new WeakMap(); // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { DwnHttpClient, DwnHttpServer, DwnProxy, createRequest, createResponse, parseRequest, parseResponse, readReq }); //# sourceMappingURL=main.cjs.map