react-sip-kit 0.3.62 → 0.5.19

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.
Files changed (32) hide show
  1. package/README.md +110 -42
  2. package/dist/configs/types.d.ts +2 -2
  3. package/dist/constructors/index.d.ts +0 -1
  4. package/dist/events/registration/index.d.ts +4 -3
  5. package/dist/{hooks/useSessionEvents → events/session}/index.d.ts +4 -1
  6. package/dist/events/transport/index.d.ts +5 -4
  7. package/dist/hooks/index.d.ts +2 -2
  8. package/dist/hooks/useDeep/index.d.ts +1 -0
  9. package/dist/hooks/useSipManager/index.d.ts +8 -0
  10. package/dist/hooks/useWatchSessionData/index.d.ts +23 -0
  11. package/dist/index.cjs +1 -1
  12. package/dist/index.d.ts +2 -2
  13. package/dist/index.mjs +1 -1
  14. package/dist/initializer.d.ts +13 -0
  15. package/dist/manager.d.ts +62 -0
  16. package/dist/methods/initialization/index.d.ts +2 -0
  17. package/dist/methods/registration/index.d.ts +4 -3
  18. package/dist/methods/session/index.d.ts +38 -2
  19. package/dist/{hooks/useSpdOptions → methods/session/spdOptions}/index.d.ts +7 -4
  20. package/dist/{hooks/useSessionMethods → methods/session}/types.d.ts +18 -2
  21. package/dist/store/index.d.ts +4 -3
  22. package/dist/store/types.d.ts +27 -20
  23. package/dist/types.d.ts +6 -18
  24. package/dist/utils/getMediaDevices/index.d.ts +9 -0
  25. package/dist/utils/getMediaDevices/types.d.ts +8 -0
  26. package/dist/utils/index.d.ts +1 -0
  27. package/package.json +4 -3
  28. package/dist/constructors/audioBlobs.d.ts +0 -13
  29. package/dist/hooks/useGetMediaDevices/index.d.ts +0 -10
  30. package/dist/hooks/useSessionMethods/index.d.ts +0 -27
  31. package/dist/provider.d.ts +0 -4
  32. /package/dist/{hooks/useSessionEvents → events/session}/types.d.ts +0 -0
package/README.md CHANGED
@@ -8,11 +8,11 @@ Supports **audio/video calls**, **recording**, **screen sharing**, and **device
8
8
  ## ✨ Features
9
9
 
10
10
  * 📞 **Audio & Video Calls** — with automatic device detection
11
- * 🎥 **Video support** — manage local & remote streams seamlessly
11
+ * 🎥 **Video Support** — manage local & remote streams seamlessly
12
12
  * 🔴 **Call Recording** — audio and video recording out of the box
13
13
  * 🖥️ **Screen Sharing** — during video calls
14
14
  * 🎧 **Device Management** — select audio/video input & output devices
15
- * 🔄 **Multi-line Support** — handle multiple concurrent calls
15
+ * 🔄 **Multi-account & Multi-line Support** — handle multiple SIP accounts and concurrent calls
16
16
  * ⚡ **TypeScript-first** — fast, modular, type-safe APIs
17
17
  * 🛠️ **Configurable & Extensible** — tailor to your SIP setup
18
18
 
@@ -30,41 +30,72 @@ yarn add react-sip-kit
30
30
 
31
31
  ## 🚀 Basic Usage
32
32
 
33
- ### 1. Wrap your app with `SipProvider`
33
+ ### 1. Initialize a global `SipManager`
34
34
 
35
- ```tsx
36
- import { SipProvider } from 'react-sip-kit';
35
+ Instead of wrapping your app with a provider, you now create a single `SipManager` instance and add accounts dynamically.
37
36
 
38
- <SipProvider
39
- configs={{
37
+ ```tsx
38
+ // main.ts
39
+ import App from './App';
40
+ import { SipManager } from 'react-sip-kit';
41
+ import { StrictMode, useEffect, useState } from 'react';
42
+ import { createRoot } from 'react-dom/client';
43
+ ------------------------------------------------------------
44
+ export const SipConnection = new SipManager(); // Initilizing SipManager
45
+ ------------------------------------------------------------
46
+ const Providers = () => {
47
+ const configs = [{
40
48
  account: {
41
- domain: 'your.sip.domain',
42
- username: 'your-username',
43
- password: 'your-password',
44
- wssServer: 'your.sip.domain',
49
+ domain: 'sip.example.com',
50
+ username: '1010',
51
+ password: 'password',
52
+ wssServer: 'sip.example.com',
45
53
  webSocketPort: '8089',
46
54
  serverPath: '/ws',
47
55
  },
48
- }}
49
- >
50
- <App />
51
- </SipProvider>
56
+ // ...(other configs)
57
+ }]
58
+
59
+ useEffect(() => {
60
+ // Add new configs dynamically
61
+ configs.forEach((config) => {
62
+ SipConnection.add(config);
63
+ });
64
+ }, [configs]);
65
+
66
+ return (
67
+ <StrictMode>
68
+ {configs.map((config) => (
69
+ <App key={config.account.username} username={config.account.username} />
70
+ ))}
71
+ </StrictMode>
72
+ );
73
+ };
74
+
75
+ createRoot(document.getElementById('root')!).render(<Providers />);
52
76
  ```
53
77
 
54
78
  ---
55
79
 
56
- ### 2. Make calls with hooks
80
+ ### 2. Access SIP state and methods (per account)
81
+
82
+ Each account is keyed by its **username**.
83
+ You can fetch **methods** and **watch state** like this:
57
84
 
58
85
  ```tsx
59
- import { useSipProvider, useSessionMethods } from 'react-sip-kit';
86
+ // App.tsx
87
+ import { SipConnection } from './main';
60
88
 
61
- function DialPad() {
62
- const { status } = useSipProvider();
63
- const { dialByNumber } = useSessionMethods();
89
+ function App({ username }: { username: string }) {
90
+ const { dialByNumber } = SipConnection.methods(username);
91
+ const { watch } = SipConnection.get(username);
92
+ const { lines, status } = watch();
64
93
 
65
94
  return (
66
95
  <>
67
- <p>Status: {status}</p>
96
+ <h2>
97
+ Web Phone {username} — {status}
98
+ </h2>
68
99
  <button onClick={() => dialByNumber('audio', '1012')}>Call 1012</button>
69
100
  <button onClick={() => dialByNumber('video', '1012')}>Video Call 1012</button>
70
101
  </>
@@ -74,7 +105,37 @@ function DialPad() {
74
105
 
75
106
  ---
76
107
 
77
- ### 3. Render media streams
108
+ ### 3. Watch line/session data with `useWatchSessionData`
109
+
110
+ For fine-grained updates, subscribe to session fields:
111
+
112
+ ```tsx
113
+ import { useWatchSessionData } from 'react-sip-kit';
114
+
115
+ function RecordingStatus({ lineNumber }: { lineNumber: number }) {
116
+ const isRecording = useWatchSessionData({
117
+ lineNumber,
118
+ name: 'recordMedia.recording',
119
+ });
120
+
121
+ return <p>Recording: {isRecording ? 'Yes' : 'No'}</p>;
122
+ }
123
+ ```
124
+
125
+ You can also watch multiple fields:
126
+
127
+ ```tsx
128
+ const [localMediaStreamStatus, isRecording] = useWatchSessionData({
129
+ lineNumber: 1,
130
+ name: ['localMediaStreamStatus', 'recordMedia.recording'],
131
+ });
132
+ ```
133
+
134
+ ---
135
+
136
+ ### 4. Render media streams
137
+
138
+ Media components (`<Video/>` & `<Audio/>`) are bound per line:
78
139
 
79
140
  ```tsx
80
141
  import { VideoStream, AudioStream } from 'react-sip-kit';
@@ -89,14 +150,24 @@ import { VideoStream, AudioStream } from 'react-sip-kit';
89
150
 
90
151
  ## ⚙️ Configuration
91
152
 
92
- All SIP and media settings can be customized via the `configs` prop.
93
- See [types.ts](https://github.com/shervin-ghajar/react-sip-kit/blob/main/src/configs/types.ts) for the full options.
153
+ Each account supports SIP and media options:
94
154
 
95
155
  ```ts
96
156
  {
97
- account: { ... },
157
+ account: {
158
+ domain: 'your.sip.domain',
159
+ username: 'user',
160
+ password: 'secret',
161
+ wssServer: 'your.sip.domain',
162
+ webSocketPort: '8089',
163
+ serverPath: '/ws',
164
+ },
98
165
  features: { enableVideo: true },
99
- media: { audioInputDeviceId: 'default' },
166
+ media: {
167
+ audioInputDeviceId: 'default',
168
+ audioOutputDeviceId: 'default',
169
+ videoInputDeviceId: 'default',
170
+ },
100
171
  registration: { registerExpires: 3600 },
101
172
  }
102
173
  ```
@@ -105,26 +176,24 @@ See [types.ts](https://github.com/shervin-ghajar/react-sip-kit/blob/main/src/con
105
176
 
106
177
  ## 💡 Best Practices
107
178
 
108
- * Use hooks (`useSipProvider`, `useSessionMethods`) for SIP state & actions.
109
- * Render media components only for active calls.
110
- * Handle device permissions and selection gracefully.
111
- * Reinitialize streams with `initiateRemoteMediaStreams` or `initiateLocalMediaStreams` if `<video>`/`<audio>` is rendered after the call starts.
112
- * Prefer TypeScript for better DX and safety.
179
+ * Always pass the `username` when calling `SipConnection.methods(username)` or `SipConnection.get(username)`.
180
+ * Use `.watch()` for reactive state (`lines`, `status`).
181
+ * Use `useWatchSessionData` for **line-specific** updates (mute, hold, video state, recording, etc.).
182
+ * Render `<VideoStream>` and `<AudioStream>` **only for active calls**.
183
+ * Manage device permissions (mic/camera) upfront.
184
+ * If adding accounts dynamically, call `SipConnection.add(config)` for each.
113
185
 
114
186
  ---
115
187
 
116
188
  ## 🧑‍💻 Full Example
117
189
 
118
- A full working demo (with call controls, transfer, hold, recording, etc.) is available in the
119
- [`/example`](https://github.com/shervin-ghajar/react-sip-kit/tree/main/example) folder of this repo.
120
-
121
- This example demonstrates:
190
+ See the [`/example`](https://github.com/shervin-ghajar/react-sip-kit/tree/main/example) folder for:
122
191
 
123
- * Multi-line SIP handling
124
- * Answering/rejecting calls
125
- * Call transfer, hold, mute
126
- * Recording and screen sharing
127
- * Local/remote audio & video streams
192
+ * Multiple SIP accounts in one UI
193
+ * Audio & video calls
194
+ * Hold, mute, attended transfer
195
+ * Call recording & screen sharing
196
+ * Local & remote media rendering
128
197
 
129
198
  ---
130
199
 
@@ -140,5 +209,4 @@ MIT License
140
209
 
141
210
  * GitHub: [@shervin-ghajar](https://github.com/shervin-ghajar)
142
211
  * NPM: [react-sip-kit](https://www.npmjs.com/package/react-sip-kit)
143
- * Repository: [react-sip-kit](https://github.com/shervin-ghajar/react-sip-kit)
144
-
212
+ * Repository: [react-sip-kit](https://github.com/shervin-ghajar/react-sip-kit)
@@ -36,8 +36,8 @@ export interface SipAdvancedConfig {
36
36
  chatEngine: string;
37
37
  }
38
38
  export interface SipRecordingConfig {
39
- videoResampleSize: 'HD' | 'FHD';
40
- recordingVideoSize: 'HD' | 'FHD';
39
+ videoResampleSize: string;
40
+ recordingVideoSize: string;
41
41
  recordingVideoFps: number;
42
42
  recordingLayout: string;
43
43
  }
@@ -1,2 +1 @@
1
1
  export * from './line';
2
- export * from './audioBlobs';
@@ -1,15 +1,16 @@
1
+ import { SipAccountConfig } from '../../configs/types';
1
2
  import { SipUserAgent } from '../../types';
2
3
  /**
3
4
  * Called when account is registered
4
5
  */
5
- export declare function onRegistered(userAgent: SipUserAgent): void;
6
+ export declare function onRegistered(username: SipAccountConfig['username'], userAgent: SipUserAgent): void;
6
7
  /**
7
8
  * Called if UserAgent can connect, but not register.
8
9
  * @param {string} response Incoming request message
9
10
  * @param {string} cause Cause message. Unused
10
11
  **/
11
- export declare function onRegisterFailed(response: any, cause: any): void;
12
+ export declare function onRegisterFailed(username: SipAccountConfig['username'], response: any, cause: any): void;
12
13
  /**
13
14
  * Called when Unregister is requested
14
15
  */
15
- export declare function onUnregistered(userAgent: SipUserAgent): void;
16
+ export declare function onUnregistered(username: SipAccountConfig['username'], userAgent: SipUserAgent): void;
@@ -1,8 +1,11 @@
1
+ import { SipAccountConfig } from '../../configs/types';
1
2
  import { LineType, SipSessionDescriptionHandler, SipSessionType } from '../../store/types';
2
3
  import { CallbackFunction } from '../../types';
3
4
  import { Bye, Message } from 'sip.js';
4
5
  import { IncomingRequestMessage, IncomingResponse } from 'sip.js/lib/core';
5
- export declare const useSessionEvents: () => {
6
+ export declare const sessionEvents: ({ username }: {
7
+ username: SipAccountConfig["username"];
8
+ }) => {
6
9
  onInviteCancel: (lineObj: LineType, response: IncomingRequestMessage, callback?: CallbackFunction<any>) => void;
7
10
  onInviteAccepted: (lineObj: LineType, videoEnabled: boolean, response?: IncomingResponse) => Promise<void>;
8
11
  onInviteTrying: (lineObj: LineType, response: IncomingResponse) => void;
@@ -1,5 +1,6 @@
1
+ import { SipAccountConfig } from '../../configs/types';
1
2
  import { SipUserAgent } from '../../types';
2
- export declare function onTransportConnected(userAgent?: SipUserAgent | undefined): void;
3
- export declare function onTransportConnectError(error: Error, userAgent?: SipUserAgent | undefined): void;
4
- export declare function onTransportDisconnected(userAgent: SipUserAgent): void;
5
- export declare function reconnectTransport(userAgent?: SipUserAgent | undefined): void;
3
+ export declare function onTransportConnected(username: SipAccountConfig['username'], userAgent?: SipUserAgent | null): void;
4
+ export declare function onTransportConnectError(error: Error, username: SipAccountConfig['username'], userAgent?: SipUserAgent | null): void;
5
+ export declare function onTransportDisconnected(username: SipAccountConfig['username'], userAgent: SipUserAgent): void;
6
+ export declare function reconnectTransport(username: SipAccountConfig['username'], userAgent?: SipUserAgent | null): void;
@@ -1,2 +1,2 @@
1
- export * from './useSessionMethods';
2
- export * from './useSessionEvents';
1
+ export * from './useSipManager';
2
+ export * from './useWatchSessionData';
@@ -0,0 +1 @@
1
+ export declare function useDeep<S, U>(selector: (state: S) => U): (state: S) => U;
@@ -0,0 +1,8 @@
1
+ import { SipAccountConfig } from '../../configs/types';
2
+ import { LineType } from '../../store/types';
3
+ export declare function useSipManager({ username }: {
4
+ username: SipAccountConfig['username'];
5
+ }): () => {
6
+ status: import("../../store/types").SipUserAgentStatus | undefined;
7
+ lines: LineType[];
8
+ };
@@ -0,0 +1,23 @@
1
+ import { SipSessionDataType } from '../../store/types';
2
+ type Primitive = string | number | boolean | symbol | null | undefined;
3
+ type Path<T> = {
4
+ [K in keyof T & string]: T[K] extends Primitive | Array<any> ? K : K | `${K}.${Path<T[K]>}`;
5
+ }[keyof T & string];
6
+ /** Resolve the value type of a dot-path string. */
7
+ type PathValue<T, P extends string> = P extends `${infer K}.${infer Rest}` ? K extends keyof T ? Rest extends string ? PathValue<T[K], Rest> : never : never : P extends keyof T ? T[P] : never;
8
+ /** ---------- Hook overloads ---------- */
9
+ export declare function useWatchSessionData(props: {
10
+ lineNumber: number;
11
+ name?: undefined;
12
+ }): SipSessionDataType;
13
+ export declare function useWatchSessionData<P extends Path<SipSessionDataType>>(props: {
14
+ lineNumber: number;
15
+ name: P;
16
+ }): PathValue<SipSessionDataType, P>;
17
+ export declare function useWatchSessionData<const P extends readonly Path<SipSessionDataType>[]>(props: {
18
+ lineNumber: number;
19
+ name: P;
20
+ }): {
21
+ [K in keyof P]: PathValue<SipSessionDataType, P[K] & string>;
22
+ };
23
+ export {};