react-jssip-kit 0.7.4 → 0.7.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +6 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +6 -6
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -490,6 +490,7 @@ function createSessionHandlers(deps) {
|
|
|
490
490
|
},
|
|
491
491
|
accepted: (e) => {
|
|
492
492
|
emitter.emit("accepted", e);
|
|
493
|
+
onSessionAccepted?.(sessionId);
|
|
493
494
|
state.batchSet({
|
|
494
495
|
sessions: state.getState().sessions.map(
|
|
495
496
|
(s) => s.id === sessionId ? {
|
|
@@ -1096,11 +1097,6 @@ var SipClient = class extends EventTargetEmitter {
|
|
|
1096
1097
|
rtc,
|
|
1097
1098
|
detachSessionHandlers: () => this.cleanupSession(sessionId, session),
|
|
1098
1099
|
onSessionFailed: (err, event) => this.onSessionFailed(err, event),
|
|
1099
|
-
onSessionConfirmed: (confirmedSessionId) => {
|
|
1100
|
-
if (this.micRecoveryEnabled) {
|
|
1101
|
-
this.enableMicrophoneRecovery(confirmedSessionId);
|
|
1102
|
-
}
|
|
1103
|
-
},
|
|
1104
1100
|
sessionId
|
|
1105
1101
|
});
|
|
1106
1102
|
}
|
|
@@ -1232,11 +1228,15 @@ var SipClient = class extends EventTargetEmitter {
|
|
|
1232
1228
|
return;
|
|
1233
1229
|
const stream = rtc.mediaStream;
|
|
1234
1230
|
const track = stream?.getAudioTracks?.()[0];
|
|
1235
|
-
const
|
|
1231
|
+
const pc2 = session2?.connection;
|
|
1232
|
+
const sender = pc2?.getSenders?.().find((s) => s.track?.kind === "audio");
|
|
1236
1233
|
if (!track && !sender)
|
|
1237
1234
|
return;
|
|
1238
1235
|
if (Date.now() - startedAt < warmupMs)
|
|
1239
1236
|
return;
|
|
1237
|
+
if (pc2?.connectionState === "new" || pc2?.connectionState === "connecting" || pc2?.iceConnectionState === "new" || pc2?.iceConnectionState === "checking") {
|
|
1238
|
+
return;
|
|
1239
|
+
}
|
|
1240
1240
|
const trackLive = track?.readyState === "live";
|
|
1241
1241
|
const senderLive = sender?.track?.readyState === "live";
|
|
1242
1242
|
if (trackLive && senderLive)
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/jssip-lib/sip/debugger.ts","../src/jssip-lib/sip/userAgent.ts","../src/jssip-lib/core/types.ts","../src/jssip-lib/core/eventEmitter.ts","../src/jssip-lib/core/sipErrorHandler.ts","../src/jssip-lib/core/sipState.ts","../src/jssip-lib/core/sipStateStore.ts","../src/jssip-lib/sip/handlers/uaHandlers.ts","../src/jssip-lib/sip/sessionState.ts","../src/jssip-lib/sip/handlers/sessionHandlers.ts","../src/jssip-lib/sip/sessionController.ts","../src/jssip-lib/sip/sessionManager.ts","../src/jssip-lib/sip/sessionLifecycle.ts","../src/jssip-lib/sip/client.ts","../src/jssip-lib/index.ts","../src/context/index.tsx","../src/hooks/useSipState.ts","../src/hooks/useSip.ts","../src/hooks/useSipActions.ts","../src/hooks/useSipSessions.ts","../src/hooks/useSipEvent.ts","../src/components/call-player.tsx","../src/jssip-lib/adapters/dom/createCallPlayer.ts","../src/provider/index.tsx"],"names":["JsSIP","message","session","useEffect","useMemo","jsx"],"mappings":"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","sourcesContent":["import JsSIP from \"jssip\";\n\ntype StorageLike = Pick<Storage, \"getItem\" | \"setItem\" | \"removeItem\">;\n\nexport interface SipDebugToggleResult {\n debug: boolean;\n text: string;\n}\n\n/**\n * Browser-friendly debugger toggle for JsSIP.\n * Persists preference in sessionStorage and exposes helpers on window for console use.\n */\nexport class SipDebugger {\n private readonly storageKey: string;\n private readonly defaultPattern: string;\n private enabled = false;\n private logger: any;\n\n constructor(storageKey = \"sip-debug-enabled\", defaultPattern = \"JsSIP:*\") {\n this.storageKey = storageKey;\n this.defaultPattern = defaultPattern;\n }\n\n initFromSession(storage: StorageLike | null = safeSessionStorage()): void {\n try {\n const saved = storage?.getItem(this.storageKey);\n if (saved) this.enable(saved, storage);\n } catch {\n /* ignore */\n }\n }\n\n enable(\n pattern: string = this.defaultPattern,\n storage: StorageLike | null = safeSessionStorage()\n ): void {\n try {\n if (typeof JsSIP?.debug?.enable === \"function\") {\n JsSIP.debug.enable(pattern);\n this.logger = console;\n }\n // Persist pattern in sessionStorage only.\n storage?.setItem?.(this.storageKey, pattern || this.defaultPattern);\n try {\n (window as any).sipDebugBridge?.(pattern);\n } catch {\n /* ignore */\n }\n this.enabled = true;\n } catch {\n /* ignore */\n }\n }\n\n disable(storage: StorageLike | null = safeSessionStorage()): void {\n try {\n if (typeof JsSIP?.debug?.disable === \"function\") {\n JsSIP.debug.disable();\n } else if (typeof JsSIP?.debug?.enable === \"function\") {\n JsSIP.debug.enable(\"\");\n }\n storage?.removeItem?.(this.storageKey);\n try {\n (window as any).sipDebugBridge?.(false);\n } catch {\n /* ignore */\n }\n this.enabled = false;\n } catch {\n /* ignore */\n }\n }\n\n toggle(\n pattern: string = this.defaultPattern,\n storage: StorageLike | null = safeSessionStorage()\n ): void {\n if (this.isEnabled()) {\n this.disable(storage);\n } else {\n this.enable(pattern, storage);\n }\n }\n\n isEnabled(): boolean {\n return this.enabled;\n }\n\n attachToWindow(win: Window & typeof globalThis = window): void {\n const api = {\n enableDebug: (): SipDebugToggleResult => {\n this.enable();\n return { debug: this.isEnabled(), text: \"press F5\" };\n },\n disableDebug: (): SipDebugToggleResult => {\n this.disable();\n return { debug: this.isEnabled(), text: \"press F5\" };\n },\n toggleDebug: (): SipDebugToggleResult => {\n this.toggle();\n return { debug: this.isEnabled(), text: \"press F5\" };\n },\n debugState: (): SipDebugToggleResult => ({\n debug: this.isEnabled(),\n text: this.isEnabled() ? \"enabled\" : \"disabled\",\n }),\n sipState: () => {\n try {\n const getter = (win as any).sipState;\n return typeof getter === \"function\"\n ? getter()\n : \"sipState helper not available; ensure client debug is enabled\";\n } catch {\n return \"sipState helper not available\";\n }\n },\n sipSessions: () => {\n try {\n const getter = (win as any).sipSessions;\n return typeof getter === \"function\"\n ? getter()\n : \"sipSessions helper not available; ensure client debug is enabled\";\n } catch {\n return \"sipSessions helper not available\";\n }\n },\n };\n\n try {\n (win as any).sipSupport = api;\n } catch {\n /* ignore */\n }\n }\n}\n\nfunction safeSessionStorage(): StorageLike | null {\n if (typeof window === \"undefined\") return null;\n try {\n return window.sessionStorage;\n } catch {\n return null;\n }\n}\n\nexport const sipDebugger = new SipDebugger();\nif (typeof window !== \"undefined\") {\n sipDebugger.attachToWindow();\n sipDebugger.initFromSession();\n}\n","import JsSIP, { UA } from \"jssip\";\r\nimport { SipConfiguration, UAConfiguration } from \"./types\";\r\n\r\ntype StartOpts = { debug?: boolean | string };\r\n\r\nexport class SipUserAgent {\r\n private _ua: UA | null = null;\r\n\r\n public get ua(): UA | null {\r\n return this._ua;\r\n }\r\n public get isStarted(): boolean {\r\n return !!this._ua;\r\n }\r\n public get isRegistered(): boolean {\r\n return !!this._ua?.isRegistered();\r\n }\r\n\r\n public start(\r\n uri: string,\r\n password: string,\r\n config: Omit<SipConfiguration, \"debug\">,\r\n opts?: StartOpts\r\n ): UA {\r\n this.stop();\r\n const uaCfg = this.buildUAConfig(config, uri, password);\r\n this.ensureValid(uaCfg);\r\n this.applyDebug(opts?.debug);\r\n const ua = this.createUA(uaCfg);\r\n ua.start();\r\n this._ua = ua;\r\n return ua;\r\n }\r\n\r\n public register(): void {\r\n const ua = this.getUA();\r\n if (!ua?.isRegistered()) ua?.register();\r\n }\r\n\r\n public stop(): void {\r\n const ua = this._ua;\r\n if (!ua) return;\r\n try {\r\n if (ua.isRegistered()) ua.unregister();\r\n ua.stop();\r\n } finally {\r\n this._ua = null;\r\n }\r\n }\r\n\r\n public getUA(): UA | null {\r\n return this._ua;\r\n }\r\n\r\n public setDebug(debug?: boolean | string): void {\r\n this.applyDebug(debug);\r\n }\r\n\r\n protected buildUAConfig(\r\n config: Omit<SipConfiguration, \"debug\">,\r\n uri: string,\r\n password: string\r\n ): UAConfiguration {\r\n return { ...(config as UAConfiguration), uri, password };\r\n }\r\n\r\n protected ensureValid(cfg: UAConfiguration): void {\r\n const sockets = cfg.sockets as UAConfiguration[\"sockets\"];\r\n if (\r\n !cfg.uri ||\r\n !cfg.password ||\r\n !sockets ||\r\n (Array.isArray(sockets) && sockets.length === 0)\r\n ) {\r\n throw new Error(\r\n \"Invalid SIP connect args: require uri, password, and at least one socket\"\r\n );\r\n }\r\n }\r\n\r\n protected applyDebug(debug?: boolean | string): void {\n const stored = debug === undefined ? this.readSessionFlag() : debug;\n const enabled = !!stored;\n const pattern = typeof stored === \"string\" ? stored : \"JsSIP:*\";\n\n if (enabled) {\n JsSIP.debug.enable(pattern);\n const dbg: any = (JsSIP as any).debug;\n if (dbg?.setLogger) dbg.setLogger(console);\n else if (dbg) dbg.logger = console;\n this.persistSessionFlag(typeof stored === \"string\" ? stored : undefined);\n } else {\n (JsSIP.debug as any)?.disable?.();\n this.clearSessionFlag();\n }\n }\n\r\n protected createUA(cfg: UAConfiguration): UA {\r\n return new JsSIP.UA(cfg);\r\n }\r\n\r\n private readSessionFlag(): string | false {\n try {\n if (typeof window === \"undefined\") return false;\n const value = window.sessionStorage.getItem(\"sip-debug-enabled\");\n if (!value) return false;\n return value;\n } catch {\n return false;\n }\n }\n\n private persistSessionFlag(pattern?: string): void {\n try {\n if (typeof window !== \"undefined\") {\n window.sessionStorage.setItem(\n \"sip-debug-enabled\",\n pattern || \"JsSIP:*\"\n );\n }\n } catch {\n /* ignore */\n }\n }\r\n\r\n private clearSessionFlag(): void {\r\n try {\r\n if (typeof window !== \"undefined\") {\r\n window.sessionStorage.removeItem(\"sip-debug-enabled\");\r\n }\r\n } catch {\r\n /* ignore */\r\n }\r\n }\r\n}\r\n","import { Originator } from \"jssip/src/RTCSession\";\r\n\r\nexport const SipStatus = {\r\n Disconnected: \"disconnected\",\r\n Connecting: \"connecting\",\r\n Connected: \"connected\",\r\n Registered: \"registered\",\r\n Unregistered: \"unregistered\",\r\n RegistrationFailed: \"registrationFailed\",\r\n} as const;\r\n\r\nexport type SipStatus = (typeof SipStatus)[keyof typeof SipStatus];\r\n\r\nexport const CallStatus = {\r\n Idle: \"idle\",\r\n Dialing: \"dialing\",\r\n Ringing: \"ringing\",\r\n Active: \"active\",\r\n Hold: \"hold\",\r\n} as const;\r\nexport type CallStatus = (typeof CallStatus)[keyof typeof CallStatus];\r\n\r\nexport type CallDirection = Originator.LOCAL | Originator.REMOTE;\r\n\r\nexport type SipSessionState = {\r\n id: string;\r\n status: CallStatus;\r\n direction: CallDirection | null;\r\n from: string | null;\r\n to: string | null;\r\n muted: boolean;\r\n acceptedAt: number | null;\r\n mediaKind: \"audio\" | \"video\";\r\n remoteVideoEnabled: boolean;\r\n};\r\n\r\nexport interface SipState {\r\n sipStatus: SipStatus;\r\n error: string | null;\r\n sessions: SipSessionState[];\r\n}\r\n\r\nexport const SipStatusList = Object.values(SipStatus);\r\nexport const CallStatusList = Object.values(CallStatus);\r\n\r\nexport function isSipStatus(v: unknown): v is SipStatus {\r\n return (\r\n typeof v === \"string\" && (SipStatusList as readonly string[]).includes(v)\r\n );\r\n}\r\nexport function isCallStatus(v: unknown): v is CallStatus {\r\n return (\r\n typeof v === \"string\" && (CallStatusList as readonly string[]).includes(v)\r\n );\r\n}\r\n\r\nexport type Unsubscribe = () => void;\r\nexport type Listener<T> = (value: T) => void;\r\n","export type Listener<T = any> = (payload: T) => void;\r\n\r\nexport class EventTargetEmitter<Events extends Record<string, any> = any> {\r\n private target = new EventTarget();\r\n\r\n on<K extends keyof Events>(event: K, fn: Listener<Events[K]>): () => void {\r\n const wrapper = (e: Event) => fn((e as CustomEvent<Events[K]>).detail);\r\n this.target.addEventListener(event as string, wrapper);\r\n return () => this.target.removeEventListener(event as string, wrapper);\r\n }\r\n\r\n emit<K extends keyof Events>(event: K, payload?: Events[K]): void {\r\n this.target.dispatchEvent(\r\n new CustomEvent(event as string, { detail: payload })\r\n );\r\n }\r\n}\r\n","export interface SipErrorPayload {\r\n cause: string;\r\n code?: string;\r\n raw?: any;\r\n message?: string;\r\n}\r\n\r\nexport interface SipErrorFormatInput {\r\n raw: any;\r\n code?: string;\r\n fallback?: string;\r\n}\r\n\r\nexport type SipErrorFormatter = (\r\n input: SipErrorFormatInput\r\n) => SipErrorPayload | undefined;\r\n\r\ntype SipErrorHandlerOptions = {\r\n formatter?: SipErrorFormatter;\r\n messages?: Record<string, string>;\r\n};\r\n\r\nexport class SipErrorHandler {\r\n private readonly formatter?: SipErrorFormatter;\r\n private readonly messages?: Record<string, string>;\r\n\r\n constructor(options: SipErrorHandlerOptions = {}) {\r\n this.formatter = options.formatter;\r\n this.messages = options.messages;\r\n }\r\n\r\n format(input: SipErrorFormatInput): SipErrorPayload {\r\n const { code, raw, fallback } = input;\r\n const mappedMessage =\r\n code && this.messages ? this.messages[code] : undefined;\r\n\r\n // Allow consumer to fully customize formatting.\r\n if (this.formatter) {\r\n const custom = this.formatter({\r\n raw,\r\n code,\r\n fallback: mappedMessage ?? fallback,\r\n });\r\n const message =\r\n custom?.message ??\r\n custom?.cause ??\r\n mappedMessage ??\r\n fallback ??\r\n this.readRawMessage(raw) ??\r\n \"unknown error\";\r\n\r\n return {\r\n cause: custom?.cause ?? message,\r\n code: custom?.code ?? code,\r\n raw: custom?.raw ?? raw,\r\n message,\r\n };\r\n }\r\n\r\n const message =\r\n mappedMessage ?? this.readRawMessage(raw) ?? fallback ?? \"unknown error\";\r\n\r\n return {\r\n cause: message,\r\n code,\r\n raw,\r\n message,\r\n };\r\n }\r\n\r\n private readRawMessage(raw: any): string | undefined {\r\n if (raw == null) return undefined;\r\n if (typeof raw === \"string\") return raw;\r\n if (typeof raw?.cause === \"string\") return raw.cause;\r\n if (typeof raw?.message === \"string\") return raw.message;\r\n return undefined;\r\n }\r\n}\r\n","import { SipState, SipStatus } from \"./types\";\r\n\r\nexport function getInitialSipState(): SipState {\r\n return {\r\n sipStatus: SipStatus.Disconnected,\r\n error: null,\r\n sessions: [],\r\n };\r\n}\r\n\r\nexport function shallowEqual(objA: any, objB: any): boolean {\r\n if (objA === objB) return true;\r\n if (!objA || !objB) return false;\r\n const keysA = Object.keys(objA);\r\n const keysB = Object.keys(objB);\r\n if (keysA.length !== keysB.length) return false;\r\n for (const key of keysA) {\r\n if (objA[key] !== objB[key]) return false;\r\n }\r\n return true;\r\n}\r\n","import { SipState } from \"./types\";\r\nimport { getInitialSipState, shallowEqual } from \"./sipState\";\r\n\r\nexport type SipStateListener = (state: SipState) => void;\r\n\r\nexport class SipStateStore {\r\n private state: SipState = getInitialSipState();\r\n private lastState: SipState = getInitialSipState();\r\n private listeners = new Set<SipStateListener>();\r\n private pendingState: Partial<SipState> | null = null;\r\n private updateScheduled = false;\r\n\r\n getState(): SipState {\r\n return this.state;\r\n }\r\n\r\n onChange(fn: SipStateListener): () => void {\r\n this.listeners.add(fn);\r\n fn(this.state);\r\n return () => this.listeners.delete(fn);\r\n }\r\n\r\n subscribe(fn: SipStateListener): () => void {\r\n return this.onChange(fn);\r\n }\r\n\r\n setState(partial: Partial<SipState>) {\r\n if (!partial || Object.keys(partial).length === 0) return;\r\n const next = { ...this.state, ...partial };\r\n // Fast-path: if sessions reference unchanged and shallow contents equal, skip emit.\r\n if (next.sessions === this.lastState.sessions && shallowEqual(this.lastState, next)) {\r\n return;\r\n }\r\n this.state = next;\r\n this.lastState = next;\r\n this.emit();\r\n }\r\n\r\n batchSet(partial: Partial<SipState>) {\r\n this.pendingState = { ...this.pendingState, ...partial };\r\n if (!this.updateScheduled) {\r\n this.updateScheduled = true;\r\n queueMicrotask(() => {\r\n if (this.pendingState) this.setState(this.pendingState);\r\n this.pendingState = null;\r\n this.updateScheduled = false;\r\n });\r\n }\r\n }\r\n\r\n reset(overrides: Partial<SipState> = {}) {\r\n this.setState({ ...getInitialSipState(), ...overrides });\r\n }\r\n\r\n private emit() {\r\n for (const fn of this.listeners) fn(this.state);\r\n }\r\n}\r\n","import { UAEventMap } from \"../types\";\r\nimport { SipStatus } from \"../../core/types\";\r\nimport { SipStateStore } from \"../../core/sipStateStore\";\r\nimport { JsSIPEventMap } from \"../types\";\r\nimport { EventTargetEmitter } from \"../../core/eventEmitter\";\r\nimport { SipErrorPayload } from \"../../core/sipErrorHandler\";\r\n\r\ntype Deps = {\r\n emitter: EventTargetEmitter<JsSIPEventMap>;\r\n state: SipStateStore;\r\n cleanupAllSessions: () => void;\r\n emitError: (\r\n raw: any,\r\n code?: string,\r\n fallback?: string\r\n ) => SipErrorPayload;\r\n onNewRTCSession: UAEventMap[\"newRTCSession\"];\r\n};\r\n\r\nexport function createUAHandlers(deps: Deps): Partial<UAEventMap> {\r\n const { emitter, state, cleanupAllSessions, emitError, onNewRTCSession } =\r\n deps;\r\n\r\n return {\r\n connecting: (e: any) => {\r\n emitter.emit(\"connecting\", e);\r\n state.batchSet({ sipStatus: SipStatus.Connecting });\r\n },\r\n connected: (e: any) => {\r\n emitter.emit(\"connected\", e);\r\n state.batchSet({ sipStatus: SipStatus.Connected });\r\n },\r\n disconnected: (e: any) => {\r\n emitter.emit(\"disconnected\", e);\r\n cleanupAllSessions();\r\n state.reset();\r\n },\r\n\r\n registered: (e: any) => {\r\n emitter.emit(\"registered\", e);\r\n state.batchSet({ sipStatus: SipStatus.Registered, error: null });\r\n },\r\n unregistered: (e: any) => {\r\n emitter.emit(\"unregistered\", e);\r\n state.batchSet({ sipStatus: SipStatus.Unregistered });\r\n },\r\n registrationFailed: (e: any) => {\r\n emitter.emit(\"registrationFailed\", e);\r\n cleanupAllSessions();\r\n emitError(\r\n {\r\n raw: e,\r\n cause: e?.cause,\r\n statusCode: e?.response?.status_code,\r\n statusText: e?.response?.reason_phrase,\r\n },\r\n \"REGISTRATION_FAILED\",\r\n \"registration failed\"\r\n );\r\n state.batchSet({\r\n sipStatus: SipStatus.RegistrationFailed,\r\n error: e?.cause || \"registration failed\",\r\n });\r\n },\r\n newRTCSession: onNewRTCSession,\r\n newMessage: (e: any) => emitter.emit(\"newMessage\", e),\r\n sipEvent: (e: any) => emitter.emit(\"sipEvent\", e),\r\n newOptions: (e: any) => emitter.emit(\"newOptions\", e),\r\n };\r\n}\r\n","import { CallStatus, SipSessionState } from \"../core/types\";\r\nimport { SipStateStore } from \"../core/sipStateStore\";\r\n\r\nexport function holdOtherSessions(\r\n state: SipStateStore,\r\n sessionId: string,\r\n holdFn: (id: string) => void\r\n) {\r\n const current = state.getState();\r\n current.sessions.forEach((s) => {\r\n if (s.id === sessionId) return;\r\n if (s.status === CallStatus.Active) {\r\n holdFn(s.id);\r\n }\r\n });\r\n}\r\n\r\nexport function upsertSessionState(\r\n state: SipStateStore,\r\n sessionId: string,\r\n partial: Partial<SipSessionState>\r\n) {\r\n const current = state.getState();\r\n const existing = current.sessions.find((s) => s.id === sessionId);\r\n const base: SipSessionState = existing ?? {\r\n id: sessionId,\r\n status: CallStatus.Idle,\r\n direction: null,\r\n from: null,\r\n to: null,\r\n muted: false,\r\n acceptedAt: null,\r\n mediaKind: \"audio\",\r\n remoteVideoEnabled: false,\r\n };\r\n\r\n const nextSession = { ...base, ...partial };\r\n const sessions = existing\r\n ? current.sessions.map((s) => (s.id === sessionId ? nextSession : s))\r\n : [...current.sessions, nextSession];\r\n\r\n state.setState({ sessions });\r\n}\r\n\r\nexport function removeSessionState(state: SipStateStore, sessionId: string) {\r\n const current = state.getState();\r\n const sessions = current.sessions.filter((s) => s.id !== sessionId);\r\n state.setState({\r\n sessions,\r\n error: null,\r\n });\r\n}\r\n","import { EndEvent, RTCSessionEventMap } from \"../types\";\nimport { CallStatus } from \"../../core/types\";\nimport { SipStateStore } from \"../../core/sipStateStore\";\nimport { WebRTCSessionController } from \"../sessionController\";\nimport { JsSIPEventMap } from \"../types\";\nimport { EventTargetEmitter } from \"../../core/eventEmitter\";\nimport { SipErrorPayload } from \"../../core/sipErrorHandler\";\nimport { upsertSessionState } from \"../sessionState\";\nimport { IncomingAckEvent, IncomingEvent, OutgoingAckEvent, OutgoingEvent } from \"jssip/src/RTCSession\";\n\ntype Deps = {\n emitter: EventTargetEmitter<JsSIPEventMap>;\n state: SipStateStore;\n rtc: WebRTCSessionController;\n detachSessionHandlers: () => void;\n emitError: (raw: any, code?: string, fallback?: string) => SipErrorPayload;\n onSessionFailed: (error?: string, event?: any) => void;\n onSessionConfirmed?: (sessionId: string) => void;\n sessionId: string;\n};\n\nexport function createSessionHandlers(deps: Deps): Partial<RTCSessionEventMap> {\n const {\n emitter,\n state,\n rtc,\n detachSessionHandlers,\n onSessionFailed,\n onSessionConfirmed,\n sessionId,\n } = deps;\n\n return {\n progress: (e: IncomingEvent | OutgoingEvent) => {\n emitter.emit(\"progress\", e);\n },\n accepted: (e: IncomingEvent | OutgoingEvent) => {\n emitter.emit(\"accepted\", e);\n state.batchSet({\n sessions: state.getState().sessions.map((s) =>\n s.id === sessionId\n ? {\n ...s,\n status: CallStatus.Active,\n acceptedAt: s.acceptedAt ?? Date.now(),\n }\n : s\n ),\n });\n },\n confirmed: (e: IncomingAckEvent | OutgoingAckEvent) => {\n emitter.emit(\"confirmed\", e);\n onSessionConfirmed?.(sessionId);\n },\n\n ended: (e: EndEvent) => {\n emitter.emit(\"ended\", e);\n detachSessionHandlers();\n rtc.cleanup();\n const nextSessions = state\n .getState()\n .sessions.filter((s) => s.id !== sessionId);\n state.batchSet({\n sessions: nextSessions,\n });\n },\n failed: (e: EndEvent) => {\n emitter.emit(\"failed\", e);\n detachSessionHandlers();\n rtc.cleanup();\n const cause = e?.cause || \"call failed\";\n onSessionFailed(cause, e);\n const nextSessions = state\n .getState()\n .sessions.filter((s) => s.id !== sessionId);\n state.batchSet({\n sessions: nextSessions,\n });\n },\n\n muted: () => {\n emitter.emit(\"muted\", undefined);\n upsertSessionState(state, sessionId, { muted: true });\n },\n unmuted: () => {\n emitter.emit(\"unmuted\", undefined);\n upsertSessionState(state, sessionId, { muted: false });\n },\n hold: () => {\n emitter.emit(\"hold\", undefined);\n upsertSessionState(state, sessionId, { status: CallStatus.Hold });\n },\n unhold: () => {\n emitter.emit(\"unhold\", undefined);\n upsertSessionState(state, sessionId, { status: CallStatus.Active });\n },\n\n reinvite: (e: any) => emitter.emit(\"reinvite\", e),\n update: (e: any) => emitter.emit(\"update\", e),\n sdp: (e: any) => emitter.emit(\"sdp\", e),\n icecandidate: (e: any) => emitter.emit(\"icecandidate\", e),\n refer: (e: any) => emitter.emit(\"refer\", e),\n replaces: (e: any) => emitter.emit(\"replaces\", e),\n newDTMF: (e: any) => emitter.emit(\"newDTMF\", e),\n newInfo: (e: any) => emitter.emit(\"newInfo\", e),\n\n getusermediafailed: (e: any) => {\n emitter.emit(\"getusermediafailed\", e);\n detachSessionHandlers();\n rtc.cleanup();\n onSessionFailed(\"getUserMedia failed\", e);\n state.batchSet({\n sessions: state.getState().sessions.filter((s) => s.id !== sessionId),\n });\n },\n \"peerconnection:createofferfailed\": (e: any) => {\n emitter.emit(\"peerconnection:createofferfailed\", e);\n detachSessionHandlers();\n rtc.cleanup();\n onSessionFailed(\"peer connection createOffer failed\", e);\n state.batchSet({\n sessions: state.getState().sessions.filter((s) => s.id !== sessionId),\n });\n },\n \"peerconnection:createanswerfailed\": (e: any) => {\n emitter.emit(\"peerconnection:createanswerfailed\", e);\n detachSessionHandlers();\n rtc.cleanup();\n onSessionFailed(\"peer connection createAnswer failed\", e);\n state.batchSet({\n sessions: state.getState().sessions.filter((s) => s.id !== sessionId),\n });\n },\n \"peerconnection:setlocaldescriptionfailed\": (e: any) => {\n emitter.emit(\"peerconnection:setlocaldescriptionfailed\", e);\n detachSessionHandlers();\n rtc.cleanup();\n onSessionFailed(\"peer connection setLocalDescription failed\", e);\n state.batchSet({\n sessions: state.getState().sessions.filter((s) => s.id !== sessionId),\n });\n },\n \"peerconnection:setremotedescriptionfailed\": (e: any) => {\n emitter.emit(\"peerconnection:setremotedescriptionfailed\", e);\n detachSessionHandlers();\n rtc.cleanup();\n onSessionFailed(\"peer connection setRemoteDescription failed\", e);\n state.batchSet({\n sessions: state.getState().sessions.filter((s) => s.id !== sessionId),\n });\n },\n peerconnection: (e: any) => emitter.emit(\"peerconnection\", e),\n };\n}\n","import type {\r\n AnswerOptions,\r\n DTMFOptions,\r\n ReferOptions,\r\n RTCSession,\r\n TerminateOptions,\r\n} from \"./types\";\r\n\r\nexport class WebRTCSessionController {\r\n currentSession: RTCSession | null = null;\r\n mediaStream: MediaStream | null = null;\r\n\r\n public setSession(session: RTCSession | null) {\r\n this.currentSession = session;\r\n }\r\n\r\n public setMediaStream(stream: MediaStream) {\r\n this.mediaStream = stream;\r\n }\r\n\r\n private getPC(): RTCPeerConnection | null {\r\n return (this.currentSession as any)?.connection ?? null;\r\n }\r\n\r\n public cleanup(stopTracks: boolean = true): void {\r\n const pc = this.getPC();\r\n\r\n if (pc && typeof pc.getSenders === \"function\") {\r\n const isClosed =\r\n pc.connectionState === \"closed\" || pc.signalingState === \"closed\";\r\n if (!isClosed) {\r\n for (const s of pc.getSenders()) {\r\n try {\r\n s.replaceTrack(null);\r\n } catch {\r\n // ignore if sender/pc already closed\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (stopTracks && this.mediaStream) {\r\n for (const t of this.mediaStream.getTracks()) t.stop();\r\n }\r\n\r\n this.mediaStream = null;\r\n this.currentSession = null;\r\n }\r\n\r\n public answer(options: AnswerOptions = {}): boolean {\r\n return this.currentSession\r\n ? (this.currentSession.answer(options), true)\r\n : false;\r\n }\r\n\r\n public hangup(options?: TerminateOptions): boolean {\r\n return this.currentSession\r\n ? (this.currentSession.terminate(\r\n options ?? ({ status_code: 486, reason_phrase: \"Busy Here\" } as any)\r\n ),\r\n true)\r\n : false;\r\n }\r\n\r\n public mute(): boolean {\r\n this.mediaStream?.getAudioTracks().forEach((t) => (t.enabled = false));\r\n return this.currentSession\r\n ? (this.currentSession.mute({ audio: true }), true)\r\n : false;\r\n }\r\n\r\n public unmute(): boolean {\r\n this.mediaStream?.getAudioTracks().forEach((t) => (t.enabled = true));\r\n return this.currentSession\r\n ? (this.currentSession.unmute({ audio: true }), true)\r\n : false;\r\n }\r\n\r\n public hold(): boolean {\r\n return this.currentSession ? (this.currentSession.hold(), true) : false;\r\n }\r\n\r\n public unhold(): boolean {\r\n return this.currentSession ? (this.currentSession.unhold(), true) : false;\r\n }\r\n\r\n public sendDTMF(tones: string | number, options?: DTMFOptions): boolean {\r\n return this.currentSession\r\n ? (this.currentSession.sendDTMF(tones, options), true)\r\n : false;\r\n }\r\n\r\n public transfer(target: string, options?: ReferOptions): boolean {\r\n return this.currentSession\r\n ? (this.currentSession.refer(target as any, options), true)\r\n : false;\r\n }\r\n\r\n public enableVideo(): void {\r\n this.mediaStream?.getVideoTracks().forEach((t) => (t.enabled = true));\r\n }\r\n\r\n public disableVideo(): void {\r\n this.mediaStream?.getVideoTracks().forEach((t) => (t.enabled = false));\r\n }\r\n\r\n public async switchCamera(\n nextVideoTrack: MediaStreamTrack\n ): Promise<boolean> {\n const pc = this.getPC();\r\n if (!pc) return false;\r\n\r\n if (!this.mediaStream) this.mediaStream = new MediaStream();\r\n\r\n const old = this.mediaStream.getVideoTracks()[0];\r\n this.mediaStream.addTrack(nextVideoTrack);\r\n if (old) this.mediaStream.removeTrack(old);\r\n\r\n const sender = pc.getSenders?.().find((s) => s.track?.kind === \"video\");\r\n if (sender) await sender.replaceTrack(nextVideoTrack);\r\n\r\n if (old && old !== nextVideoTrack) old.stop();\r\n\r\n return true;\n }\n\n public async replaceAudioTrack(\n nextAudioTrack: MediaStreamTrack\n ): Promise<boolean> {\n const pc = this.getPC();\n if (!pc) return false;\n\n if (!this.mediaStream) this.mediaStream = new MediaStream();\n\n const old = this.mediaStream.getAudioTracks()[0];\n this.mediaStream.addTrack(nextAudioTrack);\n if (old) this.mediaStream.removeTrack(old);\n\n const sender = pc.getSenders?.().find((s) => s.track?.kind === \"audio\");\n if (sender) await sender.replaceTrack(nextAudioTrack);\n\n if (old && old !== nextAudioTrack) old.stop();\n\n return true;\n }\n}\n","import { WebRTCSessionController } from \"./sessionController\";\r\nimport type { RTCSession } from \"./types\";\r\n\r\ntype SessionEntry = {\r\n rtc: WebRTCSessionController;\r\n session?: RTCSession | null;\r\n media?: MediaStream | null;\r\n};\r\n\r\nexport class SessionManager {\r\n private entries = new Map<string, SessionEntry>();\r\n private pendingMediaQueue: Array<{ stream: MediaStream; addedAt: number }> =\r\n [];\r\n private pendingMediaTtlMs = 30000;\r\n\r\n setPendingMediaTtl(ms: number | undefined) {\r\n if (typeof ms === \"number\" && ms > 0) this.pendingMediaTtlMs = ms;\r\n }\r\n\r\n enqueueOutgoingMedia(stream: MediaStream) {\r\n this.pendingMediaQueue.push({ stream, addedAt: Date.now() });\r\n }\r\n\r\n dequeueOutgoingMedia(): MediaStream | null {\r\n const now = Date.now();\r\n while (this.pendingMediaQueue.length) {\r\n const next = this.pendingMediaQueue.shift();\r\n if (!next) break;\r\n if (now - next.addedAt <= this.pendingMediaTtlMs) {\r\n return next.stream;\r\n } else {\r\n // drop stale stream\r\n next.stream.getTracks().forEach((t) => t.stop());\r\n }\r\n }\r\n return null;\r\n }\r\n\r\n getOrCreateRtc(sessionId: string, session?: RTCSession) {\r\n let entry = this.entries.get(sessionId);\r\n if (!entry) {\r\n entry = {\r\n rtc: new WebRTCSessionController(),\r\n session: null,\r\n media: null,\r\n };\r\n this.entries.set(sessionId, entry);\r\n }\r\n if (session) {\r\n entry.session = session;\r\n entry.rtc.setSession(session);\r\n }\r\n if (entry.media) entry.rtc.setMediaStream(entry.media);\r\n return entry.rtc;\r\n }\r\n\r\n getRtc(sessionId: string) {\r\n return this.entries.get(sessionId)?.rtc ?? null;\r\n }\r\n\r\n setSession(sessionId: string, session: RTCSession) {\r\n const entry = this.entries.get(sessionId);\r\n if (entry) {\r\n entry.session = session;\r\n entry.rtc.setSession(session);\r\n } else {\r\n this.entries.set(sessionId, {\r\n rtc: new WebRTCSessionController(),\r\n session,\r\n media: null,\r\n });\r\n }\r\n }\r\n\r\n setSessionMedia(sessionId: string, stream: MediaStream) {\r\n const entry = this.entries.get(sessionId) ?? {\r\n rtc: new WebRTCSessionController(),\r\n session: null,\r\n media: null,\r\n };\r\n entry.media = stream;\r\n entry.rtc.setMediaStream(stream);\r\n this.entries.set(sessionId, entry);\r\n }\r\n\r\n getSession(sessionId: string) {\r\n return this.entries.get(sessionId)?.session ?? null;\r\n }\r\n\r\n getSessionIds() {\r\n return Array.from(this.entries.keys());\r\n }\r\n\r\n getSessions() {\r\n return Array.from(this.entries.entries()).map(([id, entry]) => ({\r\n id,\r\n session: entry.session as RTCSession,\r\n }));\r\n }\r\n\r\n getActiveSessionId(activeStatuses: string[] = [\"active\"]): string | null {\r\n for (const [id, entry] of Array.from(this.entries.entries()).reverse()) {\r\n const status = (entry.session as any)?.status;\r\n if (status && activeStatuses.includes(String(status).toLowerCase())) {\r\n return id;\r\n }\r\n }\r\n return null;\r\n }\r\n\r\n cleanupSession(sessionId: string) {\r\n const entry = this.entries.get(sessionId);\r\n if (entry) {\r\n entry.rtc.cleanup();\r\n this.entries.delete(sessionId);\r\n }\r\n }\r\n\r\n cleanupAllSessions() {\r\n for (const [, entry] of this.entries.entries()) {\r\n entry.rtc.cleanup();\r\n }\r\n this.entries.clear();\r\n this.pendingMediaQueue = [];\r\n }\r\n\r\n answer(sessionId: string, options: any) {\r\n const rtc = this.getRtc(sessionId);\r\n return rtc ? rtc.answer(options) : false;\r\n }\r\n\r\n hangup(sessionId: string, options?: any) {\r\n const rtc = this.getRtc(sessionId);\r\n return rtc ? rtc.hangup(options) : false;\r\n }\r\n\r\n mute(sessionId: string) {\r\n const rtc = this.getRtc(sessionId);\r\n return rtc ? rtc.mute() : false;\r\n }\r\n\r\n unmute(sessionId: string) {\r\n const rtc = this.getRtc(sessionId);\r\n return rtc ? rtc.unmute() : false;\r\n }\r\n\r\n hold(sessionId: string) {\r\n const rtc = this.getRtc(sessionId);\r\n return rtc ? rtc.hold() : false;\r\n }\r\n\r\n unhold(sessionId: string) {\r\n const rtc = this.getRtc(sessionId);\r\n return rtc ? rtc.unhold() : false;\r\n }\r\n\r\n sendDTMF(sessionId: string, tones: string | number, options?: any) {\r\n const rtc = this.getRtc(sessionId);\r\n return rtc ? rtc.sendDTMF(tones, options) : false;\r\n }\r\n\r\n transfer(sessionId: string, target: string, options?: any) {\r\n const rtc = this.getRtc(sessionId);\r\n return rtc ? rtc.transfer(target, options) : false;\r\n }\r\n}\r\n","import { SipStateStore } from \"../core/sipStateStore\";\r\nimport { CallDirection, CallStatus } from \"../core/types\";\r\nimport { SessionManager } from \"./sessionManager\";\r\nimport { holdOtherSessions, upsertSessionState } from \"./sessionState\";\r\nimport type { JsSIPEventName, RTCSession, RTCSessionEvent } from \"./types\";\r\nimport type { SipErrorPayload } from \"../core/sipErrorHandler\";\r\n\r\ntype Deps = {\r\n state: SipStateStore;\r\n sessionManager: SessionManager;\r\n emit: <K extends JsSIPEventName>(event: K, payload: any) => void;\r\n emitError: (raw: any, code?: string, fallback?: string) => SipErrorPayload;\r\n attachSessionHandlers: (sessionId: string, session: RTCSession) => void;\r\n getMaxSessionCount: () => number;\r\n};\r\n\r\nexport class SessionLifecycle {\r\n private readonly state: SipStateStore;\r\n private readonly sessionManager: SessionManager;\r\n private readonly emit: Deps[\"emit\"];\r\n private readonly emitError: Deps[\"emitError\"];\r\n private readonly attachSessionHandlers: Deps[\"attachSessionHandlers\"];\r\n private readonly getMaxSessionCount: Deps[\"getMaxSessionCount\"];\r\n\r\n constructor(deps: Deps) {\r\n this.state = deps.state;\r\n this.sessionManager = deps.sessionManager;\r\n this.emit = deps.emit;\r\n this.emitError = deps.emitError;\r\n this.attachSessionHandlers = deps.attachSessionHandlers;\r\n this.getMaxSessionCount = deps.getMaxSessionCount;\r\n }\r\n\r\n handleNewRTCSession(e: RTCSessionEvent) {\r\n const session = e.session;\r\n const sessionId = String((session as any)?.id ?? crypto.randomUUID?.() ?? Date.now());\r\n\r\n const currentSessions = this.state.getState().sessions;\r\n if (currentSessions.length >= this.getMaxSessionCount()) {\r\n try {\r\n session.terminate?.({ status_code: 486, reason_phrase: \"Busy Here\" } as any);\r\n } catch {\r\n /* ignore termination errors */\r\n }\r\n if (e.originator === \"remote\") {\r\n this.emit(\"missed\", e);\r\n }\r\n this.emitError(\"max session count reached\", \"MAX_SESSIONS_REACHED\", \"max session count reached\");\r\n return;\r\n }\r\n\r\n const outgoingMedia = e.originator === \"local\" ? this.sessionManager.dequeueOutgoingMedia() : null;\r\n\r\n if (outgoingMedia) this.sessionManager.setSessionMedia(sessionId, outgoingMedia);\r\n\r\n const rtc = this.sessionManager.getOrCreateRtc(sessionId, session);\r\n if (outgoingMedia) rtc.setMediaStream(outgoingMedia);\r\n\r\n this.sessionManager.setSession(sessionId, session);\r\n this.attachSessionHandlers(sessionId, session);\r\n\r\n holdOtherSessions(\r\n this.state,\r\n sessionId,\r\n (id) => {\r\n const otherRtc = this.sessionManager.getRtc(id);\r\n otherRtc?.hold();\r\n }\r\n );\r\n\r\n const sdpHasVideo =\r\n (e.request?.body && e.request.body.toString().includes(\"m=video\")) ||\r\n (session as RTCSession & { connection?: RTCPeerConnection })?.connection\r\n ?.getReceivers?.()\r\n ?.some((r: RTCRtpReceiver) => r.track?.kind === \"video\");\r\n\r\n upsertSessionState(this.state, sessionId, {\r\n direction: e.originator,\r\n from: e.originator === \"remote\" ? e.request.from.uri.user : null,\r\n to: e.request.to.uri.user,\r\n status: e.originator === \"remote\" ? CallStatus.Ringing : CallStatus.Dialing,\r\n mediaKind: sdpHasVideo ? \"video\" : \"audio\",\r\n remoteVideoEnabled: sdpHasVideo,\r\n });\r\n\r\n this.emit(\"newRTCSession\", e);\r\n }\r\n}\r\n","import { SipUserAgent } from \"./userAgent\";\r\nimport {\r\n AnswerOptions,\r\n CallOptions,\r\n DTMFOptions,\r\n JsSIPEventMap,\r\n ReferOptions,\r\n RTCSession,\r\n RTCSessionEvent,\r\n RTCSessionEventMap,\r\n SipConfiguration,\r\n SipEventManager,\r\n TerminateOptions,\r\n UAEventMap,\r\n} from \"./types\";\r\n\r\nimport { SipState, SipStatus, CallStatus } from \"../core/types\";\r\nimport { EventTargetEmitter } from \"../core/eventEmitter\";\r\nimport {\r\n SipErrorHandler,\r\n SipErrorFormatter,\r\n SipErrorPayload,\r\n} from \"../core/sipErrorHandler\";\r\nimport { SipStateStore } from \"../core/sipStateStore\";\r\nimport { createUAHandlers } from \"./handlers/uaHandlers\";\r\nimport { createSessionHandlers } from \"./handlers/sessionHandlers\";\r\nimport { SessionManager } from \"./sessionManager\";\r\nimport { removeSessionState } from \"./sessionState\";\r\nimport { SessionLifecycle } from \"./sessionLifecycle\";\r\n\r\ntype SipClientOptions = {\r\n errorMessages?: Record<string, string>;\r\n formatError?: SipErrorFormatter;\r\n errorHandler?: SipErrorHandler;\r\n debug?: boolean | string;\r\n};\r\n\r\nexport type MicrophoneRecoveryOptions = {\r\n intervalMs?: number;\r\n maxRetries?: number;\r\n};\r\n\r\nconst SESSION_DEBUG_KEY = \"sip-debug-enabled\";\r\n\r\nexport class SipClient extends EventTargetEmitter<JsSIPEventMap> {\r\n public readonly userAgent = new SipUserAgent();\r\n public readonly stateStore = new SipStateStore();\r\n\r\n private readonly uaHandlers: Partial<UAEventMap>;\r\n private readonly uaHandlerKeys: (keyof UAEventMap)[];\r\n private sessionHandlers = new Map<string, Partial<RTCSessionEventMap>>();\r\n private readonly errorHandler: SipErrorHandler;\r\n private debugPattern?: boolean | string;\r\n private maxSessionCount = Infinity;\r\n private sessionManager = new SessionManager();\r\n private lifecycle: SessionLifecycle;\r\n private micRecovery = new Map<string, { stop: () => void }>();\r\n private micRecoveryEnabled = false;\r\n private micRecoveryDefaults: Required<MicrophoneRecoveryOptions> = {\r\n intervalMs: 2000,\r\n maxRetries: Infinity,\r\n };\r\n private unloadHandler?: () => void;\r\n private stateLogOff?: () => void;\r\n\r\n public get state(): SipState {\r\n return this.stateStore.getState();\r\n }\r\n\r\n constructor(options: SipClientOptions = {}) {\r\n super();\r\n\r\n this.errorHandler =\r\n options.errorHandler ??\r\n new SipErrorHandler({\r\n formatter: options.formatError,\r\n messages: options.errorMessages,\r\n });\r\n this.debugPattern = options.debug;\r\n\r\n this.uaHandlers = createUAHandlers({\r\n emitter: this,\r\n state: this.stateStore,\r\n cleanupAllSessions: () => this.cleanupAllSessions(),\r\n emitError: (raw, code, fallback) => this.emitError(raw, code, fallback),\r\n onNewRTCSession: (e: RTCSessionEvent) => this.onNewRTCSession(e),\r\n });\r\n\r\n this.uaHandlerKeys = Object.keys(this.uaHandlers) as (keyof UAEventMap)[];\r\n\r\n this.lifecycle = new SessionLifecycle({\r\n state: this.stateStore,\r\n sessionManager: this.sessionManager,\r\n emit: (event, payload) => this.emit(event as any, payload as any),\r\n emitError: (raw, code, fallback) => this.emitError(raw, code, fallback),\r\n attachSessionHandlers: (sessionId, session) =>\r\n this.attachSessionHandlers(sessionId, session),\r\n getMaxSessionCount: () => this.maxSessionCount,\r\n });\r\n\r\n if (typeof window !== \"undefined\") {\r\n // Let window.sipSupport trigger client debug toggles.\r\n (window as any).sipDebugBridge = (debug?: boolean | string) =>\r\n this.setDebug(debug ?? true);\r\n }\r\n }\r\n\r\n public connect(uri: string, password: string, config: SipConfiguration) {\r\n this.disconnect();\r\n this.stateStore.setState({ sipStatus: SipStatus.Connecting });\r\n const {\r\n debug: cfgDebug,\r\n enableMicRecovery,\r\n micRecoveryIntervalMs,\r\n micRecoveryMaxRetries,\r\n maxSessionCount,\r\n pendingMediaTtlMs,\r\n ...uaCfg\r\n } = config;\r\n this.maxSessionCount =\r\n typeof maxSessionCount === \"number\" ? maxSessionCount : Infinity;\r\n this.micRecoveryEnabled = Boolean(enableMicRecovery);\r\n if (typeof micRecoveryIntervalMs === \"number\") {\r\n this.micRecoveryDefaults.intervalMs = micRecoveryIntervalMs;\r\n }\r\n if (typeof micRecoveryMaxRetries === \"number\") {\r\n this.micRecoveryDefaults.maxRetries = micRecoveryMaxRetries;\r\n }\r\n this.sessionManager.setPendingMediaTtl(pendingMediaTtlMs);\r\n // Config debug has priority, then persisted session flag, then prior setting.\r\n const debug = cfgDebug ?? this.getPersistedDebug() ?? this.debugPattern;\r\n this.userAgent.start(uri, password, uaCfg, { debug });\r\n this.attachUAHandlers();\r\n this.attachBeforeUnload();\r\n this.syncDebugInspector(debug);\r\n }\r\n\r\n public registerUA() {\r\n this.userAgent.register();\r\n }\r\n\r\n public disconnect() {\r\n this.detachBeforeUnload();\r\n this.detachUAHandlers();\r\n this.userAgent.stop();\r\n this.cleanupAllSessions();\r\n this.stateStore.reset();\r\n }\r\n\r\n public call(target: string, callOptions: CallOptions = {}) {\r\n try {\r\n const opts = this.ensureMediaConstraints(callOptions);\r\n if (opts.mediaStream)\r\n this.sessionManager.enqueueOutgoingMedia(opts.mediaStream);\r\n\r\n const ua = this.userAgent.getUA();\r\n ua?.call(target, opts);\r\n } catch (e: unknown) {\r\n const err = this.emitError(e, \"CALL_FAILED\", \"call failed\");\r\n this.cleanupAllSessions();\r\n this.stateStore.batchSet({\r\n error: err.cause,\r\n });\r\n }\r\n }\r\n\r\n public answer(sessionId: string, options: AnswerOptions = {}) {\r\n const resolved = this.resolveExistingSessionId(sessionId);\r\n if (!resolved) return false;\r\n return this.answerSession(resolved, options);\r\n }\r\n public hangup(sessionId: string, options?: TerminateOptions) {\r\n const resolved = this.resolveExistingSessionId(sessionId);\r\n if (!resolved) return false;\r\n return this.hangupSession(resolved, options);\r\n }\r\n\r\n public hangupAll(options?: TerminateOptions) {\r\n const ids = this.getSessionIds();\r\n ids.forEach((id) => this.hangupSession(id, options));\r\n return ids.length > 0;\r\n }\r\n\r\n public toggleMute(sessionId: string) {\r\n return this.toggleMuteSession(sessionId);\r\n }\r\n public toggleHold(sessionId: string) {\r\n return this.toggleHoldSession(sessionId);\r\n }\r\n public sendDTMF(\r\n sessionId: string,\r\n tones: string | number,\r\n options?: DTMFOptions\r\n ) {\r\n return this.sendDTMFSession(sessionId, tones, options);\r\n }\r\n public transfer(sessionId: string, target: string, options?: ReferOptions) {\r\n return this.transferSession(sessionId, target, options);\r\n }\r\n\r\n public onChange(fn: (s: SipState) => void) {\r\n return this.stateStore.onChange(fn);\r\n }\r\n\r\n private attachUAHandlers() {\r\n const ua = this.userAgent.ua;\r\n if (!ua) return;\r\n\r\n this.detachUAHandlers();\r\n this.uaHandlerKeys.forEach((ev) => {\r\n const h = this.uaHandlers[ev];\r\n if (h) ua.on(ev, h as any);\r\n });\r\n }\r\n\r\n public setDebug(debug?: boolean | string) {\r\n this.debugPattern = debug;\r\n this.userAgent.setDebug(debug);\r\n this.syncDebugInspector(debug);\r\n }\r\n\r\n private attachSessionHandlers(sessionId: string, session: RTCSession) {\r\n const handlers = this.createSessionHandlersFor(sessionId, session);\r\n this.sessionHandlers.set(sessionId, handlers);\r\n\r\n (Object.keys(handlers) as (keyof RTCSessionEventMap)[]).forEach((ev) => {\r\n const h = handlers[ev];\r\n if (h) session.on(ev, h as any);\r\n });\r\n }\r\n\r\n private detachSessionHandlers(sessionId: string, session: RTCSession) {\r\n const handlers = this.sessionHandlers.get(sessionId);\r\n if (!handlers || !session) return;\r\n (Object.keys(handlers) as (keyof RTCSessionEventMap)[]).forEach((ev) => {\r\n const h = handlers[ev];\r\n if (h) session.off(ev, h as any);\r\n });\r\n this.sessionHandlers.delete(sessionId);\r\n }\r\n\r\n private detachUAHandlers() {\r\n const ua = this.userAgent.ua;\r\n if (!ua) return;\r\n this.uaHandlerKeys.forEach((ev) => {\r\n const h = this.uaHandlers[ev];\r\n if (h) ua.off(ev, h as any);\r\n });\r\n }\r\n\r\n private cleanupSession(sessionId: string, session?: RTCSession) {\r\n const targetSession =\r\n session ??\r\n this.sessionManager.getSession(sessionId) ??\r\n this.sessionManager.getRtc(sessionId)?.currentSession;\r\n this.detachSessionHandlers(sessionId, targetSession as any);\r\n this.disableMicrophoneRecovery(sessionId);\r\n this.sessionManager.cleanupSession(sessionId);\r\n removeSessionState(this.stateStore, sessionId);\r\n }\r\n\r\n private cleanupAllSessions() {\r\n this.sessionManager.cleanupAllSessions();\r\n this.micRecovery.forEach((entry) => entry.stop());\r\n this.micRecovery.clear();\r\n this.sessionHandlers.clear();\r\n this.stateStore.setState({\r\n sessions: [],\r\n error: null,\r\n });\r\n }\r\n\r\n private createSessionHandlersFor(\r\n sessionId: string,\r\n session: RTCSession\r\n ): Partial<RTCSessionEventMap> {\r\n const rtc = this.sessionManager.getOrCreateRtc(sessionId, session);\r\n return createSessionHandlers({\r\n emitter: this,\r\n state: this.stateStore,\r\n rtc,\r\n detachSessionHandlers: () => this.cleanupSession(sessionId, session),\r\n emitError: (raw, code, fallback) => this.emitError(raw, code, fallback),\r\n onSessionFailed: (err?: string, event?: RTCSessionEvent) =>\r\n this.onSessionFailed(err, event),\r\n onSessionConfirmed: (confirmedSessionId) => {\r\n if (this.micRecoveryEnabled) {\r\n this.enableMicrophoneRecovery(confirmedSessionId);\r\n }\r\n },\r\n sessionId,\r\n });\r\n }\r\n\r\n protected onNewRTCSession(e: RTCSessionEvent) {\r\n this.lifecycle.handleNewRTCSession(e);\r\n }\r\n\r\n protected onSessionFailed(error?: string, event?: RTCSessionEvent) {\r\n const rawCause = (event as any)?.cause ?? error;\r\n const statusCode = (event as any)?.message?.status_code;\r\n const statusText = (event as any)?.message?.reason_phrase;\r\n const causeText =\r\n rawCause ||\r\n (statusCode\r\n ? `${statusCode}${statusText ? \" \" + statusText : \"\"}`\r\n : \"call failed\");\r\n this.emitError(\r\n { raw: event, cause: rawCause, statusCode, statusText },\r\n \"SESSION_FAILED\",\r\n causeText\r\n );\r\n }\r\n\r\n private emitError(\r\n raw: unknown,\r\n code?: string,\r\n fallback?: string\r\n ): SipErrorPayload {\r\n const payload = this.errorHandler.format({ raw, code, fallback });\r\n this.emit(\"error\", payload);\r\n return payload;\r\n }\r\n\r\n private resolveSessionId(sessionId?: string) {\r\n if (sessionId) return sessionId;\r\n const sessions = this.stateStore.getState().sessions;\r\n const active = sessions.find((s) => s.status === CallStatus.Active);\r\n return active?.id ?? sessions[0]?.id ?? null;\r\n }\r\n\r\n private sessionExists(sessionId: string) {\r\n return (\r\n !!this.sessionManager.getSession(sessionId) ||\r\n !!this.sessionManager.getRtc(sessionId)\r\n );\r\n }\r\n\r\n private resolveExistingSessionId(sessionId?: string) {\r\n const id = this.resolveSessionId(sessionId);\r\n if (!id) return null;\r\n return this.sessionExists(id) ? id : null;\r\n }\r\n\r\n private ensureMediaConstraints<\r\n T extends {\r\n mediaStream?: MediaStream;\r\n mediaConstraints?: MediaStreamConstraints;\r\n }\r\n >(opts: T): T {\r\n if (opts.mediaStream || opts.mediaConstraints) return opts;\r\n return { ...opts, mediaConstraints: { audio: true, video: false } } as T;\r\n }\r\n\r\n public answerSession(sessionId: string, options: AnswerOptions = {}) {\r\n if (!sessionId || !this.sessionExists(sessionId)) return false;\r\n const opts = this.ensureMediaConstraints(options);\r\n if (opts.mediaStream) {\r\n this.sessionManager.setSessionMedia(sessionId, opts.mediaStream);\r\n }\r\n return this.sessionManager.answer(sessionId, opts);\r\n }\r\n\r\n public hangupSession(sessionId: string, options?: TerminateOptions) {\r\n if (!sessionId || !this.sessionExists(sessionId)) return false;\r\n return this.sessionManager.hangup(sessionId, options);\r\n }\r\n\r\n public toggleMuteSession(sessionId?: string) {\r\n const resolved = this.resolveExistingSessionId(sessionId);\r\n if (!resolved) return false;\r\n const sessionState = this.stateStore\r\n .getState()\r\n .sessions.find((s) => s.id === resolved);\r\n const muted = sessionState?.muted ?? false;\r\n if (muted) {\r\n this.sessionManager.unmute(resolved);\r\n return true;\r\n }\r\n this.sessionManager.mute(resolved);\r\n return true;\r\n }\r\n\r\n public toggleHoldSession(sessionId?: string) {\r\n const resolved = this.resolveExistingSessionId(sessionId);\r\n if (!resolved) return false;\r\n const sessionState = this.stateStore\r\n .getState()\r\n .sessions.find((s) => s.id === resolved);\r\n const isOnHold = sessionState?.status === CallStatus.Hold;\r\n if (isOnHold) {\r\n this.sessionManager.unhold(resolved);\r\n return true;\r\n }\r\n if (sessionState?.status === CallStatus.Active) {\r\n this.sessionManager.hold(resolved);\r\n return true;\r\n }\r\n return true;\r\n }\r\n\r\n public sendDTMFSession(\r\n sessionId: string,\r\n tones: string | number,\r\n options?: DTMFOptions\r\n ) {\r\n const resolved = this.resolveExistingSessionId(sessionId);\r\n if (!resolved) return false;\r\n const sessionState = this.stateStore\r\n .getState()\r\n .sessions.find((s) => s.id === resolved);\r\n if (sessionState?.status === CallStatus.Active)\r\n this.sessionManager.sendDTMF(resolved, tones, options);\r\n return true;\r\n }\r\n\r\n public transferSession(\r\n sessionId: string,\r\n target: string,\r\n options?: ReferOptions\r\n ) {\r\n const resolved = this.resolveExistingSessionId(sessionId);\r\n if (!resolved) return false;\r\n const sessionState = this.stateStore\r\n .getState()\r\n .sessions.find((s) => s.id === resolved);\r\n if (sessionState?.status === CallStatus.Active)\r\n this.sessionManager.transfer(resolved, target, options);\r\n return true;\r\n }\r\n\r\n public setSessionMedia(sessionId: string, stream: MediaStream) {\r\n this.sessionManager.setSessionMedia(sessionId, stream);\r\n }\r\n\r\n public enableMicrophoneRecovery(\r\n sessionId: string,\r\n options: MicrophoneRecoveryOptions = {}\r\n ) {\r\n const resolved = this.resolveExistingSessionId(sessionId);\r\n if (!resolved) return () => {};\r\n\r\n this.disableMicrophoneRecovery(resolved);\r\n\r\n const intervalMs =\r\n options.intervalMs ?? this.micRecoveryDefaults.intervalMs;\r\n const maxRetries =\r\n options.maxRetries ?? this.micRecoveryDefaults.maxRetries;\r\n let retries = 0;\n let stopped = false;\n const startedAt = Date.now();\n const warmupMs = Math.max(intervalMs * 2, 2000);\n\r\n const tick = async () => {\r\n if (stopped || retries >= maxRetries) return;\r\n\r\n const rtc = this.sessionManager.getRtc(resolved);\r\n const session = this.sessionManager.getSession(resolved);\r\n if (!rtc || !session) return;\r\n\r\n const sessionState = this.stateStore\r\n .getState()\r\n .sessions.find((s) => s.id === resolved);\r\n if (sessionState?.muted) return;\r\n\r\n const stream = rtc.mediaStream;\n const track = stream?.getAudioTracks?.()[0];\n const sender = (session as any)?.connection\n ?.getSenders?.()\n .find((s: RTCRtpSender) => s.track?.kind === \"audio\");\n\n if (!track && !sender) return;\n\n if (Date.now() - startedAt < warmupMs) return;\n\n const trackLive = track?.readyState === \"live\";\n const senderLive = sender?.track?.readyState === \"live\";\n if (trackLive && senderLive) return;\n\r\n this.emitError(\r\n {\r\n cause: \"microphone dropped\",\r\n trackLive,\r\n senderLive,\r\n },\r\n \"MICROPHONE_DROPPED\",\r\n \"microphone dropped\"\r\n );\r\n\r\n retries += 1;\r\n if (trackLive && !senderLive && track) {\r\n await rtc.replaceAudioTrack(track);\r\n return;\r\n }\r\n\r\n let nextStream: MediaStream;\r\n try {\r\n const deviceId =\r\n track?.getSettings?.().deviceId ??\r\n sender?.track?.getSettings?.().deviceId;\r\n nextStream = await this.requestMicrophoneStreamInternal(deviceId);\r\n } catch (err) {\r\n console.warn(\"[sip] mic recovery failed to get stream\", err);\r\n return;\r\n }\r\n const nextTrack = nextStream.getAudioTracks()[0];\r\n if (!nextTrack) return;\r\n\r\n await rtc.replaceAudioTrack(nextTrack);\r\n this.sessionManager.setSessionMedia(resolved, nextStream);\r\n };\r\n\r\n const timer = setInterval(() => {\r\n void tick();\r\n }, intervalMs);\r\n void tick();\r\n\r\n const session = this.sessionManager.getSession(resolved);\r\n const pc: RTCPeerConnection | undefined = (session as any)?.connection;\r\n const onIceChange = () => {\r\n const state = pc?.iceConnectionState;\r\n if (state === \"failed\" || state === \"disconnected\") void tick();\r\n };\r\n pc?.addEventListener?.(\"iceconnectionstatechange\", onIceChange);\r\n\r\n const stop = () => {\r\n stopped = true;\r\n clearInterval(timer);\r\n pc?.removeEventListener?.(\"iceconnectionstatechange\", onIceChange);\r\n };\r\n this.micRecovery.set(resolved, { stop });\r\n return stop;\r\n }\r\n\r\n public disableMicrophoneRecovery(sessionId: string) {\r\n const resolved = this.resolveExistingSessionId(sessionId);\r\n if (!resolved) return false;\r\n const entry = this.micRecovery.get(resolved);\r\n if (!entry) return false;\r\n entry.stop();\r\n this.micRecovery.delete(resolved);\r\n return true;\r\n }\r\n\r\n public switchCameraSession(sessionId: string, track: MediaStreamTrack) {\r\n if (!this.sessionExists(sessionId)) return false;\r\n const rtc = this.sessionManager.getRtc(sessionId);\r\n return rtc ? rtc.switchCamera(track) : false;\r\n }\r\n\r\n public enableVideoSession(sessionId: string) {\r\n if (!this.sessionExists(sessionId)) return false;\r\n const rtc = this.sessionManager.getRtc(sessionId);\r\n rtc?.enableVideo();\r\n return !!rtc;\r\n }\r\n\r\n public disableVideoSession(sessionId: string) {\r\n if (!this.sessionExists(sessionId)) return false;\r\n const rtc = this.sessionManager.getRtc(sessionId);\r\n rtc?.disableVideo();\r\n return !!rtc;\r\n }\r\n\r\n public getSession(sessionId: string) {\r\n return this.sessionManager.getSession(sessionId);\r\n }\r\n\r\n public getSessionIds() {\r\n return this.sessionManager.getSessionIds();\r\n }\r\n\r\n public getSessions() {\r\n return this.sessionManager.getSessions();\r\n }\r\n\r\n private attachBeforeUnload() {\r\n if (typeof window === \"undefined\" || this.unloadHandler) return;\r\n\r\n const handler = () => {\r\n this.hangupAll();\r\n this.disconnect();\r\n };\r\n\r\n window.addEventListener(\"beforeunload\", handler);\r\n this.unloadHandler = handler;\r\n }\r\n\r\n private detachBeforeUnload() {\r\n if (typeof window === \"undefined\" || !this.unloadHandler) return;\r\n window.removeEventListener(\"beforeunload\", this.unloadHandler);\r\n this.unloadHandler = undefined;\r\n }\r\n\r\n private syncDebugInspector(debug?: boolean | string) {\r\n if (typeof window === \"undefined\") return;\r\n this.toggleStateLogger(Boolean(debug));\r\n\r\n const win = window as any;\r\n const disabledInspector = () => {\r\n console.warn(\"SIP debug inspector disabled; enable debug to inspect.\");\r\n return null;\r\n };\r\n win.sipState = () =>\r\n debug ? this.stateStore.getState() : disabledInspector();\r\n win.sipSessions = () => (debug ? this.getSessions() : disabledInspector());\r\n }\r\n\r\n private toggleStateLogger(enabled: boolean) {\r\n if (!enabled) {\r\n this.stateLogOff?.();\r\n this.stateLogOff = undefined;\r\n return;\r\n }\r\n if (this.stateLogOff) return;\r\n\r\n let prev = this.stateStore.getState();\r\n // Emit initial snapshot right away for visibility.\r\n console.info(\"[sip][state]\", { initial: true }, prev);\r\n\r\n this.stateLogOff = this.stateStore.onChange((next) => {\r\n const changes = this.diffState(prev, next);\r\n if (changes) {\r\n // Log concise diff and the current snapshot for quick inspection.\r\n console.info(\"[sip][state]\", changes, next);\r\n }\r\n prev = next;\r\n });\r\n }\r\n\r\n private diffState(\r\n prev: SipState,\r\n next: SipState\r\n ): Record<string, { from: unknown; to: unknown }> | null {\r\n const changed: Record<string, { from: unknown; to: unknown }> = {};\r\n for (const key of Object.keys(next) as Array<keyof SipState>) {\r\n if (prev[key] !== next[key]) {\r\n changed[key as string] = { from: prev[key], to: next[key] };\r\n }\r\n }\r\n return Object.keys(changed).length ? changed : null;\r\n }\r\n\r\n private getPersistedDebug(): boolean | string | undefined {\r\n if (typeof window === \"undefined\") return undefined;\r\n try {\r\n const persisted = window.sessionStorage.getItem(SESSION_DEBUG_KEY);\r\n if (!persisted) return undefined;\r\n return persisted;\r\n } catch {\r\n return undefined;\r\n }\r\n }\r\n\r\n private async requestMicrophoneStreamInternal(\r\n deviceId?: string\r\n ): Promise<MediaStream> {\r\n if (\r\n typeof navigator === \"undefined\" ||\r\n !navigator.mediaDevices?.getUserMedia\r\n ) {\r\n throw new Error(\"getUserMedia not available\");\r\n }\r\n const audio =\r\n deviceId && deviceId !== \"default\"\r\n ? { deviceId: { exact: deviceId } }\r\n : true;\r\n try {\r\n return await navigator.mediaDevices.getUserMedia({ audio });\r\n } catch (err: any) {\r\n const cause = err?.name || \"getUserMedia failed\";\r\n this.emitError(\r\n { raw: err, cause },\r\n \"MICROPHONE_UNAVAILABLE\",\r\n \"microphone unavailable\"\r\n );\r\n throw err;\r\n }\r\n }\r\n}\r\n\r\nexport function createSipClientInstance(options?: SipClientOptions): SipClient {\r\n return new SipClient(options);\r\n}\r\n\r\nexport function createSipEventManager(client: SipClient): SipEventManager {\r\n return {\r\n onUA(event, handler) {\r\n return client.on(event, handler as any);\r\n },\r\n onSession(sessionId, event, handler) {\r\n const session = client.getSession(sessionId);\r\n if (!session) return () => {};\r\n session.on(event as any, handler as any);\r\n return () => session.off(event as any, handler as any);\r\n },\r\n };\r\n}\r\n","import \"./sip/debugger\"; // ensure window helpers attach on load\r\n\r\nexport * from \"./sip/types\";\r\n\r\nexport {\n SipClient,\n type MicrophoneRecoveryOptions,\n createSipClientInstance,\n createSipEventManager,\n} from \"./sip/client\";\nexport {\r\n SipDebugger,\r\n sipDebugger,\r\n type SipDebugToggleResult,\r\n} from \"./sip/debugger\";\r\n\r\nexport { WebRTCSessionController } from \"./sip/sessionController\";\r\nexport { SessionManager } from \"./sip/sessionManager\";\r\n\r\nexport {\r\n SipErrorHandler,\r\n type SipErrorPayload,\r\n type SipErrorFormatter,\r\n} from \"./core/sipErrorHandler\";\r\n\r\nexport { WebSocketInterface } from \"jssip\";\r\n\r\nexport {\r\n SipStatus,\r\n CallStatus,\r\n CallDirection,\r\n SipStatusList,\r\n CallStatusList,\r\n isSipStatus,\r\n isCallStatus,\r\n} from \"./core/types\";\r\n\r\nexport type {\r\n SipStatus as SipStatusType,\r\n CallStatus as CallStatusType,\r\n CallDirection as CallDirectionType,\r\n SipState,\r\n SipSessionState,\r\n} from \"./core/types\";\r\n","import { createContext } from \"react\";\r\nimport type { SipClient } from \"jssip-lib\";\r\nimport type { SipEventManager } from \"jssip-lib\";\r\n\r\nexport type SipContextType = { client: SipClient, sipEventManager: SipEventManager };\r\nexport const SipContext = createContext<SipContextType | null>(null);\r\n","import { useCallback, useSyncExternalStore } from \"react\";\r\nimport type { SipState } from \"jssip-lib\";\r\nimport { useSip } from \"./useSip\";\r\n\r\nexport function useSipState(): SipState {\r\n const { client } = useSip();\r\n const subscribe = useCallback(\r\n (onStoreChange: () => void) => client.onChange(onStoreChange),\r\n [client]\r\n );\r\n\r\n const getSnapshot = useCallback(() => client.state, [client]);\r\n\r\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\r\n}\r\n","import { useContext } from \"react\";\r\nimport { SipContext } from \"../context\";\r\n\r\nexport function useSip() {\r\n const ctx = useContext(SipContext);\r\n if (!ctx) throw new Error(\"Must be used within SipProvider\");\r\n return ctx;\r\n}\r\n","import { useMemo } from \"react\";\nimport { useSip } from \"./useSip\";\n\nexport function useSipActions() {\n const { client } = useSip();\n return useMemo(\n () => ({\n call: (...args: Parameters<typeof client.call>) => client.call(...args),\n answer: (...args: Parameters<typeof client.answerSession>) =>\n client.answerSession(...args),\n hangup: (...args: Parameters<typeof client.hangupSession>) =>\n client.hangupSession(...args),\n toggleMute: (...args: Parameters<typeof client.toggleMuteSession>) =>\n client.toggleMuteSession(...args),\n toggleHold: (...args: Parameters<typeof client.toggleHoldSession>) =>\n client.toggleHoldSession(...args),\n sendDTMF: (...args: Parameters<typeof client.sendDTMFSession>) =>\n client.sendDTMFSession(...args),\n transfer: (...args: Parameters<typeof client.transferSession>) =>\n client.transferSession(...args),\n getSession: (...args: Parameters<typeof client.getSession>) =>\n client.getSession(...args),\n getSessionIds: () => client.getSessionIds(),\n getSessions: () => client.getSessions(),\n setSessionMedia: (...args: Parameters<typeof client.setSessionMedia>) =>\n client.setSessionMedia(...args),\n enableMicrophoneRecovery: (\n ...args: Parameters<typeof client.enableMicrophoneRecovery>\n ) => client.enableMicrophoneRecovery(...args),\n disableMicrophoneRecovery: (\n ...args: Parameters<typeof client.disableMicrophoneRecovery>\n ) => client.disableMicrophoneRecovery(...args),\n switchCamera: (...args: Parameters<typeof client.switchCameraSession>) =>\n client.switchCameraSession(...args),\n enableVideo: (...args: Parameters<typeof client.enableVideoSession>) =>\n client.enableVideoSession(...args),\n disableVideo: (...args: Parameters<typeof client.disableVideoSession>) =>\n client.disableVideoSession(...args),\n }),\n [client]\n );\n}\n","import type { SipState } from \"jssip-lib\";\nimport { useSipState } from \"./useSipState\";\n\nexport function useSipSessions(): Pick<SipState, \"sessions\"> {\n const { sessions } = useSipState();\n return { sessions };\n}\n","import { useEffect } from \"react\";\nimport type {\n SessionEventName,\n SessionEventPayload,\n UAEventName,\n UAEventPayload,\n} from \"jssip-lib\";\nimport { useSip } from \"./useSip\";\n\nexport function useSipEvent<K extends UAEventName>(\n event: K,\n handler?: (payload?: UAEventPayload<K>) => void\n) {\n const { sipEventManager } = useSip();\n\n useEffect(() => {\n if (!handler) return;\n return sipEventManager.onUA(event, handler);\n }, [event, handler, sipEventManager]);\n}\n\nexport function useSipSessionEvent<K extends SessionEventName>(\n sessionId: string,\n event: K,\n handler?: (payload?: SessionEventPayload<K>) => void\n) {\n const { sipEventManager } = useSip();\n\n useEffect(() => {\n if (!handler) return;\n return sipEventManager.onSession(sessionId, event, handler);\n }, [event, handler, sessionId, sipEventManager]);\n}\n","import { useEffect, useRef } from \"react\";\r\nimport { useSip } from \"../hooks/useSip\";\r\nimport { createCallPlayer } from \"jssip-lib/dom\";\r\n\r\nexport function CallPlayer({ sessionId }: { sessionId?: string }) {\r\n const { client } = useSip();\r\n const audioRef = useRef<HTMLAudioElement | null>(null);\r\n\r\n useEffect(() => {\r\n if (!audioRef.current) return;\r\n\r\n const player = createCallPlayer(audioRef.current);\r\n const session = sessionId ? client.getSession(sessionId) : null;\r\n const off = session\r\n ? player.bindToSession(session)\r\n : player.bindToClient(client);\r\n\r\n return () => {\r\n off?.();\r\n player.detach();\r\n };\r\n }, [client, sessionId]);\r\n\r\n return <audio ref={audioRef} autoPlay playsInline />;\r\n}\r\n","import { SipClient } from \"../../sip/client\";\r\nimport type { RTCSession, RTCSessionEvent } from \"../../sip/types\";\r\n\r\nexport function createCallPlayer(audioEl: HTMLAudioElement) {\r\n let cleanupTrackListener: (() => void) | null = null;\r\n let cleanupSessionPeerListener: (() => void) | null = null;\r\n let cleanupClientListeners: (() => void) | null = null;\r\n\r\n const dispose = (fn: (() => void) | null) => {\r\n if (fn) fn();\r\n return null as null;\r\n };\r\n\r\n /** Stop all tracks and clear audio element */\r\n function clearAudioStream(stream?: MediaStream | null) {\r\n if (stream) {\r\n for (const t of stream.getTracks()) {\r\n t.stop();\r\n }\r\n }\r\n audioEl.srcObject = null;\r\n }\r\n\r\n const attachTracks = (pc: RTCPeerConnection) => {\r\n const onTrack = (e: RTCTrackEvent) => {\r\n if (e.track.kind !== \"audio\") return;\r\n\r\n const nextStream = e.streams?.[0] ?? new MediaStream([e.track]);\r\n const prev = audioEl.srcObject as MediaStream | null;\r\n\r\n if (prev && prev !== nextStream) {\r\n clearAudioStream(prev);\r\n }\r\n\r\n audioEl.srcObject = nextStream;\r\n audioEl.play?.().catch(() => {});\r\n };\r\n\r\n pc.addEventListener(\"track\", onTrack);\r\n return () => pc.removeEventListener(\"track\", onTrack);\r\n };\r\n\r\n const listenSessionPeerconnection = (session: RTCSession) => {\r\n const onPeer = (data: { peerconnection: RTCPeerConnection }) => {\r\n cleanupTrackListener = dispose(cleanupTrackListener);\r\n cleanupTrackListener = attachTracks(data.peerconnection);\r\n };\r\n session.on(\"peerconnection\", onPeer);\r\n return () => session.off(\"peerconnection\", onPeer);\r\n };\r\n\r\n function bindToSession(session: RTCSession) {\r\n if (\r\n session?.direction === \"outgoing\" &&\r\n session.connection instanceof RTCPeerConnection\r\n ) {\r\n cleanupTrackListener = dispose(cleanupTrackListener);\r\n cleanupTrackListener = attachTracks(session.connection);\r\n }\r\n\r\n cleanupSessionPeerListener = dispose(cleanupSessionPeerListener);\r\n cleanupSessionPeerListener = listenSessionPeerconnection(session);\r\n\r\n return () => {\r\n cleanupSessionPeerListener = dispose(cleanupSessionPeerListener);\r\n cleanupTrackListener = dispose(cleanupTrackListener);\r\n };\r\n }\r\n\r\n function bindToClient(client: SipClient) {\r\n const offNew = client.on(\"newRTCSession\", (payload) => {\r\n const e = (payload as any)?.data as RTCSessionEvent | undefined;\r\n cleanupSessionPeerListener = dispose(cleanupSessionPeerListener);\r\n cleanupTrackListener = dispose(cleanupTrackListener);\r\n\r\n if (!e?.session) return;\r\n\r\n cleanupSessionPeerListener = listenSessionPeerconnection(e.session);\r\n if (\r\n e.session.direction === \"outgoing\" &&\r\n e.session.connection instanceof RTCPeerConnection\r\n ) {\r\n cleanupTrackListener = attachTracks(e.session.connection);\r\n }\r\n });\r\n\r\n const offEnded = client.on(\"ended\", () => detach());\r\n const offFailed = client.on(\"failed\", () => detach());\r\n const offDisconnected = client.on(\"disconnected\", () => detach());\r\n\r\n cleanupClientListeners = () => {\r\n offNew();\r\n offEnded();\r\n offFailed();\r\n offDisconnected();\r\n };\r\n return cleanupClientListeners;\r\n }\r\n\r\n function detach() {\r\n cleanupClientListeners = dispose(cleanupClientListeners);\r\n cleanupSessionPeerListener = dispose(cleanupSessionPeerListener);\r\n cleanupTrackListener = dispose(cleanupTrackListener);\r\n clearAudioStream(audioEl.srcObject as MediaStream | null);\r\n }\r\n\r\n return {\r\n bindToSession,\r\n bindToClient,\r\n detach,\r\n };\r\n}\r\n","import React, { useMemo } from \"react\";\nimport { SipContext } from \"../context\";\nimport { createSipEventManager, type SipClient, type SipEventManager } from \"jssip-lib\";\n\nexport function SipProvider({\n client,\n children,\n sipEventManager,\n}: {\n sipEventManager?: SipEventManager;\n client: SipClient;\n children: React.ReactNode;\n}) {\n const manager = useMemo(\n () => sipEventManager ?? createSipEventManager(client),\n [client, sipEventManager]\n );\n\n const contextValue = useMemo(() => ({ client, sipEventManager: manager }), [client, manager]);\n\n return (\n <SipContext.Provider value={contextValue}>\n {children}\n </SipContext.Provider>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/jssip-lib/sip/debugger.ts","../src/jssip-lib/sip/userAgent.ts","../src/jssip-lib/core/types.ts","../src/jssip-lib/core/eventEmitter.ts","../src/jssip-lib/core/sipErrorHandler.ts","../src/jssip-lib/core/sipState.ts","../src/jssip-lib/core/sipStateStore.ts","../src/jssip-lib/sip/handlers/uaHandlers.ts","../src/jssip-lib/sip/sessionState.ts","../src/jssip-lib/sip/handlers/sessionHandlers.ts","../src/jssip-lib/sip/sessionController.ts","../src/jssip-lib/sip/sessionManager.ts","../src/jssip-lib/sip/sessionLifecycle.ts","../src/jssip-lib/sip/client.ts","../src/jssip-lib/index.ts","../src/context/index.tsx","../src/hooks/useSipState.ts","../src/hooks/useSip.ts","../src/hooks/useSipActions.ts","../src/hooks/useSipSessions.ts","../src/hooks/useSipEvent.ts","../src/components/call-player.tsx","../src/jssip-lib/adapters/dom/createCallPlayer.ts","../src/provider/index.tsx"],"names":["JsSIP","message","session","pc","useEffect","useMemo","jsx"],"mappings":";AAAA,OAAO,WAAW;AAaX,IAAM,cAAN,MAAkB;AAAA,EAMvB,YAAY,aAAa,qBAAqB,iBAAiB,WAAW;AAH1E,SAAQ,UAAU;AAIhB,SAAK,aAAa;AAClB,SAAK,iBAAiB;AAAA,EACxB;AAAA,EAEA,gBAAgB,UAA8B,mBAAmB,GAAS;AACxE,QAAI;AACF,YAAM,QAAQ,SAAS,QAAQ,KAAK,UAAU;AAC9C,UAAI;AAAO,aAAK,OAAO,OAAO,OAAO;AAAA,IACvC,QAAQ;AAAA,IAER;AAAA,EACF;AAAA,EAEA,OACE,UAAkB,KAAK,gBACvB,UAA8B,mBAAmB,GAC3C;AACN,QAAI;AACF,UAAI,OAAO,OAAO,OAAO,WAAW,YAAY;AAC9C,cAAM,MAAM,OAAO,OAAO;AAC1B,aAAK,SAAS;AAAA,MAChB;AAEA,eAAS,UAAU,KAAK,YAAY,WAAW,KAAK,cAAc;AAClE,UAAI;AACF,QAAC,OAAe,iBAAiB,OAAO;AAAA,MAC1C,QAAQ;AAAA,MAER;AACA,WAAK,UAAU;AAAA,IACjB,QAAQ;AAAA,IAER;AAAA,EACF;AAAA,EAEA,QAAQ,UAA8B,mBAAmB,GAAS;AAChE,QAAI;AACF,UAAI,OAAO,OAAO,OAAO,YAAY,YAAY;AAC/C,cAAM,MAAM,QAAQ;AAAA,MACtB,WAAW,OAAO,OAAO,OAAO,WAAW,YAAY;AACrD,cAAM,MAAM,OAAO,EAAE;AAAA,MACvB;AACA,eAAS,aAAa,KAAK,UAAU;AACrC,UAAI;AACF,QAAC,OAAe,iBAAiB,KAAK;AAAA,MACxC,QAAQ;AAAA,MAER;AACA,WAAK,UAAU;AAAA,IACjB,QAAQ;AAAA,IAER;AAAA,EACF;AAAA,EAEA,OACE,UAAkB,KAAK,gBACvB,UAA8B,mBAAmB,GAC3C;AACN,QAAI,KAAK,UAAU,GAAG;AACpB,WAAK,QAAQ,OAAO;AAAA,IACtB,OAAO;AACL,WAAK,OAAO,SAAS,OAAO;AAAA,IAC9B;AAAA,EACF;AAAA,EAEA,YAAqB;AACnB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,eAAe,MAAkC,QAAc;AAC7D,UAAM,MAAM;AAAA,MACV,aAAa,MAA4B;AACvC,aAAK,OAAO;AACZ,eAAO,EAAE,OAAO,KAAK,UAAU,GAAG,MAAM,WAAW;AAAA,MACrD;AAAA,MACA,cAAc,MAA4B;AACxC,aAAK,QAAQ;AACb,eAAO,EAAE,OAAO,KAAK,UAAU,GAAG,MAAM,WAAW;AAAA,MACrD;AAAA,MACA,aAAa,MAA4B;AACvC,aAAK,OAAO;AACZ,eAAO,EAAE,OAAO,KAAK,UAAU,GAAG,MAAM,WAAW;AAAA,MACrD;AAAA,MACA,YAAY,OAA6B;AAAA,QACvC,OAAO,KAAK,UAAU;AAAA,QACtB,MAAM,KAAK,UAAU,IAAI,YAAY;AAAA,MACvC;AAAA,MACA,UAAU,MAAM;AACd,YAAI;AACF,gBAAM,SAAU,IAAY;AAC5B,iBAAO,OAAO,WAAW,aACrB,OAAO,IACP;AAAA,QACN,QAAQ;AACN,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,MACA,aAAa,MAAM;AACjB,YAAI;AACF,gBAAM,SAAU,IAAY;AAC5B,iBAAO,OAAO,WAAW,aACrB,OAAO,IACP;AAAA,QACN,QAAQ;AACN,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAEA,QAAI;AACF,MAAC,IAAY,aAAa;AAAA,IAC5B,QAAQ;AAAA,IAER;AAAA,EACF;AACF;AAEA,SAAS,qBAAyC;AAChD,MAAI,OAAO,WAAW;AAAa,WAAO;AAC1C,MAAI;AACF,WAAO,OAAO;AAAA,EAChB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,IAAM,cAAc,IAAI,YAAY;AAC3C,IAAI,OAAO,WAAW,aAAa;AACjC,cAAY,eAAe;AAC3B,cAAY,gBAAgB;AAC9B;;;ACtJA,OAAOA,YAAmB;AAKnB,IAAM,eAAN,MAAmB;AAAA,EAAnB;AACL,SAAQ,MAAiB;AAAA;AAAA,EAEzB,IAAW,KAAgB;AACzB,WAAO,KAAK;AAAA,EACd;AAAA,EACA,IAAW,YAAqB;AAC9B,WAAO,CAAC,CAAC,KAAK;AAAA,EAChB;AAAA,EACA,IAAW,eAAwB;AACjC,WAAO,CAAC,CAAC,KAAK,KAAK,aAAa;AAAA,EAClC;AAAA,EAEO,MACL,KACA,UACA,QACA,MACI;AACJ,SAAK,KAAK;AACV,UAAM,QAAQ,KAAK,cAAc,QAAQ,KAAK,QAAQ;AACtD,SAAK,YAAY,KAAK;AACtB,SAAK,WAAW,MAAM,KAAK;AAC3B,UAAM,KAAK,KAAK,SAAS,KAAK;AAC9B,OAAG,MAAM;AACT,SAAK,MAAM;AACX,WAAO;AAAA,EACT;AAAA,EAEO,WAAiB;AACtB,UAAM,KAAK,KAAK,MAAM;AACtB,QAAI,CAAC,IAAI,aAAa;AAAG,UAAI,SAAS;AAAA,EACxC;AAAA,EAEO,OAAa;AAClB,UAAM,KAAK,KAAK;AAChB,QAAI,CAAC;AAAI;AACT,QAAI;AACF,UAAI,GAAG,aAAa;AAAG,WAAG,WAAW;AACrC,SAAG,KAAK;AAAA,IACV,UAAE;AACA,WAAK,MAAM;AAAA,IACb;AAAA,EACF;AAAA,EAEO,QAAmB;AACxB,WAAO,KAAK;AAAA,EACd;AAAA,EAEO,SAAS,OAAgC;AAC9C,SAAK,WAAW,KAAK;AAAA,EACvB;AAAA,EAEU,cACR,QACA,KACA,UACiB;AACjB,WAAO,EAAE,GAAI,QAA4B,KAAK,SAAS;AAAA,EACzD;AAAA,EAEU,YAAY,KAA4B;AAChD,UAAM,UAAU,IAAI;AACpB,QACE,CAAC,IAAI,OACL,CAAC,IAAI,YACL,CAAC,WACA,MAAM,QAAQ,OAAO,KAAK,QAAQ,WAAW,GAC9C;AACA,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEU,WAAW,OAAgC;AACnD,UAAM,SAAS,UAAU,SAAY,KAAK,gBAAgB,IAAI;AAC9D,UAAM,UAAU,CAAC,CAAC;AAClB,UAAM,UAAU,OAAO,WAAW,WAAW,SAAS;AAEtD,QAAI,SAAS;AACX,MAAAA,OAAM,MAAM,OAAO,OAAO;AAC1B,YAAM,MAAYA,OAAc;AAChC,UAAI,KAAK;AAAW,YAAI,UAAU,OAAO;AAAA,eAChC;AAAK,YAAI,SAAS;AAC3B,WAAK,mBAAmB,OAAO,WAAW,WAAW,SAAS,MAAS;AAAA,IACzE,OAAO;AACL,MAACA,OAAM,OAAe,UAAU;AAChC,WAAK,iBAAiB;AAAA,IACxB;AAAA,EACF;AAAA,EAEU,SAAS,KAA0B;AAC3C,WAAO,IAAIA,OAAM,GAAG,GAAG;AAAA,EACzB;AAAA,EAEQ,kBAAkC;AACxC,QAAI;AACF,UAAI,OAAO,WAAW;AAAa,eAAO;AAC1C,YAAM,QAAQ,OAAO,eAAe,QAAQ,mBAAmB;AAC/D,UAAI,CAAC;AAAO,eAAO;AACnB,aAAO;AAAA,IACT,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEQ,mBAAmB,SAAwB;AACjD,QAAI;AACF,UAAI,OAAO,WAAW,aAAa;AACjC,eAAO,eAAe;AAAA,UACpB;AAAA,UACA,WAAW;AAAA,QACb;AAAA,MACF;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AAAA,EAEQ,mBAAyB;AAC/B,QAAI;AACF,UAAI,OAAO,WAAW,aAAa;AACjC,eAAO,eAAe,WAAW,mBAAmB;AAAA,MACtD;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AACF;;;ACpIO,IAAM,YAAY;AAAA,EACvB,cAAc;AAAA,EACd,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,cAAc;AAAA,EACd,oBAAoB;AACtB;AAIO,IAAM,aAAa;AAAA,EACxB,MAAM;AAAA,EACN,SAAS;AAAA,EACT,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,MAAM;AACR;AAuBO,IAAM,gBAAgB,OAAO,OAAO,SAAS;AAC7C,IAAM,iBAAiB,OAAO,OAAO,UAAU;;;ACzC/C,IAAM,qBAAN,MAAmE;AAAA,EAAnE;AACL,SAAQ,SAAS,IAAI,YAAY;AAAA;AAAA,EAEjC,GAA2B,OAAU,IAAqC;AACxE,UAAM,UAAU,CAAC,MAAa,GAAI,EAA6B,MAAM;AACrE,SAAK,OAAO,iBAAiB,OAAiB,OAAO;AACrD,WAAO,MAAM,KAAK,OAAO,oBAAoB,OAAiB,OAAO;AAAA,EACvE;AAAA,EAEA,KAA6B,OAAU,SAA2B;AAChE,SAAK,OAAO;AAAA,MACV,IAAI,YAAY,OAAiB,EAAE,QAAQ,QAAQ,CAAC;AAAA,IACtD;AAAA,EACF;AACF;;;ACMO,IAAM,kBAAN,MAAsB;AAAA,EAI3B,YAAY,UAAkC,CAAC,GAAG;AAChD,SAAK,YAAY,QAAQ;AACzB,SAAK,WAAW,QAAQ;AAAA,EAC1B;AAAA,EAEA,OAAO,OAA6C;AAClD,UAAM,EAAE,MAAM,KAAK,SAAS,IAAI;AAChC,UAAM,gBACJ,QAAQ,KAAK,WAAW,KAAK,SAAS,IAAI,IAAI;AAGhD,QAAI,KAAK,WAAW;AAClB,YAAM,SAAS,KAAK,UAAU;AAAA,QAC5B;AAAA,QACA;AAAA,QACA,UAAU,iBAAiB;AAAA,MAC7B,CAAC;AACD,YAAMC,WACJ,QAAQ,WACR,QAAQ,SACR,iBACA,YACA,KAAK,eAAe,GAAG,KACvB;AAEF,aAAO;AAAA,QACL,OAAO,QAAQ,SAASA;AAAA,QACxB,MAAM,QAAQ,QAAQ;AAAA,QACtB,KAAK,QAAQ,OAAO;AAAA,QACpB,SAAAA;AAAA,MACF;AAAA,IACF;AAEA,UAAM,UACJ,iBAAiB,KAAK,eAAe,GAAG,KAAK,YAAY;AAE3D,WAAO;AAAA,MACL,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,eAAe,KAA8B;AACnD,QAAI,OAAO;AAAM,aAAO;AACxB,QAAI,OAAO,QAAQ;AAAU,aAAO;AACpC,QAAI,OAAO,KAAK,UAAU;AAAU,aAAO,IAAI;AAC/C,QAAI,OAAO,KAAK,YAAY;AAAU,aAAO,IAAI;AACjD,WAAO;AAAA,EACT;AACF;;;AC3EO,SAAS,qBAA+B;AAC7C,SAAO;AAAA,IACL,WAAW,UAAU;AAAA,IACrB,OAAO;AAAA,IACP,UAAU,CAAC;AAAA,EACb;AACF;AAEO,SAAS,aAAa,MAAW,MAAoB;AAC1D,MAAI,SAAS;AAAM,WAAO;AAC1B,MAAI,CAAC,QAAQ,CAAC;AAAM,WAAO;AAC3B,QAAM,QAAQ,OAAO,KAAK,IAAI;AAC9B,QAAM,QAAQ,OAAO,KAAK,IAAI;AAC9B,MAAI,MAAM,WAAW,MAAM;AAAQ,WAAO;AAC1C,aAAW,OAAO,OAAO;AACvB,QAAI,KAAK,GAAG,MAAM,KAAK,GAAG;AAAG,aAAO;AAAA,EACtC;AACA,SAAO;AACT;;;ACfO,IAAM,gBAAN,MAAoB;AAAA,EAApB;AACL,SAAQ,QAAkB,mBAAmB;AAC7C,SAAQ,YAAsB,mBAAmB;AACjD,SAAQ,YAAY,oBAAI,IAAsB;AAC9C,SAAQ,eAAyC;AACjD,SAAQ,kBAAkB;AAAA;AAAA,EAE1B,WAAqB;AACnB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,SAAS,IAAkC;AACzC,SAAK,UAAU,IAAI,EAAE;AACrB,OAAG,KAAK,KAAK;AACb,WAAO,MAAM,KAAK,UAAU,OAAO,EAAE;AAAA,EACvC;AAAA,EAEA,UAAU,IAAkC;AAC1C,WAAO,KAAK,SAAS,EAAE;AAAA,EACzB;AAAA,EAEA,SAAS,SAA4B;AACnC,QAAI,CAAC,WAAW,OAAO,KAAK,OAAO,EAAE,WAAW;AAAG;AACnD,UAAM,OAAO,EAAE,GAAG,KAAK,OAAO,GAAG,QAAQ;AAEzC,QAAI,KAAK,aAAa,KAAK,UAAU,YAAY,aAAa,KAAK,WAAW,IAAI,GAAG;AACnF;AAAA,IACF;AACA,SAAK,QAAQ;AACb,SAAK,YAAY;AACjB,SAAK,KAAK;AAAA,EACZ;AAAA,EAEA,SAAS,SAA4B;AACnC,SAAK,eAAe,EAAE,GAAG,KAAK,cAAc,GAAG,QAAQ;AACvD,QAAI,CAAC,KAAK,iBAAiB;AACzB,WAAK,kBAAkB;AACvB,qBAAe,MAAM;AACnB,YAAI,KAAK;AAAc,eAAK,SAAS,KAAK,YAAY;AACtD,aAAK,eAAe;AACpB,aAAK,kBAAkB;AAAA,MACzB,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEA,MAAM,YAA+B,CAAC,GAAG;AACvC,SAAK,SAAS,EAAE,GAAG,mBAAmB,GAAG,GAAG,UAAU,CAAC;AAAA,EACzD;AAAA,EAEQ,OAAO;AACb,eAAW,MAAM,KAAK;AAAW,SAAG,KAAK,KAAK;AAAA,EAChD;AACF;;;ACtCO,SAAS,iBAAiB,MAAiC;AAChE,QAAM,EAAE,SAAS,OAAO,oBAAoB,WAAW,gBAAgB,IACrE;AAEF,SAAO;AAAA,IACL,YAAY,CAAC,MAAW;AACtB,cAAQ,KAAK,cAAc,CAAC;AAC5B,YAAM,SAAS,EAAE,WAAW,UAAU,WAAW,CAAC;AAAA,IACpD;AAAA,IACA,WAAW,CAAC,MAAW;AACrB,cAAQ,KAAK,aAAa,CAAC;AAC3B,YAAM,SAAS,EAAE,WAAW,UAAU,UAAU,CAAC;AAAA,IACnD;AAAA,IACA,cAAc,CAAC,MAAW;AACxB,cAAQ,KAAK,gBAAgB,CAAC;AAC9B,yBAAmB;AACnB,YAAM,MAAM;AAAA,IACd;AAAA,IAEA,YAAY,CAAC,MAAW;AACtB,cAAQ,KAAK,cAAc,CAAC;AAC5B,YAAM,SAAS,EAAE,WAAW,UAAU,YAAY,OAAO,KAAK,CAAC;AAAA,IACjE;AAAA,IACA,cAAc,CAAC,MAAW;AACxB,cAAQ,KAAK,gBAAgB,CAAC;AAC9B,YAAM,SAAS,EAAE,WAAW,UAAU,aAAa,CAAC;AAAA,IACtD;AAAA,IACA,oBAAoB,CAAC,MAAW;AAC9B,cAAQ,KAAK,sBAAsB,CAAC;AACpC,yBAAmB;AACnB;AAAA,QACE;AAAA,UACE,KAAK;AAAA,UACL,OAAO,GAAG;AAAA,UACV,YAAY,GAAG,UAAU;AAAA,UACzB,YAAY,GAAG,UAAU;AAAA,QAC3B;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,YAAM,SAAS;AAAA,QACb,WAAW,UAAU;AAAA,QACrB,OAAO,GAAG,SAAS;AAAA,MACrB,CAAC;AAAA,IACH;AAAA,IACA,eAAe;AAAA,IACf,YAAY,CAAC,MAAW,QAAQ,KAAK,cAAc,CAAC;AAAA,IACpD,UAAU,CAAC,MAAW,QAAQ,KAAK,YAAY,CAAC;AAAA,IAChD,YAAY,CAAC,MAAW,QAAQ,KAAK,cAAc,CAAC;AAAA,EACtD;AACF;;;AClEO,SAAS,kBACd,OACA,WACA,QACA;AACA,QAAM,UAAU,MAAM,SAAS;AAC/B,UAAQ,SAAS,QAAQ,CAAC,MAAM;AAC9B,QAAI,EAAE,OAAO;AAAW;AACxB,QAAI,EAAE,WAAW,WAAW,QAAQ;AAClC,aAAO,EAAE,EAAE;AAAA,IACb;AAAA,EACF,CAAC;AACH;AAEO,SAAS,mBACd,OACA,WACA,SACA;AACA,QAAM,UAAU,MAAM,SAAS;AAC/B,QAAM,WAAW,QAAQ,SAAS,KAAK,CAAC,MAAM,EAAE,OAAO,SAAS;AAChE,QAAM,OAAwB,YAAY;AAAA,IACxC,IAAI;AAAA,IACJ,QAAQ,WAAW;AAAA,IACnB,WAAW;AAAA,IACX,MAAM;AAAA,IACN,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,YAAY;AAAA,IACZ,WAAW;AAAA,IACX,oBAAoB;AAAA,EACtB;AAEA,QAAM,cAAc,EAAE,GAAG,MAAM,GAAG,QAAQ;AAC1C,QAAM,WAAW,WACb,QAAQ,SAAS,IAAI,CAAC,MAAO,EAAE,OAAO,YAAY,cAAc,CAAE,IAClE,CAAC,GAAG,QAAQ,UAAU,WAAW;AAErC,QAAM,SAAS,EAAE,SAAS,CAAC;AAC7B;AAEO,SAAS,mBAAmB,OAAsB,WAAmB;AAC1E,QAAM,UAAU,MAAM,SAAS;AAC/B,QAAM,WAAW,QAAQ,SAAS,OAAO,CAAC,MAAM,EAAE,OAAO,SAAS;AAClE,QAAM,SAAS;AAAA,IACb;AAAA,IACA,OAAO;AAAA,EACT,CAAC;AACH;;;AC9BO,SAAS,sBAAsB,MAAyC;AAC7E,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AAEJ,SAAO;AAAA,IACL,UAAU,CAAC,MAAqC;AAC9C,cAAQ,KAAK,YAAY,CAAC;AAAA,IAC5B;AAAA,IACA,UAAU,CAAC,MAAqC;AAC9C,cAAQ,KAAK,YAAY,CAAC;AAC1B,0BAAoB,SAAS;AAC7B,YAAM,SAAS;AAAA,QACb,UAAU,MAAM,SAAS,EAAE,SAAS;AAAA,UAAI,CAAC,MACvC,EAAE,OAAO,YACL;AAAA,YACE,GAAG;AAAA,YACH,QAAQ,WAAW;AAAA,YACnB,YAAY,EAAE,cAAc,KAAK,IAAI;AAAA,UACvC,IACA;AAAA,QACN;AAAA,MACF,CAAC;AAAA,IACH;AAAA,IACA,WAAW,CAAC,MAA2C;AACrD,cAAQ,KAAK,aAAa,CAAC;AAC3B,2BAAqB,SAAS;AAAA,IAChC;AAAA,IAEA,OAAO,CAAC,MAAgB;AACtB,cAAQ,KAAK,SAAS,CAAC;AACvB,4BAAsB;AACtB,UAAI,QAAQ;AACZ,YAAM,eAAe,MAClB,SAAS,EACT,SAAS,OAAO,CAAC,MAAM,EAAE,OAAO,SAAS;AAC5C,YAAM,SAAS;AAAA,QACb,UAAU;AAAA,MACZ,CAAC;AAAA,IACH;AAAA,IACA,QAAQ,CAAC,MAAgB;AACvB,cAAQ,KAAK,UAAU,CAAC;AACxB,4BAAsB;AACtB,UAAI,QAAQ;AACZ,YAAM,QAAQ,GAAG,SAAS;AAC1B,sBAAgB,OAAO,CAAC;AACxB,YAAM,eAAe,MAClB,SAAS,EACT,SAAS,OAAO,CAAC,MAAM,EAAE,OAAO,SAAS;AAC5C,YAAM,SAAS;AAAA,QACb,UAAU;AAAA,MACZ,CAAC;AAAA,IACH;AAAA,IAEA,OAAO,MAAM;AACX,cAAQ,KAAK,SAAS,MAAS;AAC/B,yBAAmB,OAAO,WAAW,EAAE,OAAO,KAAK,CAAC;AAAA,IACtD;AAAA,IACA,SAAS,MAAM;AACb,cAAQ,KAAK,WAAW,MAAS;AACjC,yBAAmB,OAAO,WAAW,EAAE,OAAO,MAAM,CAAC;AAAA,IACvD;AAAA,IACA,MAAM,MAAM;AACV,cAAQ,KAAK,QAAQ,MAAS;AAC9B,yBAAmB,OAAO,WAAW,EAAE,QAAQ,WAAW,KAAK,CAAC;AAAA,IAClE;AAAA,IACA,QAAQ,MAAM;AACZ,cAAQ,KAAK,UAAU,MAAS;AAChC,yBAAmB,OAAO,WAAW,EAAE,QAAQ,WAAW,OAAO,CAAC;AAAA,IACpE;AAAA,IAEA,UAAU,CAAC,MAAW,QAAQ,KAAK,YAAY,CAAC;AAAA,IAChD,QAAQ,CAAC,MAAW,QAAQ,KAAK,UAAU,CAAC;AAAA,IAC5C,KAAK,CAAC,MAAW,QAAQ,KAAK,OAAO,CAAC;AAAA,IACtC,cAAc,CAAC,MAAW,QAAQ,KAAK,gBAAgB,CAAC;AAAA,IACxD,OAAO,CAAC,MAAW,QAAQ,KAAK,SAAS,CAAC;AAAA,IAC1C,UAAU,CAAC,MAAW,QAAQ,KAAK,YAAY,CAAC;AAAA,IAChD,SAAS,CAAC,MAAW,QAAQ,KAAK,WAAW,CAAC;AAAA,IAC9C,SAAS,CAAC,MAAW,QAAQ,KAAK,WAAW,CAAC;AAAA,IAE9C,oBAAoB,CAAC,MAAW;AAC9B,cAAQ,KAAK,sBAAsB,CAAC;AACpC,4BAAsB;AACtB,UAAI,QAAQ;AACZ,sBAAgB,uBAAuB,CAAC;AACxC,YAAM,SAAS;AAAA,QACb,UAAU,MAAM,SAAS,EAAE,SAAS,OAAO,CAAC,MAAM,EAAE,OAAO,SAAS;AAAA,MACtE,CAAC;AAAA,IACH;AAAA,IACA,oCAAoC,CAAC,MAAW;AAC9C,cAAQ,KAAK,oCAAoC,CAAC;AAClD,4BAAsB;AACtB,UAAI,QAAQ;AACZ,sBAAgB,sCAAsC,CAAC;AACvD,YAAM,SAAS;AAAA,QACb,UAAU,MAAM,SAAS,EAAE,SAAS,OAAO,CAAC,MAAM,EAAE,OAAO,SAAS;AAAA,MACtE,CAAC;AAAA,IACH;AAAA,IACA,qCAAqC,CAAC,MAAW;AAC/C,cAAQ,KAAK,qCAAqC,CAAC;AACnD,4BAAsB;AACtB,UAAI,QAAQ;AACZ,sBAAgB,uCAAuC,CAAC;AACxD,YAAM,SAAS;AAAA,QACb,UAAU,MAAM,SAAS,EAAE,SAAS,OAAO,CAAC,MAAM,EAAE,OAAO,SAAS;AAAA,MACtE,CAAC;AAAA,IACH;AAAA,IACA,4CAA4C,CAAC,MAAW;AACtD,cAAQ,KAAK,4CAA4C,CAAC;AAC1D,4BAAsB;AACtB,UAAI,QAAQ;AACZ,sBAAgB,8CAA8C,CAAC;AAC/D,YAAM,SAAS;AAAA,QACb,UAAU,MAAM,SAAS,EAAE,SAAS,OAAO,CAAC,MAAM,EAAE,OAAO,SAAS;AAAA,MACtE,CAAC;AAAA,IACH;AAAA,IACA,6CAA6C,CAAC,MAAW;AACvD,cAAQ,KAAK,6CAA6C,CAAC;AAC3D,4BAAsB;AACtB,UAAI,QAAQ;AACZ,sBAAgB,+CAA+C,CAAC;AAChE,YAAM,SAAS;AAAA,QACb,UAAU,MAAM,SAAS,EAAE,SAAS,OAAO,CAAC,MAAM,EAAE,OAAO,SAAS;AAAA,MACtE,CAAC;AAAA,IACH;AAAA,IACA,gBAAgB,CAAC,MAAW,QAAQ,KAAK,kBAAkB,CAAC;AAAA,EAC9D;AACF;;;AClJO,IAAM,0BAAN,MAA8B;AAAA,EAA9B;AACL,0BAAoC;AACpC,uBAAkC;AAAA;AAAA,EAE3B,WAAW,SAA4B;AAC5C,SAAK,iBAAiB;AAAA,EACxB;AAAA,EAEO,eAAe,QAAqB;AACzC,SAAK,cAAc;AAAA,EACrB;AAAA,EAEQ,QAAkC;AACxC,WAAQ,KAAK,gBAAwB,cAAc;AAAA,EACrD;AAAA,EAEO,QAAQ,aAAsB,MAAY;AAC/C,UAAM,KAAK,KAAK,MAAM;AAEtB,QAAI,MAAM,OAAO,GAAG,eAAe,YAAY;AAC7C,YAAM,WACJ,GAAG,oBAAoB,YAAY,GAAG,mBAAmB;AAC3D,UAAI,CAAC,UAAU;AACb,mBAAW,KAAK,GAAG,WAAW,GAAG;AAC/B,cAAI;AACF,cAAE,aAAa,IAAI;AAAA,UACrB,QAAQ;AAAA,UAER;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,QAAI,cAAc,KAAK,aAAa;AAClC,iBAAW,KAAK,KAAK,YAAY,UAAU;AAAG,UAAE,KAAK;AAAA,IACvD;AAEA,SAAK,cAAc;AACnB,SAAK,iBAAiB;AAAA,EACxB;AAAA,EAEO,OAAO,UAAyB,CAAC,GAAY;AAClD,WAAO,KAAK,kBACP,KAAK,eAAe,OAAO,OAAO,GAAG,QACtC;AAAA,EACN;AAAA,EAEO,OAAO,SAAqC;AACjD,WAAO,KAAK,kBACP,KAAK,eAAe;AAAA,MACnB,WAAY,EAAE,aAAa,KAAK,eAAe,YAAY;AAAA,IAC7D,GACA,QACA;AAAA,EACN;AAAA,EAEO,OAAgB;AACrB,SAAK,aAAa,eAAe,EAAE,QAAQ,CAAC,MAAO,EAAE,UAAU,KAAM;AACrE,WAAO,KAAK,kBACP,KAAK,eAAe,KAAK,EAAE,OAAO,KAAK,CAAC,GAAG,QAC5C;AAAA,EACN;AAAA,EAEO,SAAkB;AACvB,SAAK,aAAa,eAAe,EAAE,QAAQ,CAAC,MAAO,EAAE,UAAU,IAAK;AACpE,WAAO,KAAK,kBACP,KAAK,eAAe,OAAO,EAAE,OAAO,KAAK,CAAC,GAAG,QAC9C;AAAA,EACN;AAAA,EAEO,OAAgB;AACrB,WAAO,KAAK,kBAAkB,KAAK,eAAe,KAAK,GAAG,QAAQ;AAAA,EACpE;AAAA,EAEO,SAAkB;AACvB,WAAO,KAAK,kBAAkB,KAAK,eAAe,OAAO,GAAG,QAAQ;AAAA,EACtE;AAAA,EAEO,SAAS,OAAwB,SAAgC;AACtE,WAAO,KAAK,kBACP,KAAK,eAAe,SAAS,OAAO,OAAO,GAAG,QAC/C;AAAA,EACN;AAAA,EAEO,SAAS,QAAgB,SAAiC;AAC/D,WAAO,KAAK,kBACP,KAAK,eAAe,MAAM,QAAe,OAAO,GAAG,QACpD;AAAA,EACN;AAAA,EAEO,cAAoB;AACzB,SAAK,aAAa,eAAe,EAAE,QAAQ,CAAC,MAAO,EAAE,UAAU,IAAK;AAAA,EACtE;AAAA,EAEO,eAAqB;AAC1B,SAAK,aAAa,eAAe,EAAE,QAAQ,CAAC,MAAO,EAAE,UAAU,KAAM;AAAA,EACvE;AAAA,EAEA,MAAa,aACX,gBACkB;AAClB,UAAM,KAAK,KAAK,MAAM;AACtB,QAAI,CAAC;AAAI,aAAO;AAEhB,QAAI,CAAC,KAAK;AAAa,WAAK,cAAc,IAAI,YAAY;AAE1D,UAAM,MAAM,KAAK,YAAY,eAAe,EAAE,CAAC;AAC/C,SAAK,YAAY,SAAS,cAAc;AACxC,QAAI;AAAK,WAAK,YAAY,YAAY,GAAG;AAEzC,UAAM,SAAS,GAAG,aAAa,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO,SAAS,OAAO;AACtE,QAAI;AAAQ,YAAM,OAAO,aAAa,cAAc;AAEpD,QAAI,OAAO,QAAQ;AAAgB,UAAI,KAAK;AAE5C,WAAO;AAAA,EACT;AAAA,EAEA,MAAa,kBACX,gBACkB;AAClB,UAAM,KAAK,KAAK,MAAM;AACtB,QAAI,CAAC;AAAI,aAAO;AAEhB,QAAI,CAAC,KAAK;AAAa,WAAK,cAAc,IAAI,YAAY;AAE1D,UAAM,MAAM,KAAK,YAAY,eAAe,EAAE,CAAC;AAC/C,SAAK,YAAY,SAAS,cAAc;AACxC,QAAI;AAAK,WAAK,YAAY,YAAY,GAAG;AAEzC,UAAM,SAAS,GAAG,aAAa,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO,SAAS,OAAO;AACtE,QAAI;AAAQ,YAAM,OAAO,aAAa,cAAc;AAEpD,QAAI,OAAO,QAAQ;AAAgB,UAAI,KAAK;AAE5C,WAAO;AAAA,EACT;AACF;;;ACxIO,IAAM,iBAAN,MAAqB;AAAA,EAArB;AACL,SAAQ,UAAU,oBAAI,IAA0B;AAChD,SAAQ,oBACN,CAAC;AACH,SAAQ,oBAAoB;AAAA;AAAA,EAE5B,mBAAmB,IAAwB;AACzC,QAAI,OAAO,OAAO,YAAY,KAAK;AAAG,WAAK,oBAAoB;AAAA,EACjE;AAAA,EAEA,qBAAqB,QAAqB;AACxC,SAAK,kBAAkB,KAAK,EAAE,QAAQ,SAAS,KAAK,IAAI,EAAE,CAAC;AAAA,EAC7D;AAAA,EAEA,uBAA2C;AACzC,UAAM,MAAM,KAAK,IAAI;AACrB,WAAO,KAAK,kBAAkB,QAAQ;AACpC,YAAM,OAAO,KAAK,kBAAkB,MAAM;AAC1C,UAAI,CAAC;AAAM;AACX,UAAI,MAAM,KAAK,WAAW,KAAK,mBAAmB;AAChD,eAAO,KAAK;AAAA,MACd,OAAO;AAEL,aAAK,OAAO,UAAU,EAAE,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC;AAAA,MACjD;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEA,eAAe,WAAmB,SAAsB;AACtD,QAAI,QAAQ,KAAK,QAAQ,IAAI,SAAS;AACtC,QAAI,CAAC,OAAO;AACV,cAAQ;AAAA,QACN,KAAK,IAAI,wBAAwB;AAAA,QACjC,SAAS;AAAA,QACT,OAAO;AAAA,MACT;AACA,WAAK,QAAQ,IAAI,WAAW,KAAK;AAAA,IACnC;AACA,QAAI,SAAS;AACX,YAAM,UAAU;AAChB,YAAM,IAAI,WAAW,OAAO;AAAA,IAC9B;AACA,QAAI,MAAM;AAAO,YAAM,IAAI,eAAe,MAAM,KAAK;AACrD,WAAO,MAAM;AAAA,EACf;AAAA,EAEA,OAAO,WAAmB;AACxB,WAAO,KAAK,QAAQ,IAAI,SAAS,GAAG,OAAO;AAAA,EAC7C;AAAA,EAEA,WAAW,WAAmB,SAAqB;AACjD,UAAM,QAAQ,KAAK,QAAQ,IAAI,SAAS;AACxC,QAAI,OAAO;AACT,YAAM,UAAU;AAChB,YAAM,IAAI,WAAW,OAAO;AAAA,IAC9B,OAAO;AACL,WAAK,QAAQ,IAAI,WAAW;AAAA,QAC1B,KAAK,IAAI,wBAAwB;AAAA,QACjC;AAAA,QACA,OAAO;AAAA,MACT,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEA,gBAAgB,WAAmB,QAAqB;AACtD,UAAM,QAAQ,KAAK,QAAQ,IAAI,SAAS,KAAK;AAAA,MAC3C,KAAK,IAAI,wBAAwB;AAAA,MACjC,SAAS;AAAA,MACT,OAAO;AAAA,IACT;AACA,UAAM,QAAQ;AACd,UAAM,IAAI,eAAe,MAAM;AAC/B,SAAK,QAAQ,IAAI,WAAW,KAAK;AAAA,EACnC;AAAA,EAEA,WAAW,WAAmB;AAC5B,WAAO,KAAK,QAAQ,IAAI,SAAS,GAAG,WAAW;AAAA,EACjD;AAAA,EAEA,gBAAgB;AACd,WAAO,MAAM,KAAK,KAAK,QAAQ,KAAK,CAAC;AAAA,EACvC;AAAA,EAEA,cAAc;AACZ,WAAO,MAAM,KAAK,KAAK,QAAQ,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC,IAAI,KAAK,OAAO;AAAA,MAC9D;AAAA,MACA,SAAS,MAAM;AAAA,IACjB,EAAE;AAAA,EACJ;AAAA,EAEA,mBAAmB,iBAA2B,CAAC,QAAQ,GAAkB;AACvE,eAAW,CAAC,IAAI,KAAK,KAAK,MAAM,KAAK,KAAK,QAAQ,QAAQ,CAAC,EAAE,QAAQ,GAAG;AACtE,YAAM,SAAU,MAAM,SAAiB;AACvC,UAAI,UAAU,eAAe,SAAS,OAAO,MAAM,EAAE,YAAY,CAAC,GAAG;AACnE,eAAO;AAAA,MACT;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEA,eAAe,WAAmB;AAChC,UAAM,QAAQ,KAAK,QAAQ,IAAI,SAAS;AACxC,QAAI,OAAO;AACT,YAAM,IAAI,QAAQ;AAClB,WAAK,QAAQ,OAAO,SAAS;AAAA,IAC/B;AAAA,EACF;AAAA,EAEA,qBAAqB;AACnB,eAAW,CAAC,EAAE,KAAK,KAAK,KAAK,QAAQ,QAAQ,GAAG;AAC9C,YAAM,IAAI,QAAQ;AAAA,IACpB;AACA,SAAK,QAAQ,MAAM;AACnB,SAAK,oBAAoB,CAAC;AAAA,EAC5B;AAAA,EAEA,OAAO,WAAmB,SAAc;AACtC,UAAM,MAAM,KAAK,OAAO,SAAS;AACjC,WAAO,MAAM,IAAI,OAAO,OAAO,IAAI;AAAA,EACrC;AAAA,EAEA,OAAO,WAAmB,SAAe;AACvC,UAAM,MAAM,KAAK,OAAO,SAAS;AACjC,WAAO,MAAM,IAAI,OAAO,OAAO,IAAI;AAAA,EACrC;AAAA,EAEA,KAAK,WAAmB;AACtB,UAAM,MAAM,KAAK,OAAO,SAAS;AACjC,WAAO,MAAM,IAAI,KAAK,IAAI;AAAA,EAC5B;AAAA,EAEA,OAAO,WAAmB;AACxB,UAAM,MAAM,KAAK,OAAO,SAAS;AACjC,WAAO,MAAM,IAAI,OAAO,IAAI;AAAA,EAC9B;AAAA,EAEA,KAAK,WAAmB;AACtB,UAAM,MAAM,KAAK,OAAO,SAAS;AACjC,WAAO,MAAM,IAAI,KAAK,IAAI;AAAA,EAC5B;AAAA,EAEA,OAAO,WAAmB;AACxB,UAAM,MAAM,KAAK,OAAO,SAAS;AACjC,WAAO,MAAM,IAAI,OAAO,IAAI;AAAA,EAC9B;AAAA,EAEA,SAAS,WAAmB,OAAwB,SAAe;AACjE,UAAM,MAAM,KAAK,OAAO,SAAS;AACjC,WAAO,MAAM,IAAI,SAAS,OAAO,OAAO,IAAI;AAAA,EAC9C;AAAA,EAEA,SAAS,WAAmB,QAAgB,SAAe;AACzD,UAAM,MAAM,KAAK,OAAO,SAAS;AACjC,WAAO,MAAM,IAAI,SAAS,QAAQ,OAAO,IAAI;AAAA,EAC/C;AACF;;;ACrJO,IAAM,mBAAN,MAAuB;AAAA,EAQ5B,YAAY,MAAY;AACtB,SAAK,QAAQ,KAAK;AAClB,SAAK,iBAAiB,KAAK;AAC3B,SAAK,OAAO,KAAK;AACjB,SAAK,YAAY,KAAK;AACtB,SAAK,wBAAwB,KAAK;AAClC,SAAK,qBAAqB,KAAK;AAAA,EACjC;AAAA,EAEA,oBAAoB,GAAoB;AACtC,UAAM,UAAU,EAAE;AAClB,UAAM,YAAY,OAAQ,SAAiB,MAAM,OAAO,aAAa,KAAK,KAAK,IAAI,CAAC;AAEpF,UAAM,kBAAkB,KAAK,MAAM,SAAS,EAAE;AAC9C,QAAI,gBAAgB,UAAU,KAAK,mBAAmB,GAAG;AACvD,UAAI;AACF,gBAAQ,YAAY,EAAE,aAAa,KAAK,eAAe,YAAY,CAAQ;AAAA,MAC7E,QAAQ;AAAA,MAER;AACA,UAAI,EAAE,eAAe,UAAU;AAC7B,aAAK,KAAK,UAAU,CAAC;AAAA,MACvB;AACA,WAAK,UAAU,6BAA6B,wBAAwB,2BAA2B;AAC/F;AAAA,IACF;AAEA,UAAM,gBAAgB,EAAE,eAAe,UAAU,KAAK,eAAe,qBAAqB,IAAI;AAE9F,QAAI;AAAe,WAAK,eAAe,gBAAgB,WAAW,aAAa;AAE/E,UAAM,MAAM,KAAK,eAAe,eAAe,WAAW,OAAO;AACjE,QAAI;AAAe,UAAI,eAAe,aAAa;AAEnD,SAAK,eAAe,WAAW,WAAW,OAAO;AACjD,SAAK,sBAAsB,WAAW,OAAO;AAE7C;AAAA,MACE,KAAK;AAAA,MACL;AAAA,MACA,CAAC,OAAO;AACN,cAAM,WAAW,KAAK,eAAe,OAAO,EAAE;AAC9C,kBAAU,KAAK;AAAA,MACjB;AAAA,IACF;AAEA,UAAM,cACH,EAAE,SAAS,QAAQ,EAAE,QAAQ,KAAK,SAAS,EAAE,SAAS,SAAS,KAC/D,SAA6D,YAC1D,eAAe,GACf,KAAK,CAAC,MAAsB,EAAE,OAAO,SAAS,OAAO;AAE3D,uBAAmB,KAAK,OAAO,WAAW;AAAA,MACxC,WAAW,EAAE;AAAA,MACb,MAAM,EAAE,eAAe,WAAW,EAAE,QAAQ,KAAK,IAAI,OAAO;AAAA,MAC5D,IAAI,EAAE,QAAQ,GAAG,IAAI;AAAA,MACrB,QAAQ,EAAE,eAAe,WAAW,WAAW,UAAU,WAAW;AAAA,MACpE,WAAW,cAAc,UAAU;AAAA,MACnC,oBAAoB;AAAA,IACtB,CAAC;AAED,SAAK,KAAK,iBAAiB,CAAC;AAAA,EAC9B;AACF;;;AC7CA,IAAM,oBAAoB;AAEnB,IAAM,YAAN,cAAwB,mBAAkC;AAAA,EAyB/D,YAAY,UAA4B,CAAC,GAAG;AAC1C,UAAM;AAzBR,SAAgB,YAAY,IAAI,aAAa;AAC7C,SAAgB,aAAa,IAAI,cAAc;AAI/C,SAAQ,kBAAkB,oBAAI,IAAyC;AAGvE,SAAQ,kBAAkB;AAC1B,SAAQ,iBAAiB,IAAI,eAAe;AAE5C,SAAQ,cAAc,oBAAI,IAAkC;AAC5D,SAAQ,qBAAqB;AAC7B,SAAQ,sBAA2D;AAAA,MACjE,YAAY;AAAA,MACZ,YAAY;AAAA,IACd;AAWE,SAAK,eACH,QAAQ,gBACR,IAAI,gBAAgB;AAAA,MAClB,WAAW,QAAQ;AAAA,MACnB,UAAU,QAAQ;AAAA,IACpB,CAAC;AACH,SAAK,eAAe,QAAQ;AAE5B,SAAK,aAAa,iBAAiB;AAAA,MACjC,SAAS;AAAA,MACT,OAAO,KAAK;AAAA,MACZ,oBAAoB,MAAM,KAAK,mBAAmB;AAAA,MAClD,WAAW,CAAC,KAAK,MAAM,aAAa,KAAK,UAAU,KAAK,MAAM,QAAQ;AAAA,MACtE,iBAAiB,CAAC,MAAuB,KAAK,gBAAgB,CAAC;AAAA,IACjE,CAAC;AAED,SAAK,gBAAgB,OAAO,KAAK,KAAK,UAAU;AAEhD,SAAK,YAAY,IAAI,iBAAiB;AAAA,MACpC,OAAO,KAAK;AAAA,MACZ,gBAAgB,KAAK;AAAA,MACrB,MAAM,CAAC,OAAO,YAAY,KAAK,KAAK,OAAc,OAAc;AAAA,MAChE,WAAW,CAAC,KAAK,MAAM,aAAa,KAAK,UAAU,KAAK,MAAM,QAAQ;AAAA,MACtE,uBAAuB,CAAC,WAAW,YACjC,KAAK,sBAAsB,WAAW,OAAO;AAAA,MAC/C,oBAAoB,MAAM,KAAK;AAAA,IACjC,CAAC;AAED,QAAI,OAAO,WAAW,aAAa;AAEjC,MAAC,OAAe,iBAAiB,CAAC,UAChC,KAAK,SAAS,SAAS,IAAI;AAAA,IAC/B;AAAA,EACF;AAAA,EAxCA,IAAW,QAAkB;AAC3B,WAAO,KAAK,WAAW,SAAS;AAAA,EAClC;AAAA,EAwCO,QAAQ,KAAa,UAAkB,QAA0B;AACtE,SAAK,WAAW;AAChB,SAAK,WAAW,SAAS,EAAE,WAAW,UAAU,WAAW,CAAC;AAC5D,UAAM;AAAA,MACJ,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,GAAG;AAAA,IACL,IAAI;AACJ,SAAK,kBACH,OAAO,oBAAoB,WAAW,kBAAkB;AAC1D,SAAK,qBAAqB,QAAQ,iBAAiB;AACnD,QAAI,OAAO,0BAA0B,UAAU;AAC7C,WAAK,oBAAoB,aAAa;AAAA,IACxC;AACA,QAAI,OAAO,0BAA0B,UAAU;AAC7C,WAAK,oBAAoB,aAAa;AAAA,IACxC;AACA,SAAK,eAAe,mBAAmB,iBAAiB;AAExD,UAAM,QAAQ,YAAY,KAAK,kBAAkB,KAAK,KAAK;AAC3D,SAAK,UAAU,MAAM,KAAK,UAAU,OAAO,EAAE,MAAM,CAAC;AACpD,SAAK,iBAAiB;AACtB,SAAK,mBAAmB;AACxB,SAAK,mBAAmB,KAAK;AAAA,EAC/B;AAAA,EAEO,aAAa;AAClB,SAAK,UAAU,SAAS;AAAA,EAC1B;AAAA,EAEO,aAAa;AAClB,SAAK,mBAAmB;AACxB,SAAK,iBAAiB;AACtB,SAAK,UAAU,KAAK;AACpB,SAAK,mBAAmB;AACxB,SAAK,WAAW,MAAM;AAAA,EACxB;AAAA,EAEO,KAAK,QAAgB,cAA2B,CAAC,GAAG;AACzD,QAAI;AACF,YAAM,OAAO,KAAK,uBAAuB,WAAW;AACpD,UAAI,KAAK;AACP,aAAK,eAAe,qBAAqB,KAAK,WAAW;AAE3D,YAAM,KAAK,KAAK,UAAU,MAAM;AAChC,UAAI,KAAK,QAAQ,IAAI;AAAA,IACvB,SAAS,GAAY;AACnB,YAAM,MAAM,KAAK,UAAU,GAAG,eAAe,aAAa;AAC1D,WAAK,mBAAmB;AACxB,WAAK,WAAW,SAAS;AAAA,QACvB,OAAO,IAAI;AAAA,MACb,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEO,OAAO,WAAmB,UAAyB,CAAC,GAAG;AAC5D,UAAM,WAAW,KAAK,yBAAyB,SAAS;AACxD,QAAI,CAAC;AAAU,aAAO;AACtB,WAAO,KAAK,cAAc,UAAU,OAAO;AAAA,EAC7C;AAAA,EACO,OAAO,WAAmB,SAA4B;AAC3D,UAAM,WAAW,KAAK,yBAAyB,SAAS;AACxD,QAAI,CAAC;AAAU,aAAO;AACtB,WAAO,KAAK,cAAc,UAAU,OAAO;AAAA,EAC7C;AAAA,EAEO,UAAU,SAA4B;AAC3C,UAAM,MAAM,KAAK,cAAc;AAC/B,QAAI,QAAQ,CAAC,OAAO,KAAK,cAAc,IAAI,OAAO,CAAC;AACnD,WAAO,IAAI,SAAS;AAAA,EACtB;AAAA,EAEO,WAAW,WAAmB;AACnC,WAAO,KAAK,kBAAkB,SAAS;AAAA,EACzC;AAAA,EACO,WAAW,WAAmB;AACnC,WAAO,KAAK,kBAAkB,SAAS;AAAA,EACzC;AAAA,EACO,SACL,WACA,OACA,SACA;AACA,WAAO,KAAK,gBAAgB,WAAW,OAAO,OAAO;AAAA,EACvD;AAAA,EACO,SAAS,WAAmB,QAAgB,SAAwB;AACzE,WAAO,KAAK,gBAAgB,WAAW,QAAQ,OAAO;AAAA,EACxD;AAAA,EAEO,SAAS,IAA2B;AACzC,WAAO,KAAK,WAAW,SAAS,EAAE;AAAA,EACpC;AAAA,EAEQ,mBAAmB;AACzB,UAAM,KAAK,KAAK,UAAU;AAC1B,QAAI,CAAC;AAAI;AAET,SAAK,iBAAiB;AACtB,SAAK,cAAc,QAAQ,CAAC,OAAO;AACjC,YAAM,IAAI,KAAK,WAAW,EAAE;AAC5B,UAAI;AAAG,WAAG,GAAG,IAAI,CAAQ;AAAA,IAC3B,CAAC;AAAA,EACH;AAAA,EAEO,SAAS,OAA0B;AACxC,SAAK,eAAe;AACpB,SAAK,UAAU,SAAS,KAAK;AAC7B,SAAK,mBAAmB,KAAK;AAAA,EAC/B;AAAA,EAEQ,sBAAsB,WAAmB,SAAqB;AACpE,UAAM,WAAW,KAAK,yBAAyB,WAAW,OAAO;AACjE,SAAK,gBAAgB,IAAI,WAAW,QAAQ;AAE5C,IAAC,OAAO,KAAK,QAAQ,EAAmC,QAAQ,CAAC,OAAO;AACtE,YAAM,IAAI,SAAS,EAAE;AACrB,UAAI;AAAG,gBAAQ,GAAG,IAAI,CAAQ;AAAA,IAChC,CAAC;AAAA,EACH;AAAA,EAEQ,sBAAsB,WAAmB,SAAqB;AACpE,UAAM,WAAW,KAAK,gBAAgB,IAAI,SAAS;AACnD,QAAI,CAAC,YAAY,CAAC;AAAS;AAC3B,IAAC,OAAO,KAAK,QAAQ,EAAmC,QAAQ,CAAC,OAAO;AACtE,YAAM,IAAI,SAAS,EAAE;AACrB,UAAI;AAAG,gBAAQ,IAAI,IAAI,CAAQ;AAAA,IACjC,CAAC;AACD,SAAK,gBAAgB,OAAO,SAAS;AAAA,EACvC;AAAA,EAEQ,mBAAmB;AACzB,UAAM,KAAK,KAAK,UAAU;AAC1B,QAAI,CAAC;AAAI;AACT,SAAK,cAAc,QAAQ,CAAC,OAAO;AACjC,YAAM,IAAI,KAAK,WAAW,EAAE;AAC5B,UAAI;AAAG,WAAG,IAAI,IAAI,CAAQ;AAAA,IAC5B,CAAC;AAAA,EACH;AAAA,EAEQ,eAAe,WAAmB,SAAsB;AAC9D,UAAM,gBACJ,WACA,KAAK,eAAe,WAAW,SAAS,KACxC,KAAK,eAAe,OAAO,SAAS,GAAG;AACzC,SAAK,sBAAsB,WAAW,aAAoB;AAC1D,SAAK,0BAA0B,SAAS;AACxC,SAAK,eAAe,eAAe,SAAS;AAC5C,uBAAmB,KAAK,YAAY,SAAS;AAAA,EAC/C;AAAA,EAEQ,qBAAqB;AAC3B,SAAK,eAAe,mBAAmB;AACvC,SAAK,YAAY,QAAQ,CAAC,UAAU,MAAM,KAAK,CAAC;AAChD,SAAK,YAAY,MAAM;AACvB,SAAK,gBAAgB,MAAM;AAC3B,SAAK,WAAW,SAAS;AAAA,MACvB,UAAU,CAAC;AAAA,MACX,OAAO;AAAA,IACT,CAAC;AAAA,EACH;AAAA,EAEQ,yBACN,WACA,SAC6B;AAC7B,UAAM,MAAM,KAAK,eAAe,eAAe,WAAW,OAAO;AACjE,WAAO,sBAAsB;AAAA,MAC3B,SAAS;AAAA,MACT,OAAO,KAAK;AAAA,MACZ;AAAA,MACA,uBAAuB,MAAM,KAAK,eAAe,WAAW,OAAO;AAAA,MACnE,WAAW,CAAC,KAAK,MAAM,aAAa,KAAK,UAAU,KAAK,MAAM,QAAQ;AAAA,MACtE,iBAAiB,CAAC,KAAc,UAC9B,KAAK,gBAAgB,KAAK,KAAK;AAAA,MACjC,mBAAmB,CAAC,sBAAsB;AACxC,YAAI,KAAK,oBAAoB;AAC3B,eAAK,yBAAyB,iBAAiB;AAAA,QACjD;AAAA,MACF;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEU,gBAAgB,GAAoB;AAC5C,SAAK,UAAU,oBAAoB,CAAC;AAAA,EACtC;AAAA,EAEU,gBAAgB,OAAgB,OAAyB;AACjE,UAAM,WAAY,OAAe,SAAS;AAC1C,UAAM,aAAc,OAAe,SAAS;AAC5C,UAAM,aAAc,OAAe,SAAS;AAC5C,UAAM,YACJ,aACC,aACG,GAAG,UAAU,GAAG,aAAa,MAAM,aAAa,EAAE,KAClD;AACN,SAAK;AAAA,MACH,EAAE,KAAK,OAAO,OAAO,UAAU,YAAY,WAAW;AAAA,MACtD;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,UACN,KACA,MACA,UACiB;AACjB,UAAM,UAAU,KAAK,aAAa,OAAO,EAAE,KAAK,MAAM,SAAS,CAAC;AAChE,SAAK,KAAK,SAAS,OAAO;AAC1B,WAAO;AAAA,EACT;AAAA,EAEQ,iBAAiB,WAAoB;AAC3C,QAAI;AAAW,aAAO;AACtB,UAAM,WAAW,KAAK,WAAW,SAAS,EAAE;AAC5C,UAAM,SAAS,SAAS,KAAK,CAAC,MAAM,EAAE,WAAW,WAAW,MAAM;AAClE,WAAO,QAAQ,MAAM,SAAS,CAAC,GAAG,MAAM;AAAA,EAC1C;AAAA,EAEQ,cAAc,WAAmB;AACvC,WACE,CAAC,CAAC,KAAK,eAAe,WAAW,SAAS,KAC1C,CAAC,CAAC,KAAK,eAAe,OAAO,SAAS;AAAA,EAE1C;AAAA,EAEQ,yBAAyB,WAAoB;AACnD,UAAM,KAAK,KAAK,iBAAiB,SAAS;AAC1C,QAAI,CAAC;AAAI,aAAO;AAChB,WAAO,KAAK,cAAc,EAAE,IAAI,KAAK;AAAA,EACvC;AAAA,EAEQ,uBAKN,MAAY;AACZ,QAAI,KAAK,eAAe,KAAK;AAAkB,aAAO;AACtD,WAAO,EAAE,GAAG,MAAM,kBAAkB,EAAE,OAAO,MAAM,OAAO,MAAM,EAAE;AAAA,EACpE;AAAA,EAEO,cAAc,WAAmB,UAAyB,CAAC,GAAG;AACnE,QAAI,CAAC,aAAa,CAAC,KAAK,cAAc,SAAS;AAAG,aAAO;AACzD,UAAM,OAAO,KAAK,uBAAuB,OAAO;AAChD,QAAI,KAAK,aAAa;AACpB,WAAK,eAAe,gBAAgB,WAAW,KAAK,WAAW;AAAA,IACjE;AACA,WAAO,KAAK,eAAe,OAAO,WAAW,IAAI;AAAA,EACnD;AAAA,EAEO,cAAc,WAAmB,SAA4B;AAClE,QAAI,CAAC,aAAa,CAAC,KAAK,cAAc,SAAS;AAAG,aAAO;AACzD,WAAO,KAAK,eAAe,OAAO,WAAW,OAAO;AAAA,EACtD;AAAA,EAEO,kBAAkB,WAAoB;AAC3C,UAAM,WAAW,KAAK,yBAAyB,SAAS;AACxD,QAAI,CAAC;AAAU,aAAO;AACtB,UAAM,eAAe,KAAK,WACvB,SAAS,EACT,SAAS,KAAK,CAAC,MAAM,EAAE,OAAO,QAAQ;AACzC,UAAM,QAAQ,cAAc,SAAS;AACrC,QAAI,OAAO;AACT,WAAK,eAAe,OAAO,QAAQ;AACnC,aAAO;AAAA,IACT;AACA,SAAK,eAAe,KAAK,QAAQ;AACjC,WAAO;AAAA,EACT;AAAA,EAEO,kBAAkB,WAAoB;AAC3C,UAAM,WAAW,KAAK,yBAAyB,SAAS;AACxD,QAAI,CAAC;AAAU,aAAO;AACtB,UAAM,eAAe,KAAK,WACvB,SAAS,EACT,SAAS,KAAK,CAAC,MAAM,EAAE,OAAO,QAAQ;AACzC,UAAM,WAAW,cAAc,WAAW,WAAW;AACrD,QAAI,UAAU;AACZ,WAAK,eAAe,OAAO,QAAQ;AACnC,aAAO;AAAA,IACT;AACA,QAAI,cAAc,WAAW,WAAW,QAAQ;AAC9C,WAAK,eAAe,KAAK,QAAQ;AACjC,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AAAA,EAEO,gBACL,WACA,OACA,SACA;AACA,UAAM,WAAW,KAAK,yBAAyB,SAAS;AACxD,QAAI,CAAC;AAAU,aAAO;AACtB,UAAM,eAAe,KAAK,WACvB,SAAS,EACT,SAAS,KAAK,CAAC,MAAM,EAAE,OAAO,QAAQ;AACzC,QAAI,cAAc,WAAW,WAAW;AACtC,WAAK,eAAe,SAAS,UAAU,OAAO,OAAO;AACvD,WAAO;AAAA,EACT;AAAA,EAEO,gBACL,WACA,QACA,SACA;AACA,UAAM,WAAW,KAAK,yBAAyB,SAAS;AACxD,QAAI,CAAC;AAAU,aAAO;AACtB,UAAM,eAAe,KAAK,WACvB,SAAS,EACT,SAAS,KAAK,CAAC,MAAM,EAAE,OAAO,QAAQ;AACzC,QAAI,cAAc,WAAW,WAAW;AACtC,WAAK,eAAe,SAAS,UAAU,QAAQ,OAAO;AACxD,WAAO;AAAA,EACT;AAAA,EAEO,gBAAgB,WAAmB,QAAqB;AAC7D,SAAK,eAAe,gBAAgB,WAAW,MAAM;AAAA,EACvD;AAAA,EAEO,yBACL,WACA,UAAqC,CAAC,GACtC;AACA,UAAM,WAAW,KAAK,yBAAyB,SAAS;AACxD,QAAI,CAAC;AAAU,aAAO,MAAM;AAAA,MAAC;AAE7B,SAAK,0BAA0B,QAAQ;AAEvC,UAAM,aACJ,QAAQ,cAAc,KAAK,oBAAoB;AACjD,UAAM,aACJ,QAAQ,cAAc,KAAK,oBAAoB;AACjD,QAAI,UAAU;AACd,QAAI,UAAU;AACd,UAAM,YAAY,KAAK,IAAI;AAC3B,UAAM,WAAW,KAAK,IAAI,aAAa,GAAG,GAAI;AAE9C,UAAM,OAAO,YAAY;AACvB,UAAI,WAAW,WAAW;AAAY;AAEtC,YAAM,MAAM,KAAK,eAAe,OAAO,QAAQ;AAC/C,YAAMC,WAAU,KAAK,eAAe,WAAW,QAAQ;AACvD,UAAI,CAAC,OAAO,CAACA;AAAS;AAEtB,YAAM,eAAe,KAAK,WACvB,SAAS,EACT,SAAS,KAAK,CAAC,MAAM,EAAE,OAAO,QAAQ;AACzC,UAAI,cAAc;AAAO;AAEzB,YAAM,SAAS,IAAI;AACnB,YAAM,QAAQ,QAAQ,iBAAiB,EAAE,CAAC;AAC1C,YAAMC,MAAqCD,UAAiB;AAC5D,YAAM,SAASC,KACX,aAAa,EACd,KAAK,CAAC,MAAoB,EAAE,OAAO,SAAS,OAAO;AAEtD,UAAI,CAAC,SAAS,CAAC;AAAQ;AAEvB,UAAI,KAAK,IAAI,IAAI,YAAY;AAAU;AACvC,UACEA,KAAI,oBAAoB,SACxBA,KAAI,oBAAoB,gBACxBA,KAAI,uBAAuB,SAC3BA,KAAI,uBAAuB,YAC3B;AACA;AAAA,MACF;AAEA,YAAM,YAAY,OAAO,eAAe;AACxC,YAAM,aAAa,QAAQ,OAAO,eAAe;AACjD,UAAI,aAAa;AAAY;AAE7B,WAAK;AAAA,QACH;AAAA,UACE,OAAO;AAAA,UACP;AAAA,UACA;AAAA,QACF;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAEA,iBAAW;AACX,UAAI,aAAa,CAAC,cAAc,OAAO;AACrC,cAAM,IAAI,kBAAkB,KAAK;AACjC;AAAA,MACF;AAEA,UAAI;AACJ,UAAI;AACF,cAAM,WACJ,OAAO,cAAc,EAAE,YACvB,QAAQ,OAAO,cAAc,EAAE;AACjC,qBAAa,MAAM,KAAK,gCAAgC,QAAQ;AAAA,MAClE,SAAS,KAAK;AACZ,gBAAQ,KAAK,2CAA2C,GAAG;AAC3D;AAAA,MACF;AACA,YAAM,YAAY,WAAW,eAAe,EAAE,CAAC;AAC/C,UAAI,CAAC;AAAW;AAEhB,YAAM,IAAI,kBAAkB,SAAS;AACrC,WAAK,eAAe,gBAAgB,UAAU,UAAU;AAAA,IAC1D;AAEA,UAAM,QAAQ,YAAY,MAAM;AAC9B,WAAK,KAAK;AAAA,IACZ,GAAG,UAAU;AACb,SAAK,KAAK;AAEV,UAAM,UAAU,KAAK,eAAe,WAAW,QAAQ;AACvD,UAAM,KAAqC,SAAiB;AAC5D,UAAM,cAAc,MAAM;AACxB,YAAM,QAAQ,IAAI;AAClB,UAAI,UAAU,YAAY,UAAU;AAAgB,aAAK,KAAK;AAAA,IAChE;AACA,QAAI,mBAAmB,4BAA4B,WAAW;AAE9D,UAAM,OAAO,MAAM;AACjB,gBAAU;AACV,oBAAc,KAAK;AACnB,UAAI,sBAAsB,4BAA4B,WAAW;AAAA,IACnE;AACA,SAAK,YAAY,IAAI,UAAU,EAAE,KAAK,CAAC;AACvC,WAAO;AAAA,EACT;AAAA,EAEO,0BAA0B,WAAmB;AAClD,UAAM,WAAW,KAAK,yBAAyB,SAAS;AACxD,QAAI,CAAC;AAAU,aAAO;AACtB,UAAM,QAAQ,KAAK,YAAY,IAAI,QAAQ;AAC3C,QAAI,CAAC;AAAO,aAAO;AACnB,UAAM,KAAK;AACX,SAAK,YAAY,OAAO,QAAQ;AAChC,WAAO;AAAA,EACT;AAAA,EAEO,oBAAoB,WAAmB,OAAyB;AACrE,QAAI,CAAC,KAAK,cAAc,SAAS;AAAG,aAAO;AAC3C,UAAM,MAAM,KAAK,eAAe,OAAO,SAAS;AAChD,WAAO,MAAM,IAAI,aAAa,KAAK,IAAI;AAAA,EACzC;AAAA,EAEO,mBAAmB,WAAmB;AAC3C,QAAI,CAAC,KAAK,cAAc,SAAS;AAAG,aAAO;AAC3C,UAAM,MAAM,KAAK,eAAe,OAAO,SAAS;AAChD,SAAK,YAAY;AACjB,WAAO,CAAC,CAAC;AAAA,EACX;AAAA,EAEO,oBAAoB,WAAmB;AAC5C,QAAI,CAAC,KAAK,cAAc,SAAS;AAAG,aAAO;AAC3C,UAAM,MAAM,KAAK,eAAe,OAAO,SAAS;AAChD,SAAK,aAAa;AAClB,WAAO,CAAC,CAAC;AAAA,EACX;AAAA,EAEO,WAAW,WAAmB;AACnC,WAAO,KAAK,eAAe,WAAW,SAAS;AAAA,EACjD;AAAA,EAEO,gBAAgB;AACrB,WAAO,KAAK,eAAe,cAAc;AAAA,EAC3C;AAAA,EAEO,cAAc;AACnB,WAAO,KAAK,eAAe,YAAY;AAAA,EACzC;AAAA,EAEQ,qBAAqB;AAC3B,QAAI,OAAO,WAAW,eAAe,KAAK;AAAe;AAEzD,UAAM,UAAU,MAAM;AACpB,WAAK,UAAU;AACf,WAAK,WAAW;AAAA,IAClB;AAEA,WAAO,iBAAiB,gBAAgB,OAAO;AAC/C,SAAK,gBAAgB;AAAA,EACvB;AAAA,EAEQ,qBAAqB;AAC3B,QAAI,OAAO,WAAW,eAAe,CAAC,KAAK;AAAe;AAC1D,WAAO,oBAAoB,gBAAgB,KAAK,aAAa;AAC7D,SAAK,gBAAgB;AAAA,EACvB;AAAA,EAEQ,mBAAmB,OAA0B;AACnD,QAAI,OAAO,WAAW;AAAa;AACnC,SAAK,kBAAkB,QAAQ,KAAK,CAAC;AAErC,UAAM,MAAM;AACZ,UAAM,oBAAoB,MAAM;AAC9B,cAAQ,KAAK,wDAAwD;AACrE,aAAO;AAAA,IACT;AACA,QAAI,WAAW,MACb,QAAQ,KAAK,WAAW,SAAS,IAAI,kBAAkB;AACzD,QAAI,cAAc,MAAO,QAAQ,KAAK,YAAY,IAAI,kBAAkB;AAAA,EAC1E;AAAA,EAEQ,kBAAkB,SAAkB;AAC1C,QAAI,CAAC,SAAS;AACZ,WAAK,cAAc;AACnB,WAAK,cAAc;AACnB;AAAA,IACF;AACA,QAAI,KAAK;AAAa;AAEtB,QAAI,OAAO,KAAK,WAAW,SAAS;AAEpC,YAAQ,KAAK,gBAAgB,EAAE,SAAS,KAAK,GAAG,IAAI;AAEpD,SAAK,cAAc,KAAK,WAAW,SAAS,CAAC,SAAS;AACpD,YAAM,UAAU,KAAK,UAAU,MAAM,IAAI;AACzC,UAAI,SAAS;AAEX,gBAAQ,KAAK,gBAAgB,SAAS,IAAI;AAAA,MAC5C;AACA,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AAAA,EAEQ,UACN,MACA,MACuD;AACvD,UAAM,UAA0D,CAAC;AACjE,eAAW,OAAO,OAAO,KAAK,IAAI,GAA4B;AAC5D,UAAI,KAAK,GAAG,MAAM,KAAK,GAAG,GAAG;AAC3B,gBAAQ,GAAa,IAAI,EAAE,MAAM,KAAK,GAAG,GAAG,IAAI,KAAK,GAAG,EAAE;AAAA,MAC5D;AAAA,IACF;AACA,WAAO,OAAO,KAAK,OAAO,EAAE,SAAS,UAAU;AAAA,EACjD;AAAA,EAEQ,oBAAkD;AACxD,QAAI,OAAO,WAAW;AAAa,aAAO;AAC1C,QAAI;AACF,YAAM,YAAY,OAAO,eAAe,QAAQ,iBAAiB;AACjE,UAAI,CAAC;AAAW,eAAO;AACvB,aAAO;AAAA,IACT,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAc,gCACZ,UACsB;AACtB,QACE,OAAO,cAAc,eACrB,CAAC,UAAU,cAAc,cACzB;AACA,YAAM,IAAI,MAAM,4BAA4B;AAAA,IAC9C;AACA,UAAM,QACJ,YAAY,aAAa,YACrB,EAAE,UAAU,EAAE,OAAO,SAAS,EAAE,IAChC;AACN,QAAI;AACF,aAAO,MAAM,UAAU,aAAa,aAAa,EAAE,MAAM,CAAC;AAAA,IAC5D,SAAS,KAAU;AACjB,YAAM,QAAQ,KAAK,QAAQ;AAC3B,WAAK;AAAA,QACH,EAAE,KAAK,KAAK,MAAM;AAAA,QAClB;AAAA,QACA;AAAA,MACF;AACA,YAAM;AAAA,IACR;AAAA,EACF;AACF;AAEO,SAAS,wBAAwB,SAAuC;AAC7E,SAAO,IAAI,UAAU,OAAO;AAC9B;AAEO,SAAS,sBAAsB,QAAoC;AACxE,SAAO;AAAA,IACL,KAAK,OAAO,SAAS;AACnB,aAAO,OAAO,GAAG,OAAO,OAAc;AAAA,IACxC;AAAA,IACA,UAAU,WAAW,OAAO,SAAS;AACnC,YAAM,UAAU,OAAO,WAAW,SAAS;AAC3C,UAAI,CAAC;AAAS,eAAO,MAAM;AAAA,QAAC;AAC5B,cAAQ,GAAG,OAAc,OAAc;AACvC,aAAO,MAAM,QAAQ,IAAI,OAAc,OAAc;AAAA,IACvD;AAAA,EACF;AACF;;;ACzqBA,SAAS,0BAA0B;;;ACzBnC,SAAS,qBAAqB;AAKvB,IAAM,aAAa,cAAqC,IAAI;;;ACLnE,SAAS,aAAa,4BAA4B;;;ACAlD,SAAS,kBAAkB;AAGpB,SAAS,SAAS;AACvB,QAAM,MAAM,WAAW,UAAU;AACjC,MAAI,CAAC;AAAK,UAAM,IAAI,MAAM,iCAAiC;AAC3D,SAAO;AACT;;;ADHO,SAAS,cAAwB;AACtC,QAAM,EAAE,OAAO,IAAI,OAAO;AAC1B,QAAM,YAAY;AAAA,IAChB,CAAC,kBAA8B,OAAO,SAAS,aAAa;AAAA,IAC5D,CAAC,MAAM;AAAA,EACT;AAEA,QAAM,cAAc,YAAY,MAAM,OAAO,OAAO,CAAC,MAAM,CAAC;AAE5D,SAAO,qBAAqB,WAAW,aAAa,WAAW;AACjE;;;AEdA,SAAS,eAAe;AAGjB,SAAS,gBAAgB;AAC9B,QAAM,EAAE,OAAO,IAAI,OAAO;AAC1B,SAAO;AAAA,IACL,OAAO;AAAA,MACL,MAAM,IAAI,SAAyC,OAAO,KAAK,GAAG,IAAI;AAAA,MACtE,QAAQ,IAAI,SACV,OAAO,cAAc,GAAG,IAAI;AAAA,MAC9B,QAAQ,IAAI,SACV,OAAO,cAAc,GAAG,IAAI;AAAA,MAC9B,YAAY,IAAI,SACd,OAAO,kBAAkB,GAAG,IAAI;AAAA,MAClC,YAAY,IAAI,SACd,OAAO,kBAAkB,GAAG,IAAI;AAAA,MAClC,UAAU,IAAI,SACZ,OAAO,gBAAgB,GAAG,IAAI;AAAA,MAChC,UAAU,IAAI,SACZ,OAAO,gBAAgB,GAAG,IAAI;AAAA,MAChC,YAAY,IAAI,SACd,OAAO,WAAW,GAAG,IAAI;AAAA,MAC3B,eAAe,MAAM,OAAO,cAAc;AAAA,MAC1C,aAAa,MAAM,OAAO,YAAY;AAAA,MACtC,iBAAiB,IAAI,SACnB,OAAO,gBAAgB,GAAG,IAAI;AAAA,MAChC,0BAA0B,IACrB,SACA,OAAO,yBAAyB,GAAG,IAAI;AAAA,MAC5C,2BAA2B,IACtB,SACA,OAAO,0BAA0B,GAAG,IAAI;AAAA,MAC7C,cAAc,IAAI,SAChB,OAAO,oBAAoB,GAAG,IAAI;AAAA,MACpC,aAAa,IAAI,SACf,OAAO,mBAAmB,GAAG,IAAI;AAAA,MACnC,cAAc,IAAI,SAChB,OAAO,oBAAoB,GAAG,IAAI;AAAA,IACtC;AAAA,IACA,CAAC,MAAM;AAAA,EACT;AACF;;;ACtCO,SAAS,iBAA6C;AAC3D,QAAM,EAAE,SAAS,IAAI,YAAY;AACjC,SAAO,EAAE,SAAS;AACpB;;;ACNA,SAAS,iBAAiB;AASnB,SAAS,YACd,OACA,SACA;AACA,QAAM,EAAE,gBAAgB,IAAI,OAAO;AAEnC,YAAU,MAAM;AACd,QAAI,CAAC;AAAS;AACd,WAAO,gBAAgB,KAAK,OAAO,OAAO;AAAA,EAC5C,GAAG,CAAC,OAAO,SAAS,eAAe,CAAC;AACtC;AAEO,SAAS,mBACd,WACA,OACA,SACA;AACA,QAAM,EAAE,gBAAgB,IAAI,OAAO;AAEnC,YAAU,MAAM;AACd,QAAI,CAAC;AAAS;AACd,WAAO,gBAAgB,UAAU,WAAW,OAAO,OAAO;AAAA,EAC5D,GAAG,CAAC,OAAO,SAAS,WAAW,eAAe,CAAC;AACjD;;;AChCA,SAAS,aAAAC,YAAW,cAAc;;;ACG3B,SAAS,iBAAiB,SAA2B;AAC1D,MAAI,uBAA4C;AAChD,MAAI,6BAAkD;AACtD,MAAI,yBAA8C;AAElD,QAAM,UAAU,CAAC,OAA4B;AAC3C,QAAI;AAAI,SAAG;AACX,WAAO;AAAA,EACT;AAGA,WAAS,iBAAiB,QAA6B;AACrD,QAAI,QAAQ;AACV,iBAAW,KAAK,OAAO,UAAU,GAAG;AAClC,UAAE,KAAK;AAAA,MACT;AAAA,IACF;AACA,YAAQ,YAAY;AAAA,EACtB;AAEA,QAAM,eAAe,CAAC,OAA0B;AAC9C,UAAM,UAAU,CAAC,MAAqB;AACpC,UAAI,EAAE,MAAM,SAAS;AAAS;AAE9B,YAAM,aAAa,EAAE,UAAU,CAAC,KAAK,IAAI,YAAY,CAAC,EAAE,KAAK,CAAC;AAC9D,YAAM,OAAO,QAAQ;AAErB,UAAI,QAAQ,SAAS,YAAY;AAC/B,yBAAiB,IAAI;AAAA,MACvB;AAEA,cAAQ,YAAY;AACpB,cAAQ,OAAO,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AAAA,IACjC;AAEA,OAAG,iBAAiB,SAAS,OAAO;AACpC,WAAO,MAAM,GAAG,oBAAoB,SAAS,OAAO;AAAA,EACtD;AAEA,QAAM,8BAA8B,CAAC,YAAwB;AAC3D,UAAM,SAAS,CAAC,SAAgD;AAC9D,6BAAuB,QAAQ,oBAAoB;AACnD,6BAAuB,aAAa,KAAK,cAAc;AAAA,IACzD;AACA,YAAQ,GAAG,kBAAkB,MAAM;AACnC,WAAO,MAAM,QAAQ,IAAI,kBAAkB,MAAM;AAAA,EACnD;AAEA,WAAS,cAAc,SAAqB;AAC1C,QACE,SAAS,cAAc,cACvB,QAAQ,sBAAsB,mBAC9B;AACA,6BAAuB,QAAQ,oBAAoB;AACnD,6BAAuB,aAAa,QAAQ,UAAU;AAAA,IACxD;AAEA,iCAA6B,QAAQ,0BAA0B;AAC/D,iCAA6B,4BAA4B,OAAO;AAEhE,WAAO,MAAM;AACX,mCAA6B,QAAQ,0BAA0B;AAC/D,6BAAuB,QAAQ,oBAAoB;AAAA,IACrD;AAAA,EACF;AAEA,WAAS,aAAa,QAAmB;AACvC,UAAM,SAAS,OAAO,GAAG,iBAAiB,CAAC,YAAY;AACrD,YAAM,IAAK,SAAiB;AAC5B,mCAA6B,QAAQ,0BAA0B;AAC/D,6BAAuB,QAAQ,oBAAoB;AAEnD,UAAI,CAAC,GAAG;AAAS;AAEjB,mCAA6B,4BAA4B,EAAE,OAAO;AAClE,UACE,EAAE,QAAQ,cAAc,cACxB,EAAE,QAAQ,sBAAsB,mBAChC;AACA,+BAAuB,aAAa,EAAE,QAAQ,UAAU;AAAA,MAC1D;AAAA,IACF,CAAC;AAED,UAAM,WAAW,OAAO,GAAG,SAAS,MAAM,OAAO,CAAC;AAClD,UAAM,YAAY,OAAO,GAAG,UAAU,MAAM,OAAO,CAAC;AACpD,UAAM,kBAAkB,OAAO,GAAG,gBAAgB,MAAM,OAAO,CAAC;AAEhE,6BAAyB,MAAM;AAC7B,aAAO;AACP,eAAS;AACT,gBAAU;AACV,sBAAgB;AAAA,IAClB;AACA,WAAO;AAAA,EACT;AAEA,WAAS,SAAS;AAChB,6BAAyB,QAAQ,sBAAsB;AACvD,iCAA6B,QAAQ,0BAA0B;AAC/D,2BAAuB,QAAQ,oBAAoB;AACnD,qBAAiB,QAAQ,SAA+B;AAAA,EAC1D;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ADxFS;AAnBF,SAAS,WAAW,EAAE,UAAU,GAA2B;AAChE,QAAM,EAAE,OAAO,IAAI,OAAO;AAC1B,QAAM,WAAW,OAAgC,IAAI;AAErD,EAAAA,WAAU,MAAM;AACd,QAAI,CAAC,SAAS;AAAS;AAEvB,UAAM,SAAS,iBAAiB,SAAS,OAAO;AAChD,UAAM,UAAU,YAAY,OAAO,WAAW,SAAS,IAAI;AAC3D,UAAM,MAAM,UACR,OAAO,cAAc,OAAO,IAC5B,OAAO,aAAa,MAAM;AAE9B,WAAO,MAAM;AACX,YAAM;AACN,aAAO,OAAO;AAAA,IAChB;AAAA,EACF,GAAG,CAAC,QAAQ,SAAS,CAAC;AAEtB,SAAO,oBAAC,WAAM,KAAK,UAAU,UAAQ,MAAC,aAAW,MAAC;AACpD;;;AExBA,SAAgB,WAAAC,gBAAe;AAqB3B,gBAAAC,YAAA;AAjBG,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,QAAM,UAAUD;AAAA,IACd,MAAM,mBAAmB,sBAAsB,MAAM;AAAA,IACrD,CAAC,QAAQ,eAAe;AAAA,EAC1B;AAEA,QAAM,eAAeA,SAAQ,OAAO,EAAE,QAAQ,iBAAiB,QAAQ,IAAI,CAAC,QAAQ,OAAO,CAAC;AAE5F,SACE,gBAAAC,KAAC,WAAW,UAAX,EAAoB,OAAO,cACzB,UACH;AAEJ","sourcesContent":["import JsSIP from \"jssip\";\n\ntype StorageLike = Pick<Storage, \"getItem\" | \"setItem\" | \"removeItem\">;\n\nexport interface SipDebugToggleResult {\n debug: boolean;\n text: string;\n}\n\n/**\n * Browser-friendly debugger toggle for JsSIP.\n * Persists preference in sessionStorage and exposes helpers on window for console use.\n */\nexport class SipDebugger {\n private readonly storageKey: string;\n private readonly defaultPattern: string;\n private enabled = false;\n private logger: any;\n\n constructor(storageKey = \"sip-debug-enabled\", defaultPattern = \"JsSIP:*\") {\n this.storageKey = storageKey;\n this.defaultPattern = defaultPattern;\n }\n\n initFromSession(storage: StorageLike | null = safeSessionStorage()): void {\n try {\n const saved = storage?.getItem(this.storageKey);\n if (saved) this.enable(saved, storage);\n } catch {\n /* ignore */\n }\n }\n\n enable(\n pattern: string = this.defaultPattern,\n storage: StorageLike | null = safeSessionStorage()\n ): void {\n try {\n if (typeof JsSIP?.debug?.enable === \"function\") {\n JsSIP.debug.enable(pattern);\n this.logger = console;\n }\n // Persist pattern in sessionStorage only.\n storage?.setItem?.(this.storageKey, pattern || this.defaultPattern);\n try {\n (window as any).sipDebugBridge?.(pattern);\n } catch {\n /* ignore */\n }\n this.enabled = true;\n } catch {\n /* ignore */\n }\n }\n\n disable(storage: StorageLike | null = safeSessionStorage()): void {\n try {\n if (typeof JsSIP?.debug?.disable === \"function\") {\n JsSIP.debug.disable();\n } else if (typeof JsSIP?.debug?.enable === \"function\") {\n JsSIP.debug.enable(\"\");\n }\n storage?.removeItem?.(this.storageKey);\n try {\n (window as any).sipDebugBridge?.(false);\n } catch {\n /* ignore */\n }\n this.enabled = false;\n } catch {\n /* ignore */\n }\n }\n\n toggle(\n pattern: string = this.defaultPattern,\n storage: StorageLike | null = safeSessionStorage()\n ): void {\n if (this.isEnabled()) {\n this.disable(storage);\n } else {\n this.enable(pattern, storage);\n }\n }\n\n isEnabled(): boolean {\n return this.enabled;\n }\n\n attachToWindow(win: Window & typeof globalThis = window): void {\n const api = {\n enableDebug: (): SipDebugToggleResult => {\n this.enable();\n return { debug: this.isEnabled(), text: \"press F5\" };\n },\n disableDebug: (): SipDebugToggleResult => {\n this.disable();\n return { debug: this.isEnabled(), text: \"press F5\" };\n },\n toggleDebug: (): SipDebugToggleResult => {\n this.toggle();\n return { debug: this.isEnabled(), text: \"press F5\" };\n },\n debugState: (): SipDebugToggleResult => ({\n debug: this.isEnabled(),\n text: this.isEnabled() ? \"enabled\" : \"disabled\",\n }),\n sipState: () => {\n try {\n const getter = (win as any).sipState;\n return typeof getter === \"function\"\n ? getter()\n : \"sipState helper not available; ensure client debug is enabled\";\n } catch {\n return \"sipState helper not available\";\n }\n },\n sipSessions: () => {\n try {\n const getter = (win as any).sipSessions;\n return typeof getter === \"function\"\n ? getter()\n : \"sipSessions helper not available; ensure client debug is enabled\";\n } catch {\n return \"sipSessions helper not available\";\n }\n },\n };\n\n try {\n (win as any).sipSupport = api;\n } catch {\n /* ignore */\n }\n }\n}\n\nfunction safeSessionStorage(): StorageLike | null {\n if (typeof window === \"undefined\") return null;\n try {\n return window.sessionStorage;\n } catch {\n return null;\n }\n}\n\nexport const sipDebugger = new SipDebugger();\nif (typeof window !== \"undefined\") {\n sipDebugger.attachToWindow();\n sipDebugger.initFromSession();\n}\n","import JsSIP, { UA } from \"jssip\";\r\nimport { SipConfiguration, UAConfiguration } from \"./types\";\r\n\r\ntype StartOpts = { debug?: boolean | string };\r\n\r\nexport class SipUserAgent {\r\n private _ua: UA | null = null;\r\n\r\n public get ua(): UA | null {\r\n return this._ua;\r\n }\r\n public get isStarted(): boolean {\r\n return !!this._ua;\r\n }\r\n public get isRegistered(): boolean {\r\n return !!this._ua?.isRegistered();\r\n }\r\n\r\n public start(\r\n uri: string,\r\n password: string,\r\n config: Omit<SipConfiguration, \"debug\">,\r\n opts?: StartOpts\r\n ): UA {\r\n this.stop();\r\n const uaCfg = this.buildUAConfig(config, uri, password);\r\n this.ensureValid(uaCfg);\r\n this.applyDebug(opts?.debug);\r\n const ua = this.createUA(uaCfg);\r\n ua.start();\r\n this._ua = ua;\r\n return ua;\r\n }\r\n\r\n public register(): void {\r\n const ua = this.getUA();\r\n if (!ua?.isRegistered()) ua?.register();\r\n }\r\n\r\n public stop(): void {\r\n const ua = this._ua;\r\n if (!ua) return;\r\n try {\r\n if (ua.isRegistered()) ua.unregister();\r\n ua.stop();\r\n } finally {\r\n this._ua = null;\r\n }\r\n }\r\n\r\n public getUA(): UA | null {\r\n return this._ua;\r\n }\r\n\r\n public setDebug(debug?: boolean | string): void {\r\n this.applyDebug(debug);\r\n }\r\n\r\n protected buildUAConfig(\r\n config: Omit<SipConfiguration, \"debug\">,\r\n uri: string,\r\n password: string\r\n ): UAConfiguration {\r\n return { ...(config as UAConfiguration), uri, password };\r\n }\r\n\r\n protected ensureValid(cfg: UAConfiguration): void {\r\n const sockets = cfg.sockets as UAConfiguration[\"sockets\"];\r\n if (\r\n !cfg.uri ||\r\n !cfg.password ||\r\n !sockets ||\r\n (Array.isArray(sockets) && sockets.length === 0)\r\n ) {\r\n throw new Error(\r\n \"Invalid SIP connect args: require uri, password, and at least one socket\"\r\n );\r\n }\r\n }\r\n\r\n protected applyDebug(debug?: boolean | string): void {\n const stored = debug === undefined ? this.readSessionFlag() : debug;\n const enabled = !!stored;\n const pattern = typeof stored === \"string\" ? stored : \"JsSIP:*\";\n\n if (enabled) {\n JsSIP.debug.enable(pattern);\n const dbg: any = (JsSIP as any).debug;\n if (dbg?.setLogger) dbg.setLogger(console);\n else if (dbg) dbg.logger = console;\n this.persistSessionFlag(typeof stored === \"string\" ? stored : undefined);\n } else {\n (JsSIP.debug as any)?.disable?.();\n this.clearSessionFlag();\n }\n }\n\r\n protected createUA(cfg: UAConfiguration): UA {\r\n return new JsSIP.UA(cfg);\r\n }\r\n\r\n private readSessionFlag(): string | false {\n try {\n if (typeof window === \"undefined\") return false;\n const value = window.sessionStorage.getItem(\"sip-debug-enabled\");\n if (!value) return false;\n return value;\n } catch {\n return false;\n }\n }\n\n private persistSessionFlag(pattern?: string): void {\n try {\n if (typeof window !== \"undefined\") {\n window.sessionStorage.setItem(\n \"sip-debug-enabled\",\n pattern || \"JsSIP:*\"\n );\n }\n } catch {\n /* ignore */\n }\n }\r\n\r\n private clearSessionFlag(): void {\r\n try {\r\n if (typeof window !== \"undefined\") {\r\n window.sessionStorage.removeItem(\"sip-debug-enabled\");\r\n }\r\n } catch {\r\n /* ignore */\r\n }\r\n }\r\n}\r\n","import { Originator } from \"jssip/src/RTCSession\";\r\n\r\nexport const SipStatus = {\r\n Disconnected: \"disconnected\",\r\n Connecting: \"connecting\",\r\n Connected: \"connected\",\r\n Registered: \"registered\",\r\n Unregistered: \"unregistered\",\r\n RegistrationFailed: \"registrationFailed\",\r\n} as const;\r\n\r\nexport type SipStatus = (typeof SipStatus)[keyof typeof SipStatus];\r\n\r\nexport const CallStatus = {\r\n Idle: \"idle\",\r\n Dialing: \"dialing\",\r\n Ringing: \"ringing\",\r\n Active: \"active\",\r\n Hold: \"hold\",\r\n} as const;\r\nexport type CallStatus = (typeof CallStatus)[keyof typeof CallStatus];\r\n\r\nexport type CallDirection = Originator.LOCAL | Originator.REMOTE;\r\n\r\nexport type SipSessionState = {\r\n id: string;\r\n status: CallStatus;\r\n direction: CallDirection | null;\r\n from: string | null;\r\n to: string | null;\r\n muted: boolean;\r\n acceptedAt: number | null;\r\n mediaKind: \"audio\" | \"video\";\r\n remoteVideoEnabled: boolean;\r\n};\r\n\r\nexport interface SipState {\r\n sipStatus: SipStatus;\r\n error: string | null;\r\n sessions: SipSessionState[];\r\n}\r\n\r\nexport const SipStatusList = Object.values(SipStatus);\r\nexport const CallStatusList = Object.values(CallStatus);\r\n\r\nexport function isSipStatus(v: unknown): v is SipStatus {\r\n return (\r\n typeof v === \"string\" && (SipStatusList as readonly string[]).includes(v)\r\n );\r\n}\r\nexport function isCallStatus(v: unknown): v is CallStatus {\r\n return (\r\n typeof v === \"string\" && (CallStatusList as readonly string[]).includes(v)\r\n );\r\n}\r\n\r\nexport type Unsubscribe = () => void;\r\nexport type Listener<T> = (value: T) => void;\r\n","export type Listener<T = any> = (payload: T) => void;\r\n\r\nexport class EventTargetEmitter<Events extends Record<string, any> = any> {\r\n private target = new EventTarget();\r\n\r\n on<K extends keyof Events>(event: K, fn: Listener<Events[K]>): () => void {\r\n const wrapper = (e: Event) => fn((e as CustomEvent<Events[K]>).detail);\r\n this.target.addEventListener(event as string, wrapper);\r\n return () => this.target.removeEventListener(event as string, wrapper);\r\n }\r\n\r\n emit<K extends keyof Events>(event: K, payload?: Events[K]): void {\r\n this.target.dispatchEvent(\r\n new CustomEvent(event as string, { detail: payload })\r\n );\r\n }\r\n}\r\n","export interface SipErrorPayload {\r\n cause: string;\r\n code?: string;\r\n raw?: any;\r\n message?: string;\r\n}\r\n\r\nexport interface SipErrorFormatInput {\r\n raw: any;\r\n code?: string;\r\n fallback?: string;\r\n}\r\n\r\nexport type SipErrorFormatter = (\r\n input: SipErrorFormatInput\r\n) => SipErrorPayload | undefined;\r\n\r\ntype SipErrorHandlerOptions = {\r\n formatter?: SipErrorFormatter;\r\n messages?: Record<string, string>;\r\n};\r\n\r\nexport class SipErrorHandler {\r\n private readonly formatter?: SipErrorFormatter;\r\n private readonly messages?: Record<string, string>;\r\n\r\n constructor(options: SipErrorHandlerOptions = {}) {\r\n this.formatter = options.formatter;\r\n this.messages = options.messages;\r\n }\r\n\r\n format(input: SipErrorFormatInput): SipErrorPayload {\r\n const { code, raw, fallback } = input;\r\n const mappedMessage =\r\n code && this.messages ? this.messages[code] : undefined;\r\n\r\n // Allow consumer to fully customize formatting.\r\n if (this.formatter) {\r\n const custom = this.formatter({\r\n raw,\r\n code,\r\n fallback: mappedMessage ?? fallback,\r\n });\r\n const message =\r\n custom?.message ??\r\n custom?.cause ??\r\n mappedMessage ??\r\n fallback ??\r\n this.readRawMessage(raw) ??\r\n \"unknown error\";\r\n\r\n return {\r\n cause: custom?.cause ?? message,\r\n code: custom?.code ?? code,\r\n raw: custom?.raw ?? raw,\r\n message,\r\n };\r\n }\r\n\r\n const message =\r\n mappedMessage ?? this.readRawMessage(raw) ?? fallback ?? \"unknown error\";\r\n\r\n return {\r\n cause: message,\r\n code,\r\n raw,\r\n message,\r\n };\r\n }\r\n\r\n private readRawMessage(raw: any): string | undefined {\r\n if (raw == null) return undefined;\r\n if (typeof raw === \"string\") return raw;\r\n if (typeof raw?.cause === \"string\") return raw.cause;\r\n if (typeof raw?.message === \"string\") return raw.message;\r\n return undefined;\r\n }\r\n}\r\n","import { SipState, SipStatus } from \"./types\";\r\n\r\nexport function getInitialSipState(): SipState {\r\n return {\r\n sipStatus: SipStatus.Disconnected,\r\n error: null,\r\n sessions: [],\r\n };\r\n}\r\n\r\nexport function shallowEqual(objA: any, objB: any): boolean {\r\n if (objA === objB) return true;\r\n if (!objA || !objB) return false;\r\n const keysA = Object.keys(objA);\r\n const keysB = Object.keys(objB);\r\n if (keysA.length !== keysB.length) return false;\r\n for (const key of keysA) {\r\n if (objA[key] !== objB[key]) return false;\r\n }\r\n return true;\r\n}\r\n","import { SipState } from \"./types\";\r\nimport { getInitialSipState, shallowEqual } from \"./sipState\";\r\n\r\nexport type SipStateListener = (state: SipState) => void;\r\n\r\nexport class SipStateStore {\r\n private state: SipState = getInitialSipState();\r\n private lastState: SipState = getInitialSipState();\r\n private listeners = new Set<SipStateListener>();\r\n private pendingState: Partial<SipState> | null = null;\r\n private updateScheduled = false;\r\n\r\n getState(): SipState {\r\n return this.state;\r\n }\r\n\r\n onChange(fn: SipStateListener): () => void {\r\n this.listeners.add(fn);\r\n fn(this.state);\r\n return () => this.listeners.delete(fn);\r\n }\r\n\r\n subscribe(fn: SipStateListener): () => void {\r\n return this.onChange(fn);\r\n }\r\n\r\n setState(partial: Partial<SipState>) {\r\n if (!partial || Object.keys(partial).length === 0) return;\r\n const next = { ...this.state, ...partial };\r\n // Fast-path: if sessions reference unchanged and shallow contents equal, skip emit.\r\n if (next.sessions === this.lastState.sessions && shallowEqual(this.lastState, next)) {\r\n return;\r\n }\r\n this.state = next;\r\n this.lastState = next;\r\n this.emit();\r\n }\r\n\r\n batchSet(partial: Partial<SipState>) {\r\n this.pendingState = { ...this.pendingState, ...partial };\r\n if (!this.updateScheduled) {\r\n this.updateScheduled = true;\r\n queueMicrotask(() => {\r\n if (this.pendingState) this.setState(this.pendingState);\r\n this.pendingState = null;\r\n this.updateScheduled = false;\r\n });\r\n }\r\n }\r\n\r\n reset(overrides: Partial<SipState> = {}) {\r\n this.setState({ ...getInitialSipState(), ...overrides });\r\n }\r\n\r\n private emit() {\r\n for (const fn of this.listeners) fn(this.state);\r\n }\r\n}\r\n","import { UAEventMap } from \"../types\";\r\nimport { SipStatus } from \"../../core/types\";\r\nimport { SipStateStore } from \"../../core/sipStateStore\";\r\nimport { JsSIPEventMap } from \"../types\";\r\nimport { EventTargetEmitter } from \"../../core/eventEmitter\";\r\nimport { SipErrorPayload } from \"../../core/sipErrorHandler\";\r\n\r\ntype Deps = {\r\n emitter: EventTargetEmitter<JsSIPEventMap>;\r\n state: SipStateStore;\r\n cleanupAllSessions: () => void;\r\n emitError: (\r\n raw: any,\r\n code?: string,\r\n fallback?: string\r\n ) => SipErrorPayload;\r\n onNewRTCSession: UAEventMap[\"newRTCSession\"];\r\n};\r\n\r\nexport function createUAHandlers(deps: Deps): Partial<UAEventMap> {\r\n const { emitter, state, cleanupAllSessions, emitError, onNewRTCSession } =\r\n deps;\r\n\r\n return {\r\n connecting: (e: any) => {\r\n emitter.emit(\"connecting\", e);\r\n state.batchSet({ sipStatus: SipStatus.Connecting });\r\n },\r\n connected: (e: any) => {\r\n emitter.emit(\"connected\", e);\r\n state.batchSet({ sipStatus: SipStatus.Connected });\r\n },\r\n disconnected: (e: any) => {\r\n emitter.emit(\"disconnected\", e);\r\n cleanupAllSessions();\r\n state.reset();\r\n },\r\n\r\n registered: (e: any) => {\r\n emitter.emit(\"registered\", e);\r\n state.batchSet({ sipStatus: SipStatus.Registered, error: null });\r\n },\r\n unregistered: (e: any) => {\r\n emitter.emit(\"unregistered\", e);\r\n state.batchSet({ sipStatus: SipStatus.Unregistered });\r\n },\r\n registrationFailed: (e: any) => {\r\n emitter.emit(\"registrationFailed\", e);\r\n cleanupAllSessions();\r\n emitError(\r\n {\r\n raw: e,\r\n cause: e?.cause,\r\n statusCode: e?.response?.status_code,\r\n statusText: e?.response?.reason_phrase,\r\n },\r\n \"REGISTRATION_FAILED\",\r\n \"registration failed\"\r\n );\r\n state.batchSet({\r\n sipStatus: SipStatus.RegistrationFailed,\r\n error: e?.cause || \"registration failed\",\r\n });\r\n },\r\n newRTCSession: onNewRTCSession,\r\n newMessage: (e: any) => emitter.emit(\"newMessage\", e),\r\n sipEvent: (e: any) => emitter.emit(\"sipEvent\", e),\r\n newOptions: (e: any) => emitter.emit(\"newOptions\", e),\r\n };\r\n}\r\n","import { CallStatus, SipSessionState } from \"../core/types\";\r\nimport { SipStateStore } from \"../core/sipStateStore\";\r\n\r\nexport function holdOtherSessions(\r\n state: SipStateStore,\r\n sessionId: string,\r\n holdFn: (id: string) => void\r\n) {\r\n const current = state.getState();\r\n current.sessions.forEach((s) => {\r\n if (s.id === sessionId) return;\r\n if (s.status === CallStatus.Active) {\r\n holdFn(s.id);\r\n }\r\n });\r\n}\r\n\r\nexport function upsertSessionState(\r\n state: SipStateStore,\r\n sessionId: string,\r\n partial: Partial<SipSessionState>\r\n) {\r\n const current = state.getState();\r\n const existing = current.sessions.find((s) => s.id === sessionId);\r\n const base: SipSessionState = existing ?? {\r\n id: sessionId,\r\n status: CallStatus.Idle,\r\n direction: null,\r\n from: null,\r\n to: null,\r\n muted: false,\r\n acceptedAt: null,\r\n mediaKind: \"audio\",\r\n remoteVideoEnabled: false,\r\n };\r\n\r\n const nextSession = { ...base, ...partial };\r\n const sessions = existing\r\n ? current.sessions.map((s) => (s.id === sessionId ? nextSession : s))\r\n : [...current.sessions, nextSession];\r\n\r\n state.setState({ sessions });\r\n}\r\n\r\nexport function removeSessionState(state: SipStateStore, sessionId: string) {\r\n const current = state.getState();\r\n const sessions = current.sessions.filter((s) => s.id !== sessionId);\r\n state.setState({\r\n sessions,\r\n error: null,\r\n });\r\n}\r\n","import { EndEvent, RTCSessionEventMap } from \"../types\";\nimport { CallStatus } from \"../../core/types\";\nimport { SipStateStore } from \"../../core/sipStateStore\";\nimport { WebRTCSessionController } from \"../sessionController\";\nimport { JsSIPEventMap } from \"../types\";\nimport { EventTargetEmitter } from \"../../core/eventEmitter\";\nimport { SipErrorPayload } from \"../../core/sipErrorHandler\";\nimport { upsertSessionState } from \"../sessionState\";\nimport { IncomingAckEvent, IncomingEvent, OutgoingAckEvent, OutgoingEvent } from \"jssip/src/RTCSession\";\n\ntype Deps = {\n emitter: EventTargetEmitter<JsSIPEventMap>;\n state: SipStateStore;\n rtc: WebRTCSessionController;\n detachSessionHandlers: () => void;\n emitError: (raw: any, code?: string, fallback?: string) => SipErrorPayload;\n onSessionFailed: (error?: string, event?: any) => void;\n onSessionAccepted?: (sessionId: string) => void;\n sessionId: string;\n};\n\nexport function createSessionHandlers(deps: Deps): Partial<RTCSessionEventMap> {\n const {\n emitter,\n state,\n rtc,\n detachSessionHandlers,\n onSessionFailed,\n onSessionConfirmed,\n sessionId,\n } = deps;\n\n return {\n progress: (e: IncomingEvent | OutgoingEvent) => {\n emitter.emit(\"progress\", e);\n },\n accepted: (e: IncomingEvent | OutgoingEvent) => {\n emitter.emit(\"accepted\", e);\n onSessionAccepted?.(sessionId);\n state.batchSet({\n sessions: state.getState().sessions.map((s) =>\n s.id === sessionId\n ? {\n ...s,\n status: CallStatus.Active,\n acceptedAt: s.acceptedAt ?? Date.now(),\n }\n : s\n ),\n });\n },\n confirmed: (e: IncomingAckEvent | OutgoingAckEvent) => {\n emitter.emit(\"confirmed\", e);\n onSessionConfirmed?.(sessionId);\n },\n\n ended: (e: EndEvent) => {\n emitter.emit(\"ended\", e);\n detachSessionHandlers();\n rtc.cleanup();\n const nextSessions = state\n .getState()\n .sessions.filter((s) => s.id !== sessionId);\n state.batchSet({\n sessions: nextSessions,\n });\n },\n failed: (e: EndEvent) => {\n emitter.emit(\"failed\", e);\n detachSessionHandlers();\n rtc.cleanup();\n const cause = e?.cause || \"call failed\";\n onSessionFailed(cause, e);\n const nextSessions = state\n .getState()\n .sessions.filter((s) => s.id !== sessionId);\n state.batchSet({\n sessions: nextSessions,\n });\n },\n\n muted: () => {\n emitter.emit(\"muted\", undefined);\n upsertSessionState(state, sessionId, { muted: true });\n },\n unmuted: () => {\n emitter.emit(\"unmuted\", undefined);\n upsertSessionState(state, sessionId, { muted: false });\n },\n hold: () => {\n emitter.emit(\"hold\", undefined);\n upsertSessionState(state, sessionId, { status: CallStatus.Hold });\n },\n unhold: () => {\n emitter.emit(\"unhold\", undefined);\n upsertSessionState(state, sessionId, { status: CallStatus.Active });\n },\n\n reinvite: (e: any) => emitter.emit(\"reinvite\", e),\n update: (e: any) => emitter.emit(\"update\", e),\n sdp: (e: any) => emitter.emit(\"sdp\", e),\n icecandidate: (e: any) => emitter.emit(\"icecandidate\", e),\n refer: (e: any) => emitter.emit(\"refer\", e),\n replaces: (e: any) => emitter.emit(\"replaces\", e),\n newDTMF: (e: any) => emitter.emit(\"newDTMF\", e),\n newInfo: (e: any) => emitter.emit(\"newInfo\", e),\n\n getusermediafailed: (e: any) => {\n emitter.emit(\"getusermediafailed\", e);\n detachSessionHandlers();\n rtc.cleanup();\n onSessionFailed(\"getUserMedia failed\", e);\n state.batchSet({\n sessions: state.getState().sessions.filter((s) => s.id !== sessionId),\n });\n },\n \"peerconnection:createofferfailed\": (e: any) => {\n emitter.emit(\"peerconnection:createofferfailed\", e);\n detachSessionHandlers();\n rtc.cleanup();\n onSessionFailed(\"peer connection createOffer failed\", e);\n state.batchSet({\n sessions: state.getState().sessions.filter((s) => s.id !== sessionId),\n });\n },\n \"peerconnection:createanswerfailed\": (e: any) => {\n emitter.emit(\"peerconnection:createanswerfailed\", e);\n detachSessionHandlers();\n rtc.cleanup();\n onSessionFailed(\"peer connection createAnswer failed\", e);\n state.batchSet({\n sessions: state.getState().sessions.filter((s) => s.id !== sessionId),\n });\n },\n \"peerconnection:setlocaldescriptionfailed\": (e: any) => {\n emitter.emit(\"peerconnection:setlocaldescriptionfailed\", e);\n detachSessionHandlers();\n rtc.cleanup();\n onSessionFailed(\"peer connection setLocalDescription failed\", e);\n state.batchSet({\n sessions: state.getState().sessions.filter((s) => s.id !== sessionId),\n });\n },\n \"peerconnection:setremotedescriptionfailed\": (e: any) => {\n emitter.emit(\"peerconnection:setremotedescriptionfailed\", e);\n detachSessionHandlers();\n rtc.cleanup();\n onSessionFailed(\"peer connection setRemoteDescription failed\", e);\n state.batchSet({\n sessions: state.getState().sessions.filter((s) => s.id !== sessionId),\n });\n },\n peerconnection: (e: any) => emitter.emit(\"peerconnection\", e),\n };\n}\n","import type {\r\n AnswerOptions,\r\n DTMFOptions,\r\n ReferOptions,\r\n RTCSession,\r\n TerminateOptions,\r\n} from \"./types\";\r\n\r\nexport class WebRTCSessionController {\r\n currentSession: RTCSession | null = null;\r\n mediaStream: MediaStream | null = null;\r\n\r\n public setSession(session: RTCSession | null) {\r\n this.currentSession = session;\r\n }\r\n\r\n public setMediaStream(stream: MediaStream) {\r\n this.mediaStream = stream;\r\n }\r\n\r\n private getPC(): RTCPeerConnection | null {\r\n return (this.currentSession as any)?.connection ?? null;\r\n }\r\n\r\n public cleanup(stopTracks: boolean = true): void {\r\n const pc = this.getPC();\r\n\r\n if (pc && typeof pc.getSenders === \"function\") {\r\n const isClosed =\r\n pc.connectionState === \"closed\" || pc.signalingState === \"closed\";\r\n if (!isClosed) {\r\n for (const s of pc.getSenders()) {\r\n try {\r\n s.replaceTrack(null);\r\n } catch {\r\n // ignore if sender/pc already closed\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (stopTracks && this.mediaStream) {\r\n for (const t of this.mediaStream.getTracks()) t.stop();\r\n }\r\n\r\n this.mediaStream = null;\r\n this.currentSession = null;\r\n }\r\n\r\n public answer(options: AnswerOptions = {}): boolean {\r\n return this.currentSession\r\n ? (this.currentSession.answer(options), true)\r\n : false;\r\n }\r\n\r\n public hangup(options?: TerminateOptions): boolean {\r\n return this.currentSession\r\n ? (this.currentSession.terminate(\r\n options ?? ({ status_code: 486, reason_phrase: \"Busy Here\" } as any)\r\n ),\r\n true)\r\n : false;\r\n }\r\n\r\n public mute(): boolean {\r\n this.mediaStream?.getAudioTracks().forEach((t) => (t.enabled = false));\r\n return this.currentSession\r\n ? (this.currentSession.mute({ audio: true }), true)\r\n : false;\r\n }\r\n\r\n public unmute(): boolean {\r\n this.mediaStream?.getAudioTracks().forEach((t) => (t.enabled = true));\r\n return this.currentSession\r\n ? (this.currentSession.unmute({ audio: true }), true)\r\n : false;\r\n }\r\n\r\n public hold(): boolean {\r\n return this.currentSession ? (this.currentSession.hold(), true) : false;\r\n }\r\n\r\n public unhold(): boolean {\r\n return this.currentSession ? (this.currentSession.unhold(), true) : false;\r\n }\r\n\r\n public sendDTMF(tones: string | number, options?: DTMFOptions): boolean {\r\n return this.currentSession\r\n ? (this.currentSession.sendDTMF(tones, options), true)\r\n : false;\r\n }\r\n\r\n public transfer(target: string, options?: ReferOptions): boolean {\r\n return this.currentSession\r\n ? (this.currentSession.refer(target as any, options), true)\r\n : false;\r\n }\r\n\r\n public enableVideo(): void {\r\n this.mediaStream?.getVideoTracks().forEach((t) => (t.enabled = true));\r\n }\r\n\r\n public disableVideo(): void {\r\n this.mediaStream?.getVideoTracks().forEach((t) => (t.enabled = false));\r\n }\r\n\r\n public async switchCamera(\n nextVideoTrack: MediaStreamTrack\n ): Promise<boolean> {\n const pc = this.getPC();\r\n if (!pc) return false;\r\n\r\n if (!this.mediaStream) this.mediaStream = new MediaStream();\r\n\r\n const old = this.mediaStream.getVideoTracks()[0];\r\n this.mediaStream.addTrack(nextVideoTrack);\r\n if (old) this.mediaStream.removeTrack(old);\r\n\r\n const sender = pc.getSenders?.().find((s) => s.track?.kind === \"video\");\r\n if (sender) await sender.replaceTrack(nextVideoTrack);\r\n\r\n if (old && old !== nextVideoTrack) old.stop();\r\n\r\n return true;\n }\n\n public async replaceAudioTrack(\n nextAudioTrack: MediaStreamTrack\n ): Promise<boolean> {\n const pc = this.getPC();\n if (!pc) return false;\n\n if (!this.mediaStream) this.mediaStream = new MediaStream();\n\n const old = this.mediaStream.getAudioTracks()[0];\n this.mediaStream.addTrack(nextAudioTrack);\n if (old) this.mediaStream.removeTrack(old);\n\n const sender = pc.getSenders?.().find((s) => s.track?.kind === \"audio\");\n if (sender) await sender.replaceTrack(nextAudioTrack);\n\n if (old && old !== nextAudioTrack) old.stop();\n\n return true;\n }\n}\n","import { WebRTCSessionController } from \"./sessionController\";\r\nimport type { RTCSession } from \"./types\";\r\n\r\ntype SessionEntry = {\r\n rtc: WebRTCSessionController;\r\n session?: RTCSession | null;\r\n media?: MediaStream | null;\r\n};\r\n\r\nexport class SessionManager {\r\n private entries = new Map<string, SessionEntry>();\r\n private pendingMediaQueue: Array<{ stream: MediaStream; addedAt: number }> =\r\n [];\r\n private pendingMediaTtlMs = 30000;\r\n\r\n setPendingMediaTtl(ms: number | undefined) {\r\n if (typeof ms === \"number\" && ms > 0) this.pendingMediaTtlMs = ms;\r\n }\r\n\r\n enqueueOutgoingMedia(stream: MediaStream) {\r\n this.pendingMediaQueue.push({ stream, addedAt: Date.now() });\r\n }\r\n\r\n dequeueOutgoingMedia(): MediaStream | null {\r\n const now = Date.now();\r\n while (this.pendingMediaQueue.length) {\r\n const next = this.pendingMediaQueue.shift();\r\n if (!next) break;\r\n if (now - next.addedAt <= this.pendingMediaTtlMs) {\r\n return next.stream;\r\n } else {\r\n // drop stale stream\r\n next.stream.getTracks().forEach((t) => t.stop());\r\n }\r\n }\r\n return null;\r\n }\r\n\r\n getOrCreateRtc(sessionId: string, session?: RTCSession) {\r\n let entry = this.entries.get(sessionId);\r\n if (!entry) {\r\n entry = {\r\n rtc: new WebRTCSessionController(),\r\n session: null,\r\n media: null,\r\n };\r\n this.entries.set(sessionId, entry);\r\n }\r\n if (session) {\r\n entry.session = session;\r\n entry.rtc.setSession(session);\r\n }\r\n if (entry.media) entry.rtc.setMediaStream(entry.media);\r\n return entry.rtc;\r\n }\r\n\r\n getRtc(sessionId: string) {\r\n return this.entries.get(sessionId)?.rtc ?? null;\r\n }\r\n\r\n setSession(sessionId: string, session: RTCSession) {\r\n const entry = this.entries.get(sessionId);\r\n if (entry) {\r\n entry.session = session;\r\n entry.rtc.setSession(session);\r\n } else {\r\n this.entries.set(sessionId, {\r\n rtc: new WebRTCSessionController(),\r\n session,\r\n media: null,\r\n });\r\n }\r\n }\r\n\r\n setSessionMedia(sessionId: string, stream: MediaStream) {\r\n const entry = this.entries.get(sessionId) ?? {\r\n rtc: new WebRTCSessionController(),\r\n session: null,\r\n media: null,\r\n };\r\n entry.media = stream;\r\n entry.rtc.setMediaStream(stream);\r\n this.entries.set(sessionId, entry);\r\n }\r\n\r\n getSession(sessionId: string) {\r\n return this.entries.get(sessionId)?.session ?? null;\r\n }\r\n\r\n getSessionIds() {\r\n return Array.from(this.entries.keys());\r\n }\r\n\r\n getSessions() {\r\n return Array.from(this.entries.entries()).map(([id, entry]) => ({\r\n id,\r\n session: entry.session as RTCSession,\r\n }));\r\n }\r\n\r\n getActiveSessionId(activeStatuses: string[] = [\"active\"]): string | null {\r\n for (const [id, entry] of Array.from(this.entries.entries()).reverse()) {\r\n const status = (entry.session as any)?.status;\r\n if (status && activeStatuses.includes(String(status).toLowerCase())) {\r\n return id;\r\n }\r\n }\r\n return null;\r\n }\r\n\r\n cleanupSession(sessionId: string) {\r\n const entry = this.entries.get(sessionId);\r\n if (entry) {\r\n entry.rtc.cleanup();\r\n this.entries.delete(sessionId);\r\n }\r\n }\r\n\r\n cleanupAllSessions() {\r\n for (const [, entry] of this.entries.entries()) {\r\n entry.rtc.cleanup();\r\n }\r\n this.entries.clear();\r\n this.pendingMediaQueue = [];\r\n }\r\n\r\n answer(sessionId: string, options: any) {\r\n const rtc = this.getRtc(sessionId);\r\n return rtc ? rtc.answer(options) : false;\r\n }\r\n\r\n hangup(sessionId: string, options?: any) {\r\n const rtc = this.getRtc(sessionId);\r\n return rtc ? rtc.hangup(options) : false;\r\n }\r\n\r\n mute(sessionId: string) {\r\n const rtc = this.getRtc(sessionId);\r\n return rtc ? rtc.mute() : false;\r\n }\r\n\r\n unmute(sessionId: string) {\r\n const rtc = this.getRtc(sessionId);\r\n return rtc ? rtc.unmute() : false;\r\n }\r\n\r\n hold(sessionId: string) {\r\n const rtc = this.getRtc(sessionId);\r\n return rtc ? rtc.hold() : false;\r\n }\r\n\r\n unhold(sessionId: string) {\r\n const rtc = this.getRtc(sessionId);\r\n return rtc ? rtc.unhold() : false;\r\n }\r\n\r\n sendDTMF(sessionId: string, tones: string | number, options?: any) {\r\n const rtc = this.getRtc(sessionId);\r\n return rtc ? rtc.sendDTMF(tones, options) : false;\r\n }\r\n\r\n transfer(sessionId: string, target: string, options?: any) {\r\n const rtc = this.getRtc(sessionId);\r\n return rtc ? rtc.transfer(target, options) : false;\r\n }\r\n}\r\n","import { SipStateStore } from \"../core/sipStateStore\";\r\nimport { CallDirection, CallStatus } from \"../core/types\";\r\nimport { SessionManager } from \"./sessionManager\";\r\nimport { holdOtherSessions, upsertSessionState } from \"./sessionState\";\r\nimport type { JsSIPEventName, RTCSession, RTCSessionEvent } from \"./types\";\r\nimport type { SipErrorPayload } from \"../core/sipErrorHandler\";\r\n\r\ntype Deps = {\r\n state: SipStateStore;\r\n sessionManager: SessionManager;\r\n emit: <K extends JsSIPEventName>(event: K, payload: any) => void;\r\n emitError: (raw: any, code?: string, fallback?: string) => SipErrorPayload;\r\n attachSessionHandlers: (sessionId: string, session: RTCSession) => void;\r\n getMaxSessionCount: () => number;\r\n};\r\n\r\nexport class SessionLifecycle {\r\n private readonly state: SipStateStore;\r\n private readonly sessionManager: SessionManager;\r\n private readonly emit: Deps[\"emit\"];\r\n private readonly emitError: Deps[\"emitError\"];\r\n private readonly attachSessionHandlers: Deps[\"attachSessionHandlers\"];\r\n private readonly getMaxSessionCount: Deps[\"getMaxSessionCount\"];\r\n\r\n constructor(deps: Deps) {\r\n this.state = deps.state;\r\n this.sessionManager = deps.sessionManager;\r\n this.emit = deps.emit;\r\n this.emitError = deps.emitError;\r\n this.attachSessionHandlers = deps.attachSessionHandlers;\r\n this.getMaxSessionCount = deps.getMaxSessionCount;\r\n }\r\n\r\n handleNewRTCSession(e: RTCSessionEvent) {\r\n const session = e.session;\r\n const sessionId = String((session as any)?.id ?? crypto.randomUUID?.() ?? Date.now());\r\n\r\n const currentSessions = this.state.getState().sessions;\r\n if (currentSessions.length >= this.getMaxSessionCount()) {\r\n try {\r\n session.terminate?.({ status_code: 486, reason_phrase: \"Busy Here\" } as any);\r\n } catch {\r\n /* ignore termination errors */\r\n }\r\n if (e.originator === \"remote\") {\r\n this.emit(\"missed\", e);\r\n }\r\n this.emitError(\"max session count reached\", \"MAX_SESSIONS_REACHED\", \"max session count reached\");\r\n return;\r\n }\r\n\r\n const outgoingMedia = e.originator === \"local\" ? this.sessionManager.dequeueOutgoingMedia() : null;\r\n\r\n if (outgoingMedia) this.sessionManager.setSessionMedia(sessionId, outgoingMedia);\r\n\r\n const rtc = this.sessionManager.getOrCreateRtc(sessionId, session);\r\n if (outgoingMedia) rtc.setMediaStream(outgoingMedia);\r\n\r\n this.sessionManager.setSession(sessionId, session);\r\n this.attachSessionHandlers(sessionId, session);\r\n\r\n holdOtherSessions(\r\n this.state,\r\n sessionId,\r\n (id) => {\r\n const otherRtc = this.sessionManager.getRtc(id);\r\n otherRtc?.hold();\r\n }\r\n );\r\n\r\n const sdpHasVideo =\r\n (e.request?.body && e.request.body.toString().includes(\"m=video\")) ||\r\n (session as RTCSession & { connection?: RTCPeerConnection })?.connection\r\n ?.getReceivers?.()\r\n ?.some((r: RTCRtpReceiver) => r.track?.kind === \"video\");\r\n\r\n upsertSessionState(this.state, sessionId, {\r\n direction: e.originator,\r\n from: e.originator === \"remote\" ? e.request.from.uri.user : null,\r\n to: e.request.to.uri.user,\r\n status: e.originator === \"remote\" ? CallStatus.Ringing : CallStatus.Dialing,\r\n mediaKind: sdpHasVideo ? \"video\" : \"audio\",\r\n remoteVideoEnabled: sdpHasVideo,\r\n });\r\n\r\n this.emit(\"newRTCSession\", e);\r\n }\r\n}\r\n","import { SipUserAgent } from \"./userAgent\";\r\nimport {\r\n AnswerOptions,\r\n CallOptions,\r\n DTMFOptions,\r\n JsSIPEventMap,\r\n ReferOptions,\r\n RTCSession,\r\n RTCSessionEvent,\r\n RTCSessionEventMap,\r\n SipConfiguration,\r\n SipEventManager,\r\n TerminateOptions,\r\n UAEventMap,\r\n} from \"./types\";\r\n\r\nimport { SipState, SipStatus, CallStatus } from \"../core/types\";\r\nimport { EventTargetEmitter } from \"../core/eventEmitter\";\r\nimport {\r\n SipErrorHandler,\r\n SipErrorFormatter,\r\n SipErrorPayload,\r\n} from \"../core/sipErrorHandler\";\r\nimport { SipStateStore } from \"../core/sipStateStore\";\r\nimport { createUAHandlers } from \"./handlers/uaHandlers\";\r\nimport { createSessionHandlers } from \"./handlers/sessionHandlers\";\r\nimport { SessionManager } from \"./sessionManager\";\r\nimport { removeSessionState } from \"./sessionState\";\r\nimport { SessionLifecycle } from \"./sessionLifecycle\";\r\n\r\ntype SipClientOptions = {\r\n errorMessages?: Record<string, string>;\r\n formatError?: SipErrorFormatter;\r\n errorHandler?: SipErrorHandler;\r\n debug?: boolean | string;\r\n};\r\n\r\nexport type MicrophoneRecoveryOptions = {\r\n intervalMs?: number;\r\n maxRetries?: number;\r\n};\r\n\r\nconst SESSION_DEBUG_KEY = \"sip-debug-enabled\";\r\n\r\nexport class SipClient extends EventTargetEmitter<JsSIPEventMap> {\r\n public readonly userAgent = new SipUserAgent();\r\n public readonly stateStore = new SipStateStore();\r\n\r\n private readonly uaHandlers: Partial<UAEventMap>;\r\n private readonly uaHandlerKeys: (keyof UAEventMap)[];\r\n private sessionHandlers = new Map<string, Partial<RTCSessionEventMap>>();\r\n private readonly errorHandler: SipErrorHandler;\r\n private debugPattern?: boolean | string;\r\n private maxSessionCount = Infinity;\r\n private sessionManager = new SessionManager();\r\n private lifecycle: SessionLifecycle;\r\n private micRecovery = new Map<string, { stop: () => void }>();\r\n private micRecoveryEnabled = false;\r\n private micRecoveryDefaults: Required<MicrophoneRecoveryOptions> = {\r\n intervalMs: 2000,\r\n maxRetries: Infinity,\r\n };\r\n private unloadHandler?: () => void;\r\n private stateLogOff?: () => void;\r\n\r\n public get state(): SipState {\r\n return this.stateStore.getState();\r\n }\r\n\r\n constructor(options: SipClientOptions = {}) {\r\n super();\r\n\r\n this.errorHandler =\r\n options.errorHandler ??\r\n new SipErrorHandler({\r\n formatter: options.formatError,\r\n messages: options.errorMessages,\r\n });\r\n this.debugPattern = options.debug;\r\n\r\n this.uaHandlers = createUAHandlers({\r\n emitter: this,\r\n state: this.stateStore,\r\n cleanupAllSessions: () => this.cleanupAllSessions(),\r\n emitError: (raw, code, fallback) => this.emitError(raw, code, fallback),\r\n onNewRTCSession: (e: RTCSessionEvent) => this.onNewRTCSession(e),\r\n });\r\n\r\n this.uaHandlerKeys = Object.keys(this.uaHandlers) as (keyof UAEventMap)[];\r\n\r\n this.lifecycle = new SessionLifecycle({\r\n state: this.stateStore,\r\n sessionManager: this.sessionManager,\r\n emit: (event, payload) => this.emit(event as any, payload as any),\r\n emitError: (raw, code, fallback) => this.emitError(raw, code, fallback),\r\n attachSessionHandlers: (sessionId, session) =>\r\n this.attachSessionHandlers(sessionId, session),\r\n getMaxSessionCount: () => this.maxSessionCount,\r\n });\r\n\r\n if (typeof window !== \"undefined\") {\r\n // Let window.sipSupport trigger client debug toggles.\r\n (window as any).sipDebugBridge = (debug?: boolean | string) =>\r\n this.setDebug(debug ?? true);\r\n }\r\n }\r\n\r\n public connect(uri: string, password: string, config: SipConfiguration) {\r\n this.disconnect();\r\n this.stateStore.setState({ sipStatus: SipStatus.Connecting });\r\n const {\r\n debug: cfgDebug,\r\n enableMicRecovery,\r\n micRecoveryIntervalMs,\r\n micRecoveryMaxRetries,\r\n maxSessionCount,\r\n pendingMediaTtlMs,\r\n ...uaCfg\r\n } = config;\r\n this.maxSessionCount =\r\n typeof maxSessionCount === \"number\" ? maxSessionCount : Infinity;\r\n this.micRecoveryEnabled = Boolean(enableMicRecovery);\r\n if (typeof micRecoveryIntervalMs === \"number\") {\r\n this.micRecoveryDefaults.intervalMs = micRecoveryIntervalMs;\r\n }\r\n if (typeof micRecoveryMaxRetries === \"number\") {\r\n this.micRecoveryDefaults.maxRetries = micRecoveryMaxRetries;\r\n }\r\n this.sessionManager.setPendingMediaTtl(pendingMediaTtlMs);\r\n // Config debug has priority, then persisted session flag, then prior setting.\r\n const debug = cfgDebug ?? this.getPersistedDebug() ?? this.debugPattern;\r\n this.userAgent.start(uri, password, uaCfg, { debug });\r\n this.attachUAHandlers();\r\n this.attachBeforeUnload();\r\n this.syncDebugInspector(debug);\r\n }\r\n\r\n public registerUA() {\r\n this.userAgent.register();\r\n }\r\n\r\n public disconnect() {\r\n this.detachBeforeUnload();\r\n this.detachUAHandlers();\r\n this.userAgent.stop();\r\n this.cleanupAllSessions();\r\n this.stateStore.reset();\r\n }\r\n\r\n public call(target: string, callOptions: CallOptions = {}) {\r\n try {\r\n const opts = this.ensureMediaConstraints(callOptions);\r\n if (opts.mediaStream)\r\n this.sessionManager.enqueueOutgoingMedia(opts.mediaStream);\r\n\r\n const ua = this.userAgent.getUA();\r\n ua?.call(target, opts);\r\n } catch (e: unknown) {\r\n const err = this.emitError(e, \"CALL_FAILED\", \"call failed\");\r\n this.cleanupAllSessions();\r\n this.stateStore.batchSet({\r\n error: err.cause,\r\n });\r\n }\r\n }\r\n\r\n public answer(sessionId: string, options: AnswerOptions = {}) {\r\n const resolved = this.resolveExistingSessionId(sessionId);\r\n if (!resolved) return false;\r\n return this.answerSession(resolved, options);\r\n }\r\n public hangup(sessionId: string, options?: TerminateOptions) {\r\n const resolved = this.resolveExistingSessionId(sessionId);\r\n if (!resolved) return false;\r\n return this.hangupSession(resolved, options);\r\n }\r\n\r\n public hangupAll(options?: TerminateOptions) {\r\n const ids = this.getSessionIds();\r\n ids.forEach((id) => this.hangupSession(id, options));\r\n return ids.length > 0;\r\n }\r\n\r\n public toggleMute(sessionId: string) {\r\n return this.toggleMuteSession(sessionId);\r\n }\r\n public toggleHold(sessionId: string) {\r\n return this.toggleHoldSession(sessionId);\r\n }\r\n public sendDTMF(\r\n sessionId: string,\r\n tones: string | number,\r\n options?: DTMFOptions\r\n ) {\r\n return this.sendDTMFSession(sessionId, tones, options);\r\n }\r\n public transfer(sessionId: string, target: string, options?: ReferOptions) {\r\n return this.transferSession(sessionId, target, options);\r\n }\r\n\r\n public onChange(fn: (s: SipState) => void) {\r\n return this.stateStore.onChange(fn);\r\n }\r\n\r\n private attachUAHandlers() {\r\n const ua = this.userAgent.ua;\r\n if (!ua) return;\r\n\r\n this.detachUAHandlers();\r\n this.uaHandlerKeys.forEach((ev) => {\r\n const h = this.uaHandlers[ev];\r\n if (h) ua.on(ev, h as any);\r\n });\r\n }\r\n\r\n public setDebug(debug?: boolean | string) {\r\n this.debugPattern = debug;\r\n this.userAgent.setDebug(debug);\r\n this.syncDebugInspector(debug);\r\n }\r\n\r\n private attachSessionHandlers(sessionId: string, session: RTCSession) {\r\n const handlers = this.createSessionHandlersFor(sessionId, session);\r\n this.sessionHandlers.set(sessionId, handlers);\r\n\r\n (Object.keys(handlers) as (keyof RTCSessionEventMap)[]).forEach((ev) => {\r\n const h = handlers[ev];\r\n if (h) session.on(ev, h as any);\r\n });\r\n }\r\n\r\n private detachSessionHandlers(sessionId: string, session: RTCSession) {\r\n const handlers = this.sessionHandlers.get(sessionId);\r\n if (!handlers || !session) return;\r\n (Object.keys(handlers) as (keyof RTCSessionEventMap)[]).forEach((ev) => {\r\n const h = handlers[ev];\r\n if (h) session.off(ev, h as any);\r\n });\r\n this.sessionHandlers.delete(sessionId);\r\n }\r\n\r\n private detachUAHandlers() {\r\n const ua = this.userAgent.ua;\r\n if (!ua) return;\r\n this.uaHandlerKeys.forEach((ev) => {\r\n const h = this.uaHandlers[ev];\r\n if (h) ua.off(ev, h as any);\r\n });\r\n }\r\n\r\n private cleanupSession(sessionId: string, session?: RTCSession) {\r\n const targetSession =\r\n session ??\r\n this.sessionManager.getSession(sessionId) ??\r\n this.sessionManager.getRtc(sessionId)?.currentSession;\r\n this.detachSessionHandlers(sessionId, targetSession as any);\r\n this.disableMicrophoneRecovery(sessionId);\r\n this.sessionManager.cleanupSession(sessionId);\r\n removeSessionState(this.stateStore, sessionId);\r\n }\r\n\r\n private cleanupAllSessions() {\r\n this.sessionManager.cleanupAllSessions();\r\n this.micRecovery.forEach((entry) => entry.stop());\r\n this.micRecovery.clear();\r\n this.sessionHandlers.clear();\r\n this.stateStore.setState({\r\n sessions: [],\r\n error: null,\r\n });\r\n }\r\n\r\n private createSessionHandlersFor(\r\n sessionId: string,\r\n session: RTCSession\r\n ): Partial<RTCSessionEventMap> {\r\n const rtc = this.sessionManager.getOrCreateRtc(sessionId, session);\r\n return createSessionHandlers({\r\n emitter: this,\r\n state: this.stateStore,\r\n rtc,\r\n detachSessionHandlers: () => this.cleanupSession(sessionId, session),\r\n emitError: (raw, code, fallback) => this.emitError(raw, code, fallback),\r\n onSessionFailed: (err?: string, event?: RTCSessionEvent) =>\r\n this.onSessionFailed(err, event),\r\n onSessionAccepted: (acceptedSessionId) => {\n if (this.micRecoveryEnabled) {\n this.enableMicrophoneRecovery(acceptedSessionId);\n }\n },\n sessionId,\r\n });\r\n }\r\n\r\n protected onNewRTCSession(e: RTCSessionEvent) {\r\n this.lifecycle.handleNewRTCSession(e);\r\n }\r\n\r\n protected onSessionFailed(error?: string, event?: RTCSessionEvent) {\r\n const rawCause = (event as any)?.cause ?? error;\r\n const statusCode = (event as any)?.message?.status_code;\r\n const statusText = (event as any)?.message?.reason_phrase;\r\n const causeText =\r\n rawCause ||\r\n (statusCode\r\n ? `${statusCode}${statusText ? \" \" + statusText : \"\"}`\r\n : \"call failed\");\r\n this.emitError(\r\n { raw: event, cause: rawCause, statusCode, statusText },\r\n \"SESSION_FAILED\",\r\n causeText\r\n );\r\n }\r\n\r\n private emitError(\r\n raw: unknown,\r\n code?: string,\r\n fallback?: string\r\n ): SipErrorPayload {\r\n const payload = this.errorHandler.format({ raw, code, fallback });\r\n this.emit(\"error\", payload);\r\n return payload;\r\n }\r\n\r\n private resolveSessionId(sessionId?: string) {\r\n if (sessionId) return sessionId;\r\n const sessions = this.stateStore.getState().sessions;\r\n const active = sessions.find((s) => s.status === CallStatus.Active);\r\n return active?.id ?? sessions[0]?.id ?? null;\r\n }\r\n\r\n private sessionExists(sessionId: string) {\r\n return (\r\n !!this.sessionManager.getSession(sessionId) ||\r\n !!this.sessionManager.getRtc(sessionId)\r\n );\r\n }\r\n\r\n private resolveExistingSessionId(sessionId?: string) {\r\n const id = this.resolveSessionId(sessionId);\r\n if (!id) return null;\r\n return this.sessionExists(id) ? id : null;\r\n }\r\n\r\n private ensureMediaConstraints<\r\n T extends {\r\n mediaStream?: MediaStream;\r\n mediaConstraints?: MediaStreamConstraints;\r\n }\r\n >(opts: T): T {\r\n if (opts.mediaStream || opts.mediaConstraints) return opts;\r\n return { ...opts, mediaConstraints: { audio: true, video: false } } as T;\r\n }\r\n\r\n public answerSession(sessionId: string, options: AnswerOptions = {}) {\r\n if (!sessionId || !this.sessionExists(sessionId)) return false;\r\n const opts = this.ensureMediaConstraints(options);\r\n if (opts.mediaStream) {\r\n this.sessionManager.setSessionMedia(sessionId, opts.mediaStream);\r\n }\r\n return this.sessionManager.answer(sessionId, opts);\r\n }\r\n\r\n public hangupSession(sessionId: string, options?: TerminateOptions) {\r\n if (!sessionId || !this.sessionExists(sessionId)) return false;\r\n return this.sessionManager.hangup(sessionId, options);\r\n }\r\n\r\n public toggleMuteSession(sessionId?: string) {\r\n const resolved = this.resolveExistingSessionId(sessionId);\r\n if (!resolved) return false;\r\n const sessionState = this.stateStore\r\n .getState()\r\n .sessions.find((s) => s.id === resolved);\r\n const muted = sessionState?.muted ?? false;\r\n if (muted) {\r\n this.sessionManager.unmute(resolved);\r\n return true;\r\n }\r\n this.sessionManager.mute(resolved);\r\n return true;\r\n }\r\n\r\n public toggleHoldSession(sessionId?: string) {\r\n const resolved = this.resolveExistingSessionId(sessionId);\r\n if (!resolved) return false;\r\n const sessionState = this.stateStore\r\n .getState()\r\n .sessions.find((s) => s.id === resolved);\r\n const isOnHold = sessionState?.status === CallStatus.Hold;\r\n if (isOnHold) {\r\n this.sessionManager.unhold(resolved);\r\n return true;\r\n }\r\n if (sessionState?.status === CallStatus.Active) {\r\n this.sessionManager.hold(resolved);\r\n return true;\r\n }\r\n return true;\r\n }\r\n\r\n public sendDTMFSession(\r\n sessionId: string,\r\n tones: string | number,\r\n options?: DTMFOptions\r\n ) {\r\n const resolved = this.resolveExistingSessionId(sessionId);\r\n if (!resolved) return false;\r\n const sessionState = this.stateStore\r\n .getState()\r\n .sessions.find((s) => s.id === resolved);\r\n if (sessionState?.status === CallStatus.Active)\r\n this.sessionManager.sendDTMF(resolved, tones, options);\r\n return true;\r\n }\r\n\r\n public transferSession(\r\n sessionId: string,\r\n target: string,\r\n options?: ReferOptions\r\n ) {\r\n const resolved = this.resolveExistingSessionId(sessionId);\r\n if (!resolved) return false;\r\n const sessionState = this.stateStore\r\n .getState()\r\n .sessions.find((s) => s.id === resolved);\r\n if (sessionState?.status === CallStatus.Active)\r\n this.sessionManager.transfer(resolved, target, options);\r\n return true;\r\n }\r\n\r\n public setSessionMedia(sessionId: string, stream: MediaStream) {\r\n this.sessionManager.setSessionMedia(sessionId, stream);\r\n }\r\n\r\n public enableMicrophoneRecovery(\r\n sessionId: string,\r\n options: MicrophoneRecoveryOptions = {}\r\n ) {\r\n const resolved = this.resolveExistingSessionId(sessionId);\r\n if (!resolved) return () => {};\r\n\r\n this.disableMicrophoneRecovery(resolved);\r\n\r\n const intervalMs =\r\n options.intervalMs ?? this.micRecoveryDefaults.intervalMs;\r\n const maxRetries =\r\n options.maxRetries ?? this.micRecoveryDefaults.maxRetries;\r\n let retries = 0;\n let stopped = false;\n const startedAt = Date.now();\n const warmupMs = Math.max(intervalMs * 2, 2000);\n\r\n const tick = async () => {\r\n if (stopped || retries >= maxRetries) return;\r\n\r\n const rtc = this.sessionManager.getRtc(resolved);\r\n const session = this.sessionManager.getSession(resolved);\r\n if (!rtc || !session) return;\r\n\r\n const sessionState = this.stateStore\r\n .getState()\r\n .sessions.find((s) => s.id === resolved);\r\n if (sessionState?.muted) return;\r\n\r\n const stream = rtc.mediaStream;\n const track = stream?.getAudioTracks?.()[0];\n const pc: RTCPeerConnection | undefined = (session as any)?.connection;\n const sender = pc\n ?.getSenders?.()\n .find((s: RTCRtpSender) => s.track?.kind === \"audio\");\n\n if (!track && !sender) return;\n\n if (Date.now() - startedAt < warmupMs) return;\n if (\n pc?.connectionState === \"new\" ||\n pc?.connectionState === \"connecting\" ||\n pc?.iceConnectionState === \"new\" ||\n pc?.iceConnectionState === \"checking\"\n ) {\n return;\n }\n\n const trackLive = track?.readyState === \"live\";\n const senderLive = sender?.track?.readyState === \"live\";\n if (trackLive && senderLive) return;\n\r\n this.emitError(\r\n {\r\n cause: \"microphone dropped\",\r\n trackLive,\r\n senderLive,\r\n },\r\n \"MICROPHONE_DROPPED\",\r\n \"microphone dropped\"\r\n );\r\n\r\n retries += 1;\r\n if (trackLive && !senderLive && track) {\r\n await rtc.replaceAudioTrack(track);\r\n return;\r\n }\r\n\r\n let nextStream: MediaStream;\r\n try {\r\n const deviceId =\r\n track?.getSettings?.().deviceId ??\r\n sender?.track?.getSettings?.().deviceId;\r\n nextStream = await this.requestMicrophoneStreamInternal(deviceId);\r\n } catch (err) {\r\n console.warn(\"[sip] mic recovery failed to get stream\", err);\r\n return;\r\n }\r\n const nextTrack = nextStream.getAudioTracks()[0];\r\n if (!nextTrack) return;\r\n\r\n await rtc.replaceAudioTrack(nextTrack);\r\n this.sessionManager.setSessionMedia(resolved, nextStream);\r\n };\r\n\r\n const timer = setInterval(() => {\r\n void tick();\r\n }, intervalMs);\r\n void tick();\r\n\r\n const session = this.sessionManager.getSession(resolved);\r\n const pc: RTCPeerConnection | undefined = (session as any)?.connection;\r\n const onIceChange = () => {\r\n const state = pc?.iceConnectionState;\r\n if (state === \"failed\" || state === \"disconnected\") void tick();\r\n };\r\n pc?.addEventListener?.(\"iceconnectionstatechange\", onIceChange);\r\n\r\n const stop = () => {\r\n stopped = true;\r\n clearInterval(timer);\r\n pc?.removeEventListener?.(\"iceconnectionstatechange\", onIceChange);\r\n };\r\n this.micRecovery.set(resolved, { stop });\r\n return stop;\r\n }\r\n\r\n public disableMicrophoneRecovery(sessionId: string) {\r\n const resolved = this.resolveExistingSessionId(sessionId);\r\n if (!resolved) return false;\r\n const entry = this.micRecovery.get(resolved);\r\n if (!entry) return false;\r\n entry.stop();\r\n this.micRecovery.delete(resolved);\r\n return true;\r\n }\r\n\r\n public switchCameraSession(sessionId: string, track: MediaStreamTrack) {\r\n if (!this.sessionExists(sessionId)) return false;\r\n const rtc = this.sessionManager.getRtc(sessionId);\r\n return rtc ? rtc.switchCamera(track) : false;\r\n }\r\n\r\n public enableVideoSession(sessionId: string) {\r\n if (!this.sessionExists(sessionId)) return false;\r\n const rtc = this.sessionManager.getRtc(sessionId);\r\n rtc?.enableVideo();\r\n return !!rtc;\r\n }\r\n\r\n public disableVideoSession(sessionId: string) {\r\n if (!this.sessionExists(sessionId)) return false;\r\n const rtc = this.sessionManager.getRtc(sessionId);\r\n rtc?.disableVideo();\r\n return !!rtc;\r\n }\r\n\r\n public getSession(sessionId: string) {\r\n return this.sessionManager.getSession(sessionId);\r\n }\r\n\r\n public getSessionIds() {\r\n return this.sessionManager.getSessionIds();\r\n }\r\n\r\n public getSessions() {\r\n return this.sessionManager.getSessions();\r\n }\r\n\r\n private attachBeforeUnload() {\r\n if (typeof window === \"undefined\" || this.unloadHandler) return;\r\n\r\n const handler = () => {\r\n this.hangupAll();\r\n this.disconnect();\r\n };\r\n\r\n window.addEventListener(\"beforeunload\", handler);\r\n this.unloadHandler = handler;\r\n }\r\n\r\n private detachBeforeUnload() {\r\n if (typeof window === \"undefined\" || !this.unloadHandler) return;\r\n window.removeEventListener(\"beforeunload\", this.unloadHandler);\r\n this.unloadHandler = undefined;\r\n }\r\n\r\n private syncDebugInspector(debug?: boolean | string) {\r\n if (typeof window === \"undefined\") return;\r\n this.toggleStateLogger(Boolean(debug));\r\n\r\n const win = window as any;\r\n const disabledInspector = () => {\r\n console.warn(\"SIP debug inspector disabled; enable debug to inspect.\");\r\n return null;\r\n };\r\n win.sipState = () =>\r\n debug ? this.stateStore.getState() : disabledInspector();\r\n win.sipSessions = () => (debug ? this.getSessions() : disabledInspector());\r\n }\r\n\r\n private toggleStateLogger(enabled: boolean) {\r\n if (!enabled) {\r\n this.stateLogOff?.();\r\n this.stateLogOff = undefined;\r\n return;\r\n }\r\n if (this.stateLogOff) return;\r\n\r\n let prev = this.stateStore.getState();\r\n // Emit initial snapshot right away for visibility.\r\n console.info(\"[sip][state]\", { initial: true }, prev);\r\n\r\n this.stateLogOff = this.stateStore.onChange((next) => {\r\n const changes = this.diffState(prev, next);\r\n if (changes) {\r\n // Log concise diff and the current snapshot for quick inspection.\r\n console.info(\"[sip][state]\", changes, next);\r\n }\r\n prev = next;\r\n });\r\n }\r\n\r\n private diffState(\r\n prev: SipState,\r\n next: SipState\r\n ): Record<string, { from: unknown; to: unknown }> | null {\r\n const changed: Record<string, { from: unknown; to: unknown }> = {};\r\n for (const key of Object.keys(next) as Array<keyof SipState>) {\r\n if (prev[key] !== next[key]) {\r\n changed[key as string] = { from: prev[key], to: next[key] };\r\n }\r\n }\r\n return Object.keys(changed).length ? changed : null;\r\n }\r\n\r\n private getPersistedDebug(): boolean | string | undefined {\r\n if (typeof window === \"undefined\") return undefined;\r\n try {\r\n const persisted = window.sessionStorage.getItem(SESSION_DEBUG_KEY);\r\n if (!persisted) return undefined;\r\n return persisted;\r\n } catch {\r\n return undefined;\r\n }\r\n }\r\n\r\n private async requestMicrophoneStreamInternal(\r\n deviceId?: string\r\n ): Promise<MediaStream> {\r\n if (\r\n typeof navigator === \"undefined\" ||\r\n !navigator.mediaDevices?.getUserMedia\r\n ) {\r\n throw new Error(\"getUserMedia not available\");\r\n }\r\n const audio =\r\n deviceId && deviceId !== \"default\"\r\n ? { deviceId: { exact: deviceId } }\r\n : true;\r\n try {\r\n return await navigator.mediaDevices.getUserMedia({ audio });\r\n } catch (err: any) {\r\n const cause = err?.name || \"getUserMedia failed\";\r\n this.emitError(\r\n { raw: err, cause },\r\n \"MICROPHONE_UNAVAILABLE\",\r\n \"microphone unavailable\"\r\n );\r\n throw err;\r\n }\r\n }\r\n}\r\n\r\nexport function createSipClientInstance(options?: SipClientOptions): SipClient {\r\n return new SipClient(options);\r\n}\r\n\r\nexport function createSipEventManager(client: SipClient): SipEventManager {\r\n return {\r\n onUA(event, handler) {\r\n return client.on(event, handler as any);\r\n },\r\n onSession(sessionId, event, handler) {\r\n const session = client.getSession(sessionId);\r\n if (!session) return () => {};\r\n session.on(event as any, handler as any);\r\n return () => session.off(event as any, handler as any);\r\n },\r\n };\r\n}\r\n","import \"./sip/debugger\"; // ensure window helpers attach on load\r\n\r\nexport * from \"./sip/types\";\r\n\r\nexport {\n SipClient,\n type MicrophoneRecoveryOptions,\n createSipClientInstance,\n createSipEventManager,\n} from \"./sip/client\";\nexport {\r\n SipDebugger,\r\n sipDebugger,\r\n type SipDebugToggleResult,\r\n} from \"./sip/debugger\";\r\n\r\nexport { WebRTCSessionController } from \"./sip/sessionController\";\r\nexport { SessionManager } from \"./sip/sessionManager\";\r\n\r\nexport {\r\n SipErrorHandler,\r\n type SipErrorPayload,\r\n type SipErrorFormatter,\r\n} from \"./core/sipErrorHandler\";\r\n\r\nexport { WebSocketInterface } from \"jssip\";\r\n\r\nexport {\r\n SipStatus,\r\n CallStatus,\r\n CallDirection,\r\n SipStatusList,\r\n CallStatusList,\r\n isSipStatus,\r\n isCallStatus,\r\n} from \"./core/types\";\r\n\r\nexport type {\r\n SipStatus as SipStatusType,\r\n CallStatus as CallStatusType,\r\n CallDirection as CallDirectionType,\r\n SipState,\r\n SipSessionState,\r\n} from \"./core/types\";\r\n","import { createContext } from \"react\";\r\nimport type { SipClient } from \"jssip-lib\";\r\nimport type { SipEventManager } from \"jssip-lib\";\r\n\r\nexport type SipContextType = { client: SipClient, sipEventManager: SipEventManager };\r\nexport const SipContext = createContext<SipContextType | null>(null);\r\n","import { useCallback, useSyncExternalStore } from \"react\";\r\nimport type { SipState } from \"jssip-lib\";\r\nimport { useSip } from \"./useSip\";\r\n\r\nexport function useSipState(): SipState {\r\n const { client } = useSip();\r\n const subscribe = useCallback(\r\n (onStoreChange: () => void) => client.onChange(onStoreChange),\r\n [client]\r\n );\r\n\r\n const getSnapshot = useCallback(() => client.state, [client]);\r\n\r\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\r\n}\r\n","import { useContext } from \"react\";\r\nimport { SipContext } from \"../context\";\r\n\r\nexport function useSip() {\r\n const ctx = useContext(SipContext);\r\n if (!ctx) throw new Error(\"Must be used within SipProvider\");\r\n return ctx;\r\n}\r\n","import { useMemo } from \"react\";\nimport { useSip } from \"./useSip\";\n\nexport function useSipActions() {\n const { client } = useSip();\n return useMemo(\n () => ({\n call: (...args: Parameters<typeof client.call>) => client.call(...args),\n answer: (...args: Parameters<typeof client.answerSession>) =>\n client.answerSession(...args),\n hangup: (...args: Parameters<typeof client.hangupSession>) =>\n client.hangupSession(...args),\n toggleMute: (...args: Parameters<typeof client.toggleMuteSession>) =>\n client.toggleMuteSession(...args),\n toggleHold: (...args: Parameters<typeof client.toggleHoldSession>) =>\n client.toggleHoldSession(...args),\n sendDTMF: (...args: Parameters<typeof client.sendDTMFSession>) =>\n client.sendDTMFSession(...args),\n transfer: (...args: Parameters<typeof client.transferSession>) =>\n client.transferSession(...args),\n getSession: (...args: Parameters<typeof client.getSession>) =>\n client.getSession(...args),\n getSessionIds: () => client.getSessionIds(),\n getSessions: () => client.getSessions(),\n setSessionMedia: (...args: Parameters<typeof client.setSessionMedia>) =>\n client.setSessionMedia(...args),\n enableMicrophoneRecovery: (\n ...args: Parameters<typeof client.enableMicrophoneRecovery>\n ) => client.enableMicrophoneRecovery(...args),\n disableMicrophoneRecovery: (\n ...args: Parameters<typeof client.disableMicrophoneRecovery>\n ) => client.disableMicrophoneRecovery(...args),\n switchCamera: (...args: Parameters<typeof client.switchCameraSession>) =>\n client.switchCameraSession(...args),\n enableVideo: (...args: Parameters<typeof client.enableVideoSession>) =>\n client.enableVideoSession(...args),\n disableVideo: (...args: Parameters<typeof client.disableVideoSession>) =>\n client.disableVideoSession(...args),\n }),\n [client]\n );\n}\n","import type { SipState } from \"jssip-lib\";\nimport { useSipState } from \"./useSipState\";\n\nexport function useSipSessions(): Pick<SipState, \"sessions\"> {\n const { sessions } = useSipState();\n return { sessions };\n}\n","import { useEffect } from \"react\";\nimport type {\n SessionEventName,\n SessionEventPayload,\n UAEventName,\n UAEventPayload,\n} from \"jssip-lib\";\nimport { useSip } from \"./useSip\";\n\nexport function useSipEvent<K extends UAEventName>(\n event: K,\n handler?: (payload?: UAEventPayload<K>) => void\n) {\n const { sipEventManager } = useSip();\n\n useEffect(() => {\n if (!handler) return;\n return sipEventManager.onUA(event, handler);\n }, [event, handler, sipEventManager]);\n}\n\nexport function useSipSessionEvent<K extends SessionEventName>(\n sessionId: string,\n event: K,\n handler?: (payload?: SessionEventPayload<K>) => void\n) {\n const { sipEventManager } = useSip();\n\n useEffect(() => {\n if (!handler) return;\n return sipEventManager.onSession(sessionId, event, handler);\n }, [event, handler, sessionId, sipEventManager]);\n}\n","import { useEffect, useRef } from \"react\";\r\nimport { useSip } from \"../hooks/useSip\";\r\nimport { createCallPlayer } from \"jssip-lib/dom\";\r\n\r\nexport function CallPlayer({ sessionId }: { sessionId?: string }) {\r\n const { client } = useSip();\r\n const audioRef = useRef<HTMLAudioElement | null>(null);\r\n\r\n useEffect(() => {\r\n if (!audioRef.current) return;\r\n\r\n const player = createCallPlayer(audioRef.current);\r\n const session = sessionId ? client.getSession(sessionId) : null;\r\n const off = session\r\n ? player.bindToSession(session)\r\n : player.bindToClient(client);\r\n\r\n return () => {\r\n off?.();\r\n player.detach();\r\n };\r\n }, [client, sessionId]);\r\n\r\n return <audio ref={audioRef} autoPlay playsInline />;\r\n}\r\n","import { SipClient } from \"../../sip/client\";\r\nimport type { RTCSession, RTCSessionEvent } from \"../../sip/types\";\r\n\r\nexport function createCallPlayer(audioEl: HTMLAudioElement) {\r\n let cleanupTrackListener: (() => void) | null = null;\r\n let cleanupSessionPeerListener: (() => void) | null = null;\r\n let cleanupClientListeners: (() => void) | null = null;\r\n\r\n const dispose = (fn: (() => void) | null) => {\r\n if (fn) fn();\r\n return null as null;\r\n };\r\n\r\n /** Stop all tracks and clear audio element */\r\n function clearAudioStream(stream?: MediaStream | null) {\r\n if (stream) {\r\n for (const t of stream.getTracks()) {\r\n t.stop();\r\n }\r\n }\r\n audioEl.srcObject = null;\r\n }\r\n\r\n const attachTracks = (pc: RTCPeerConnection) => {\r\n const onTrack = (e: RTCTrackEvent) => {\r\n if (e.track.kind !== \"audio\") return;\r\n\r\n const nextStream = e.streams?.[0] ?? new MediaStream([e.track]);\r\n const prev = audioEl.srcObject as MediaStream | null;\r\n\r\n if (prev && prev !== nextStream) {\r\n clearAudioStream(prev);\r\n }\r\n\r\n audioEl.srcObject = nextStream;\r\n audioEl.play?.().catch(() => {});\r\n };\r\n\r\n pc.addEventListener(\"track\", onTrack);\r\n return () => pc.removeEventListener(\"track\", onTrack);\r\n };\r\n\r\n const listenSessionPeerconnection = (session: RTCSession) => {\r\n const onPeer = (data: { peerconnection: RTCPeerConnection }) => {\r\n cleanupTrackListener = dispose(cleanupTrackListener);\r\n cleanupTrackListener = attachTracks(data.peerconnection);\r\n };\r\n session.on(\"peerconnection\", onPeer);\r\n return () => session.off(\"peerconnection\", onPeer);\r\n };\r\n\r\n function bindToSession(session: RTCSession) {\r\n if (\r\n session?.direction === \"outgoing\" &&\r\n session.connection instanceof RTCPeerConnection\r\n ) {\r\n cleanupTrackListener = dispose(cleanupTrackListener);\r\n cleanupTrackListener = attachTracks(session.connection);\r\n }\r\n\r\n cleanupSessionPeerListener = dispose(cleanupSessionPeerListener);\r\n cleanupSessionPeerListener = listenSessionPeerconnection(session);\r\n\r\n return () => {\r\n cleanupSessionPeerListener = dispose(cleanupSessionPeerListener);\r\n cleanupTrackListener = dispose(cleanupTrackListener);\r\n };\r\n }\r\n\r\n function bindToClient(client: SipClient) {\r\n const offNew = client.on(\"newRTCSession\", (payload) => {\r\n const e = (payload as any)?.data as RTCSessionEvent | undefined;\r\n cleanupSessionPeerListener = dispose(cleanupSessionPeerListener);\r\n cleanupTrackListener = dispose(cleanupTrackListener);\r\n\r\n if (!e?.session) return;\r\n\r\n cleanupSessionPeerListener = listenSessionPeerconnection(e.session);\r\n if (\r\n e.session.direction === \"outgoing\" &&\r\n e.session.connection instanceof RTCPeerConnection\r\n ) {\r\n cleanupTrackListener = attachTracks(e.session.connection);\r\n }\r\n });\r\n\r\n const offEnded = client.on(\"ended\", () => detach());\r\n const offFailed = client.on(\"failed\", () => detach());\r\n const offDisconnected = client.on(\"disconnected\", () => detach());\r\n\r\n cleanupClientListeners = () => {\r\n offNew();\r\n offEnded();\r\n offFailed();\r\n offDisconnected();\r\n };\r\n return cleanupClientListeners;\r\n }\r\n\r\n function detach() {\r\n cleanupClientListeners = dispose(cleanupClientListeners);\r\n cleanupSessionPeerListener = dispose(cleanupSessionPeerListener);\r\n cleanupTrackListener = dispose(cleanupTrackListener);\r\n clearAudioStream(audioEl.srcObject as MediaStream | null);\r\n }\r\n\r\n return {\r\n bindToSession,\r\n bindToClient,\r\n detach,\r\n };\r\n}\r\n","import React, { useMemo } from \"react\";\nimport { SipContext } from \"../context\";\nimport { createSipEventManager, type SipClient, type SipEventManager } from \"jssip-lib\";\n\nexport function SipProvider({\n client,\n children,\n sipEventManager,\n}: {\n sipEventManager?: SipEventManager;\n client: SipClient;\n children: React.ReactNode;\n}) {\n const manager = useMemo(\n () => sipEventManager ?? createSipEventManager(client),\n [client, sipEventManager]\n );\n\n const contextValue = useMemo(() => ({ client, sipEventManager: manager }), [client, manager]);\n\n return (\n <SipContext.Provider value={contextValue}>\n {children}\n </SipContext.Provider>\n );\n}\n"]}
|
package/dist/index.js
CHANGED
|
@@ -485,6 +485,7 @@ function createSessionHandlers(deps) {
|
|
|
485
485
|
},
|
|
486
486
|
accepted: (e) => {
|
|
487
487
|
emitter.emit("accepted", e);
|
|
488
|
+
onSessionAccepted?.(sessionId);
|
|
488
489
|
state.batchSet({
|
|
489
490
|
sessions: state.getState().sessions.map(
|
|
490
491
|
(s) => s.id === sessionId ? {
|
|
@@ -1091,11 +1092,6 @@ var SipClient = class extends EventTargetEmitter {
|
|
|
1091
1092
|
rtc,
|
|
1092
1093
|
detachSessionHandlers: () => this.cleanupSession(sessionId, session),
|
|
1093
1094
|
onSessionFailed: (err, event) => this.onSessionFailed(err, event),
|
|
1094
|
-
onSessionConfirmed: (confirmedSessionId) => {
|
|
1095
|
-
if (this.micRecoveryEnabled) {
|
|
1096
|
-
this.enableMicrophoneRecovery(confirmedSessionId);
|
|
1097
|
-
}
|
|
1098
|
-
},
|
|
1099
1095
|
sessionId
|
|
1100
1096
|
});
|
|
1101
1097
|
}
|
|
@@ -1227,11 +1223,15 @@ var SipClient = class extends EventTargetEmitter {
|
|
|
1227
1223
|
return;
|
|
1228
1224
|
const stream = rtc.mediaStream;
|
|
1229
1225
|
const track = stream?.getAudioTracks?.()[0];
|
|
1230
|
-
const
|
|
1226
|
+
const pc2 = session2?.connection;
|
|
1227
|
+
const sender = pc2?.getSenders?.().find((s) => s.track?.kind === "audio");
|
|
1231
1228
|
if (!track && !sender)
|
|
1232
1229
|
return;
|
|
1233
1230
|
if (Date.now() - startedAt < warmupMs)
|
|
1234
1231
|
return;
|
|
1232
|
+
if (pc2?.connectionState === "new" || pc2?.connectionState === "connecting" || pc2?.iceConnectionState === "new" || pc2?.iceConnectionState === "checking") {
|
|
1233
|
+
return;
|
|
1234
|
+
}
|
|
1235
1235
|
const trackLive = track?.readyState === "live";
|
|
1236
1236
|
const senderLive = sender?.track?.readyState === "live";
|
|
1237
1237
|
if (trackLive && senderLive)
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/jssip-lib/sip/debugger.ts","../src/jssip-lib/sip/userAgent.ts","../src/jssip-lib/core/types.ts","../src/jssip-lib/core/eventEmitter.ts","../src/jssip-lib/core/sipErrorHandler.ts","../src/jssip-lib/core/sipState.ts","../src/jssip-lib/core/sipStateStore.ts","../src/jssip-lib/sip/handlers/uaHandlers.ts","../src/jssip-lib/sip/sessionState.ts","../src/jssip-lib/sip/handlers/sessionHandlers.ts","../src/jssip-lib/sip/sessionController.ts","../src/jssip-lib/sip/sessionManager.ts","../src/jssip-lib/sip/sessionLifecycle.ts","../src/jssip-lib/sip/client.ts","../src/jssip-lib/index.ts","../src/context/index.tsx","../src/hooks/useSipState.ts","../src/hooks/useSip.ts","../src/hooks/useSipActions.ts","../src/hooks/useSipSessions.ts","../src/hooks/useSipEvent.ts","../src/components/call-player.tsx","../src/jssip-lib/adapters/dom/createCallPlayer.ts","../src/provider/index.tsx"],"names":["JsSIP","message","session","useEffect","useMemo","jsx"],"mappings":"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","sourcesContent":["import JsSIP from \"jssip\";\n\ntype StorageLike = Pick<Storage, \"getItem\" | \"setItem\" | \"removeItem\">;\n\nexport interface SipDebugToggleResult {\n debug: boolean;\n text: string;\n}\n\n/**\n * Browser-friendly debugger toggle for JsSIP.\n * Persists preference in sessionStorage and exposes helpers on window for console use.\n */\nexport class SipDebugger {\n private readonly storageKey: string;\n private readonly defaultPattern: string;\n private enabled = false;\n private logger: any;\n\n constructor(storageKey = \"sip-debug-enabled\", defaultPattern = \"JsSIP:*\") {\n this.storageKey = storageKey;\n this.defaultPattern = defaultPattern;\n }\n\n initFromSession(storage: StorageLike | null = safeSessionStorage()): void {\n try {\n const saved = storage?.getItem(this.storageKey);\n if (saved) this.enable(saved, storage);\n } catch {\n /* ignore */\n }\n }\n\n enable(\n pattern: string = this.defaultPattern,\n storage: StorageLike | null = safeSessionStorage()\n ): void {\n try {\n if (typeof JsSIP?.debug?.enable === \"function\") {\n JsSIP.debug.enable(pattern);\n this.logger = console;\n }\n // Persist pattern in sessionStorage only.\n storage?.setItem?.(this.storageKey, pattern || this.defaultPattern);\n try {\n (window as any).sipDebugBridge?.(pattern);\n } catch {\n /* ignore */\n }\n this.enabled = true;\n } catch {\n /* ignore */\n }\n }\n\n disable(storage: StorageLike | null = safeSessionStorage()): void {\n try {\n if (typeof JsSIP?.debug?.disable === \"function\") {\n JsSIP.debug.disable();\n } else if (typeof JsSIP?.debug?.enable === \"function\") {\n JsSIP.debug.enable(\"\");\n }\n storage?.removeItem?.(this.storageKey);\n try {\n (window as any).sipDebugBridge?.(false);\n } catch {\n /* ignore */\n }\n this.enabled = false;\n } catch {\n /* ignore */\n }\n }\n\n toggle(\n pattern: string = this.defaultPattern,\n storage: StorageLike | null = safeSessionStorage()\n ): void {\n if (this.isEnabled()) {\n this.disable(storage);\n } else {\n this.enable(pattern, storage);\n }\n }\n\n isEnabled(): boolean {\n return this.enabled;\n }\n\n attachToWindow(win: Window & typeof globalThis = window): void {\n const api = {\n enableDebug: (): SipDebugToggleResult => {\n this.enable();\n return { debug: this.isEnabled(), text: \"press F5\" };\n },\n disableDebug: (): SipDebugToggleResult => {\n this.disable();\n return { debug: this.isEnabled(), text: \"press F5\" };\n },\n toggleDebug: (): SipDebugToggleResult => {\n this.toggle();\n return { debug: this.isEnabled(), text: \"press F5\" };\n },\n debugState: (): SipDebugToggleResult => ({\n debug: this.isEnabled(),\n text: this.isEnabled() ? \"enabled\" : \"disabled\",\n }),\n sipState: () => {\n try {\n const getter = (win as any).sipState;\n return typeof getter === \"function\"\n ? getter()\n : \"sipState helper not available; ensure client debug is enabled\";\n } catch {\n return \"sipState helper not available\";\n }\n },\n sipSessions: () => {\n try {\n const getter = (win as any).sipSessions;\n return typeof getter === \"function\"\n ? getter()\n : \"sipSessions helper not available; ensure client debug is enabled\";\n } catch {\n return \"sipSessions helper not available\";\n }\n },\n };\n\n try {\n (win as any).sipSupport = api;\n } catch {\n /* ignore */\n }\n }\n}\n\nfunction safeSessionStorage(): StorageLike | null {\n if (typeof window === \"undefined\") return null;\n try {\n return window.sessionStorage;\n } catch {\n return null;\n }\n}\n\nexport const sipDebugger = new SipDebugger();\nif (typeof window !== \"undefined\") {\n sipDebugger.attachToWindow();\n sipDebugger.initFromSession();\n}\n","import JsSIP, { UA } from \"jssip\";\r\nimport { SipConfiguration, UAConfiguration } from \"./types\";\r\n\r\ntype StartOpts = { debug?: boolean | string };\r\n\r\nexport class SipUserAgent {\r\n private _ua: UA | null = null;\r\n\r\n public get ua(): UA | null {\r\n return this._ua;\r\n }\r\n public get isStarted(): boolean {\r\n return !!this._ua;\r\n }\r\n public get isRegistered(): boolean {\r\n return !!this._ua?.isRegistered();\r\n }\r\n\r\n public start(\r\n uri: string,\r\n password: string,\r\n config: Omit<SipConfiguration, \"debug\">,\r\n opts?: StartOpts\r\n ): UA {\r\n this.stop();\r\n const uaCfg = this.buildUAConfig(config, uri, password);\r\n this.ensureValid(uaCfg);\r\n this.applyDebug(opts?.debug);\r\n const ua = this.createUA(uaCfg);\r\n ua.start();\r\n this._ua = ua;\r\n return ua;\r\n }\r\n\r\n public register(): void {\r\n const ua = this.getUA();\r\n if (!ua?.isRegistered()) ua?.register();\r\n }\r\n\r\n public stop(): void {\r\n const ua = this._ua;\r\n if (!ua) return;\r\n try {\r\n if (ua.isRegistered()) ua.unregister();\r\n ua.stop();\r\n } finally {\r\n this._ua = null;\r\n }\r\n }\r\n\r\n public getUA(): UA | null {\r\n return this._ua;\r\n }\r\n\r\n public setDebug(debug?: boolean | string): void {\r\n this.applyDebug(debug);\r\n }\r\n\r\n protected buildUAConfig(\r\n config: Omit<SipConfiguration, \"debug\">,\r\n uri: string,\r\n password: string\r\n ): UAConfiguration {\r\n return { ...(config as UAConfiguration), uri, password };\r\n }\r\n\r\n protected ensureValid(cfg: UAConfiguration): void {\r\n const sockets = cfg.sockets as UAConfiguration[\"sockets\"];\r\n if (\r\n !cfg.uri ||\r\n !cfg.password ||\r\n !sockets ||\r\n (Array.isArray(sockets) && sockets.length === 0)\r\n ) {\r\n throw new Error(\r\n \"Invalid SIP connect args: require uri, password, and at least one socket\"\r\n );\r\n }\r\n }\r\n\r\n protected applyDebug(debug?: boolean | string): void {\n const stored = debug === undefined ? this.readSessionFlag() : debug;\n const enabled = !!stored;\n const pattern = typeof stored === \"string\" ? stored : \"JsSIP:*\";\n\n if (enabled) {\n JsSIP.debug.enable(pattern);\n const dbg: any = (JsSIP as any).debug;\n if (dbg?.setLogger) dbg.setLogger(console);\n else if (dbg) dbg.logger = console;\n this.persistSessionFlag(typeof stored === \"string\" ? stored : undefined);\n } else {\n (JsSIP.debug as any)?.disable?.();\n this.clearSessionFlag();\n }\n }\n\r\n protected createUA(cfg: UAConfiguration): UA {\r\n return new JsSIP.UA(cfg);\r\n }\r\n\r\n private readSessionFlag(): string | false {\n try {\n if (typeof window === \"undefined\") return false;\n const value = window.sessionStorage.getItem(\"sip-debug-enabled\");\n if (!value) return false;\n return value;\n } catch {\n return false;\n }\n }\n\n private persistSessionFlag(pattern?: string): void {\n try {\n if (typeof window !== \"undefined\") {\n window.sessionStorage.setItem(\n \"sip-debug-enabled\",\n pattern || \"JsSIP:*\"\n );\n }\n } catch {\n /* ignore */\n }\n }\r\n\r\n private clearSessionFlag(): void {\r\n try {\r\n if (typeof window !== \"undefined\") {\r\n window.sessionStorage.removeItem(\"sip-debug-enabled\");\r\n }\r\n } catch {\r\n /* ignore */\r\n }\r\n }\r\n}\r\n","import { Originator } from \"jssip/src/RTCSession\";\r\n\r\nexport const SipStatus = {\r\n Disconnected: \"disconnected\",\r\n Connecting: \"connecting\",\r\n Connected: \"connected\",\r\n Registered: \"registered\",\r\n Unregistered: \"unregistered\",\r\n RegistrationFailed: \"registrationFailed\",\r\n} as const;\r\n\r\nexport type SipStatus = (typeof SipStatus)[keyof typeof SipStatus];\r\n\r\nexport const CallStatus = {\r\n Idle: \"idle\",\r\n Dialing: \"dialing\",\r\n Ringing: \"ringing\",\r\n Active: \"active\",\r\n Hold: \"hold\",\r\n} as const;\r\nexport type CallStatus = (typeof CallStatus)[keyof typeof CallStatus];\r\n\r\nexport type CallDirection = Originator.LOCAL | Originator.REMOTE;\r\n\r\nexport type SipSessionState = {\r\n id: string;\r\n status: CallStatus;\r\n direction: CallDirection | null;\r\n from: string | null;\r\n to: string | null;\r\n muted: boolean;\r\n acceptedAt: number | null;\r\n mediaKind: \"audio\" | \"video\";\r\n remoteVideoEnabled: boolean;\r\n};\r\n\r\nexport interface SipState {\r\n sipStatus: SipStatus;\r\n error: string | null;\r\n sessions: SipSessionState[];\r\n}\r\n\r\nexport const SipStatusList = Object.values(SipStatus);\r\nexport const CallStatusList = Object.values(CallStatus);\r\n\r\nexport function isSipStatus(v: unknown): v is SipStatus {\r\n return (\r\n typeof v === \"string\" && (SipStatusList as readonly string[]).includes(v)\r\n );\r\n}\r\nexport function isCallStatus(v: unknown): v is CallStatus {\r\n return (\r\n typeof v === \"string\" && (CallStatusList as readonly string[]).includes(v)\r\n );\r\n}\r\n\r\nexport type Unsubscribe = () => void;\r\nexport type Listener<T> = (value: T) => void;\r\n","export type Listener<T = any> = (payload: T) => void;\r\n\r\nexport class EventTargetEmitter<Events extends Record<string, any> = any> {\r\n private target = new EventTarget();\r\n\r\n on<K extends keyof Events>(event: K, fn: Listener<Events[K]>): () => void {\r\n const wrapper = (e: Event) => fn((e as CustomEvent<Events[K]>).detail);\r\n this.target.addEventListener(event as string, wrapper);\r\n return () => this.target.removeEventListener(event as string, wrapper);\r\n }\r\n\r\n emit<K extends keyof Events>(event: K, payload?: Events[K]): void {\r\n this.target.dispatchEvent(\r\n new CustomEvent(event as string, { detail: payload })\r\n );\r\n }\r\n}\r\n","export interface SipErrorPayload {\r\n cause: string;\r\n code?: string;\r\n raw?: any;\r\n message?: string;\r\n}\r\n\r\nexport interface SipErrorFormatInput {\r\n raw: any;\r\n code?: string;\r\n fallback?: string;\r\n}\r\n\r\nexport type SipErrorFormatter = (\r\n input: SipErrorFormatInput\r\n) => SipErrorPayload | undefined;\r\n\r\ntype SipErrorHandlerOptions = {\r\n formatter?: SipErrorFormatter;\r\n messages?: Record<string, string>;\r\n};\r\n\r\nexport class SipErrorHandler {\r\n private readonly formatter?: SipErrorFormatter;\r\n private readonly messages?: Record<string, string>;\r\n\r\n constructor(options: SipErrorHandlerOptions = {}) {\r\n this.formatter = options.formatter;\r\n this.messages = options.messages;\r\n }\r\n\r\n format(input: SipErrorFormatInput): SipErrorPayload {\r\n const { code, raw, fallback } = input;\r\n const mappedMessage =\r\n code && this.messages ? this.messages[code] : undefined;\r\n\r\n // Allow consumer to fully customize formatting.\r\n if (this.formatter) {\r\n const custom = this.formatter({\r\n raw,\r\n code,\r\n fallback: mappedMessage ?? fallback,\r\n });\r\n const message =\r\n custom?.message ??\r\n custom?.cause ??\r\n mappedMessage ??\r\n fallback ??\r\n this.readRawMessage(raw) ??\r\n \"unknown error\";\r\n\r\n return {\r\n cause: custom?.cause ?? message,\r\n code: custom?.code ?? code,\r\n raw: custom?.raw ?? raw,\r\n message,\r\n };\r\n }\r\n\r\n const message =\r\n mappedMessage ?? this.readRawMessage(raw) ?? fallback ?? \"unknown error\";\r\n\r\n return {\r\n cause: message,\r\n code,\r\n raw,\r\n message,\r\n };\r\n }\r\n\r\n private readRawMessage(raw: any): string | undefined {\r\n if (raw == null) return undefined;\r\n if (typeof raw === \"string\") return raw;\r\n if (typeof raw?.cause === \"string\") return raw.cause;\r\n if (typeof raw?.message === \"string\") return raw.message;\r\n return undefined;\r\n }\r\n}\r\n","import { SipState, SipStatus } from \"./types\";\r\n\r\nexport function getInitialSipState(): SipState {\r\n return {\r\n sipStatus: SipStatus.Disconnected,\r\n error: null,\r\n sessions: [],\r\n };\r\n}\r\n\r\nexport function shallowEqual(objA: any, objB: any): boolean {\r\n if (objA === objB) return true;\r\n if (!objA || !objB) return false;\r\n const keysA = Object.keys(objA);\r\n const keysB = Object.keys(objB);\r\n if (keysA.length !== keysB.length) return false;\r\n for (const key of keysA) {\r\n if (objA[key] !== objB[key]) return false;\r\n }\r\n return true;\r\n}\r\n","import { SipState } from \"./types\";\r\nimport { getInitialSipState, shallowEqual } from \"./sipState\";\r\n\r\nexport type SipStateListener = (state: SipState) => void;\r\n\r\nexport class SipStateStore {\r\n private state: SipState = getInitialSipState();\r\n private lastState: SipState = getInitialSipState();\r\n private listeners = new Set<SipStateListener>();\r\n private pendingState: Partial<SipState> | null = null;\r\n private updateScheduled = false;\r\n\r\n getState(): SipState {\r\n return this.state;\r\n }\r\n\r\n onChange(fn: SipStateListener): () => void {\r\n this.listeners.add(fn);\r\n fn(this.state);\r\n return () => this.listeners.delete(fn);\r\n }\r\n\r\n subscribe(fn: SipStateListener): () => void {\r\n return this.onChange(fn);\r\n }\r\n\r\n setState(partial: Partial<SipState>) {\r\n if (!partial || Object.keys(partial).length === 0) return;\r\n const next = { ...this.state, ...partial };\r\n // Fast-path: if sessions reference unchanged and shallow contents equal, skip emit.\r\n if (next.sessions === this.lastState.sessions && shallowEqual(this.lastState, next)) {\r\n return;\r\n }\r\n this.state = next;\r\n this.lastState = next;\r\n this.emit();\r\n }\r\n\r\n batchSet(partial: Partial<SipState>) {\r\n this.pendingState = { ...this.pendingState, ...partial };\r\n if (!this.updateScheduled) {\r\n this.updateScheduled = true;\r\n queueMicrotask(() => {\r\n if (this.pendingState) this.setState(this.pendingState);\r\n this.pendingState = null;\r\n this.updateScheduled = false;\r\n });\r\n }\r\n }\r\n\r\n reset(overrides: Partial<SipState> = {}) {\r\n this.setState({ ...getInitialSipState(), ...overrides });\r\n }\r\n\r\n private emit() {\r\n for (const fn of this.listeners) fn(this.state);\r\n }\r\n}\r\n","import { UAEventMap } from \"../types\";\r\nimport { SipStatus } from \"../../core/types\";\r\nimport { SipStateStore } from \"../../core/sipStateStore\";\r\nimport { JsSIPEventMap } from \"../types\";\r\nimport { EventTargetEmitter } from \"../../core/eventEmitter\";\r\nimport { SipErrorPayload } from \"../../core/sipErrorHandler\";\r\n\r\ntype Deps = {\r\n emitter: EventTargetEmitter<JsSIPEventMap>;\r\n state: SipStateStore;\r\n cleanupAllSessions: () => void;\r\n emitError: (\r\n raw: any,\r\n code?: string,\r\n fallback?: string\r\n ) => SipErrorPayload;\r\n onNewRTCSession: UAEventMap[\"newRTCSession\"];\r\n};\r\n\r\nexport function createUAHandlers(deps: Deps): Partial<UAEventMap> {\r\n const { emitter, state, cleanupAllSessions, emitError, onNewRTCSession } =\r\n deps;\r\n\r\n return {\r\n connecting: (e: any) => {\r\n emitter.emit(\"connecting\", e);\r\n state.batchSet({ sipStatus: SipStatus.Connecting });\r\n },\r\n connected: (e: any) => {\r\n emitter.emit(\"connected\", e);\r\n state.batchSet({ sipStatus: SipStatus.Connected });\r\n },\r\n disconnected: (e: any) => {\r\n emitter.emit(\"disconnected\", e);\r\n cleanupAllSessions();\r\n state.reset();\r\n },\r\n\r\n registered: (e: any) => {\r\n emitter.emit(\"registered\", e);\r\n state.batchSet({ sipStatus: SipStatus.Registered, error: null });\r\n },\r\n unregistered: (e: any) => {\r\n emitter.emit(\"unregistered\", e);\r\n state.batchSet({ sipStatus: SipStatus.Unregistered });\r\n },\r\n registrationFailed: (e: any) => {\r\n emitter.emit(\"registrationFailed\", e);\r\n cleanupAllSessions();\r\n emitError(\r\n {\r\n raw: e,\r\n cause: e?.cause,\r\n statusCode: e?.response?.status_code,\r\n statusText: e?.response?.reason_phrase,\r\n },\r\n \"REGISTRATION_FAILED\",\r\n \"registration failed\"\r\n );\r\n state.batchSet({\r\n sipStatus: SipStatus.RegistrationFailed,\r\n error: e?.cause || \"registration failed\",\r\n });\r\n },\r\n newRTCSession: onNewRTCSession,\r\n newMessage: (e: any) => emitter.emit(\"newMessage\", e),\r\n sipEvent: (e: any) => emitter.emit(\"sipEvent\", e),\r\n newOptions: (e: any) => emitter.emit(\"newOptions\", e),\r\n };\r\n}\r\n","import { CallStatus, SipSessionState } from \"../core/types\";\r\nimport { SipStateStore } from \"../core/sipStateStore\";\r\n\r\nexport function holdOtherSessions(\r\n state: SipStateStore,\r\n sessionId: string,\r\n holdFn: (id: string) => void\r\n) {\r\n const current = state.getState();\r\n current.sessions.forEach((s) => {\r\n if (s.id === sessionId) return;\r\n if (s.status === CallStatus.Active) {\r\n holdFn(s.id);\r\n }\r\n });\r\n}\r\n\r\nexport function upsertSessionState(\r\n state: SipStateStore,\r\n sessionId: string,\r\n partial: Partial<SipSessionState>\r\n) {\r\n const current = state.getState();\r\n const existing = current.sessions.find((s) => s.id === sessionId);\r\n const base: SipSessionState = existing ?? {\r\n id: sessionId,\r\n status: CallStatus.Idle,\r\n direction: null,\r\n from: null,\r\n to: null,\r\n muted: false,\r\n acceptedAt: null,\r\n mediaKind: \"audio\",\r\n remoteVideoEnabled: false,\r\n };\r\n\r\n const nextSession = { ...base, ...partial };\r\n const sessions = existing\r\n ? current.sessions.map((s) => (s.id === sessionId ? nextSession : s))\r\n : [...current.sessions, nextSession];\r\n\r\n state.setState({ sessions });\r\n}\r\n\r\nexport function removeSessionState(state: SipStateStore, sessionId: string) {\r\n const current = state.getState();\r\n const sessions = current.sessions.filter((s) => s.id !== sessionId);\r\n state.setState({\r\n sessions,\r\n error: null,\r\n });\r\n}\r\n","import { EndEvent, RTCSessionEventMap } from \"../types\";\nimport { CallStatus } from \"../../core/types\";\nimport { SipStateStore } from \"../../core/sipStateStore\";\nimport { WebRTCSessionController } from \"../sessionController\";\nimport { JsSIPEventMap } from \"../types\";\nimport { EventTargetEmitter } from \"../../core/eventEmitter\";\nimport { SipErrorPayload } from \"../../core/sipErrorHandler\";\nimport { upsertSessionState } from \"../sessionState\";\nimport { IncomingAckEvent, IncomingEvent, OutgoingAckEvent, OutgoingEvent } from \"jssip/src/RTCSession\";\n\ntype Deps = {\n emitter: EventTargetEmitter<JsSIPEventMap>;\n state: SipStateStore;\n rtc: WebRTCSessionController;\n detachSessionHandlers: () => void;\n emitError: (raw: any, code?: string, fallback?: string) => SipErrorPayload;\n onSessionFailed: (error?: string, event?: any) => void;\n onSessionConfirmed?: (sessionId: string) => void;\n sessionId: string;\n};\n\nexport function createSessionHandlers(deps: Deps): Partial<RTCSessionEventMap> {\n const {\n emitter,\n state,\n rtc,\n detachSessionHandlers,\n onSessionFailed,\n onSessionConfirmed,\n sessionId,\n } = deps;\n\n return {\n progress: (e: IncomingEvent | OutgoingEvent) => {\n emitter.emit(\"progress\", e);\n },\n accepted: (e: IncomingEvent | OutgoingEvent) => {\n emitter.emit(\"accepted\", e);\n state.batchSet({\n sessions: state.getState().sessions.map((s) =>\n s.id === sessionId\n ? {\n ...s,\n status: CallStatus.Active,\n acceptedAt: s.acceptedAt ?? Date.now(),\n }\n : s\n ),\n });\n },\n confirmed: (e: IncomingAckEvent | OutgoingAckEvent) => {\n emitter.emit(\"confirmed\", e);\n onSessionConfirmed?.(sessionId);\n },\n\n ended: (e: EndEvent) => {\n emitter.emit(\"ended\", e);\n detachSessionHandlers();\n rtc.cleanup();\n const nextSessions = state\n .getState()\n .sessions.filter((s) => s.id !== sessionId);\n state.batchSet({\n sessions: nextSessions,\n });\n },\n failed: (e: EndEvent) => {\n emitter.emit(\"failed\", e);\n detachSessionHandlers();\n rtc.cleanup();\n const cause = e?.cause || \"call failed\";\n onSessionFailed(cause, e);\n const nextSessions = state\n .getState()\n .sessions.filter((s) => s.id !== sessionId);\n state.batchSet({\n sessions: nextSessions,\n });\n },\n\n muted: () => {\n emitter.emit(\"muted\", undefined);\n upsertSessionState(state, sessionId, { muted: true });\n },\n unmuted: () => {\n emitter.emit(\"unmuted\", undefined);\n upsertSessionState(state, sessionId, { muted: false });\n },\n hold: () => {\n emitter.emit(\"hold\", undefined);\n upsertSessionState(state, sessionId, { status: CallStatus.Hold });\n },\n unhold: () => {\n emitter.emit(\"unhold\", undefined);\n upsertSessionState(state, sessionId, { status: CallStatus.Active });\n },\n\n reinvite: (e: any) => emitter.emit(\"reinvite\", e),\n update: (e: any) => emitter.emit(\"update\", e),\n sdp: (e: any) => emitter.emit(\"sdp\", e),\n icecandidate: (e: any) => emitter.emit(\"icecandidate\", e),\n refer: (e: any) => emitter.emit(\"refer\", e),\n replaces: (e: any) => emitter.emit(\"replaces\", e),\n newDTMF: (e: any) => emitter.emit(\"newDTMF\", e),\n newInfo: (e: any) => emitter.emit(\"newInfo\", e),\n\n getusermediafailed: (e: any) => {\n emitter.emit(\"getusermediafailed\", e);\n detachSessionHandlers();\n rtc.cleanup();\n onSessionFailed(\"getUserMedia failed\", e);\n state.batchSet({\n sessions: state.getState().sessions.filter((s) => s.id !== sessionId),\n });\n },\n \"peerconnection:createofferfailed\": (e: any) => {\n emitter.emit(\"peerconnection:createofferfailed\", e);\n detachSessionHandlers();\n rtc.cleanup();\n onSessionFailed(\"peer connection createOffer failed\", e);\n state.batchSet({\n sessions: state.getState().sessions.filter((s) => s.id !== sessionId),\n });\n },\n \"peerconnection:createanswerfailed\": (e: any) => {\n emitter.emit(\"peerconnection:createanswerfailed\", e);\n detachSessionHandlers();\n rtc.cleanup();\n onSessionFailed(\"peer connection createAnswer failed\", e);\n state.batchSet({\n sessions: state.getState().sessions.filter((s) => s.id !== sessionId),\n });\n },\n \"peerconnection:setlocaldescriptionfailed\": (e: any) => {\n emitter.emit(\"peerconnection:setlocaldescriptionfailed\", e);\n detachSessionHandlers();\n rtc.cleanup();\n onSessionFailed(\"peer connection setLocalDescription failed\", e);\n state.batchSet({\n sessions: state.getState().sessions.filter((s) => s.id !== sessionId),\n });\n },\n \"peerconnection:setremotedescriptionfailed\": (e: any) => {\n emitter.emit(\"peerconnection:setremotedescriptionfailed\", e);\n detachSessionHandlers();\n rtc.cleanup();\n onSessionFailed(\"peer connection setRemoteDescription failed\", e);\n state.batchSet({\n sessions: state.getState().sessions.filter((s) => s.id !== sessionId),\n });\n },\n peerconnection: (e: any) => emitter.emit(\"peerconnection\", e),\n };\n}\n","import type {\r\n AnswerOptions,\r\n DTMFOptions,\r\n ReferOptions,\r\n RTCSession,\r\n TerminateOptions,\r\n} from \"./types\";\r\n\r\nexport class WebRTCSessionController {\r\n currentSession: RTCSession | null = null;\r\n mediaStream: MediaStream | null = null;\r\n\r\n public setSession(session: RTCSession | null) {\r\n this.currentSession = session;\r\n }\r\n\r\n public setMediaStream(stream: MediaStream) {\r\n this.mediaStream = stream;\r\n }\r\n\r\n private getPC(): RTCPeerConnection | null {\r\n return (this.currentSession as any)?.connection ?? null;\r\n }\r\n\r\n public cleanup(stopTracks: boolean = true): void {\r\n const pc = this.getPC();\r\n\r\n if (pc && typeof pc.getSenders === \"function\") {\r\n const isClosed =\r\n pc.connectionState === \"closed\" || pc.signalingState === \"closed\";\r\n if (!isClosed) {\r\n for (const s of pc.getSenders()) {\r\n try {\r\n s.replaceTrack(null);\r\n } catch {\r\n // ignore if sender/pc already closed\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (stopTracks && this.mediaStream) {\r\n for (const t of this.mediaStream.getTracks()) t.stop();\r\n }\r\n\r\n this.mediaStream = null;\r\n this.currentSession = null;\r\n }\r\n\r\n public answer(options: AnswerOptions = {}): boolean {\r\n return this.currentSession\r\n ? (this.currentSession.answer(options), true)\r\n : false;\r\n }\r\n\r\n public hangup(options?: TerminateOptions): boolean {\r\n return this.currentSession\r\n ? (this.currentSession.terminate(\r\n options ?? ({ status_code: 486, reason_phrase: \"Busy Here\" } as any)\r\n ),\r\n true)\r\n : false;\r\n }\r\n\r\n public mute(): boolean {\r\n this.mediaStream?.getAudioTracks().forEach((t) => (t.enabled = false));\r\n return this.currentSession\r\n ? (this.currentSession.mute({ audio: true }), true)\r\n : false;\r\n }\r\n\r\n public unmute(): boolean {\r\n this.mediaStream?.getAudioTracks().forEach((t) => (t.enabled = true));\r\n return this.currentSession\r\n ? (this.currentSession.unmute({ audio: true }), true)\r\n : false;\r\n }\r\n\r\n public hold(): boolean {\r\n return this.currentSession ? (this.currentSession.hold(), true) : false;\r\n }\r\n\r\n public unhold(): boolean {\r\n return this.currentSession ? (this.currentSession.unhold(), true) : false;\r\n }\r\n\r\n public sendDTMF(tones: string | number, options?: DTMFOptions): boolean {\r\n return this.currentSession\r\n ? (this.currentSession.sendDTMF(tones, options), true)\r\n : false;\r\n }\r\n\r\n public transfer(target: string, options?: ReferOptions): boolean {\r\n return this.currentSession\r\n ? (this.currentSession.refer(target as any, options), true)\r\n : false;\r\n }\r\n\r\n public enableVideo(): void {\r\n this.mediaStream?.getVideoTracks().forEach((t) => (t.enabled = true));\r\n }\r\n\r\n public disableVideo(): void {\r\n this.mediaStream?.getVideoTracks().forEach((t) => (t.enabled = false));\r\n }\r\n\r\n public async switchCamera(\n nextVideoTrack: MediaStreamTrack\n ): Promise<boolean> {\n const pc = this.getPC();\r\n if (!pc) return false;\r\n\r\n if (!this.mediaStream) this.mediaStream = new MediaStream();\r\n\r\n const old = this.mediaStream.getVideoTracks()[0];\r\n this.mediaStream.addTrack(nextVideoTrack);\r\n if (old) this.mediaStream.removeTrack(old);\r\n\r\n const sender = pc.getSenders?.().find((s) => s.track?.kind === \"video\");\r\n if (sender) await sender.replaceTrack(nextVideoTrack);\r\n\r\n if (old && old !== nextVideoTrack) old.stop();\r\n\r\n return true;\n }\n\n public async replaceAudioTrack(\n nextAudioTrack: MediaStreamTrack\n ): Promise<boolean> {\n const pc = this.getPC();\n if (!pc) return false;\n\n if (!this.mediaStream) this.mediaStream = new MediaStream();\n\n const old = this.mediaStream.getAudioTracks()[0];\n this.mediaStream.addTrack(nextAudioTrack);\n if (old) this.mediaStream.removeTrack(old);\n\n const sender = pc.getSenders?.().find((s) => s.track?.kind === \"audio\");\n if (sender) await sender.replaceTrack(nextAudioTrack);\n\n if (old && old !== nextAudioTrack) old.stop();\n\n return true;\n }\n}\n","import { WebRTCSessionController } from \"./sessionController\";\r\nimport type { RTCSession } from \"./types\";\r\n\r\ntype SessionEntry = {\r\n rtc: WebRTCSessionController;\r\n session?: RTCSession | null;\r\n media?: MediaStream | null;\r\n};\r\n\r\nexport class SessionManager {\r\n private entries = new Map<string, SessionEntry>();\r\n private pendingMediaQueue: Array<{ stream: MediaStream; addedAt: number }> =\r\n [];\r\n private pendingMediaTtlMs = 30000;\r\n\r\n setPendingMediaTtl(ms: number | undefined) {\r\n if (typeof ms === \"number\" && ms > 0) this.pendingMediaTtlMs = ms;\r\n }\r\n\r\n enqueueOutgoingMedia(stream: MediaStream) {\r\n this.pendingMediaQueue.push({ stream, addedAt: Date.now() });\r\n }\r\n\r\n dequeueOutgoingMedia(): MediaStream | null {\r\n const now = Date.now();\r\n while (this.pendingMediaQueue.length) {\r\n const next = this.pendingMediaQueue.shift();\r\n if (!next) break;\r\n if (now - next.addedAt <= this.pendingMediaTtlMs) {\r\n return next.stream;\r\n } else {\r\n // drop stale stream\r\n next.stream.getTracks().forEach((t) => t.stop());\r\n }\r\n }\r\n return null;\r\n }\r\n\r\n getOrCreateRtc(sessionId: string, session?: RTCSession) {\r\n let entry = this.entries.get(sessionId);\r\n if (!entry) {\r\n entry = {\r\n rtc: new WebRTCSessionController(),\r\n session: null,\r\n media: null,\r\n };\r\n this.entries.set(sessionId, entry);\r\n }\r\n if (session) {\r\n entry.session = session;\r\n entry.rtc.setSession(session);\r\n }\r\n if (entry.media) entry.rtc.setMediaStream(entry.media);\r\n return entry.rtc;\r\n }\r\n\r\n getRtc(sessionId: string) {\r\n return this.entries.get(sessionId)?.rtc ?? null;\r\n }\r\n\r\n setSession(sessionId: string, session: RTCSession) {\r\n const entry = this.entries.get(sessionId);\r\n if (entry) {\r\n entry.session = session;\r\n entry.rtc.setSession(session);\r\n } else {\r\n this.entries.set(sessionId, {\r\n rtc: new WebRTCSessionController(),\r\n session,\r\n media: null,\r\n });\r\n }\r\n }\r\n\r\n setSessionMedia(sessionId: string, stream: MediaStream) {\r\n const entry = this.entries.get(sessionId) ?? {\r\n rtc: new WebRTCSessionController(),\r\n session: null,\r\n media: null,\r\n };\r\n entry.media = stream;\r\n entry.rtc.setMediaStream(stream);\r\n this.entries.set(sessionId, entry);\r\n }\r\n\r\n getSession(sessionId: string) {\r\n return this.entries.get(sessionId)?.session ?? null;\r\n }\r\n\r\n getSessionIds() {\r\n return Array.from(this.entries.keys());\r\n }\r\n\r\n getSessions() {\r\n return Array.from(this.entries.entries()).map(([id, entry]) => ({\r\n id,\r\n session: entry.session as RTCSession,\r\n }));\r\n }\r\n\r\n getActiveSessionId(activeStatuses: string[] = [\"active\"]): string | null {\r\n for (const [id, entry] of Array.from(this.entries.entries()).reverse()) {\r\n const status = (entry.session as any)?.status;\r\n if (status && activeStatuses.includes(String(status).toLowerCase())) {\r\n return id;\r\n }\r\n }\r\n return null;\r\n }\r\n\r\n cleanupSession(sessionId: string) {\r\n const entry = this.entries.get(sessionId);\r\n if (entry) {\r\n entry.rtc.cleanup();\r\n this.entries.delete(sessionId);\r\n }\r\n }\r\n\r\n cleanupAllSessions() {\r\n for (const [, entry] of this.entries.entries()) {\r\n entry.rtc.cleanup();\r\n }\r\n this.entries.clear();\r\n this.pendingMediaQueue = [];\r\n }\r\n\r\n answer(sessionId: string, options: any) {\r\n const rtc = this.getRtc(sessionId);\r\n return rtc ? rtc.answer(options) : false;\r\n }\r\n\r\n hangup(sessionId: string, options?: any) {\r\n const rtc = this.getRtc(sessionId);\r\n return rtc ? rtc.hangup(options) : false;\r\n }\r\n\r\n mute(sessionId: string) {\r\n const rtc = this.getRtc(sessionId);\r\n return rtc ? rtc.mute() : false;\r\n }\r\n\r\n unmute(sessionId: string) {\r\n const rtc = this.getRtc(sessionId);\r\n return rtc ? rtc.unmute() : false;\r\n }\r\n\r\n hold(sessionId: string) {\r\n const rtc = this.getRtc(sessionId);\r\n return rtc ? rtc.hold() : false;\r\n }\r\n\r\n unhold(sessionId: string) {\r\n const rtc = this.getRtc(sessionId);\r\n return rtc ? rtc.unhold() : false;\r\n }\r\n\r\n sendDTMF(sessionId: string, tones: string | number, options?: any) {\r\n const rtc = this.getRtc(sessionId);\r\n return rtc ? rtc.sendDTMF(tones, options) : false;\r\n }\r\n\r\n transfer(sessionId: string, target: string, options?: any) {\r\n const rtc = this.getRtc(sessionId);\r\n return rtc ? rtc.transfer(target, options) : false;\r\n }\r\n}\r\n","import { SipStateStore } from \"../core/sipStateStore\";\r\nimport { CallDirection, CallStatus } from \"../core/types\";\r\nimport { SessionManager } from \"./sessionManager\";\r\nimport { holdOtherSessions, upsertSessionState } from \"./sessionState\";\r\nimport type { JsSIPEventName, RTCSession, RTCSessionEvent } from \"./types\";\r\nimport type { SipErrorPayload } from \"../core/sipErrorHandler\";\r\n\r\ntype Deps = {\r\n state: SipStateStore;\r\n sessionManager: SessionManager;\r\n emit: <K extends JsSIPEventName>(event: K, payload: any) => void;\r\n emitError: (raw: any, code?: string, fallback?: string) => SipErrorPayload;\r\n attachSessionHandlers: (sessionId: string, session: RTCSession) => void;\r\n getMaxSessionCount: () => number;\r\n};\r\n\r\nexport class SessionLifecycle {\r\n private readonly state: SipStateStore;\r\n private readonly sessionManager: SessionManager;\r\n private readonly emit: Deps[\"emit\"];\r\n private readonly emitError: Deps[\"emitError\"];\r\n private readonly attachSessionHandlers: Deps[\"attachSessionHandlers\"];\r\n private readonly getMaxSessionCount: Deps[\"getMaxSessionCount\"];\r\n\r\n constructor(deps: Deps) {\r\n this.state = deps.state;\r\n this.sessionManager = deps.sessionManager;\r\n this.emit = deps.emit;\r\n this.emitError = deps.emitError;\r\n this.attachSessionHandlers = deps.attachSessionHandlers;\r\n this.getMaxSessionCount = deps.getMaxSessionCount;\r\n }\r\n\r\n handleNewRTCSession(e: RTCSessionEvent) {\r\n const session = e.session;\r\n const sessionId = String((session as any)?.id ?? crypto.randomUUID?.() ?? Date.now());\r\n\r\n const currentSessions = this.state.getState().sessions;\r\n if (currentSessions.length >= this.getMaxSessionCount()) {\r\n try {\r\n session.terminate?.({ status_code: 486, reason_phrase: \"Busy Here\" } as any);\r\n } catch {\r\n /* ignore termination errors */\r\n }\r\n if (e.originator === \"remote\") {\r\n this.emit(\"missed\", e);\r\n }\r\n this.emitError(\"max session count reached\", \"MAX_SESSIONS_REACHED\", \"max session count reached\");\r\n return;\r\n }\r\n\r\n const outgoingMedia = e.originator === \"local\" ? this.sessionManager.dequeueOutgoingMedia() : null;\r\n\r\n if (outgoingMedia) this.sessionManager.setSessionMedia(sessionId, outgoingMedia);\r\n\r\n const rtc = this.sessionManager.getOrCreateRtc(sessionId, session);\r\n if (outgoingMedia) rtc.setMediaStream(outgoingMedia);\r\n\r\n this.sessionManager.setSession(sessionId, session);\r\n this.attachSessionHandlers(sessionId, session);\r\n\r\n holdOtherSessions(\r\n this.state,\r\n sessionId,\r\n (id) => {\r\n const otherRtc = this.sessionManager.getRtc(id);\r\n otherRtc?.hold();\r\n }\r\n );\r\n\r\n const sdpHasVideo =\r\n (e.request?.body && e.request.body.toString().includes(\"m=video\")) ||\r\n (session as RTCSession & { connection?: RTCPeerConnection })?.connection\r\n ?.getReceivers?.()\r\n ?.some((r: RTCRtpReceiver) => r.track?.kind === \"video\");\r\n\r\n upsertSessionState(this.state, sessionId, {\r\n direction: e.originator,\r\n from: e.originator === \"remote\" ? e.request.from.uri.user : null,\r\n to: e.request.to.uri.user,\r\n status: e.originator === \"remote\" ? CallStatus.Ringing : CallStatus.Dialing,\r\n mediaKind: sdpHasVideo ? \"video\" : \"audio\",\r\n remoteVideoEnabled: sdpHasVideo,\r\n });\r\n\r\n this.emit(\"newRTCSession\", e);\r\n }\r\n}\r\n","import { SipUserAgent } from \"./userAgent\";\r\nimport {\r\n AnswerOptions,\r\n CallOptions,\r\n DTMFOptions,\r\n JsSIPEventMap,\r\n ReferOptions,\r\n RTCSession,\r\n RTCSessionEvent,\r\n RTCSessionEventMap,\r\n SipConfiguration,\r\n SipEventManager,\r\n TerminateOptions,\r\n UAEventMap,\r\n} from \"./types\";\r\n\r\nimport { SipState, SipStatus, CallStatus } from \"../core/types\";\r\nimport { EventTargetEmitter } from \"../core/eventEmitter\";\r\nimport {\r\n SipErrorHandler,\r\n SipErrorFormatter,\r\n SipErrorPayload,\r\n} from \"../core/sipErrorHandler\";\r\nimport { SipStateStore } from \"../core/sipStateStore\";\r\nimport { createUAHandlers } from \"./handlers/uaHandlers\";\r\nimport { createSessionHandlers } from \"./handlers/sessionHandlers\";\r\nimport { SessionManager } from \"./sessionManager\";\r\nimport { removeSessionState } from \"./sessionState\";\r\nimport { SessionLifecycle } from \"./sessionLifecycle\";\r\n\r\ntype SipClientOptions = {\r\n errorMessages?: Record<string, string>;\r\n formatError?: SipErrorFormatter;\r\n errorHandler?: SipErrorHandler;\r\n debug?: boolean | string;\r\n};\r\n\r\nexport type MicrophoneRecoveryOptions = {\r\n intervalMs?: number;\r\n maxRetries?: number;\r\n};\r\n\r\nconst SESSION_DEBUG_KEY = \"sip-debug-enabled\";\r\n\r\nexport class SipClient extends EventTargetEmitter<JsSIPEventMap> {\r\n public readonly userAgent = new SipUserAgent();\r\n public readonly stateStore = new SipStateStore();\r\n\r\n private readonly uaHandlers: Partial<UAEventMap>;\r\n private readonly uaHandlerKeys: (keyof UAEventMap)[];\r\n private sessionHandlers = new Map<string, Partial<RTCSessionEventMap>>();\r\n private readonly errorHandler: SipErrorHandler;\r\n private debugPattern?: boolean | string;\r\n private maxSessionCount = Infinity;\r\n private sessionManager = new SessionManager();\r\n private lifecycle: SessionLifecycle;\r\n private micRecovery = new Map<string, { stop: () => void }>();\r\n private micRecoveryEnabled = false;\r\n private micRecoveryDefaults: Required<MicrophoneRecoveryOptions> = {\r\n intervalMs: 2000,\r\n maxRetries: Infinity,\r\n };\r\n private unloadHandler?: () => void;\r\n private stateLogOff?: () => void;\r\n\r\n public get state(): SipState {\r\n return this.stateStore.getState();\r\n }\r\n\r\n constructor(options: SipClientOptions = {}) {\r\n super();\r\n\r\n this.errorHandler =\r\n options.errorHandler ??\r\n new SipErrorHandler({\r\n formatter: options.formatError,\r\n messages: options.errorMessages,\r\n });\r\n this.debugPattern = options.debug;\r\n\r\n this.uaHandlers = createUAHandlers({\r\n emitter: this,\r\n state: this.stateStore,\r\n cleanupAllSessions: () => this.cleanupAllSessions(),\r\n emitError: (raw, code, fallback) => this.emitError(raw, code, fallback),\r\n onNewRTCSession: (e: RTCSessionEvent) => this.onNewRTCSession(e),\r\n });\r\n\r\n this.uaHandlerKeys = Object.keys(this.uaHandlers) as (keyof UAEventMap)[];\r\n\r\n this.lifecycle = new SessionLifecycle({\r\n state: this.stateStore,\r\n sessionManager: this.sessionManager,\r\n emit: (event, payload) => this.emit(event as any, payload as any),\r\n emitError: (raw, code, fallback) => this.emitError(raw, code, fallback),\r\n attachSessionHandlers: (sessionId, session) =>\r\n this.attachSessionHandlers(sessionId, session),\r\n getMaxSessionCount: () => this.maxSessionCount,\r\n });\r\n\r\n if (typeof window !== \"undefined\") {\r\n // Let window.sipSupport trigger client debug toggles.\r\n (window as any).sipDebugBridge = (debug?: boolean | string) =>\r\n this.setDebug(debug ?? true);\r\n }\r\n }\r\n\r\n public connect(uri: string, password: string, config: SipConfiguration) {\r\n this.disconnect();\r\n this.stateStore.setState({ sipStatus: SipStatus.Connecting });\r\n const {\r\n debug: cfgDebug,\r\n enableMicRecovery,\r\n micRecoveryIntervalMs,\r\n micRecoveryMaxRetries,\r\n maxSessionCount,\r\n pendingMediaTtlMs,\r\n ...uaCfg\r\n } = config;\r\n this.maxSessionCount =\r\n typeof maxSessionCount === \"number\" ? maxSessionCount : Infinity;\r\n this.micRecoveryEnabled = Boolean(enableMicRecovery);\r\n if (typeof micRecoveryIntervalMs === \"number\") {\r\n this.micRecoveryDefaults.intervalMs = micRecoveryIntervalMs;\r\n }\r\n if (typeof micRecoveryMaxRetries === \"number\") {\r\n this.micRecoveryDefaults.maxRetries = micRecoveryMaxRetries;\r\n }\r\n this.sessionManager.setPendingMediaTtl(pendingMediaTtlMs);\r\n // Config debug has priority, then persisted session flag, then prior setting.\r\n const debug = cfgDebug ?? this.getPersistedDebug() ?? this.debugPattern;\r\n this.userAgent.start(uri, password, uaCfg, { debug });\r\n this.attachUAHandlers();\r\n this.attachBeforeUnload();\r\n this.syncDebugInspector(debug);\r\n }\r\n\r\n public registerUA() {\r\n this.userAgent.register();\r\n }\r\n\r\n public disconnect() {\r\n this.detachBeforeUnload();\r\n this.detachUAHandlers();\r\n this.userAgent.stop();\r\n this.cleanupAllSessions();\r\n this.stateStore.reset();\r\n }\r\n\r\n public call(target: string, callOptions: CallOptions = {}) {\r\n try {\r\n const opts = this.ensureMediaConstraints(callOptions);\r\n if (opts.mediaStream)\r\n this.sessionManager.enqueueOutgoingMedia(opts.mediaStream);\r\n\r\n const ua = this.userAgent.getUA();\r\n ua?.call(target, opts);\r\n } catch (e: unknown) {\r\n const err = this.emitError(e, \"CALL_FAILED\", \"call failed\");\r\n this.cleanupAllSessions();\r\n this.stateStore.batchSet({\r\n error: err.cause,\r\n });\r\n }\r\n }\r\n\r\n public answer(sessionId: string, options: AnswerOptions = {}) {\r\n const resolved = this.resolveExistingSessionId(sessionId);\r\n if (!resolved) return false;\r\n return this.answerSession(resolved, options);\r\n }\r\n public hangup(sessionId: string, options?: TerminateOptions) {\r\n const resolved = this.resolveExistingSessionId(sessionId);\r\n if (!resolved) return false;\r\n return this.hangupSession(resolved, options);\r\n }\r\n\r\n public hangupAll(options?: TerminateOptions) {\r\n const ids = this.getSessionIds();\r\n ids.forEach((id) => this.hangupSession(id, options));\r\n return ids.length > 0;\r\n }\r\n\r\n public toggleMute(sessionId: string) {\r\n return this.toggleMuteSession(sessionId);\r\n }\r\n public toggleHold(sessionId: string) {\r\n return this.toggleHoldSession(sessionId);\r\n }\r\n public sendDTMF(\r\n sessionId: string,\r\n tones: string | number,\r\n options?: DTMFOptions\r\n ) {\r\n return this.sendDTMFSession(sessionId, tones, options);\r\n }\r\n public transfer(sessionId: string, target: string, options?: ReferOptions) {\r\n return this.transferSession(sessionId, target, options);\r\n }\r\n\r\n public onChange(fn: (s: SipState) => void) {\r\n return this.stateStore.onChange(fn);\r\n }\r\n\r\n private attachUAHandlers() {\r\n const ua = this.userAgent.ua;\r\n if (!ua) return;\r\n\r\n this.detachUAHandlers();\r\n this.uaHandlerKeys.forEach((ev) => {\r\n const h = this.uaHandlers[ev];\r\n if (h) ua.on(ev, h as any);\r\n });\r\n }\r\n\r\n public setDebug(debug?: boolean | string) {\r\n this.debugPattern = debug;\r\n this.userAgent.setDebug(debug);\r\n this.syncDebugInspector(debug);\r\n }\r\n\r\n private attachSessionHandlers(sessionId: string, session: RTCSession) {\r\n const handlers = this.createSessionHandlersFor(sessionId, session);\r\n this.sessionHandlers.set(sessionId, handlers);\r\n\r\n (Object.keys(handlers) as (keyof RTCSessionEventMap)[]).forEach((ev) => {\r\n const h = handlers[ev];\r\n if (h) session.on(ev, h as any);\r\n });\r\n }\r\n\r\n private detachSessionHandlers(sessionId: string, session: RTCSession) {\r\n const handlers = this.sessionHandlers.get(sessionId);\r\n if (!handlers || !session) return;\r\n (Object.keys(handlers) as (keyof RTCSessionEventMap)[]).forEach((ev) => {\r\n const h = handlers[ev];\r\n if (h) session.off(ev, h as any);\r\n });\r\n this.sessionHandlers.delete(sessionId);\r\n }\r\n\r\n private detachUAHandlers() {\r\n const ua = this.userAgent.ua;\r\n if (!ua) return;\r\n this.uaHandlerKeys.forEach((ev) => {\r\n const h = this.uaHandlers[ev];\r\n if (h) ua.off(ev, h as any);\r\n });\r\n }\r\n\r\n private cleanupSession(sessionId: string, session?: RTCSession) {\r\n const targetSession =\r\n session ??\r\n this.sessionManager.getSession(sessionId) ??\r\n this.sessionManager.getRtc(sessionId)?.currentSession;\r\n this.detachSessionHandlers(sessionId, targetSession as any);\r\n this.disableMicrophoneRecovery(sessionId);\r\n this.sessionManager.cleanupSession(sessionId);\r\n removeSessionState(this.stateStore, sessionId);\r\n }\r\n\r\n private cleanupAllSessions() {\r\n this.sessionManager.cleanupAllSessions();\r\n this.micRecovery.forEach((entry) => entry.stop());\r\n this.micRecovery.clear();\r\n this.sessionHandlers.clear();\r\n this.stateStore.setState({\r\n sessions: [],\r\n error: null,\r\n });\r\n }\r\n\r\n private createSessionHandlersFor(\r\n sessionId: string,\r\n session: RTCSession\r\n ): Partial<RTCSessionEventMap> {\r\n const rtc = this.sessionManager.getOrCreateRtc(sessionId, session);\r\n return createSessionHandlers({\r\n emitter: this,\r\n state: this.stateStore,\r\n rtc,\r\n detachSessionHandlers: () => this.cleanupSession(sessionId, session),\r\n emitError: (raw, code, fallback) => this.emitError(raw, code, fallback),\r\n onSessionFailed: (err?: string, event?: RTCSessionEvent) =>\r\n this.onSessionFailed(err, event),\r\n onSessionConfirmed: (confirmedSessionId) => {\r\n if (this.micRecoveryEnabled) {\r\n this.enableMicrophoneRecovery(confirmedSessionId);\r\n }\r\n },\r\n sessionId,\r\n });\r\n }\r\n\r\n protected onNewRTCSession(e: RTCSessionEvent) {\r\n this.lifecycle.handleNewRTCSession(e);\r\n }\r\n\r\n protected onSessionFailed(error?: string, event?: RTCSessionEvent) {\r\n const rawCause = (event as any)?.cause ?? error;\r\n const statusCode = (event as any)?.message?.status_code;\r\n const statusText = (event as any)?.message?.reason_phrase;\r\n const causeText =\r\n rawCause ||\r\n (statusCode\r\n ? `${statusCode}${statusText ? \" \" + statusText : \"\"}`\r\n : \"call failed\");\r\n this.emitError(\r\n { raw: event, cause: rawCause, statusCode, statusText },\r\n \"SESSION_FAILED\",\r\n causeText\r\n );\r\n }\r\n\r\n private emitError(\r\n raw: unknown,\r\n code?: string,\r\n fallback?: string\r\n ): SipErrorPayload {\r\n const payload = this.errorHandler.format({ raw, code, fallback });\r\n this.emit(\"error\", payload);\r\n return payload;\r\n }\r\n\r\n private resolveSessionId(sessionId?: string) {\r\n if (sessionId) return sessionId;\r\n const sessions = this.stateStore.getState().sessions;\r\n const active = sessions.find((s) => s.status === CallStatus.Active);\r\n return active?.id ?? sessions[0]?.id ?? null;\r\n }\r\n\r\n private sessionExists(sessionId: string) {\r\n return (\r\n !!this.sessionManager.getSession(sessionId) ||\r\n !!this.sessionManager.getRtc(sessionId)\r\n );\r\n }\r\n\r\n private resolveExistingSessionId(sessionId?: string) {\r\n const id = this.resolveSessionId(sessionId);\r\n if (!id) return null;\r\n return this.sessionExists(id) ? id : null;\r\n }\r\n\r\n private ensureMediaConstraints<\r\n T extends {\r\n mediaStream?: MediaStream;\r\n mediaConstraints?: MediaStreamConstraints;\r\n }\r\n >(opts: T): T {\r\n if (opts.mediaStream || opts.mediaConstraints) return opts;\r\n return { ...opts, mediaConstraints: { audio: true, video: false } } as T;\r\n }\r\n\r\n public answerSession(sessionId: string, options: AnswerOptions = {}) {\r\n if (!sessionId || !this.sessionExists(sessionId)) return false;\r\n const opts = this.ensureMediaConstraints(options);\r\n if (opts.mediaStream) {\r\n this.sessionManager.setSessionMedia(sessionId, opts.mediaStream);\r\n }\r\n return this.sessionManager.answer(sessionId, opts);\r\n }\r\n\r\n public hangupSession(sessionId: string, options?: TerminateOptions) {\r\n if (!sessionId || !this.sessionExists(sessionId)) return false;\r\n return this.sessionManager.hangup(sessionId, options);\r\n }\r\n\r\n public toggleMuteSession(sessionId?: string) {\r\n const resolved = this.resolveExistingSessionId(sessionId);\r\n if (!resolved) return false;\r\n const sessionState = this.stateStore\r\n .getState()\r\n .sessions.find((s) => s.id === resolved);\r\n const muted = sessionState?.muted ?? false;\r\n if (muted) {\r\n this.sessionManager.unmute(resolved);\r\n return true;\r\n }\r\n this.sessionManager.mute(resolved);\r\n return true;\r\n }\r\n\r\n public toggleHoldSession(sessionId?: string) {\r\n const resolved = this.resolveExistingSessionId(sessionId);\r\n if (!resolved) return false;\r\n const sessionState = this.stateStore\r\n .getState()\r\n .sessions.find((s) => s.id === resolved);\r\n const isOnHold = sessionState?.status === CallStatus.Hold;\r\n if (isOnHold) {\r\n this.sessionManager.unhold(resolved);\r\n return true;\r\n }\r\n if (sessionState?.status === CallStatus.Active) {\r\n this.sessionManager.hold(resolved);\r\n return true;\r\n }\r\n return true;\r\n }\r\n\r\n public sendDTMFSession(\r\n sessionId: string,\r\n tones: string | number,\r\n options?: DTMFOptions\r\n ) {\r\n const resolved = this.resolveExistingSessionId(sessionId);\r\n if (!resolved) return false;\r\n const sessionState = this.stateStore\r\n .getState()\r\n .sessions.find((s) => s.id === resolved);\r\n if (sessionState?.status === CallStatus.Active)\r\n this.sessionManager.sendDTMF(resolved, tones, options);\r\n return true;\r\n }\r\n\r\n public transferSession(\r\n sessionId: string,\r\n target: string,\r\n options?: ReferOptions\r\n ) {\r\n const resolved = this.resolveExistingSessionId(sessionId);\r\n if (!resolved) return false;\r\n const sessionState = this.stateStore\r\n .getState()\r\n .sessions.find((s) => s.id === resolved);\r\n if (sessionState?.status === CallStatus.Active)\r\n this.sessionManager.transfer(resolved, target, options);\r\n return true;\r\n }\r\n\r\n public setSessionMedia(sessionId: string, stream: MediaStream) {\r\n this.sessionManager.setSessionMedia(sessionId, stream);\r\n }\r\n\r\n public enableMicrophoneRecovery(\r\n sessionId: string,\r\n options: MicrophoneRecoveryOptions = {}\r\n ) {\r\n const resolved = this.resolveExistingSessionId(sessionId);\r\n if (!resolved) return () => {};\r\n\r\n this.disableMicrophoneRecovery(resolved);\r\n\r\n const intervalMs =\r\n options.intervalMs ?? this.micRecoveryDefaults.intervalMs;\r\n const maxRetries =\r\n options.maxRetries ?? this.micRecoveryDefaults.maxRetries;\r\n let retries = 0;\n let stopped = false;\n const startedAt = Date.now();\n const warmupMs = Math.max(intervalMs * 2, 2000);\n\r\n const tick = async () => {\r\n if (stopped || retries >= maxRetries) return;\r\n\r\n const rtc = this.sessionManager.getRtc(resolved);\r\n const session = this.sessionManager.getSession(resolved);\r\n if (!rtc || !session) return;\r\n\r\n const sessionState = this.stateStore\r\n .getState()\r\n .sessions.find((s) => s.id === resolved);\r\n if (sessionState?.muted) return;\r\n\r\n const stream = rtc.mediaStream;\n const track = stream?.getAudioTracks?.()[0];\n const sender = (session as any)?.connection\n ?.getSenders?.()\n .find((s: RTCRtpSender) => s.track?.kind === \"audio\");\n\n if (!track && !sender) return;\n\n if (Date.now() - startedAt < warmupMs) return;\n\n const trackLive = track?.readyState === \"live\";\n const senderLive = sender?.track?.readyState === \"live\";\n if (trackLive && senderLive) return;\n\r\n this.emitError(\r\n {\r\n cause: \"microphone dropped\",\r\n trackLive,\r\n senderLive,\r\n },\r\n \"MICROPHONE_DROPPED\",\r\n \"microphone dropped\"\r\n );\r\n\r\n retries += 1;\r\n if (trackLive && !senderLive && track) {\r\n await rtc.replaceAudioTrack(track);\r\n return;\r\n }\r\n\r\n let nextStream: MediaStream;\r\n try {\r\n const deviceId =\r\n track?.getSettings?.().deviceId ??\r\n sender?.track?.getSettings?.().deviceId;\r\n nextStream = await this.requestMicrophoneStreamInternal(deviceId);\r\n } catch (err) {\r\n console.warn(\"[sip] mic recovery failed to get stream\", err);\r\n return;\r\n }\r\n const nextTrack = nextStream.getAudioTracks()[0];\r\n if (!nextTrack) return;\r\n\r\n await rtc.replaceAudioTrack(nextTrack);\r\n this.sessionManager.setSessionMedia(resolved, nextStream);\r\n };\r\n\r\n const timer = setInterval(() => {\r\n void tick();\r\n }, intervalMs);\r\n void tick();\r\n\r\n const session = this.sessionManager.getSession(resolved);\r\n const pc: RTCPeerConnection | undefined = (session as any)?.connection;\r\n const onIceChange = () => {\r\n const state = pc?.iceConnectionState;\r\n if (state === \"failed\" || state === \"disconnected\") void tick();\r\n };\r\n pc?.addEventListener?.(\"iceconnectionstatechange\", onIceChange);\r\n\r\n const stop = () => {\r\n stopped = true;\r\n clearInterval(timer);\r\n pc?.removeEventListener?.(\"iceconnectionstatechange\", onIceChange);\r\n };\r\n this.micRecovery.set(resolved, { stop });\r\n return stop;\r\n }\r\n\r\n public disableMicrophoneRecovery(sessionId: string) {\r\n const resolved = this.resolveExistingSessionId(sessionId);\r\n if (!resolved) return false;\r\n const entry = this.micRecovery.get(resolved);\r\n if (!entry) return false;\r\n entry.stop();\r\n this.micRecovery.delete(resolved);\r\n return true;\r\n }\r\n\r\n public switchCameraSession(sessionId: string, track: MediaStreamTrack) {\r\n if (!this.sessionExists(sessionId)) return false;\r\n const rtc = this.sessionManager.getRtc(sessionId);\r\n return rtc ? rtc.switchCamera(track) : false;\r\n }\r\n\r\n public enableVideoSession(sessionId: string) {\r\n if (!this.sessionExists(sessionId)) return false;\r\n const rtc = this.sessionManager.getRtc(sessionId);\r\n rtc?.enableVideo();\r\n return !!rtc;\r\n }\r\n\r\n public disableVideoSession(sessionId: string) {\r\n if (!this.sessionExists(sessionId)) return false;\r\n const rtc = this.sessionManager.getRtc(sessionId);\r\n rtc?.disableVideo();\r\n return !!rtc;\r\n }\r\n\r\n public getSession(sessionId: string) {\r\n return this.sessionManager.getSession(sessionId);\r\n }\r\n\r\n public getSessionIds() {\r\n return this.sessionManager.getSessionIds();\r\n }\r\n\r\n public getSessions() {\r\n return this.sessionManager.getSessions();\r\n }\r\n\r\n private attachBeforeUnload() {\r\n if (typeof window === \"undefined\" || this.unloadHandler) return;\r\n\r\n const handler = () => {\r\n this.hangupAll();\r\n this.disconnect();\r\n };\r\n\r\n window.addEventListener(\"beforeunload\", handler);\r\n this.unloadHandler = handler;\r\n }\r\n\r\n private detachBeforeUnload() {\r\n if (typeof window === \"undefined\" || !this.unloadHandler) return;\r\n window.removeEventListener(\"beforeunload\", this.unloadHandler);\r\n this.unloadHandler = undefined;\r\n }\r\n\r\n private syncDebugInspector(debug?: boolean | string) {\r\n if (typeof window === \"undefined\") return;\r\n this.toggleStateLogger(Boolean(debug));\r\n\r\n const win = window as any;\r\n const disabledInspector = () => {\r\n console.warn(\"SIP debug inspector disabled; enable debug to inspect.\");\r\n return null;\r\n };\r\n win.sipState = () =>\r\n debug ? this.stateStore.getState() : disabledInspector();\r\n win.sipSessions = () => (debug ? this.getSessions() : disabledInspector());\r\n }\r\n\r\n private toggleStateLogger(enabled: boolean) {\r\n if (!enabled) {\r\n this.stateLogOff?.();\r\n this.stateLogOff = undefined;\r\n return;\r\n }\r\n if (this.stateLogOff) return;\r\n\r\n let prev = this.stateStore.getState();\r\n // Emit initial snapshot right away for visibility.\r\n console.info(\"[sip][state]\", { initial: true }, prev);\r\n\r\n this.stateLogOff = this.stateStore.onChange((next) => {\r\n const changes = this.diffState(prev, next);\r\n if (changes) {\r\n // Log concise diff and the current snapshot for quick inspection.\r\n console.info(\"[sip][state]\", changes, next);\r\n }\r\n prev = next;\r\n });\r\n }\r\n\r\n private diffState(\r\n prev: SipState,\r\n next: SipState\r\n ): Record<string, { from: unknown; to: unknown }> | null {\r\n const changed: Record<string, { from: unknown; to: unknown }> = {};\r\n for (const key of Object.keys(next) as Array<keyof SipState>) {\r\n if (prev[key] !== next[key]) {\r\n changed[key as string] = { from: prev[key], to: next[key] };\r\n }\r\n }\r\n return Object.keys(changed).length ? changed : null;\r\n }\r\n\r\n private getPersistedDebug(): boolean | string | undefined {\r\n if (typeof window === \"undefined\") return undefined;\r\n try {\r\n const persisted = window.sessionStorage.getItem(SESSION_DEBUG_KEY);\r\n if (!persisted) return undefined;\r\n return persisted;\r\n } catch {\r\n return undefined;\r\n }\r\n }\r\n\r\n private async requestMicrophoneStreamInternal(\r\n deviceId?: string\r\n ): Promise<MediaStream> {\r\n if (\r\n typeof navigator === \"undefined\" ||\r\n !navigator.mediaDevices?.getUserMedia\r\n ) {\r\n throw new Error(\"getUserMedia not available\");\r\n }\r\n const audio =\r\n deviceId && deviceId !== \"default\"\r\n ? { deviceId: { exact: deviceId } }\r\n : true;\r\n try {\r\n return await navigator.mediaDevices.getUserMedia({ audio });\r\n } catch (err: any) {\r\n const cause = err?.name || \"getUserMedia failed\";\r\n this.emitError(\r\n { raw: err, cause },\r\n \"MICROPHONE_UNAVAILABLE\",\r\n \"microphone unavailable\"\r\n );\r\n throw err;\r\n }\r\n }\r\n}\r\n\r\nexport function createSipClientInstance(options?: SipClientOptions): SipClient {\r\n return new SipClient(options);\r\n}\r\n\r\nexport function createSipEventManager(client: SipClient): SipEventManager {\r\n return {\r\n onUA(event, handler) {\r\n return client.on(event, handler as any);\r\n },\r\n onSession(sessionId, event, handler) {\r\n const session = client.getSession(sessionId);\r\n if (!session) return () => {};\r\n session.on(event as any, handler as any);\r\n return () => session.off(event as any, handler as any);\r\n },\r\n };\r\n}\r\n","import \"./sip/debugger\"; // ensure window helpers attach on load\r\n\r\nexport * from \"./sip/types\";\r\n\r\nexport {\n SipClient,\n type MicrophoneRecoveryOptions,\n createSipClientInstance,\n createSipEventManager,\n} from \"./sip/client\";\nexport {\r\n SipDebugger,\r\n sipDebugger,\r\n type SipDebugToggleResult,\r\n} from \"./sip/debugger\";\r\n\r\nexport { WebRTCSessionController } from \"./sip/sessionController\";\r\nexport { SessionManager } from \"./sip/sessionManager\";\r\n\r\nexport {\r\n SipErrorHandler,\r\n type SipErrorPayload,\r\n type SipErrorFormatter,\r\n} from \"./core/sipErrorHandler\";\r\n\r\nexport { WebSocketInterface } from \"jssip\";\r\n\r\nexport {\r\n SipStatus,\r\n CallStatus,\r\n CallDirection,\r\n SipStatusList,\r\n CallStatusList,\r\n isSipStatus,\r\n isCallStatus,\r\n} from \"./core/types\";\r\n\r\nexport type {\r\n SipStatus as SipStatusType,\r\n CallStatus as CallStatusType,\r\n CallDirection as CallDirectionType,\r\n SipState,\r\n SipSessionState,\r\n} from \"./core/types\";\r\n","import { createContext } from \"react\";\r\nimport type { SipClient } from \"jssip-lib\";\r\nimport type { SipEventManager } from \"jssip-lib\";\r\n\r\nexport type SipContextType = { client: SipClient, sipEventManager: SipEventManager };\r\nexport const SipContext = createContext<SipContextType | null>(null);\r\n","import { useCallback, useSyncExternalStore } from \"react\";\r\nimport type { SipState } from \"jssip-lib\";\r\nimport { useSip } from \"./useSip\";\r\n\r\nexport function useSipState(): SipState {\r\n const { client } = useSip();\r\n const subscribe = useCallback(\r\n (onStoreChange: () => void) => client.onChange(onStoreChange),\r\n [client]\r\n );\r\n\r\n const getSnapshot = useCallback(() => client.state, [client]);\r\n\r\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\r\n}\r\n","import { useContext } from \"react\";\r\nimport { SipContext } from \"../context\";\r\n\r\nexport function useSip() {\r\n const ctx = useContext(SipContext);\r\n if (!ctx) throw new Error(\"Must be used within SipProvider\");\r\n return ctx;\r\n}\r\n","import { useMemo } from \"react\";\nimport { useSip } from \"./useSip\";\n\nexport function useSipActions() {\n const { client } = useSip();\n return useMemo(\n () => ({\n call: (...args: Parameters<typeof client.call>) => client.call(...args),\n answer: (...args: Parameters<typeof client.answerSession>) =>\n client.answerSession(...args),\n hangup: (...args: Parameters<typeof client.hangupSession>) =>\n client.hangupSession(...args),\n toggleMute: (...args: Parameters<typeof client.toggleMuteSession>) =>\n client.toggleMuteSession(...args),\n toggleHold: (...args: Parameters<typeof client.toggleHoldSession>) =>\n client.toggleHoldSession(...args),\n sendDTMF: (...args: Parameters<typeof client.sendDTMFSession>) =>\n client.sendDTMFSession(...args),\n transfer: (...args: Parameters<typeof client.transferSession>) =>\n client.transferSession(...args),\n getSession: (...args: Parameters<typeof client.getSession>) =>\n client.getSession(...args),\n getSessionIds: () => client.getSessionIds(),\n getSessions: () => client.getSessions(),\n setSessionMedia: (...args: Parameters<typeof client.setSessionMedia>) =>\n client.setSessionMedia(...args),\n enableMicrophoneRecovery: (\n ...args: Parameters<typeof client.enableMicrophoneRecovery>\n ) => client.enableMicrophoneRecovery(...args),\n disableMicrophoneRecovery: (\n ...args: Parameters<typeof client.disableMicrophoneRecovery>\n ) => client.disableMicrophoneRecovery(...args),\n switchCamera: (...args: Parameters<typeof client.switchCameraSession>) =>\n client.switchCameraSession(...args),\n enableVideo: (...args: Parameters<typeof client.enableVideoSession>) =>\n client.enableVideoSession(...args),\n disableVideo: (...args: Parameters<typeof client.disableVideoSession>) =>\n client.disableVideoSession(...args),\n }),\n [client]\n );\n}\n","import type { SipState } from \"jssip-lib\";\nimport { useSipState } from \"./useSipState\";\n\nexport function useSipSessions(): Pick<SipState, \"sessions\"> {\n const { sessions } = useSipState();\n return { sessions };\n}\n","import { useEffect } from \"react\";\nimport type {\n SessionEventName,\n SessionEventPayload,\n UAEventName,\n UAEventPayload,\n} from \"jssip-lib\";\nimport { useSip } from \"./useSip\";\n\nexport function useSipEvent<K extends UAEventName>(\n event: K,\n handler?: (payload?: UAEventPayload<K>) => void\n) {\n const { sipEventManager } = useSip();\n\n useEffect(() => {\n if (!handler) return;\n return sipEventManager.onUA(event, handler);\n }, [event, handler, sipEventManager]);\n}\n\nexport function useSipSessionEvent<K extends SessionEventName>(\n sessionId: string,\n event: K,\n handler?: (payload?: SessionEventPayload<K>) => void\n) {\n const { sipEventManager } = useSip();\n\n useEffect(() => {\n if (!handler) return;\n return sipEventManager.onSession(sessionId, event, handler);\n }, [event, handler, sessionId, sipEventManager]);\n}\n","import { useEffect, useRef } from \"react\";\r\nimport { useSip } from \"../hooks/useSip\";\r\nimport { createCallPlayer } from \"jssip-lib/dom\";\r\n\r\nexport function CallPlayer({ sessionId }: { sessionId?: string }) {\r\n const { client } = useSip();\r\n const audioRef = useRef<HTMLAudioElement | null>(null);\r\n\r\n useEffect(() => {\r\n if (!audioRef.current) return;\r\n\r\n const player = createCallPlayer(audioRef.current);\r\n const session = sessionId ? client.getSession(sessionId) : null;\r\n const off = session\r\n ? player.bindToSession(session)\r\n : player.bindToClient(client);\r\n\r\n return () => {\r\n off?.();\r\n player.detach();\r\n };\r\n }, [client, sessionId]);\r\n\r\n return <audio ref={audioRef} autoPlay playsInline />;\r\n}\r\n","import { SipClient } from \"../../sip/client\";\r\nimport type { RTCSession, RTCSessionEvent } from \"../../sip/types\";\r\n\r\nexport function createCallPlayer(audioEl: HTMLAudioElement) {\r\n let cleanupTrackListener: (() => void) | null = null;\r\n let cleanupSessionPeerListener: (() => void) | null = null;\r\n let cleanupClientListeners: (() => void) | null = null;\r\n\r\n const dispose = (fn: (() => void) | null) => {\r\n if (fn) fn();\r\n return null as null;\r\n };\r\n\r\n /** Stop all tracks and clear audio element */\r\n function clearAudioStream(stream?: MediaStream | null) {\r\n if (stream) {\r\n for (const t of stream.getTracks()) {\r\n t.stop();\r\n }\r\n }\r\n audioEl.srcObject = null;\r\n }\r\n\r\n const attachTracks = (pc: RTCPeerConnection) => {\r\n const onTrack = (e: RTCTrackEvent) => {\r\n if (e.track.kind !== \"audio\") return;\r\n\r\n const nextStream = e.streams?.[0] ?? new MediaStream([e.track]);\r\n const prev = audioEl.srcObject as MediaStream | null;\r\n\r\n if (prev && prev !== nextStream) {\r\n clearAudioStream(prev);\r\n }\r\n\r\n audioEl.srcObject = nextStream;\r\n audioEl.play?.().catch(() => {});\r\n };\r\n\r\n pc.addEventListener(\"track\", onTrack);\r\n return () => pc.removeEventListener(\"track\", onTrack);\r\n };\r\n\r\n const listenSessionPeerconnection = (session: RTCSession) => {\r\n const onPeer = (data: { peerconnection: RTCPeerConnection }) => {\r\n cleanupTrackListener = dispose(cleanupTrackListener);\r\n cleanupTrackListener = attachTracks(data.peerconnection);\r\n };\r\n session.on(\"peerconnection\", onPeer);\r\n return () => session.off(\"peerconnection\", onPeer);\r\n };\r\n\r\n function bindToSession(session: RTCSession) {\r\n if (\r\n session?.direction === \"outgoing\" &&\r\n session.connection instanceof RTCPeerConnection\r\n ) {\r\n cleanupTrackListener = dispose(cleanupTrackListener);\r\n cleanupTrackListener = attachTracks(session.connection);\r\n }\r\n\r\n cleanupSessionPeerListener = dispose(cleanupSessionPeerListener);\r\n cleanupSessionPeerListener = listenSessionPeerconnection(session);\r\n\r\n return () => {\r\n cleanupSessionPeerListener = dispose(cleanupSessionPeerListener);\r\n cleanupTrackListener = dispose(cleanupTrackListener);\r\n };\r\n }\r\n\r\n function bindToClient(client: SipClient) {\r\n const offNew = client.on(\"newRTCSession\", (payload) => {\r\n const e = (payload as any)?.data as RTCSessionEvent | undefined;\r\n cleanupSessionPeerListener = dispose(cleanupSessionPeerListener);\r\n cleanupTrackListener = dispose(cleanupTrackListener);\r\n\r\n if (!e?.session) return;\r\n\r\n cleanupSessionPeerListener = listenSessionPeerconnection(e.session);\r\n if (\r\n e.session.direction === \"outgoing\" &&\r\n e.session.connection instanceof RTCPeerConnection\r\n ) {\r\n cleanupTrackListener = attachTracks(e.session.connection);\r\n }\r\n });\r\n\r\n const offEnded = client.on(\"ended\", () => detach());\r\n const offFailed = client.on(\"failed\", () => detach());\r\n const offDisconnected = client.on(\"disconnected\", () => detach());\r\n\r\n cleanupClientListeners = () => {\r\n offNew();\r\n offEnded();\r\n offFailed();\r\n offDisconnected();\r\n };\r\n return cleanupClientListeners;\r\n }\r\n\r\n function detach() {\r\n cleanupClientListeners = dispose(cleanupClientListeners);\r\n cleanupSessionPeerListener = dispose(cleanupSessionPeerListener);\r\n cleanupTrackListener = dispose(cleanupTrackListener);\r\n clearAudioStream(audioEl.srcObject as MediaStream | null);\r\n }\r\n\r\n return {\r\n bindToSession,\r\n bindToClient,\r\n detach,\r\n };\r\n}\r\n","import React, { useMemo } from \"react\";\nimport { SipContext } from \"../context\";\nimport { createSipEventManager, type SipClient, type SipEventManager } from \"jssip-lib\";\n\nexport function SipProvider({\n client,\n children,\n sipEventManager,\n}: {\n sipEventManager?: SipEventManager;\n client: SipClient;\n children: React.ReactNode;\n}) {\n const manager = useMemo(\n () => sipEventManager ?? createSipEventManager(client),\n [client, sipEventManager]\n );\n\n const contextValue = useMemo(() => ({ client, sipEventManager: manager }), [client, manager]);\n\n return (\n <SipContext.Provider value={contextValue}>\n {children}\n </SipContext.Provider>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/jssip-lib/sip/debugger.ts","../src/jssip-lib/sip/userAgent.ts","../src/jssip-lib/core/types.ts","../src/jssip-lib/core/eventEmitter.ts","../src/jssip-lib/core/sipErrorHandler.ts","../src/jssip-lib/core/sipState.ts","../src/jssip-lib/core/sipStateStore.ts","../src/jssip-lib/sip/handlers/uaHandlers.ts","../src/jssip-lib/sip/sessionState.ts","../src/jssip-lib/sip/handlers/sessionHandlers.ts","../src/jssip-lib/sip/sessionController.ts","../src/jssip-lib/sip/sessionManager.ts","../src/jssip-lib/sip/sessionLifecycle.ts","../src/jssip-lib/sip/client.ts","../src/jssip-lib/index.ts","../src/context/index.tsx","../src/hooks/useSipState.ts","../src/hooks/useSip.ts","../src/hooks/useSipActions.ts","../src/hooks/useSipSessions.ts","../src/hooks/useSipEvent.ts","../src/components/call-player.tsx","../src/jssip-lib/adapters/dom/createCallPlayer.ts","../src/provider/index.tsx"],"names":["JsSIP","message","session","pc","useEffect","useMemo","jsx"],"mappings":"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","sourcesContent":["import JsSIP from \"jssip\";\n\ntype StorageLike = Pick<Storage, \"getItem\" | \"setItem\" | \"removeItem\">;\n\nexport interface SipDebugToggleResult {\n debug: boolean;\n text: string;\n}\n\n/**\n * Browser-friendly debugger toggle for JsSIP.\n * Persists preference in sessionStorage and exposes helpers on window for console use.\n */\nexport class SipDebugger {\n private readonly storageKey: string;\n private readonly defaultPattern: string;\n private enabled = false;\n private logger: any;\n\n constructor(storageKey = \"sip-debug-enabled\", defaultPattern = \"JsSIP:*\") {\n this.storageKey = storageKey;\n this.defaultPattern = defaultPattern;\n }\n\n initFromSession(storage: StorageLike | null = safeSessionStorage()): void {\n try {\n const saved = storage?.getItem(this.storageKey);\n if (saved) this.enable(saved, storage);\n } catch {\n /* ignore */\n }\n }\n\n enable(\n pattern: string = this.defaultPattern,\n storage: StorageLike | null = safeSessionStorage()\n ): void {\n try {\n if (typeof JsSIP?.debug?.enable === \"function\") {\n JsSIP.debug.enable(pattern);\n this.logger = console;\n }\n // Persist pattern in sessionStorage only.\n storage?.setItem?.(this.storageKey, pattern || this.defaultPattern);\n try {\n (window as any).sipDebugBridge?.(pattern);\n } catch {\n /* ignore */\n }\n this.enabled = true;\n } catch {\n /* ignore */\n }\n }\n\n disable(storage: StorageLike | null = safeSessionStorage()): void {\n try {\n if (typeof JsSIP?.debug?.disable === \"function\") {\n JsSIP.debug.disable();\n } else if (typeof JsSIP?.debug?.enable === \"function\") {\n JsSIP.debug.enable(\"\");\n }\n storage?.removeItem?.(this.storageKey);\n try {\n (window as any).sipDebugBridge?.(false);\n } catch {\n /* ignore */\n }\n this.enabled = false;\n } catch {\n /* ignore */\n }\n }\n\n toggle(\n pattern: string = this.defaultPattern,\n storage: StorageLike | null = safeSessionStorage()\n ): void {\n if (this.isEnabled()) {\n this.disable(storage);\n } else {\n this.enable(pattern, storage);\n }\n }\n\n isEnabled(): boolean {\n return this.enabled;\n }\n\n attachToWindow(win: Window & typeof globalThis = window): void {\n const api = {\n enableDebug: (): SipDebugToggleResult => {\n this.enable();\n return { debug: this.isEnabled(), text: \"press F5\" };\n },\n disableDebug: (): SipDebugToggleResult => {\n this.disable();\n return { debug: this.isEnabled(), text: \"press F5\" };\n },\n toggleDebug: (): SipDebugToggleResult => {\n this.toggle();\n return { debug: this.isEnabled(), text: \"press F5\" };\n },\n debugState: (): SipDebugToggleResult => ({\n debug: this.isEnabled(),\n text: this.isEnabled() ? \"enabled\" : \"disabled\",\n }),\n sipState: () => {\n try {\n const getter = (win as any).sipState;\n return typeof getter === \"function\"\n ? getter()\n : \"sipState helper not available; ensure client debug is enabled\";\n } catch {\n return \"sipState helper not available\";\n }\n },\n sipSessions: () => {\n try {\n const getter = (win as any).sipSessions;\n return typeof getter === \"function\"\n ? getter()\n : \"sipSessions helper not available; ensure client debug is enabled\";\n } catch {\n return \"sipSessions helper not available\";\n }\n },\n };\n\n try {\n (win as any).sipSupport = api;\n } catch {\n /* ignore */\n }\n }\n}\n\nfunction safeSessionStorage(): StorageLike | null {\n if (typeof window === \"undefined\") return null;\n try {\n return window.sessionStorage;\n } catch {\n return null;\n }\n}\n\nexport const sipDebugger = new SipDebugger();\nif (typeof window !== \"undefined\") {\n sipDebugger.attachToWindow();\n sipDebugger.initFromSession();\n}\n","import JsSIP, { UA } from \"jssip\";\r\nimport { SipConfiguration, UAConfiguration } from \"./types\";\r\n\r\ntype StartOpts = { debug?: boolean | string };\r\n\r\nexport class SipUserAgent {\r\n private _ua: UA | null = null;\r\n\r\n public get ua(): UA | null {\r\n return this._ua;\r\n }\r\n public get isStarted(): boolean {\r\n return !!this._ua;\r\n }\r\n public get isRegistered(): boolean {\r\n return !!this._ua?.isRegistered();\r\n }\r\n\r\n public start(\r\n uri: string,\r\n password: string,\r\n config: Omit<SipConfiguration, \"debug\">,\r\n opts?: StartOpts\r\n ): UA {\r\n this.stop();\r\n const uaCfg = this.buildUAConfig(config, uri, password);\r\n this.ensureValid(uaCfg);\r\n this.applyDebug(opts?.debug);\r\n const ua = this.createUA(uaCfg);\r\n ua.start();\r\n this._ua = ua;\r\n return ua;\r\n }\r\n\r\n public register(): void {\r\n const ua = this.getUA();\r\n if (!ua?.isRegistered()) ua?.register();\r\n }\r\n\r\n public stop(): void {\r\n const ua = this._ua;\r\n if (!ua) return;\r\n try {\r\n if (ua.isRegistered()) ua.unregister();\r\n ua.stop();\r\n } finally {\r\n this._ua = null;\r\n }\r\n }\r\n\r\n public getUA(): UA | null {\r\n return this._ua;\r\n }\r\n\r\n public setDebug(debug?: boolean | string): void {\r\n this.applyDebug(debug);\r\n }\r\n\r\n protected buildUAConfig(\r\n config: Omit<SipConfiguration, \"debug\">,\r\n uri: string,\r\n password: string\r\n ): UAConfiguration {\r\n return { ...(config as UAConfiguration), uri, password };\r\n }\r\n\r\n protected ensureValid(cfg: UAConfiguration): void {\r\n const sockets = cfg.sockets as UAConfiguration[\"sockets\"];\r\n if (\r\n !cfg.uri ||\r\n !cfg.password ||\r\n !sockets ||\r\n (Array.isArray(sockets) && sockets.length === 0)\r\n ) {\r\n throw new Error(\r\n \"Invalid SIP connect args: require uri, password, and at least one socket\"\r\n );\r\n }\r\n }\r\n\r\n protected applyDebug(debug?: boolean | string): void {\n const stored = debug === undefined ? this.readSessionFlag() : debug;\n const enabled = !!stored;\n const pattern = typeof stored === \"string\" ? stored : \"JsSIP:*\";\n\n if (enabled) {\n JsSIP.debug.enable(pattern);\n const dbg: any = (JsSIP as any).debug;\n if (dbg?.setLogger) dbg.setLogger(console);\n else if (dbg) dbg.logger = console;\n this.persistSessionFlag(typeof stored === \"string\" ? stored : undefined);\n } else {\n (JsSIP.debug as any)?.disable?.();\n this.clearSessionFlag();\n }\n }\n\r\n protected createUA(cfg: UAConfiguration): UA {\r\n return new JsSIP.UA(cfg);\r\n }\r\n\r\n private readSessionFlag(): string | false {\n try {\n if (typeof window === \"undefined\") return false;\n const value = window.sessionStorage.getItem(\"sip-debug-enabled\");\n if (!value) return false;\n return value;\n } catch {\n return false;\n }\n }\n\n private persistSessionFlag(pattern?: string): void {\n try {\n if (typeof window !== \"undefined\") {\n window.sessionStorage.setItem(\n \"sip-debug-enabled\",\n pattern || \"JsSIP:*\"\n );\n }\n } catch {\n /* ignore */\n }\n }\r\n\r\n private clearSessionFlag(): void {\r\n try {\r\n if (typeof window !== \"undefined\") {\r\n window.sessionStorage.removeItem(\"sip-debug-enabled\");\r\n }\r\n } catch {\r\n /* ignore */\r\n }\r\n }\r\n}\r\n","import { Originator } from \"jssip/src/RTCSession\";\r\n\r\nexport const SipStatus = {\r\n Disconnected: \"disconnected\",\r\n Connecting: \"connecting\",\r\n Connected: \"connected\",\r\n Registered: \"registered\",\r\n Unregistered: \"unregistered\",\r\n RegistrationFailed: \"registrationFailed\",\r\n} as const;\r\n\r\nexport type SipStatus = (typeof SipStatus)[keyof typeof SipStatus];\r\n\r\nexport const CallStatus = {\r\n Idle: \"idle\",\r\n Dialing: \"dialing\",\r\n Ringing: \"ringing\",\r\n Active: \"active\",\r\n Hold: \"hold\",\r\n} as const;\r\nexport type CallStatus = (typeof CallStatus)[keyof typeof CallStatus];\r\n\r\nexport type CallDirection = Originator.LOCAL | Originator.REMOTE;\r\n\r\nexport type SipSessionState = {\r\n id: string;\r\n status: CallStatus;\r\n direction: CallDirection | null;\r\n from: string | null;\r\n to: string | null;\r\n muted: boolean;\r\n acceptedAt: number | null;\r\n mediaKind: \"audio\" | \"video\";\r\n remoteVideoEnabled: boolean;\r\n};\r\n\r\nexport interface SipState {\r\n sipStatus: SipStatus;\r\n error: string | null;\r\n sessions: SipSessionState[];\r\n}\r\n\r\nexport const SipStatusList = Object.values(SipStatus);\r\nexport const CallStatusList = Object.values(CallStatus);\r\n\r\nexport function isSipStatus(v: unknown): v is SipStatus {\r\n return (\r\n typeof v === \"string\" && (SipStatusList as readonly string[]).includes(v)\r\n );\r\n}\r\nexport function isCallStatus(v: unknown): v is CallStatus {\r\n return (\r\n typeof v === \"string\" && (CallStatusList as readonly string[]).includes(v)\r\n );\r\n}\r\n\r\nexport type Unsubscribe = () => void;\r\nexport type Listener<T> = (value: T) => void;\r\n","export type Listener<T = any> = (payload: T) => void;\r\n\r\nexport class EventTargetEmitter<Events extends Record<string, any> = any> {\r\n private target = new EventTarget();\r\n\r\n on<K extends keyof Events>(event: K, fn: Listener<Events[K]>): () => void {\r\n const wrapper = (e: Event) => fn((e as CustomEvent<Events[K]>).detail);\r\n this.target.addEventListener(event as string, wrapper);\r\n return () => this.target.removeEventListener(event as string, wrapper);\r\n }\r\n\r\n emit<K extends keyof Events>(event: K, payload?: Events[K]): void {\r\n this.target.dispatchEvent(\r\n new CustomEvent(event as string, { detail: payload })\r\n );\r\n }\r\n}\r\n","export interface SipErrorPayload {\r\n cause: string;\r\n code?: string;\r\n raw?: any;\r\n message?: string;\r\n}\r\n\r\nexport interface SipErrorFormatInput {\r\n raw: any;\r\n code?: string;\r\n fallback?: string;\r\n}\r\n\r\nexport type SipErrorFormatter = (\r\n input: SipErrorFormatInput\r\n) => SipErrorPayload | undefined;\r\n\r\ntype SipErrorHandlerOptions = {\r\n formatter?: SipErrorFormatter;\r\n messages?: Record<string, string>;\r\n};\r\n\r\nexport class SipErrorHandler {\r\n private readonly formatter?: SipErrorFormatter;\r\n private readonly messages?: Record<string, string>;\r\n\r\n constructor(options: SipErrorHandlerOptions = {}) {\r\n this.formatter = options.formatter;\r\n this.messages = options.messages;\r\n }\r\n\r\n format(input: SipErrorFormatInput): SipErrorPayload {\r\n const { code, raw, fallback } = input;\r\n const mappedMessage =\r\n code && this.messages ? this.messages[code] : undefined;\r\n\r\n // Allow consumer to fully customize formatting.\r\n if (this.formatter) {\r\n const custom = this.formatter({\r\n raw,\r\n code,\r\n fallback: mappedMessage ?? fallback,\r\n });\r\n const message =\r\n custom?.message ??\r\n custom?.cause ??\r\n mappedMessage ??\r\n fallback ??\r\n this.readRawMessage(raw) ??\r\n \"unknown error\";\r\n\r\n return {\r\n cause: custom?.cause ?? message,\r\n code: custom?.code ?? code,\r\n raw: custom?.raw ?? raw,\r\n message,\r\n };\r\n }\r\n\r\n const message =\r\n mappedMessage ?? this.readRawMessage(raw) ?? fallback ?? \"unknown error\";\r\n\r\n return {\r\n cause: message,\r\n code,\r\n raw,\r\n message,\r\n };\r\n }\r\n\r\n private readRawMessage(raw: any): string | undefined {\r\n if (raw == null) return undefined;\r\n if (typeof raw === \"string\") return raw;\r\n if (typeof raw?.cause === \"string\") return raw.cause;\r\n if (typeof raw?.message === \"string\") return raw.message;\r\n return undefined;\r\n }\r\n}\r\n","import { SipState, SipStatus } from \"./types\";\r\n\r\nexport function getInitialSipState(): SipState {\r\n return {\r\n sipStatus: SipStatus.Disconnected,\r\n error: null,\r\n sessions: [],\r\n };\r\n}\r\n\r\nexport function shallowEqual(objA: any, objB: any): boolean {\r\n if (objA === objB) return true;\r\n if (!objA || !objB) return false;\r\n const keysA = Object.keys(objA);\r\n const keysB = Object.keys(objB);\r\n if (keysA.length !== keysB.length) return false;\r\n for (const key of keysA) {\r\n if (objA[key] !== objB[key]) return false;\r\n }\r\n return true;\r\n}\r\n","import { SipState } from \"./types\";\r\nimport { getInitialSipState, shallowEqual } from \"./sipState\";\r\n\r\nexport type SipStateListener = (state: SipState) => void;\r\n\r\nexport class SipStateStore {\r\n private state: SipState = getInitialSipState();\r\n private lastState: SipState = getInitialSipState();\r\n private listeners = new Set<SipStateListener>();\r\n private pendingState: Partial<SipState> | null = null;\r\n private updateScheduled = false;\r\n\r\n getState(): SipState {\r\n return this.state;\r\n }\r\n\r\n onChange(fn: SipStateListener): () => void {\r\n this.listeners.add(fn);\r\n fn(this.state);\r\n return () => this.listeners.delete(fn);\r\n }\r\n\r\n subscribe(fn: SipStateListener): () => void {\r\n return this.onChange(fn);\r\n }\r\n\r\n setState(partial: Partial<SipState>) {\r\n if (!partial || Object.keys(partial).length === 0) return;\r\n const next = { ...this.state, ...partial };\r\n // Fast-path: if sessions reference unchanged and shallow contents equal, skip emit.\r\n if (next.sessions === this.lastState.sessions && shallowEqual(this.lastState, next)) {\r\n return;\r\n }\r\n this.state = next;\r\n this.lastState = next;\r\n this.emit();\r\n }\r\n\r\n batchSet(partial: Partial<SipState>) {\r\n this.pendingState = { ...this.pendingState, ...partial };\r\n if (!this.updateScheduled) {\r\n this.updateScheduled = true;\r\n queueMicrotask(() => {\r\n if (this.pendingState) this.setState(this.pendingState);\r\n this.pendingState = null;\r\n this.updateScheduled = false;\r\n });\r\n }\r\n }\r\n\r\n reset(overrides: Partial<SipState> = {}) {\r\n this.setState({ ...getInitialSipState(), ...overrides });\r\n }\r\n\r\n private emit() {\r\n for (const fn of this.listeners) fn(this.state);\r\n }\r\n}\r\n","import { UAEventMap } from \"../types\";\r\nimport { SipStatus } from \"../../core/types\";\r\nimport { SipStateStore } from \"../../core/sipStateStore\";\r\nimport { JsSIPEventMap } from \"../types\";\r\nimport { EventTargetEmitter } from \"../../core/eventEmitter\";\r\nimport { SipErrorPayload } from \"../../core/sipErrorHandler\";\r\n\r\ntype Deps = {\r\n emitter: EventTargetEmitter<JsSIPEventMap>;\r\n state: SipStateStore;\r\n cleanupAllSessions: () => void;\r\n emitError: (\r\n raw: any,\r\n code?: string,\r\n fallback?: string\r\n ) => SipErrorPayload;\r\n onNewRTCSession: UAEventMap[\"newRTCSession\"];\r\n};\r\n\r\nexport function createUAHandlers(deps: Deps): Partial<UAEventMap> {\r\n const { emitter, state, cleanupAllSessions, emitError, onNewRTCSession } =\r\n deps;\r\n\r\n return {\r\n connecting: (e: any) => {\r\n emitter.emit(\"connecting\", e);\r\n state.batchSet({ sipStatus: SipStatus.Connecting });\r\n },\r\n connected: (e: any) => {\r\n emitter.emit(\"connected\", e);\r\n state.batchSet({ sipStatus: SipStatus.Connected });\r\n },\r\n disconnected: (e: any) => {\r\n emitter.emit(\"disconnected\", e);\r\n cleanupAllSessions();\r\n state.reset();\r\n },\r\n\r\n registered: (e: any) => {\r\n emitter.emit(\"registered\", e);\r\n state.batchSet({ sipStatus: SipStatus.Registered, error: null });\r\n },\r\n unregistered: (e: any) => {\r\n emitter.emit(\"unregistered\", e);\r\n state.batchSet({ sipStatus: SipStatus.Unregistered });\r\n },\r\n registrationFailed: (e: any) => {\r\n emitter.emit(\"registrationFailed\", e);\r\n cleanupAllSessions();\r\n emitError(\r\n {\r\n raw: e,\r\n cause: e?.cause,\r\n statusCode: e?.response?.status_code,\r\n statusText: e?.response?.reason_phrase,\r\n },\r\n \"REGISTRATION_FAILED\",\r\n \"registration failed\"\r\n );\r\n state.batchSet({\r\n sipStatus: SipStatus.RegistrationFailed,\r\n error: e?.cause || \"registration failed\",\r\n });\r\n },\r\n newRTCSession: onNewRTCSession,\r\n newMessage: (e: any) => emitter.emit(\"newMessage\", e),\r\n sipEvent: (e: any) => emitter.emit(\"sipEvent\", e),\r\n newOptions: (e: any) => emitter.emit(\"newOptions\", e),\r\n };\r\n}\r\n","import { CallStatus, SipSessionState } from \"../core/types\";\r\nimport { SipStateStore } from \"../core/sipStateStore\";\r\n\r\nexport function holdOtherSessions(\r\n state: SipStateStore,\r\n sessionId: string,\r\n holdFn: (id: string) => void\r\n) {\r\n const current = state.getState();\r\n current.sessions.forEach((s) => {\r\n if (s.id === sessionId) return;\r\n if (s.status === CallStatus.Active) {\r\n holdFn(s.id);\r\n }\r\n });\r\n}\r\n\r\nexport function upsertSessionState(\r\n state: SipStateStore,\r\n sessionId: string,\r\n partial: Partial<SipSessionState>\r\n) {\r\n const current = state.getState();\r\n const existing = current.sessions.find((s) => s.id === sessionId);\r\n const base: SipSessionState = existing ?? {\r\n id: sessionId,\r\n status: CallStatus.Idle,\r\n direction: null,\r\n from: null,\r\n to: null,\r\n muted: false,\r\n acceptedAt: null,\r\n mediaKind: \"audio\",\r\n remoteVideoEnabled: false,\r\n };\r\n\r\n const nextSession = { ...base, ...partial };\r\n const sessions = existing\r\n ? current.sessions.map((s) => (s.id === sessionId ? nextSession : s))\r\n : [...current.sessions, nextSession];\r\n\r\n state.setState({ sessions });\r\n}\r\n\r\nexport function removeSessionState(state: SipStateStore, sessionId: string) {\r\n const current = state.getState();\r\n const sessions = current.sessions.filter((s) => s.id !== sessionId);\r\n state.setState({\r\n sessions,\r\n error: null,\r\n });\r\n}\r\n","import { EndEvent, RTCSessionEventMap } from \"../types\";\nimport { CallStatus } from \"../../core/types\";\nimport { SipStateStore } from \"../../core/sipStateStore\";\nimport { WebRTCSessionController } from \"../sessionController\";\nimport { JsSIPEventMap } from \"../types\";\nimport { EventTargetEmitter } from \"../../core/eventEmitter\";\nimport { SipErrorPayload } from \"../../core/sipErrorHandler\";\nimport { upsertSessionState } from \"../sessionState\";\nimport { IncomingAckEvent, IncomingEvent, OutgoingAckEvent, OutgoingEvent } from \"jssip/src/RTCSession\";\n\ntype Deps = {\n emitter: EventTargetEmitter<JsSIPEventMap>;\n state: SipStateStore;\n rtc: WebRTCSessionController;\n detachSessionHandlers: () => void;\n emitError: (raw: any, code?: string, fallback?: string) => SipErrorPayload;\n onSessionFailed: (error?: string, event?: any) => void;\n onSessionAccepted?: (sessionId: string) => void;\n sessionId: string;\n};\n\nexport function createSessionHandlers(deps: Deps): Partial<RTCSessionEventMap> {\n const {\n emitter,\n state,\n rtc,\n detachSessionHandlers,\n onSessionFailed,\n onSessionConfirmed,\n sessionId,\n } = deps;\n\n return {\n progress: (e: IncomingEvent | OutgoingEvent) => {\n emitter.emit(\"progress\", e);\n },\n accepted: (e: IncomingEvent | OutgoingEvent) => {\n emitter.emit(\"accepted\", e);\n onSessionAccepted?.(sessionId);\n state.batchSet({\n sessions: state.getState().sessions.map((s) =>\n s.id === sessionId\n ? {\n ...s,\n status: CallStatus.Active,\n acceptedAt: s.acceptedAt ?? Date.now(),\n }\n : s\n ),\n });\n },\n confirmed: (e: IncomingAckEvent | OutgoingAckEvent) => {\n emitter.emit(\"confirmed\", e);\n onSessionConfirmed?.(sessionId);\n },\n\n ended: (e: EndEvent) => {\n emitter.emit(\"ended\", e);\n detachSessionHandlers();\n rtc.cleanup();\n const nextSessions = state\n .getState()\n .sessions.filter((s) => s.id !== sessionId);\n state.batchSet({\n sessions: nextSessions,\n });\n },\n failed: (e: EndEvent) => {\n emitter.emit(\"failed\", e);\n detachSessionHandlers();\n rtc.cleanup();\n const cause = e?.cause || \"call failed\";\n onSessionFailed(cause, e);\n const nextSessions = state\n .getState()\n .sessions.filter((s) => s.id !== sessionId);\n state.batchSet({\n sessions: nextSessions,\n });\n },\n\n muted: () => {\n emitter.emit(\"muted\", undefined);\n upsertSessionState(state, sessionId, { muted: true });\n },\n unmuted: () => {\n emitter.emit(\"unmuted\", undefined);\n upsertSessionState(state, sessionId, { muted: false });\n },\n hold: () => {\n emitter.emit(\"hold\", undefined);\n upsertSessionState(state, sessionId, { status: CallStatus.Hold });\n },\n unhold: () => {\n emitter.emit(\"unhold\", undefined);\n upsertSessionState(state, sessionId, { status: CallStatus.Active });\n },\n\n reinvite: (e: any) => emitter.emit(\"reinvite\", e),\n update: (e: any) => emitter.emit(\"update\", e),\n sdp: (e: any) => emitter.emit(\"sdp\", e),\n icecandidate: (e: any) => emitter.emit(\"icecandidate\", e),\n refer: (e: any) => emitter.emit(\"refer\", e),\n replaces: (e: any) => emitter.emit(\"replaces\", e),\n newDTMF: (e: any) => emitter.emit(\"newDTMF\", e),\n newInfo: (e: any) => emitter.emit(\"newInfo\", e),\n\n getusermediafailed: (e: any) => {\n emitter.emit(\"getusermediafailed\", e);\n detachSessionHandlers();\n rtc.cleanup();\n onSessionFailed(\"getUserMedia failed\", e);\n state.batchSet({\n sessions: state.getState().sessions.filter((s) => s.id !== sessionId),\n });\n },\n \"peerconnection:createofferfailed\": (e: any) => {\n emitter.emit(\"peerconnection:createofferfailed\", e);\n detachSessionHandlers();\n rtc.cleanup();\n onSessionFailed(\"peer connection createOffer failed\", e);\n state.batchSet({\n sessions: state.getState().sessions.filter((s) => s.id !== sessionId),\n });\n },\n \"peerconnection:createanswerfailed\": (e: any) => {\n emitter.emit(\"peerconnection:createanswerfailed\", e);\n detachSessionHandlers();\n rtc.cleanup();\n onSessionFailed(\"peer connection createAnswer failed\", e);\n state.batchSet({\n sessions: state.getState().sessions.filter((s) => s.id !== sessionId),\n });\n },\n \"peerconnection:setlocaldescriptionfailed\": (e: any) => {\n emitter.emit(\"peerconnection:setlocaldescriptionfailed\", e);\n detachSessionHandlers();\n rtc.cleanup();\n onSessionFailed(\"peer connection setLocalDescription failed\", e);\n state.batchSet({\n sessions: state.getState().sessions.filter((s) => s.id !== sessionId),\n });\n },\n \"peerconnection:setremotedescriptionfailed\": (e: any) => {\n emitter.emit(\"peerconnection:setremotedescriptionfailed\", e);\n detachSessionHandlers();\n rtc.cleanup();\n onSessionFailed(\"peer connection setRemoteDescription failed\", e);\n state.batchSet({\n sessions: state.getState().sessions.filter((s) => s.id !== sessionId),\n });\n },\n peerconnection: (e: any) => emitter.emit(\"peerconnection\", e),\n };\n}\n","import type {\r\n AnswerOptions,\r\n DTMFOptions,\r\n ReferOptions,\r\n RTCSession,\r\n TerminateOptions,\r\n} from \"./types\";\r\n\r\nexport class WebRTCSessionController {\r\n currentSession: RTCSession | null = null;\r\n mediaStream: MediaStream | null = null;\r\n\r\n public setSession(session: RTCSession | null) {\r\n this.currentSession = session;\r\n }\r\n\r\n public setMediaStream(stream: MediaStream) {\r\n this.mediaStream = stream;\r\n }\r\n\r\n private getPC(): RTCPeerConnection | null {\r\n return (this.currentSession as any)?.connection ?? null;\r\n }\r\n\r\n public cleanup(stopTracks: boolean = true): void {\r\n const pc = this.getPC();\r\n\r\n if (pc && typeof pc.getSenders === \"function\") {\r\n const isClosed =\r\n pc.connectionState === \"closed\" || pc.signalingState === \"closed\";\r\n if (!isClosed) {\r\n for (const s of pc.getSenders()) {\r\n try {\r\n s.replaceTrack(null);\r\n } catch {\r\n // ignore if sender/pc already closed\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (stopTracks && this.mediaStream) {\r\n for (const t of this.mediaStream.getTracks()) t.stop();\r\n }\r\n\r\n this.mediaStream = null;\r\n this.currentSession = null;\r\n }\r\n\r\n public answer(options: AnswerOptions = {}): boolean {\r\n return this.currentSession\r\n ? (this.currentSession.answer(options), true)\r\n : false;\r\n }\r\n\r\n public hangup(options?: TerminateOptions): boolean {\r\n return this.currentSession\r\n ? (this.currentSession.terminate(\r\n options ?? ({ status_code: 486, reason_phrase: \"Busy Here\" } as any)\r\n ),\r\n true)\r\n : false;\r\n }\r\n\r\n public mute(): boolean {\r\n this.mediaStream?.getAudioTracks().forEach((t) => (t.enabled = false));\r\n return this.currentSession\r\n ? (this.currentSession.mute({ audio: true }), true)\r\n : false;\r\n }\r\n\r\n public unmute(): boolean {\r\n this.mediaStream?.getAudioTracks().forEach((t) => (t.enabled = true));\r\n return this.currentSession\r\n ? (this.currentSession.unmute({ audio: true }), true)\r\n : false;\r\n }\r\n\r\n public hold(): boolean {\r\n return this.currentSession ? (this.currentSession.hold(), true) : false;\r\n }\r\n\r\n public unhold(): boolean {\r\n return this.currentSession ? (this.currentSession.unhold(), true) : false;\r\n }\r\n\r\n public sendDTMF(tones: string | number, options?: DTMFOptions): boolean {\r\n return this.currentSession\r\n ? (this.currentSession.sendDTMF(tones, options), true)\r\n : false;\r\n }\r\n\r\n public transfer(target: string, options?: ReferOptions): boolean {\r\n return this.currentSession\r\n ? (this.currentSession.refer(target as any, options), true)\r\n : false;\r\n }\r\n\r\n public enableVideo(): void {\r\n this.mediaStream?.getVideoTracks().forEach((t) => (t.enabled = true));\r\n }\r\n\r\n public disableVideo(): void {\r\n this.mediaStream?.getVideoTracks().forEach((t) => (t.enabled = false));\r\n }\r\n\r\n public async switchCamera(\n nextVideoTrack: MediaStreamTrack\n ): Promise<boolean> {\n const pc = this.getPC();\r\n if (!pc) return false;\r\n\r\n if (!this.mediaStream) this.mediaStream = new MediaStream();\r\n\r\n const old = this.mediaStream.getVideoTracks()[0];\r\n this.mediaStream.addTrack(nextVideoTrack);\r\n if (old) this.mediaStream.removeTrack(old);\r\n\r\n const sender = pc.getSenders?.().find((s) => s.track?.kind === \"video\");\r\n if (sender) await sender.replaceTrack(nextVideoTrack);\r\n\r\n if (old && old !== nextVideoTrack) old.stop();\r\n\r\n return true;\n }\n\n public async replaceAudioTrack(\n nextAudioTrack: MediaStreamTrack\n ): Promise<boolean> {\n const pc = this.getPC();\n if (!pc) return false;\n\n if (!this.mediaStream) this.mediaStream = new MediaStream();\n\n const old = this.mediaStream.getAudioTracks()[0];\n this.mediaStream.addTrack(nextAudioTrack);\n if (old) this.mediaStream.removeTrack(old);\n\n const sender = pc.getSenders?.().find((s) => s.track?.kind === \"audio\");\n if (sender) await sender.replaceTrack(nextAudioTrack);\n\n if (old && old !== nextAudioTrack) old.stop();\n\n return true;\n }\n}\n","import { WebRTCSessionController } from \"./sessionController\";\r\nimport type { RTCSession } from \"./types\";\r\n\r\ntype SessionEntry = {\r\n rtc: WebRTCSessionController;\r\n session?: RTCSession | null;\r\n media?: MediaStream | null;\r\n};\r\n\r\nexport class SessionManager {\r\n private entries = new Map<string, SessionEntry>();\r\n private pendingMediaQueue: Array<{ stream: MediaStream; addedAt: number }> =\r\n [];\r\n private pendingMediaTtlMs = 30000;\r\n\r\n setPendingMediaTtl(ms: number | undefined) {\r\n if (typeof ms === \"number\" && ms > 0) this.pendingMediaTtlMs = ms;\r\n }\r\n\r\n enqueueOutgoingMedia(stream: MediaStream) {\r\n this.pendingMediaQueue.push({ stream, addedAt: Date.now() });\r\n }\r\n\r\n dequeueOutgoingMedia(): MediaStream | null {\r\n const now = Date.now();\r\n while (this.pendingMediaQueue.length) {\r\n const next = this.pendingMediaQueue.shift();\r\n if (!next) break;\r\n if (now - next.addedAt <= this.pendingMediaTtlMs) {\r\n return next.stream;\r\n } else {\r\n // drop stale stream\r\n next.stream.getTracks().forEach((t) => t.stop());\r\n }\r\n }\r\n return null;\r\n }\r\n\r\n getOrCreateRtc(sessionId: string, session?: RTCSession) {\r\n let entry = this.entries.get(sessionId);\r\n if (!entry) {\r\n entry = {\r\n rtc: new WebRTCSessionController(),\r\n session: null,\r\n media: null,\r\n };\r\n this.entries.set(sessionId, entry);\r\n }\r\n if (session) {\r\n entry.session = session;\r\n entry.rtc.setSession(session);\r\n }\r\n if (entry.media) entry.rtc.setMediaStream(entry.media);\r\n return entry.rtc;\r\n }\r\n\r\n getRtc(sessionId: string) {\r\n return this.entries.get(sessionId)?.rtc ?? null;\r\n }\r\n\r\n setSession(sessionId: string, session: RTCSession) {\r\n const entry = this.entries.get(sessionId);\r\n if (entry) {\r\n entry.session = session;\r\n entry.rtc.setSession(session);\r\n } else {\r\n this.entries.set(sessionId, {\r\n rtc: new WebRTCSessionController(),\r\n session,\r\n media: null,\r\n });\r\n }\r\n }\r\n\r\n setSessionMedia(sessionId: string, stream: MediaStream) {\r\n const entry = this.entries.get(sessionId) ?? {\r\n rtc: new WebRTCSessionController(),\r\n session: null,\r\n media: null,\r\n };\r\n entry.media = stream;\r\n entry.rtc.setMediaStream(stream);\r\n this.entries.set(sessionId, entry);\r\n }\r\n\r\n getSession(sessionId: string) {\r\n return this.entries.get(sessionId)?.session ?? null;\r\n }\r\n\r\n getSessionIds() {\r\n return Array.from(this.entries.keys());\r\n }\r\n\r\n getSessions() {\r\n return Array.from(this.entries.entries()).map(([id, entry]) => ({\r\n id,\r\n session: entry.session as RTCSession,\r\n }));\r\n }\r\n\r\n getActiveSessionId(activeStatuses: string[] = [\"active\"]): string | null {\r\n for (const [id, entry] of Array.from(this.entries.entries()).reverse()) {\r\n const status = (entry.session as any)?.status;\r\n if (status && activeStatuses.includes(String(status).toLowerCase())) {\r\n return id;\r\n }\r\n }\r\n return null;\r\n }\r\n\r\n cleanupSession(sessionId: string) {\r\n const entry = this.entries.get(sessionId);\r\n if (entry) {\r\n entry.rtc.cleanup();\r\n this.entries.delete(sessionId);\r\n }\r\n }\r\n\r\n cleanupAllSessions() {\r\n for (const [, entry] of this.entries.entries()) {\r\n entry.rtc.cleanup();\r\n }\r\n this.entries.clear();\r\n this.pendingMediaQueue = [];\r\n }\r\n\r\n answer(sessionId: string, options: any) {\r\n const rtc = this.getRtc(sessionId);\r\n return rtc ? rtc.answer(options) : false;\r\n }\r\n\r\n hangup(sessionId: string, options?: any) {\r\n const rtc = this.getRtc(sessionId);\r\n return rtc ? rtc.hangup(options) : false;\r\n }\r\n\r\n mute(sessionId: string) {\r\n const rtc = this.getRtc(sessionId);\r\n return rtc ? rtc.mute() : false;\r\n }\r\n\r\n unmute(sessionId: string) {\r\n const rtc = this.getRtc(sessionId);\r\n return rtc ? rtc.unmute() : false;\r\n }\r\n\r\n hold(sessionId: string) {\r\n const rtc = this.getRtc(sessionId);\r\n return rtc ? rtc.hold() : false;\r\n }\r\n\r\n unhold(sessionId: string) {\r\n const rtc = this.getRtc(sessionId);\r\n return rtc ? rtc.unhold() : false;\r\n }\r\n\r\n sendDTMF(sessionId: string, tones: string | number, options?: any) {\r\n const rtc = this.getRtc(sessionId);\r\n return rtc ? rtc.sendDTMF(tones, options) : false;\r\n }\r\n\r\n transfer(sessionId: string, target: string, options?: any) {\r\n const rtc = this.getRtc(sessionId);\r\n return rtc ? rtc.transfer(target, options) : false;\r\n }\r\n}\r\n","import { SipStateStore } from \"../core/sipStateStore\";\r\nimport { CallDirection, CallStatus } from \"../core/types\";\r\nimport { SessionManager } from \"./sessionManager\";\r\nimport { holdOtherSessions, upsertSessionState } from \"./sessionState\";\r\nimport type { JsSIPEventName, RTCSession, RTCSessionEvent } from \"./types\";\r\nimport type { SipErrorPayload } from \"../core/sipErrorHandler\";\r\n\r\ntype Deps = {\r\n state: SipStateStore;\r\n sessionManager: SessionManager;\r\n emit: <K extends JsSIPEventName>(event: K, payload: any) => void;\r\n emitError: (raw: any, code?: string, fallback?: string) => SipErrorPayload;\r\n attachSessionHandlers: (sessionId: string, session: RTCSession) => void;\r\n getMaxSessionCount: () => number;\r\n};\r\n\r\nexport class SessionLifecycle {\r\n private readonly state: SipStateStore;\r\n private readonly sessionManager: SessionManager;\r\n private readonly emit: Deps[\"emit\"];\r\n private readonly emitError: Deps[\"emitError\"];\r\n private readonly attachSessionHandlers: Deps[\"attachSessionHandlers\"];\r\n private readonly getMaxSessionCount: Deps[\"getMaxSessionCount\"];\r\n\r\n constructor(deps: Deps) {\r\n this.state = deps.state;\r\n this.sessionManager = deps.sessionManager;\r\n this.emit = deps.emit;\r\n this.emitError = deps.emitError;\r\n this.attachSessionHandlers = deps.attachSessionHandlers;\r\n this.getMaxSessionCount = deps.getMaxSessionCount;\r\n }\r\n\r\n handleNewRTCSession(e: RTCSessionEvent) {\r\n const session = e.session;\r\n const sessionId = String((session as any)?.id ?? crypto.randomUUID?.() ?? Date.now());\r\n\r\n const currentSessions = this.state.getState().sessions;\r\n if (currentSessions.length >= this.getMaxSessionCount()) {\r\n try {\r\n session.terminate?.({ status_code: 486, reason_phrase: \"Busy Here\" } as any);\r\n } catch {\r\n /* ignore termination errors */\r\n }\r\n if (e.originator === \"remote\") {\r\n this.emit(\"missed\", e);\r\n }\r\n this.emitError(\"max session count reached\", \"MAX_SESSIONS_REACHED\", \"max session count reached\");\r\n return;\r\n }\r\n\r\n const outgoingMedia = e.originator === \"local\" ? this.sessionManager.dequeueOutgoingMedia() : null;\r\n\r\n if (outgoingMedia) this.sessionManager.setSessionMedia(sessionId, outgoingMedia);\r\n\r\n const rtc = this.sessionManager.getOrCreateRtc(sessionId, session);\r\n if (outgoingMedia) rtc.setMediaStream(outgoingMedia);\r\n\r\n this.sessionManager.setSession(sessionId, session);\r\n this.attachSessionHandlers(sessionId, session);\r\n\r\n holdOtherSessions(\r\n this.state,\r\n sessionId,\r\n (id) => {\r\n const otherRtc = this.sessionManager.getRtc(id);\r\n otherRtc?.hold();\r\n }\r\n );\r\n\r\n const sdpHasVideo =\r\n (e.request?.body && e.request.body.toString().includes(\"m=video\")) ||\r\n (session as RTCSession & { connection?: RTCPeerConnection })?.connection\r\n ?.getReceivers?.()\r\n ?.some((r: RTCRtpReceiver) => r.track?.kind === \"video\");\r\n\r\n upsertSessionState(this.state, sessionId, {\r\n direction: e.originator,\r\n from: e.originator === \"remote\" ? e.request.from.uri.user : null,\r\n to: e.request.to.uri.user,\r\n status: e.originator === \"remote\" ? CallStatus.Ringing : CallStatus.Dialing,\r\n mediaKind: sdpHasVideo ? \"video\" : \"audio\",\r\n remoteVideoEnabled: sdpHasVideo,\r\n });\r\n\r\n this.emit(\"newRTCSession\", e);\r\n }\r\n}\r\n","import { SipUserAgent } from \"./userAgent\";\r\nimport {\r\n AnswerOptions,\r\n CallOptions,\r\n DTMFOptions,\r\n JsSIPEventMap,\r\n ReferOptions,\r\n RTCSession,\r\n RTCSessionEvent,\r\n RTCSessionEventMap,\r\n SipConfiguration,\r\n SipEventManager,\r\n TerminateOptions,\r\n UAEventMap,\r\n} from \"./types\";\r\n\r\nimport { SipState, SipStatus, CallStatus } from \"../core/types\";\r\nimport { EventTargetEmitter } from \"../core/eventEmitter\";\r\nimport {\r\n SipErrorHandler,\r\n SipErrorFormatter,\r\n SipErrorPayload,\r\n} from \"../core/sipErrorHandler\";\r\nimport { SipStateStore } from \"../core/sipStateStore\";\r\nimport { createUAHandlers } from \"./handlers/uaHandlers\";\r\nimport { createSessionHandlers } from \"./handlers/sessionHandlers\";\r\nimport { SessionManager } from \"./sessionManager\";\r\nimport { removeSessionState } from \"./sessionState\";\r\nimport { SessionLifecycle } from \"./sessionLifecycle\";\r\n\r\ntype SipClientOptions = {\r\n errorMessages?: Record<string, string>;\r\n formatError?: SipErrorFormatter;\r\n errorHandler?: SipErrorHandler;\r\n debug?: boolean | string;\r\n};\r\n\r\nexport type MicrophoneRecoveryOptions = {\r\n intervalMs?: number;\r\n maxRetries?: number;\r\n};\r\n\r\nconst SESSION_DEBUG_KEY = \"sip-debug-enabled\";\r\n\r\nexport class SipClient extends EventTargetEmitter<JsSIPEventMap> {\r\n public readonly userAgent = new SipUserAgent();\r\n public readonly stateStore = new SipStateStore();\r\n\r\n private readonly uaHandlers: Partial<UAEventMap>;\r\n private readonly uaHandlerKeys: (keyof UAEventMap)[];\r\n private sessionHandlers = new Map<string, Partial<RTCSessionEventMap>>();\r\n private readonly errorHandler: SipErrorHandler;\r\n private debugPattern?: boolean | string;\r\n private maxSessionCount = Infinity;\r\n private sessionManager = new SessionManager();\r\n private lifecycle: SessionLifecycle;\r\n private micRecovery = new Map<string, { stop: () => void }>();\r\n private micRecoveryEnabled = false;\r\n private micRecoveryDefaults: Required<MicrophoneRecoveryOptions> = {\r\n intervalMs: 2000,\r\n maxRetries: Infinity,\r\n };\r\n private unloadHandler?: () => void;\r\n private stateLogOff?: () => void;\r\n\r\n public get state(): SipState {\r\n return this.stateStore.getState();\r\n }\r\n\r\n constructor(options: SipClientOptions = {}) {\r\n super();\r\n\r\n this.errorHandler =\r\n options.errorHandler ??\r\n new SipErrorHandler({\r\n formatter: options.formatError,\r\n messages: options.errorMessages,\r\n });\r\n this.debugPattern = options.debug;\r\n\r\n this.uaHandlers = createUAHandlers({\r\n emitter: this,\r\n state: this.stateStore,\r\n cleanupAllSessions: () => this.cleanupAllSessions(),\r\n emitError: (raw, code, fallback) => this.emitError(raw, code, fallback),\r\n onNewRTCSession: (e: RTCSessionEvent) => this.onNewRTCSession(e),\r\n });\r\n\r\n this.uaHandlerKeys = Object.keys(this.uaHandlers) as (keyof UAEventMap)[];\r\n\r\n this.lifecycle = new SessionLifecycle({\r\n state: this.stateStore,\r\n sessionManager: this.sessionManager,\r\n emit: (event, payload) => this.emit(event as any, payload as any),\r\n emitError: (raw, code, fallback) => this.emitError(raw, code, fallback),\r\n attachSessionHandlers: (sessionId, session) =>\r\n this.attachSessionHandlers(sessionId, session),\r\n getMaxSessionCount: () => this.maxSessionCount,\r\n });\r\n\r\n if (typeof window !== \"undefined\") {\r\n // Let window.sipSupport trigger client debug toggles.\r\n (window as any).sipDebugBridge = (debug?: boolean | string) =>\r\n this.setDebug(debug ?? true);\r\n }\r\n }\r\n\r\n public connect(uri: string, password: string, config: SipConfiguration) {\r\n this.disconnect();\r\n this.stateStore.setState({ sipStatus: SipStatus.Connecting });\r\n const {\r\n debug: cfgDebug,\r\n enableMicRecovery,\r\n micRecoveryIntervalMs,\r\n micRecoveryMaxRetries,\r\n maxSessionCount,\r\n pendingMediaTtlMs,\r\n ...uaCfg\r\n } = config;\r\n this.maxSessionCount =\r\n typeof maxSessionCount === \"number\" ? maxSessionCount : Infinity;\r\n this.micRecoveryEnabled = Boolean(enableMicRecovery);\r\n if (typeof micRecoveryIntervalMs === \"number\") {\r\n this.micRecoveryDefaults.intervalMs = micRecoveryIntervalMs;\r\n }\r\n if (typeof micRecoveryMaxRetries === \"number\") {\r\n this.micRecoveryDefaults.maxRetries = micRecoveryMaxRetries;\r\n }\r\n this.sessionManager.setPendingMediaTtl(pendingMediaTtlMs);\r\n // Config debug has priority, then persisted session flag, then prior setting.\r\n const debug = cfgDebug ?? this.getPersistedDebug() ?? this.debugPattern;\r\n this.userAgent.start(uri, password, uaCfg, { debug });\r\n this.attachUAHandlers();\r\n this.attachBeforeUnload();\r\n this.syncDebugInspector(debug);\r\n }\r\n\r\n public registerUA() {\r\n this.userAgent.register();\r\n }\r\n\r\n public disconnect() {\r\n this.detachBeforeUnload();\r\n this.detachUAHandlers();\r\n this.userAgent.stop();\r\n this.cleanupAllSessions();\r\n this.stateStore.reset();\r\n }\r\n\r\n public call(target: string, callOptions: CallOptions = {}) {\r\n try {\r\n const opts = this.ensureMediaConstraints(callOptions);\r\n if (opts.mediaStream)\r\n this.sessionManager.enqueueOutgoingMedia(opts.mediaStream);\r\n\r\n const ua = this.userAgent.getUA();\r\n ua?.call(target, opts);\r\n } catch (e: unknown) {\r\n const err = this.emitError(e, \"CALL_FAILED\", \"call failed\");\r\n this.cleanupAllSessions();\r\n this.stateStore.batchSet({\r\n error: err.cause,\r\n });\r\n }\r\n }\r\n\r\n public answer(sessionId: string, options: AnswerOptions = {}) {\r\n const resolved = this.resolveExistingSessionId(sessionId);\r\n if (!resolved) return false;\r\n return this.answerSession(resolved, options);\r\n }\r\n public hangup(sessionId: string, options?: TerminateOptions) {\r\n const resolved = this.resolveExistingSessionId(sessionId);\r\n if (!resolved) return false;\r\n return this.hangupSession(resolved, options);\r\n }\r\n\r\n public hangupAll(options?: TerminateOptions) {\r\n const ids = this.getSessionIds();\r\n ids.forEach((id) => this.hangupSession(id, options));\r\n return ids.length > 0;\r\n }\r\n\r\n public toggleMute(sessionId: string) {\r\n return this.toggleMuteSession(sessionId);\r\n }\r\n public toggleHold(sessionId: string) {\r\n return this.toggleHoldSession(sessionId);\r\n }\r\n public sendDTMF(\r\n sessionId: string,\r\n tones: string | number,\r\n options?: DTMFOptions\r\n ) {\r\n return this.sendDTMFSession(sessionId, tones, options);\r\n }\r\n public transfer(sessionId: string, target: string, options?: ReferOptions) {\r\n return this.transferSession(sessionId, target, options);\r\n }\r\n\r\n public onChange(fn: (s: SipState) => void) {\r\n return this.stateStore.onChange(fn);\r\n }\r\n\r\n private attachUAHandlers() {\r\n const ua = this.userAgent.ua;\r\n if (!ua) return;\r\n\r\n this.detachUAHandlers();\r\n this.uaHandlerKeys.forEach((ev) => {\r\n const h = this.uaHandlers[ev];\r\n if (h) ua.on(ev, h as any);\r\n });\r\n }\r\n\r\n public setDebug(debug?: boolean | string) {\r\n this.debugPattern = debug;\r\n this.userAgent.setDebug(debug);\r\n this.syncDebugInspector(debug);\r\n }\r\n\r\n private attachSessionHandlers(sessionId: string, session: RTCSession) {\r\n const handlers = this.createSessionHandlersFor(sessionId, session);\r\n this.sessionHandlers.set(sessionId, handlers);\r\n\r\n (Object.keys(handlers) as (keyof RTCSessionEventMap)[]).forEach((ev) => {\r\n const h = handlers[ev];\r\n if (h) session.on(ev, h as any);\r\n });\r\n }\r\n\r\n private detachSessionHandlers(sessionId: string, session: RTCSession) {\r\n const handlers = this.sessionHandlers.get(sessionId);\r\n if (!handlers || !session) return;\r\n (Object.keys(handlers) as (keyof RTCSessionEventMap)[]).forEach((ev) => {\r\n const h = handlers[ev];\r\n if (h) session.off(ev, h as any);\r\n });\r\n this.sessionHandlers.delete(sessionId);\r\n }\r\n\r\n private detachUAHandlers() {\r\n const ua = this.userAgent.ua;\r\n if (!ua) return;\r\n this.uaHandlerKeys.forEach((ev) => {\r\n const h = this.uaHandlers[ev];\r\n if (h) ua.off(ev, h as any);\r\n });\r\n }\r\n\r\n private cleanupSession(sessionId: string, session?: RTCSession) {\r\n const targetSession =\r\n session ??\r\n this.sessionManager.getSession(sessionId) ??\r\n this.sessionManager.getRtc(sessionId)?.currentSession;\r\n this.detachSessionHandlers(sessionId, targetSession as any);\r\n this.disableMicrophoneRecovery(sessionId);\r\n this.sessionManager.cleanupSession(sessionId);\r\n removeSessionState(this.stateStore, sessionId);\r\n }\r\n\r\n private cleanupAllSessions() {\r\n this.sessionManager.cleanupAllSessions();\r\n this.micRecovery.forEach((entry) => entry.stop());\r\n this.micRecovery.clear();\r\n this.sessionHandlers.clear();\r\n this.stateStore.setState({\r\n sessions: [],\r\n error: null,\r\n });\r\n }\r\n\r\n private createSessionHandlersFor(\r\n sessionId: string,\r\n session: RTCSession\r\n ): Partial<RTCSessionEventMap> {\r\n const rtc = this.sessionManager.getOrCreateRtc(sessionId, session);\r\n return createSessionHandlers({\r\n emitter: this,\r\n state: this.stateStore,\r\n rtc,\r\n detachSessionHandlers: () => this.cleanupSession(sessionId, session),\r\n emitError: (raw, code, fallback) => this.emitError(raw, code, fallback),\r\n onSessionFailed: (err?: string, event?: RTCSessionEvent) =>\r\n this.onSessionFailed(err, event),\r\n onSessionAccepted: (acceptedSessionId) => {\n if (this.micRecoveryEnabled) {\n this.enableMicrophoneRecovery(acceptedSessionId);\n }\n },\n sessionId,\r\n });\r\n }\r\n\r\n protected onNewRTCSession(e: RTCSessionEvent) {\r\n this.lifecycle.handleNewRTCSession(e);\r\n }\r\n\r\n protected onSessionFailed(error?: string, event?: RTCSessionEvent) {\r\n const rawCause = (event as any)?.cause ?? error;\r\n const statusCode = (event as any)?.message?.status_code;\r\n const statusText = (event as any)?.message?.reason_phrase;\r\n const causeText =\r\n rawCause ||\r\n (statusCode\r\n ? `${statusCode}${statusText ? \" \" + statusText : \"\"}`\r\n : \"call failed\");\r\n this.emitError(\r\n { raw: event, cause: rawCause, statusCode, statusText },\r\n \"SESSION_FAILED\",\r\n causeText\r\n );\r\n }\r\n\r\n private emitError(\r\n raw: unknown,\r\n code?: string,\r\n fallback?: string\r\n ): SipErrorPayload {\r\n const payload = this.errorHandler.format({ raw, code, fallback });\r\n this.emit(\"error\", payload);\r\n return payload;\r\n }\r\n\r\n private resolveSessionId(sessionId?: string) {\r\n if (sessionId) return sessionId;\r\n const sessions = this.stateStore.getState().sessions;\r\n const active = sessions.find((s) => s.status === CallStatus.Active);\r\n return active?.id ?? sessions[0]?.id ?? null;\r\n }\r\n\r\n private sessionExists(sessionId: string) {\r\n return (\r\n !!this.sessionManager.getSession(sessionId) ||\r\n !!this.sessionManager.getRtc(sessionId)\r\n );\r\n }\r\n\r\n private resolveExistingSessionId(sessionId?: string) {\r\n const id = this.resolveSessionId(sessionId);\r\n if (!id) return null;\r\n return this.sessionExists(id) ? id : null;\r\n }\r\n\r\n private ensureMediaConstraints<\r\n T extends {\r\n mediaStream?: MediaStream;\r\n mediaConstraints?: MediaStreamConstraints;\r\n }\r\n >(opts: T): T {\r\n if (opts.mediaStream || opts.mediaConstraints) return opts;\r\n return { ...opts, mediaConstraints: { audio: true, video: false } } as T;\r\n }\r\n\r\n public answerSession(sessionId: string, options: AnswerOptions = {}) {\r\n if (!sessionId || !this.sessionExists(sessionId)) return false;\r\n const opts = this.ensureMediaConstraints(options);\r\n if (opts.mediaStream) {\r\n this.sessionManager.setSessionMedia(sessionId, opts.mediaStream);\r\n }\r\n return this.sessionManager.answer(sessionId, opts);\r\n }\r\n\r\n public hangupSession(sessionId: string, options?: TerminateOptions) {\r\n if (!sessionId || !this.sessionExists(sessionId)) return false;\r\n return this.sessionManager.hangup(sessionId, options);\r\n }\r\n\r\n public toggleMuteSession(sessionId?: string) {\r\n const resolved = this.resolveExistingSessionId(sessionId);\r\n if (!resolved) return false;\r\n const sessionState = this.stateStore\r\n .getState()\r\n .sessions.find((s) => s.id === resolved);\r\n const muted = sessionState?.muted ?? false;\r\n if (muted) {\r\n this.sessionManager.unmute(resolved);\r\n return true;\r\n }\r\n this.sessionManager.mute(resolved);\r\n return true;\r\n }\r\n\r\n public toggleHoldSession(sessionId?: string) {\r\n const resolved = this.resolveExistingSessionId(sessionId);\r\n if (!resolved) return false;\r\n const sessionState = this.stateStore\r\n .getState()\r\n .sessions.find((s) => s.id === resolved);\r\n const isOnHold = sessionState?.status === CallStatus.Hold;\r\n if (isOnHold) {\r\n this.sessionManager.unhold(resolved);\r\n return true;\r\n }\r\n if (sessionState?.status === CallStatus.Active) {\r\n this.sessionManager.hold(resolved);\r\n return true;\r\n }\r\n return true;\r\n }\r\n\r\n public sendDTMFSession(\r\n sessionId: string,\r\n tones: string | number,\r\n options?: DTMFOptions\r\n ) {\r\n const resolved = this.resolveExistingSessionId(sessionId);\r\n if (!resolved) return false;\r\n const sessionState = this.stateStore\r\n .getState()\r\n .sessions.find((s) => s.id === resolved);\r\n if (sessionState?.status === CallStatus.Active)\r\n this.sessionManager.sendDTMF(resolved, tones, options);\r\n return true;\r\n }\r\n\r\n public transferSession(\r\n sessionId: string,\r\n target: string,\r\n options?: ReferOptions\r\n ) {\r\n const resolved = this.resolveExistingSessionId(sessionId);\r\n if (!resolved) return false;\r\n const sessionState = this.stateStore\r\n .getState()\r\n .sessions.find((s) => s.id === resolved);\r\n if (sessionState?.status === CallStatus.Active)\r\n this.sessionManager.transfer(resolved, target, options);\r\n return true;\r\n }\r\n\r\n public setSessionMedia(sessionId: string, stream: MediaStream) {\r\n this.sessionManager.setSessionMedia(sessionId, stream);\r\n }\r\n\r\n public enableMicrophoneRecovery(\r\n sessionId: string,\r\n options: MicrophoneRecoveryOptions = {}\r\n ) {\r\n const resolved = this.resolveExistingSessionId(sessionId);\r\n if (!resolved) return () => {};\r\n\r\n this.disableMicrophoneRecovery(resolved);\r\n\r\n const intervalMs =\r\n options.intervalMs ?? this.micRecoveryDefaults.intervalMs;\r\n const maxRetries =\r\n options.maxRetries ?? this.micRecoveryDefaults.maxRetries;\r\n let retries = 0;\n let stopped = false;\n const startedAt = Date.now();\n const warmupMs = Math.max(intervalMs * 2, 2000);\n\r\n const tick = async () => {\r\n if (stopped || retries >= maxRetries) return;\r\n\r\n const rtc = this.sessionManager.getRtc(resolved);\r\n const session = this.sessionManager.getSession(resolved);\r\n if (!rtc || !session) return;\r\n\r\n const sessionState = this.stateStore\r\n .getState()\r\n .sessions.find((s) => s.id === resolved);\r\n if (sessionState?.muted) return;\r\n\r\n const stream = rtc.mediaStream;\n const track = stream?.getAudioTracks?.()[0];\n const pc: RTCPeerConnection | undefined = (session as any)?.connection;\n const sender = pc\n ?.getSenders?.()\n .find((s: RTCRtpSender) => s.track?.kind === \"audio\");\n\n if (!track && !sender) return;\n\n if (Date.now() - startedAt < warmupMs) return;\n if (\n pc?.connectionState === \"new\" ||\n pc?.connectionState === \"connecting\" ||\n pc?.iceConnectionState === \"new\" ||\n pc?.iceConnectionState === \"checking\"\n ) {\n return;\n }\n\n const trackLive = track?.readyState === \"live\";\n const senderLive = sender?.track?.readyState === \"live\";\n if (trackLive && senderLive) return;\n\r\n this.emitError(\r\n {\r\n cause: \"microphone dropped\",\r\n trackLive,\r\n senderLive,\r\n },\r\n \"MICROPHONE_DROPPED\",\r\n \"microphone dropped\"\r\n );\r\n\r\n retries += 1;\r\n if (trackLive && !senderLive && track) {\r\n await rtc.replaceAudioTrack(track);\r\n return;\r\n }\r\n\r\n let nextStream: MediaStream;\r\n try {\r\n const deviceId =\r\n track?.getSettings?.().deviceId ??\r\n sender?.track?.getSettings?.().deviceId;\r\n nextStream = await this.requestMicrophoneStreamInternal(deviceId);\r\n } catch (err) {\r\n console.warn(\"[sip] mic recovery failed to get stream\", err);\r\n return;\r\n }\r\n const nextTrack = nextStream.getAudioTracks()[0];\r\n if (!nextTrack) return;\r\n\r\n await rtc.replaceAudioTrack(nextTrack);\r\n this.sessionManager.setSessionMedia(resolved, nextStream);\r\n };\r\n\r\n const timer = setInterval(() => {\r\n void tick();\r\n }, intervalMs);\r\n void tick();\r\n\r\n const session = this.sessionManager.getSession(resolved);\r\n const pc: RTCPeerConnection | undefined = (session as any)?.connection;\r\n const onIceChange = () => {\r\n const state = pc?.iceConnectionState;\r\n if (state === \"failed\" || state === \"disconnected\") void tick();\r\n };\r\n pc?.addEventListener?.(\"iceconnectionstatechange\", onIceChange);\r\n\r\n const stop = () => {\r\n stopped = true;\r\n clearInterval(timer);\r\n pc?.removeEventListener?.(\"iceconnectionstatechange\", onIceChange);\r\n };\r\n this.micRecovery.set(resolved, { stop });\r\n return stop;\r\n }\r\n\r\n public disableMicrophoneRecovery(sessionId: string) {\r\n const resolved = this.resolveExistingSessionId(sessionId);\r\n if (!resolved) return false;\r\n const entry = this.micRecovery.get(resolved);\r\n if (!entry) return false;\r\n entry.stop();\r\n this.micRecovery.delete(resolved);\r\n return true;\r\n }\r\n\r\n public switchCameraSession(sessionId: string, track: MediaStreamTrack) {\r\n if (!this.sessionExists(sessionId)) return false;\r\n const rtc = this.sessionManager.getRtc(sessionId);\r\n return rtc ? rtc.switchCamera(track) : false;\r\n }\r\n\r\n public enableVideoSession(sessionId: string) {\r\n if (!this.sessionExists(sessionId)) return false;\r\n const rtc = this.sessionManager.getRtc(sessionId);\r\n rtc?.enableVideo();\r\n return !!rtc;\r\n }\r\n\r\n public disableVideoSession(sessionId: string) {\r\n if (!this.sessionExists(sessionId)) return false;\r\n const rtc = this.sessionManager.getRtc(sessionId);\r\n rtc?.disableVideo();\r\n return !!rtc;\r\n }\r\n\r\n public getSession(sessionId: string) {\r\n return this.sessionManager.getSession(sessionId);\r\n }\r\n\r\n public getSessionIds() {\r\n return this.sessionManager.getSessionIds();\r\n }\r\n\r\n public getSessions() {\r\n return this.sessionManager.getSessions();\r\n }\r\n\r\n private attachBeforeUnload() {\r\n if (typeof window === \"undefined\" || this.unloadHandler) return;\r\n\r\n const handler = () => {\r\n this.hangupAll();\r\n this.disconnect();\r\n };\r\n\r\n window.addEventListener(\"beforeunload\", handler);\r\n this.unloadHandler = handler;\r\n }\r\n\r\n private detachBeforeUnload() {\r\n if (typeof window === \"undefined\" || !this.unloadHandler) return;\r\n window.removeEventListener(\"beforeunload\", this.unloadHandler);\r\n this.unloadHandler = undefined;\r\n }\r\n\r\n private syncDebugInspector(debug?: boolean | string) {\r\n if (typeof window === \"undefined\") return;\r\n this.toggleStateLogger(Boolean(debug));\r\n\r\n const win = window as any;\r\n const disabledInspector = () => {\r\n console.warn(\"SIP debug inspector disabled; enable debug to inspect.\");\r\n return null;\r\n };\r\n win.sipState = () =>\r\n debug ? this.stateStore.getState() : disabledInspector();\r\n win.sipSessions = () => (debug ? this.getSessions() : disabledInspector());\r\n }\r\n\r\n private toggleStateLogger(enabled: boolean) {\r\n if (!enabled) {\r\n this.stateLogOff?.();\r\n this.stateLogOff = undefined;\r\n return;\r\n }\r\n if (this.stateLogOff) return;\r\n\r\n let prev = this.stateStore.getState();\r\n // Emit initial snapshot right away for visibility.\r\n console.info(\"[sip][state]\", { initial: true }, prev);\r\n\r\n this.stateLogOff = this.stateStore.onChange((next) => {\r\n const changes = this.diffState(prev, next);\r\n if (changes) {\r\n // Log concise diff and the current snapshot for quick inspection.\r\n console.info(\"[sip][state]\", changes, next);\r\n }\r\n prev = next;\r\n });\r\n }\r\n\r\n private diffState(\r\n prev: SipState,\r\n next: SipState\r\n ): Record<string, { from: unknown; to: unknown }> | null {\r\n const changed: Record<string, { from: unknown; to: unknown }> = {};\r\n for (const key of Object.keys(next) as Array<keyof SipState>) {\r\n if (prev[key] !== next[key]) {\r\n changed[key as string] = { from: prev[key], to: next[key] };\r\n }\r\n }\r\n return Object.keys(changed).length ? changed : null;\r\n }\r\n\r\n private getPersistedDebug(): boolean | string | undefined {\r\n if (typeof window === \"undefined\") return undefined;\r\n try {\r\n const persisted = window.sessionStorage.getItem(SESSION_DEBUG_KEY);\r\n if (!persisted) return undefined;\r\n return persisted;\r\n } catch {\r\n return undefined;\r\n }\r\n }\r\n\r\n private async requestMicrophoneStreamInternal(\r\n deviceId?: string\r\n ): Promise<MediaStream> {\r\n if (\r\n typeof navigator === \"undefined\" ||\r\n !navigator.mediaDevices?.getUserMedia\r\n ) {\r\n throw new Error(\"getUserMedia not available\");\r\n }\r\n const audio =\r\n deviceId && deviceId !== \"default\"\r\n ? { deviceId: { exact: deviceId } }\r\n : true;\r\n try {\r\n return await navigator.mediaDevices.getUserMedia({ audio });\r\n } catch (err: any) {\r\n const cause = err?.name || \"getUserMedia failed\";\r\n this.emitError(\r\n { raw: err, cause },\r\n \"MICROPHONE_UNAVAILABLE\",\r\n \"microphone unavailable\"\r\n );\r\n throw err;\r\n }\r\n }\r\n}\r\n\r\nexport function createSipClientInstance(options?: SipClientOptions): SipClient {\r\n return new SipClient(options);\r\n}\r\n\r\nexport function createSipEventManager(client: SipClient): SipEventManager {\r\n return {\r\n onUA(event, handler) {\r\n return client.on(event, handler as any);\r\n },\r\n onSession(sessionId, event, handler) {\r\n const session = client.getSession(sessionId);\r\n if (!session) return () => {};\r\n session.on(event as any, handler as any);\r\n return () => session.off(event as any, handler as any);\r\n },\r\n };\r\n}\r\n","import \"./sip/debugger\"; // ensure window helpers attach on load\r\n\r\nexport * from \"./sip/types\";\r\n\r\nexport {\n SipClient,\n type MicrophoneRecoveryOptions,\n createSipClientInstance,\n createSipEventManager,\n} from \"./sip/client\";\nexport {\r\n SipDebugger,\r\n sipDebugger,\r\n type SipDebugToggleResult,\r\n} from \"./sip/debugger\";\r\n\r\nexport { WebRTCSessionController } from \"./sip/sessionController\";\r\nexport { SessionManager } from \"./sip/sessionManager\";\r\n\r\nexport {\r\n SipErrorHandler,\r\n type SipErrorPayload,\r\n type SipErrorFormatter,\r\n} from \"./core/sipErrorHandler\";\r\n\r\nexport { WebSocketInterface } from \"jssip\";\r\n\r\nexport {\r\n SipStatus,\r\n CallStatus,\r\n CallDirection,\r\n SipStatusList,\r\n CallStatusList,\r\n isSipStatus,\r\n isCallStatus,\r\n} from \"./core/types\";\r\n\r\nexport type {\r\n SipStatus as SipStatusType,\r\n CallStatus as CallStatusType,\r\n CallDirection as CallDirectionType,\r\n SipState,\r\n SipSessionState,\r\n} from \"./core/types\";\r\n","import { createContext } from \"react\";\r\nimport type { SipClient } from \"jssip-lib\";\r\nimport type { SipEventManager } from \"jssip-lib\";\r\n\r\nexport type SipContextType = { client: SipClient, sipEventManager: SipEventManager };\r\nexport const SipContext = createContext<SipContextType | null>(null);\r\n","import { useCallback, useSyncExternalStore } from \"react\";\r\nimport type { SipState } from \"jssip-lib\";\r\nimport { useSip } from \"./useSip\";\r\n\r\nexport function useSipState(): SipState {\r\n const { client } = useSip();\r\n const subscribe = useCallback(\r\n (onStoreChange: () => void) => client.onChange(onStoreChange),\r\n [client]\r\n );\r\n\r\n const getSnapshot = useCallback(() => client.state, [client]);\r\n\r\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\r\n}\r\n","import { useContext } from \"react\";\r\nimport { SipContext } from \"../context\";\r\n\r\nexport function useSip() {\r\n const ctx = useContext(SipContext);\r\n if (!ctx) throw new Error(\"Must be used within SipProvider\");\r\n return ctx;\r\n}\r\n","import { useMemo } from \"react\";\nimport { useSip } from \"./useSip\";\n\nexport function useSipActions() {\n const { client } = useSip();\n return useMemo(\n () => ({\n call: (...args: Parameters<typeof client.call>) => client.call(...args),\n answer: (...args: Parameters<typeof client.answerSession>) =>\n client.answerSession(...args),\n hangup: (...args: Parameters<typeof client.hangupSession>) =>\n client.hangupSession(...args),\n toggleMute: (...args: Parameters<typeof client.toggleMuteSession>) =>\n client.toggleMuteSession(...args),\n toggleHold: (...args: Parameters<typeof client.toggleHoldSession>) =>\n client.toggleHoldSession(...args),\n sendDTMF: (...args: Parameters<typeof client.sendDTMFSession>) =>\n client.sendDTMFSession(...args),\n transfer: (...args: Parameters<typeof client.transferSession>) =>\n client.transferSession(...args),\n getSession: (...args: Parameters<typeof client.getSession>) =>\n client.getSession(...args),\n getSessionIds: () => client.getSessionIds(),\n getSessions: () => client.getSessions(),\n setSessionMedia: (...args: Parameters<typeof client.setSessionMedia>) =>\n client.setSessionMedia(...args),\n enableMicrophoneRecovery: (\n ...args: Parameters<typeof client.enableMicrophoneRecovery>\n ) => client.enableMicrophoneRecovery(...args),\n disableMicrophoneRecovery: (\n ...args: Parameters<typeof client.disableMicrophoneRecovery>\n ) => client.disableMicrophoneRecovery(...args),\n switchCamera: (...args: Parameters<typeof client.switchCameraSession>) =>\n client.switchCameraSession(...args),\n enableVideo: (...args: Parameters<typeof client.enableVideoSession>) =>\n client.enableVideoSession(...args),\n disableVideo: (...args: Parameters<typeof client.disableVideoSession>) =>\n client.disableVideoSession(...args),\n }),\n [client]\n );\n}\n","import type { SipState } from \"jssip-lib\";\nimport { useSipState } from \"./useSipState\";\n\nexport function useSipSessions(): Pick<SipState, \"sessions\"> {\n const { sessions } = useSipState();\n return { sessions };\n}\n","import { useEffect } from \"react\";\nimport type {\n SessionEventName,\n SessionEventPayload,\n UAEventName,\n UAEventPayload,\n} from \"jssip-lib\";\nimport { useSip } from \"./useSip\";\n\nexport function useSipEvent<K extends UAEventName>(\n event: K,\n handler?: (payload?: UAEventPayload<K>) => void\n) {\n const { sipEventManager } = useSip();\n\n useEffect(() => {\n if (!handler) return;\n return sipEventManager.onUA(event, handler);\n }, [event, handler, sipEventManager]);\n}\n\nexport function useSipSessionEvent<K extends SessionEventName>(\n sessionId: string,\n event: K,\n handler?: (payload?: SessionEventPayload<K>) => void\n) {\n const { sipEventManager } = useSip();\n\n useEffect(() => {\n if (!handler) return;\n return sipEventManager.onSession(sessionId, event, handler);\n }, [event, handler, sessionId, sipEventManager]);\n}\n","import { useEffect, useRef } from \"react\";\r\nimport { useSip } from \"../hooks/useSip\";\r\nimport { createCallPlayer } from \"jssip-lib/dom\";\r\n\r\nexport function CallPlayer({ sessionId }: { sessionId?: string }) {\r\n const { client } = useSip();\r\n const audioRef = useRef<HTMLAudioElement | null>(null);\r\n\r\n useEffect(() => {\r\n if (!audioRef.current) return;\r\n\r\n const player = createCallPlayer(audioRef.current);\r\n const session = sessionId ? client.getSession(sessionId) : null;\r\n const off = session\r\n ? player.bindToSession(session)\r\n : player.bindToClient(client);\r\n\r\n return () => {\r\n off?.();\r\n player.detach();\r\n };\r\n }, [client, sessionId]);\r\n\r\n return <audio ref={audioRef} autoPlay playsInline />;\r\n}\r\n","import { SipClient } from \"../../sip/client\";\r\nimport type { RTCSession, RTCSessionEvent } from \"../../sip/types\";\r\n\r\nexport function createCallPlayer(audioEl: HTMLAudioElement) {\r\n let cleanupTrackListener: (() => void) | null = null;\r\n let cleanupSessionPeerListener: (() => void) | null = null;\r\n let cleanupClientListeners: (() => void) | null = null;\r\n\r\n const dispose = (fn: (() => void) | null) => {\r\n if (fn) fn();\r\n return null as null;\r\n };\r\n\r\n /** Stop all tracks and clear audio element */\r\n function clearAudioStream(stream?: MediaStream | null) {\r\n if (stream) {\r\n for (const t of stream.getTracks()) {\r\n t.stop();\r\n }\r\n }\r\n audioEl.srcObject = null;\r\n }\r\n\r\n const attachTracks = (pc: RTCPeerConnection) => {\r\n const onTrack = (e: RTCTrackEvent) => {\r\n if (e.track.kind !== \"audio\") return;\r\n\r\n const nextStream = e.streams?.[0] ?? new MediaStream([e.track]);\r\n const prev = audioEl.srcObject as MediaStream | null;\r\n\r\n if (prev && prev !== nextStream) {\r\n clearAudioStream(prev);\r\n }\r\n\r\n audioEl.srcObject = nextStream;\r\n audioEl.play?.().catch(() => {});\r\n };\r\n\r\n pc.addEventListener(\"track\", onTrack);\r\n return () => pc.removeEventListener(\"track\", onTrack);\r\n };\r\n\r\n const listenSessionPeerconnection = (session: RTCSession) => {\r\n const onPeer = (data: { peerconnection: RTCPeerConnection }) => {\r\n cleanupTrackListener = dispose(cleanupTrackListener);\r\n cleanupTrackListener = attachTracks(data.peerconnection);\r\n };\r\n session.on(\"peerconnection\", onPeer);\r\n return () => session.off(\"peerconnection\", onPeer);\r\n };\r\n\r\n function bindToSession(session: RTCSession) {\r\n if (\r\n session?.direction === \"outgoing\" &&\r\n session.connection instanceof RTCPeerConnection\r\n ) {\r\n cleanupTrackListener = dispose(cleanupTrackListener);\r\n cleanupTrackListener = attachTracks(session.connection);\r\n }\r\n\r\n cleanupSessionPeerListener = dispose(cleanupSessionPeerListener);\r\n cleanupSessionPeerListener = listenSessionPeerconnection(session);\r\n\r\n return () => {\r\n cleanupSessionPeerListener = dispose(cleanupSessionPeerListener);\r\n cleanupTrackListener = dispose(cleanupTrackListener);\r\n };\r\n }\r\n\r\n function bindToClient(client: SipClient) {\r\n const offNew = client.on(\"newRTCSession\", (payload) => {\r\n const e = (payload as any)?.data as RTCSessionEvent | undefined;\r\n cleanupSessionPeerListener = dispose(cleanupSessionPeerListener);\r\n cleanupTrackListener = dispose(cleanupTrackListener);\r\n\r\n if (!e?.session) return;\r\n\r\n cleanupSessionPeerListener = listenSessionPeerconnection(e.session);\r\n if (\r\n e.session.direction === \"outgoing\" &&\r\n e.session.connection instanceof RTCPeerConnection\r\n ) {\r\n cleanupTrackListener = attachTracks(e.session.connection);\r\n }\r\n });\r\n\r\n const offEnded = client.on(\"ended\", () => detach());\r\n const offFailed = client.on(\"failed\", () => detach());\r\n const offDisconnected = client.on(\"disconnected\", () => detach());\r\n\r\n cleanupClientListeners = () => {\r\n offNew();\r\n offEnded();\r\n offFailed();\r\n offDisconnected();\r\n };\r\n return cleanupClientListeners;\r\n }\r\n\r\n function detach() {\r\n cleanupClientListeners = dispose(cleanupClientListeners);\r\n cleanupSessionPeerListener = dispose(cleanupSessionPeerListener);\r\n cleanupTrackListener = dispose(cleanupTrackListener);\r\n clearAudioStream(audioEl.srcObject as MediaStream | null);\r\n }\r\n\r\n return {\r\n bindToSession,\r\n bindToClient,\r\n detach,\r\n };\r\n}\r\n","import React, { useMemo } from \"react\";\nimport { SipContext } from \"../context\";\nimport { createSipEventManager, type SipClient, type SipEventManager } from \"jssip-lib\";\n\nexport function SipProvider({\n client,\n children,\n sipEventManager,\n}: {\n sipEventManager?: SipEventManager;\n client: SipClient;\n children: React.ReactNode;\n}) {\n const manager = useMemo(\n () => sipEventManager ?? createSipEventManager(client),\n [client, sipEventManager]\n );\n\n const contextValue = useMemo(() => ({ client, sipEventManager: manager }), [client, manager]);\n\n return (\n <SipContext.Provider value={contextValue}>\n {children}\n </SipContext.Provider>\n );\n}\n"]}
|