UNPKG

@tbd54566975/dwn-proxy-js

Version:

Bidirectional proxy between DWM's <> RESTful

267 lines (260 loc) 8.65 kB
var __defProp = Object.defineProperty; var __defProps = Object.defineProperties; var __getOwnPropDescs = Object.getOwnPropertyDescriptors; var __getOwnPropSymbols = Object.getOwnPropertySymbols; 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 __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/dwn-http-client.ts import { DidIonApi } from "@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 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 import express from "express"; import cors from "cors"; 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 = express(); this.api.use(cors({ 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 import { DidIonApi as DidIonApi2 } from "@tbd54566975/dids"; var generateDidState = async (endpoint) => { const didState = await new DidIonApi2().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 import { Dwn } from "@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 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(); export { DwnHttpClient, DwnHttpServer, DwnProxy, createRequest, createResponse, parseRequest, parseResponse, readReq }; //# sourceMappingURL=main.mjs.map