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.
- package/README.md +110 -42
- package/dist/configs/types.d.ts +2 -2
- package/dist/constructors/index.d.ts +0 -1
- package/dist/events/registration/index.d.ts +4 -3
- package/dist/{hooks/useSessionEvents → events/session}/index.d.ts +4 -1
- package/dist/events/transport/index.d.ts +5 -4
- package/dist/hooks/index.d.ts +2 -2
- package/dist/hooks/useDeep/index.d.ts +1 -0
- package/dist/hooks/useSipManager/index.d.ts +8 -0
- package/dist/hooks/useWatchSessionData/index.d.ts +23 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.mjs +1 -1
- package/dist/initializer.d.ts +13 -0
- package/dist/manager.d.ts +62 -0
- package/dist/methods/initialization/index.d.ts +2 -0
- package/dist/methods/registration/index.d.ts +4 -3
- package/dist/methods/session/index.d.ts +38 -2
- package/dist/{hooks/useSpdOptions → methods/session/spdOptions}/index.d.ts +7 -4
- package/dist/{hooks/useSessionMethods → methods/session}/types.d.ts +18 -2
- package/dist/store/index.d.ts +4 -3
- package/dist/store/types.d.ts +27 -20
- package/dist/types.d.ts +6 -18
- package/dist/utils/getMediaDevices/index.d.ts +9 -0
- package/dist/utils/getMediaDevices/types.d.ts +8 -0
- package/dist/utils/index.d.ts +1 -0
- package/package.json +4 -3
- package/dist/constructors/audioBlobs.d.ts +0 -13
- package/dist/hooks/useGetMediaDevices/index.d.ts +0 -10
- package/dist/hooks/useSessionMethods/index.d.ts +0 -27
- package/dist/provider.d.ts +0 -4
- /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
|
|
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.
|
|
33
|
+
### 1. Initialize a global `SipManager`
|
|
34
34
|
|
|
35
|
-
|
|
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
|
-
|
|
39
|
-
|
|
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: '
|
|
42
|
-
username: '
|
|
43
|
-
password: '
|
|
44
|
-
wssServer: '
|
|
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
|
-
|
|
51
|
-
|
|
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.
|
|
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
|
-
|
|
86
|
+
// App.tsx
|
|
87
|
+
import { SipConnection } from './main';
|
|
60
88
|
|
|
61
|
-
function
|
|
62
|
-
const {
|
|
63
|
-
const {
|
|
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
|
-
<
|
|
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.
|
|
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
|
-
|
|
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: {
|
|
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
|
-
*
|
|
109
|
-
*
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
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
|
-
|
|
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
|
-
*
|
|
124
|
-
*
|
|
125
|
-
*
|
|
126
|
-
*
|
|
127
|
-
* Local
|
|
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)
|
package/dist/configs/types.d.ts
CHANGED
|
@@ -36,8 +36,8 @@ export interface SipAdvancedConfig {
|
|
|
36
36
|
chatEngine: string;
|
|
37
37
|
}
|
|
38
38
|
export interface SipRecordingConfig {
|
|
39
|
-
videoResampleSize:
|
|
40
|
-
recordingVideoSize:
|
|
39
|
+
videoResampleSize: string;
|
|
40
|
+
recordingVideoSize: string;
|
|
41
41
|
recordingVideoFps: number;
|
|
42
42
|
recordingLayout: string;
|
|
43
43
|
}
|
|
@@ -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
|
|
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 |
|
|
3
|
-
export declare function onTransportConnectError(error: Error, userAgent?: SipUserAgent |
|
|
4
|
-
export declare function onTransportDisconnected(userAgent: SipUserAgent): void;
|
|
5
|
-
export declare function reconnectTransport(userAgent?: SipUserAgent |
|
|
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;
|
package/dist/hooks/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export * from './
|
|
2
|
-
export * from './
|
|
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 {};
|