{"version":3,"file":"AuthSocketClient.cjs","names":["Utils","SocketClientTransport","Peer"],"sources":["../../src/AuthSocketClient.ts"],"sourcesContent":["import {\n  io as realIo,\n  Socket as IoClientSocket,\n  ManagerOptions,\n  SocketOptions\n} from 'socket.io-client'\nimport {\n  RequestedCertificateSet,\n  SessionManager,\n  AsyncSessionManager,\n  Peer,\n  WalletInterface,\n  Utils,\n  OriginatorDomainNameStringUnder250Bytes,\n  stringifyBRC100\n} from '@bsv/sdk'\nimport { SocketClientTransport } from './SocketClientTransport.js'\n\nexport type AuthSocketClientErrorPhase = 'authentication' | 'application' | 'send'\n\nexport interface AuthSocketClientErrorContext {\n  phase: AuthSocketClientErrorPhase\n  socketId?: string\n  eventName?: string\n}\n\nexport type AuthSocketClientErrorHandler = (\n  error: unknown,\n  context: AuthSocketClientErrorContext\n) => void | Promise<void>\n\nexport function decodeAuthSocketEventPayload(payload: number[]): { eventName: string; data: any } {\n  try {\n    const str = Utils.toUTF8(payload)\n    const decoded: unknown = JSON.parse(str)\n    if (\n      decoded === null ||\n      typeof decoded !== 'object' ||\n      Array.isArray(decoded) ||\n      typeof (decoded as { eventName?: unknown }).eventName !== 'string'\n    ) {\n      return { eventName: '_unknown', data: undefined }\n    }\n    return {\n      eventName: (decoded as { eventName: string }).eventName,\n      data: (decoded as { data?: unknown }).data\n    }\n  } catch {\n    return { eventName: '_unknown', data: undefined }\n  }\n}\n\nexport interface AuthSocketClientOptions {\n  wallet: WalletInterface\n  requestedCertificates?: RequestedCertificateSet\n  sessionManager?: SessionManager | AsyncSessionManager\n  managerOptions?: Partial<ManagerOptions & SocketOptions>\n  originator?: OriginatorDomainNameStringUnder250Bytes\n  /** Maximum authentication messages processed concurrently. Defaults to 32. */\n  maxPendingAuthMessages?: number\n  /** Receives contained transport and application errors without exposing remote payloads. */\n  onError?: AuthSocketClientErrorHandler\n}\n\n/**\n * Internal class that wraps a Socket.IO client connection with BRC-103 mutual authentication,\n * enabling secure and identity-aware communication with a server.\n */\nclass AuthSocketClientImpl {\n  public connected = false\n  public id: string = ''\n  public serverIdentityKey: string | undefined\n  private readonly eventCallbacks = new Map<string, Array<(data: any) => void | Promise<void>>>()\n\n  /**\n   * Creates an instance of AuthSocketClient.\n   *\n   * @param ioSocket - The underlying Socket.IO client socket instance.\n   * @param peer - The BRC-103 Peer instance responsible for managing authenticated\n   *               communication, including message signing and verification.\n   */\n  constructor(\n    private readonly ioSocket: IoClientSocket,\n    private readonly peer: Peer,\n    private readonly onError: AuthSocketClientErrorHandler = () => {}\n  ) {\n    // Listen for 'connect' and 'disconnect' from underlying Socket.IO\n    this.ioSocket.on('connect', () => {\n      this.connected = true\n      this.id = this.ioSocket.id ?? ''\n      // Re-dispatch to dev if they've called \"socket.on('connect', ...)\"\n      void this.fireEventCallbacks('connect')\n    })\n\n    this.ioSocket.on('disconnect', reason => {\n      this.connected = false\n      // Re-dispatch\n      void this.fireEventCallbacks('disconnect', reason)\n    })\n\n    // Also listen for BRC-103 \"general\" messages\n    // We'll rely on peer.listenForGeneralMessages\n    this.peer.listenForGeneralMessages(async (senderKey, payload) => {\n      this.serverIdentityKey = senderKey\n      const { eventName, data } = this.decodeEventPayload(payload)\n      await this.fireEventCallbacks(eventName, data)\n    })\n  }\n\n  on(eventName: string, callback: (data?: any) => void | Promise<void>): this {\n    let arr = this.eventCallbacks.get(eventName)\n    if (arr === undefined) {\n      arr = []\n      this.eventCallbacks.set(eventName, arr)\n    }\n    arr.push(callback)\n    return this\n  }\n\n  emit(eventName: string, data: any): this {\n    // We sign a BRC-103 \"general\" message and send to the server\n    // via peer.toPeer\n    let encoded: number[]\n    try {\n      encoded = this.encodeEventPayload(eventName, data)\n    } catch (error) {\n      this.reportError(error, {\n        phase: 'send',\n        socketId: this.ioSocket.id ?? this.id,\n        eventName\n      })\n      return this\n    }\n    this.peer.toPeer(encoded, this.serverIdentityKey).catch(err => {\n      this.reportError(err, {\n        phase: 'send',\n        socketId: this.ioSocket.id ?? this.id,\n        eventName\n      })\n    })\n    return this\n  }\n\n  disconnect(): void {\n    this.serverIdentityKey = undefined\n    this.ioSocket.disconnect()\n  }\n\n  private async fireEventCallbacks(eventName: string, data?: any): Promise<void> {\n    const cbs = this.eventCallbacks.get(eventName)\n    if (cbs === undefined) return\n    try {\n      for (const cb of cbs) {\n        const result = cb(data)\n        if (result != null && typeof (result as PromiseLike<void>).then === 'function') {\n          await result\n        }\n      }\n    } catch (error) {\n      this.reportError(error, {\n        phase: 'application',\n        socketId: this.ioSocket.id ?? this.id,\n        eventName\n      })\n      if (eventName !== 'disconnect') this.disconnectSafely()\n    }\n  }\n\n  private encodeEventPayload(eventName: string, data: any): number[] {\n    const obj = { eventName, data }\n    return Utils.toArray(stringifyBRC100(obj), 'utf8')\n  }\n\n  private decodeEventPayload(payload: number[]): { eventName: string; data: any } {\n    return decodeAuthSocketEventPayload(payload)\n  }\n\n  private reportError(error: unknown, context: AuthSocketClientErrorContext): void {\n    void Promise.resolve()\n      .then(async () => await this.onError(error, context))\n      .catch(() => {})\n  }\n\n  private disconnectSafely(): void {\n    try {\n      this.ioSocket.disconnect()\n    } catch {\n      // The original failure is already contained and reported.\n    }\n  }\n}\n\n/**\n * Factory function for creating a new AuthSocketClientImpl instance.\n *\n * @param url  - The server URL\n * @param opts - Contains wallet, requested certificates, and other optional settings\n */\nexport function AuthSocketClient(url: string, opts: AuthSocketClientOptions): AuthSocketClientImpl {\n  // 1) Create real socket.io-client connection\n  const socket = realIo(url, opts.managerOptions)\n\n  // 2) Create a BRC-103 transport for the new socket\n  const transport = new SocketClientTransport(socket, {\n    maxPendingMessages: opts.maxPendingAuthMessages,\n    onError: error => {\n      reportErrorSafely(opts.onError, error, {\n        phase: 'authentication',\n        socketId: socket.id\n      })\n    }\n  })\n\n  // 3) Create a Peer\n  const peer = new Peer(\n    opts.wallet,\n    transport,\n    opts.requestedCertificates,\n    opts.sessionManager,\n    undefined,\n    opts.originator\n  )\n\n  // 4) Return our new AuthSocketClientImpl\n  return new AuthSocketClientImpl(socket, peer, (error, context) => {\n    reportErrorSafely(opts.onError, error, context)\n  })\n}\n\nfunction reportErrorSafely(\n  handler: AuthSocketClientErrorHandler | undefined,\n  error: unknown,\n  context: AuthSocketClientErrorContext\n): void {\n  void Promise.resolve()\n    .then(async () => await handler?.(error, context))\n    .catch(() => {})\n}\n"],"mappings":"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"}