UNPKG

@bsv/authsocket-client

Version:
160 lines (159 loc) 4.7 kB
const require_SocketClientTransport = require("./SocketClientTransport.cjs"); let socket_io_client = require("socket.io-client"); let _bsv_sdk = require("@bsv/sdk"); //#region src/AuthSocketClient.ts function decodeAuthSocketEventPayload(payload) { try { const str = _bsv_sdk.Utils.toUTF8(payload); const decoded = JSON.parse(str); if (decoded === null || typeof decoded !== "object" || Array.isArray(decoded) || typeof decoded.eventName !== "string") return { eventName: "_unknown", data: void 0 }; return { eventName: decoded.eventName, data: decoded.data }; } catch { return { eventName: "_unknown", data: void 0 }; } } /** * Internal class that wraps a Socket.IO client connection with BRC-103 mutual authentication, * enabling secure and identity-aware communication with a server. */ var AuthSocketClientImpl = class { ioSocket; peer; onError; connected = false; id = ""; serverIdentityKey; eventCallbacks = /* @__PURE__ */ new Map(); /** * Creates an instance of AuthSocketClient. * * @param ioSocket - The underlying Socket.IO client socket instance. * @param peer - The BRC-103 Peer instance responsible for managing authenticated * communication, including message signing and verification. */ constructor(ioSocket, peer, onError = () => {}) { this.ioSocket = ioSocket; this.peer = peer; this.onError = onError; this.ioSocket.on("connect", () => { this.connected = true; this.id = this.ioSocket.id ?? ""; this.fireEventCallbacks("connect"); }); this.ioSocket.on("disconnect", (reason) => { this.connected = false; this.fireEventCallbacks("disconnect", reason); }); this.peer.listenForGeneralMessages(async (senderKey, payload) => { this.serverIdentityKey = senderKey; const { eventName, data } = this.decodeEventPayload(payload); await this.fireEventCallbacks(eventName, data); }); } on(eventName, callback) { let arr = this.eventCallbacks.get(eventName); if (arr === void 0) { arr = []; this.eventCallbacks.set(eventName, arr); } arr.push(callback); return this; } emit(eventName, data) { let encoded; try { encoded = this.encodeEventPayload(eventName, data); } catch (error) { this.reportError(error, { phase: "send", socketId: this.ioSocket.id ?? this.id, eventName }); return this; } this.peer.toPeer(encoded, this.serverIdentityKey).catch((err) => { this.reportError(err, { phase: "send", socketId: this.ioSocket.id ?? this.id, eventName }); }); return this; } disconnect() { this.serverIdentityKey = void 0; this.ioSocket.disconnect(); } async fireEventCallbacks(eventName, data) { const cbs = this.eventCallbacks.get(eventName); if (cbs === void 0) return; try { for (const cb of cbs) { const result = cb(data); if (result != null && typeof result.then === "function") await result; } } catch (error) { this.reportError(error, { phase: "application", socketId: this.ioSocket.id ?? this.id, eventName }); if (eventName !== "disconnect") this.disconnectSafely(); } } encodeEventPayload(eventName, data) { const obj = { eventName, data }; return _bsv_sdk.Utils.toArray((0, _bsv_sdk.stringifyBRC100)(obj), "utf8"); } decodeEventPayload(payload) { return decodeAuthSocketEventPayload(payload); } reportError(error, context) { Promise.resolve().then(async () => await this.onError(error, context)).catch(() => {}); } disconnectSafely() { try { this.ioSocket.disconnect(); } catch {} } }; /** * Factory function for creating a new AuthSocketClientImpl instance. * * @param url - The server URL * @param opts - Contains wallet, requested certificates, and other optional settings */ function AuthSocketClient(url, opts) { const socket = (0, socket_io_client.io)(url, opts.managerOptions); const transport = new require_SocketClientTransport.SocketClientTransport(socket, { maxPendingMessages: opts.maxPendingAuthMessages, onError: (error) => { reportErrorSafely(opts.onError, error, { phase: "authentication", socketId: socket.id }); } }); return new AuthSocketClientImpl(socket, new _bsv_sdk.Peer(opts.wallet, transport, opts.requestedCertificates, opts.sessionManager, void 0, opts.originator), (error, context) => { reportErrorSafely(opts.onError, error, context); }); } function reportErrorSafely(handler, error, context) { Promise.resolve().then(async () => await handler?.(error, context)).catch(() => {}); } //#endregion exports.AuthSocketClient = AuthSocketClient; exports.decodeAuthSocketEventPayload = decodeAuthSocketEventPayload; //# sourceMappingURL=AuthSocketClient.cjs.map