@web5/agent
Version:
90 lines • 4.82 kB
JavaScript
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
import { CryptoUtils } from '@web5/crypto';
import { createJsonRpcRequest, createJsonRpcSubscriptionRequest } from './json-rpc.js';
import { JsonRpcSocket } from './json-rpc-socket.js';
export class WebSocketDwnRpcClient {
get transportProtocols() { return ['ws:', 'wss:']; }
sendDwnRequest(request, jsonRpcSocketOptions) {
return __awaiter(this, void 0, void 0, function* () {
// validate that the dwn URL provided is a valid WebSocket URL
const url = new URL(request.dwnUrl);
if (url.protocol !== 'ws:' && url.protocol !== 'wss:') {
throw new Error(`Invalid websocket protocol ${url.protocol}`);
}
// check if there is already a connection to this host, if it does not exist, initiate a new connection
const hasConnection = WebSocketDwnRpcClient.connections.has(url.host);
if (!hasConnection) {
try {
const socket = yield JsonRpcSocket.connect(url.toString(), jsonRpcSocketOptions);
const subscriptions = new Map();
WebSocketDwnRpcClient.connections.set(url.host, { socket, subscriptions });
}
catch (error) {
throw new Error(`Error connecting to ${url.host}: ${error.message}`);
}
}
const connection = WebSocketDwnRpcClient.connections.get(url.host);
const { targetDid, message, subscriptionHandler } = request;
if (subscriptionHandler) {
return WebSocketDwnRpcClient.subscriptionRequest(connection, targetDid, message, subscriptionHandler);
}
return WebSocketDwnRpcClient.processMessage(connection, targetDid, message);
});
}
static processMessage(connection, target, message) {
return __awaiter(this, void 0, void 0, function* () {
const requestId = CryptoUtils.randomUuid();
const request = createJsonRpcRequest(requestId, 'dwn.processMessage', { target, message });
const { socket } = connection;
const response = yield socket.request(request);
const { error, result } = response;
if (error !== undefined) {
throw new Error(`error sending DWN request: ${error.message}`);
}
return result.reply;
});
}
static subscriptionRequest(connection, target, message, messageHandler) {
return __awaiter(this, void 0, void 0, function* () {
const requestId = CryptoUtils.randomUuid();
const subscriptionId = CryptoUtils.randomUuid();
const request = createJsonRpcSubscriptionRequest(requestId, 'dwn.processMessage', subscriptionId, { target, message });
const { socket, subscriptions } = connection;
const { response, close } = yield socket.subscribe(request, (response) => {
const { result, error } = response;
if (error) {
// if there is an error, close the subscription and delete it from the connection
const subscription = subscriptions.get(subscriptionId);
if (subscription) {
subscription.close();
}
subscriptions.delete(subscriptionId);
return;
}
const { event } = result;
messageHandler(event);
});
const { error, result } = response;
if (error) {
throw new Error(`could not subscribe via jsonrpc socket: ${error.message}`);
}
const { reply } = result;
if (reply.subscription && close) {
subscriptions.set(subscriptionId, Object.assign(Object.assign({}, reply.subscription), { close }));
reply.subscription.close = close;
}
return reply;
});
}
}
// a map of dwn host to WebSocket connection
WebSocketDwnRpcClient.connections = new Map();
//# sourceMappingURL=web-socket-clients.js.map