@dora-cell/sdk 0.1.1-beta.6 → 1.0.0

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 CHANGED
@@ -8,124 +8,100 @@ VoIP calling SDK for Dora Cell - Make calls from any JavaScript application with
8
8
  ✅ **TypeScript support** - Full type definitions included
9
9
  ✅ **WebRTC-based** - High-quality voice calls using JsSIP
10
10
  ✅ **Event-driven API** - Listen to call state changes
11
- ✅ **API token authentication** - Secure, no user login required
11
+ ✅ **Multiple Auth Modes** - Support for API Token and Direct Extension login
12
12
  ✅ **Auto-extension selection** - Automatically selects first available extension
13
- ✅ **React bindings** - Optional React hooks for easy integration
13
+ ✅ **React bindings** - Optional React hooks for easy integration
14
14
 
15
15
  ## Installation
16
16
 
17
17
  ```bash
18
- npm install @dora-cell/sdk jssip
18
+ npm install @dora-cell/sdk
19
19
  # or
20
- yarn add @dora-cell/sdk jssip
20
+ yarn add @dora-cell/sdk
21
21
  # or
22
- pnpm add @dora-cell/sdk jssip
22
+ pnpm add @dora-cell/sdk
23
23
  ```
24
24
 
25
- For React projects:
26
- ```bash
27
- npm install @dora-cell/sdk @dora-cell/sdk-react jssip
28
- ```
25
+ > [!NOTE]
26
+ > `jssip` is a dependency of this SDK and will be installed automatically. You only need to install it manually if you want to use a specific version.
29
27
 
30
28
  ## Quick Start
31
29
 
32
- ### Vanilla JavaScript
30
+ ### 1. Initialize the SDK
31
+
32
+ Choose your preferred authentication method:
33
+
34
+ #### Option A: Extension Authentication (Recommended for Testing)
35
+
36
+ Best for quick testing or internal apps where default credentials are used.
33
37
 
34
38
  ```javascript
35
- import { DoraCell } from '@dora-cell/sdk';
39
+ import { DoraCell } from "@dora-cell/sdk";
36
40
 
37
- // Initialize SDK with API token
38
41
  const sdk = new DoraCell({
39
42
  auth: {
40
- type: 'api-token',
41
- apiToken: 'your-api-token-here',
42
- apiBaseUrl: 'https://api.usedora.com'
43
+ type: "extension",
44
+ extension: "1001",
43
45
  },
44
- debug: true // Enable console logging
45
46
  });
47
+ ```
46
48
 
47
- // Initialize connection
48
- await sdk.initialize();
49
+ #### Option B: API Token Authentication (Production)
49
50
 
50
- // Listen for connection status
51
- sdk.on('connection:status', (state) => {
52
- console.log('Connection status:', state.status);
53
- });
51
+ Securely fetch credentials from your backend.
54
52
 
55
- // Listen for call events
56
- sdk.on('call:connected', (call) => {
57
- console.log('Call connected:', call.remoteNumber);
53
+ ```javascript
54
+ const sdk = new DoraCell({
55
+ auth: {
56
+ type: "api-token",
57
+ apiToken: "your-api-token-here",
58
+ // apiBaseUrl: "https://api.yourdomain.com", // Optional override
59
+ },
58
60
  });
61
+ ```
62
+
63
+ #### Option C: Direct Credentials (Advanced)
59
64
 
60
- sdk.on('call:ended', (call, reason) => {
61
- console.log('Call ended:', reason);
65
+ If you already have SIP credentials.
66
+
67
+ ```javascript
68
+ const sdk = new DoraCell({
69
+ auth: {
70
+ type: "direct",
71
+ sipUri: "sip:1001@voice.example.com",
72
+ password: "your-password",
73
+ wsUrl: "wss://voice.example.com:8089/ws",
74
+ },
62
75
  });
76
+ ```
63
77
 
64
- // Make a call
65
- const call = await sdk.call('+2348012345678');
78
+ ### 2. Connect and Register
66
79
 
67
- // Mute/unmute
68
- call.mute();
69
- call.unmute();
80
+ ```javascript
81
+ // Listen for registration
82
+ sdk.on("connection:status", (state) => {
83
+ if (state.status === "registered") {
84
+ console.log("SIP Ready to make calls!");
85
+ }
86
+ });
70
87
 
71
- // Hang up
72
- call.hangup();
88
+ // Initialize connection
89
+ await sdk.initialize();
73
90
  ```
74
91
 
75
- ### React
76
-
77
- ```tsx
78
- import { DoraCellProvider, useCall, useConnectionStatus } from '@dora-cell/sdk-react';
79
-
80
- function App() {
81
- return (
82
- <DoraCellProvider
83
- config={{
84
- auth: {
85
- type: 'api-token',
86
- apiToken: 'your-api-token-here',
87
- apiBaseUrl: 'https://api.usedora.com'
88
- }
89
- }}
90
- >
91
- <CallInterface />
92
- </DoraCellProvider>
93
- );
94
- }
92
+ ### 3. Make a Call
93
+
94
+ ```javascript
95
+ try {
96
+ const call = await sdk.call("+2348012345678");
97
+
98
+ // Mute/unmute
99
+ call.mute();
95
100
 
96
- function CallInterface() {
97
- const { call, hangup, toggleMute, callStatus, callDuration, isMuted } = useCall();
98
- const { isConnected } = useConnectionStatus();
99
- const [number, setNumber] = useState('');
100
-
101
- const handleCall = async () => {
102
- try {
103
- await call(number);
104
- } catch (error) {
105
- console.error('Call failed:', error);
106
- }
107
- };
108
-
109
- return (
110
- <div>
111
- <p>Status: {isConnected ? 'Connected' : 'Disconnected'}</p>
112
- <input
113
- value={number}
114
- onChange={(e) => setNumber(e.target.value)}
115
- placeholder="Enter phone number"
116
- />
117
- <button onClick={handleCall} disabled={!isConnected}>
118
- Call
119
- </button>
120
- {callStatus === 'ongoing' && (
121
- <>
122
- <p>Duration: {callDuration}</p>
123
- <button onClick={toggleMute}>{isMuted ? 'Unmute' : 'Mute'}</button>
124
- <button onClick={hangup}>Hang Up</button>
125
- </>
126
- )}
127
- </div>
128
- );
101
+ // Hang up
102
+ call.hangup();
103
+ } catch (error) {
104
+ console.error("Call failed:", error.message);
129
105
  }
130
106
  ```
131
107
 
@@ -133,143 +109,61 @@ function CallInterface() {
133
109
 
134
110
  ### DoraCell Class
135
111
 
136
- #### Constructor
112
+ #### `new DoraCell(config)`
137
113
 
138
- ```typescript
139
- new DoraCell(config: DoraCellConfig)
140
- ```
141
-
142
- **Config options:**
143
- - `auth` - Authentication configuration (required)
144
- - `type: 'api-token'` - Use API token authentication
145
- - `apiToken: string` - Your Dora Cell API token
146
- - `apiBaseUrl?: string` - API base URL (optional)
147
- - `turnServers?: RTCIceServer[]` - Custom TURN/STUN servers
148
- - `debug?: boolean` - Enable debug logging
149
- - `autoSelectExtension?: boolean` - Auto-select first extension (default: true)
114
+ - `config.auth` (Required)
115
+ - `type: 'extension' | 'api-token'`
116
+ - `extension: string` (for extension type)
117
+ - `apiToken: string` (for api-token type)
118
+ - `config.debug?: boolean` - Enable JsSIP debug logs (default: false)
150
119
 
151
120
  #### Methods
152
121
 
153
- **`initialize(): Promise<void>`**
154
- Initialize the SDK and connect to SIP server.
155
-
156
- **`call(phoneNumber: string, options?: CallOptions): Promise<Call>`**
157
- Make an outbound call.
158
-
159
- Options:
160
- - `extension?: string` - Specific extension to use for this call
161
-
162
- **`hangup(): void`**
163
- Hang up the current call.
164
-
165
- **`answerCall(): void`**
166
- Answer an incoming call.
167
-
168
- **`getCurrentCall(): Call | null`**
169
- Get the current active call.
170
-
171
- **`getStatus(): ConnectionStatus`**
172
- Get current connection status.
173
-
174
- **`getExtensions(): string[]`**
175
- Get list of available extensions.
176
-
177
- **`on(event, handler): void`**
178
- Register event listener.
179
-
180
- **`off(event, handler): void`**
181
- Remove event listener.
182
-
183
- **`destroy(): void`**
184
- Cleanup and destroy SDK instance.
185
-
186
- ### Events
187
-
188
- ```typescript
189
- sdk.on('connection:status', (state: ConnectionState) => {});
190
- sdk.on('call:incoming', (call: Call) => {});
191
- sdk.on('call:outgoing', (call: Call) => {});
192
- sdk.on('call:ringing', (call: Call) => {});
193
- sdk.on('call:connected', (call: Call) => {});
194
- sdk.on('call:ended', (call: Call, reason?: string) => {});
195
- sdk.on('call:failed', (call: Call, error: string) => {});
196
- sdk.on('error', (error: Error) => {});
197
- ```
122
+ - `initialize(): Promise<void>` - Connect to the SIP server and register the extension.
123
+ - `call(number, options?): Promise<Call>` - Initiate an outbound call.
124
+ - `options.extension`: Specify a specific extension to call from.
125
+ - `options.mediaConstraints`: Custom WebRTC media constraints.
126
+ - `answerCall(): void` - Answer a pending incoming call.
127
+ - `hangup(): void` - End the current active call.
128
+ - `on(event, handler): void` - Listen for events (see below).
129
+ - `destroy(): void` - Cleanup and disconnect.
198
130
 
199
131
  ### Call Object
200
132
 
201
- ```typescript
202
- interface Call {
203
- id: string;
204
- status: CallStatus;
205
- direction: 'inbound' | 'outbound';
206
- remoteNumber: string;
207
- localExtension: string;
208
- duration: number;
209
-
210
- mute(): void;
211
- unmute(): void;
212
- hangup(): void;
213
- isMuted(): boolean;
214
- }
215
- ```
216
-
217
- ## Authentication
218
-
219
- ### Getting an API Token
220
-
221
- 1. Log in to your Dora Cell dashboard
222
- 2. Navigate to Settings → API Tokens
223
- 3. Generate a new API token
224
- 4. Copy the token and use it in your SDK configuration
225
-
226
- ### Backend API Endpoint
227
-
228
- The SDK expects your backend to provide a `/api/sip-credentials` endpoint that:
229
- - Accepts `Authorization: Bearer <token>` header
230
- - Returns SIP credentials in this format:
231
-
232
- ```json
233
- {
234
- "ws_url": "wss://cell.usedora.com:8089/ws",
235
- "sip_uri": "sip:101@64.227.10.164",
236
- "password": "your-password",
237
- "extensions": [
238
- { "extension": "101", "displayName": "Main Line" }
239
- ]
240
- }
241
- ```
242
-
243
- ## Phone Number Formatting
133
+ Returned by `call()` and emitted in events.
244
134
 
245
- The SDK automatically handles Nigerian phone number formatting:
135
+ - `id`: Unique call ID.
136
+ - `status`: `'idle' | 'connecting' | 'ringing' | 'ongoing' | 'ended'`.
137
+ - `direction`: `'inbound' | 'outbound'`.
138
+ - `remoteNumber`: The other party's number.
139
+ - `duration`: Call duration in seconds.
140
+ - `mute()` / `unmute()`: Control microphone.
141
+ - `hangup()`: End this specific call.
142
+ - `getRemoteStream()`: Returns the WebRTC `MediaStream` for audio playback.
246
143
 
247
- - `08012345678` → `sip:2348012345678@domain`
248
- - `2348012345678` → `sip:2348012345678@domain`
249
- - `101` (extension) → `sip:101@domain`
144
+ ## Events
250
145
 
251
- ## Error Handling
146
+ | Event | Description | Data |
147
+ | ------------------- | ------------------------------ | ---------------------------------- |
148
+ | `connection:status` | SIP registration status change | `{ status: string, error?: string }` |
149
+ | `call:incoming` | New incoming call detected | `Call` object |
150
+ | `call:outgoing` | New outbound call started | `Call` object |
151
+ | `call:ringing` | Remote party is ringing | `Call` object |
152
+ | `call:connected` | Call answered and connected | `Call` object |
153
+ | `call:ended` | Call terminated | `Call` object, `reason: string` |
154
+ | `call:failed` | Call failed to connect | `Call` object, `error: string` |
155
+ | `error` | General SDK error | `Error` object |
252
156
 
253
- ```javascript
254
- import { AuthenticationError, CallError, ConnectionError } from '@dora-cell/sdk';
157
+ ## Browser Requirements
255
158
 
256
- try {
257
- await sdk.initialize();
258
- } catch (error) {
259
- if (error instanceof AuthenticationError) {
260
- console.error('Authentication failed:', error.message);
261
- } else if (error instanceof ConnectionError) {
262
- console.error('Connection failed:', error.message);
263
- }
264
- }
265
- ```
159
+ - **HTTPS**: WebRTC and microphone access require a secure context (HTTPS or localhost).
160
+ - **Environment**: Modern browsers with WebRTC support (Chrome, Firefox, Safari, Edge).
266
161
 
267
162
  ## Examples
268
163
 
269
- See the `/examples` directory for complete working examples:
270
- - `vanilla-js/` - Pure JavaScript implementation
271
- - `react-app/` - React application
272
- - `nextjs-app/` - Next.js application
164
+ Check the [`examples/`](../../examples) directory in the main repository:
165
+
166
+ - `next-js-demo/` - Complete Next.js implementation with React components
273
167
 
274
168
  ## License
275
169
 
package/dist/index.d.mts CHANGED
@@ -14,7 +14,13 @@ interface DirectCredentialsAuth {
14
14
  password: string;
15
15
  wsUrl: string;
16
16
  }
17
- type AuthConfig = ApiTokenAuth | DirectCredentialsAuth;
17
+ interface ExtensionAuth {
18
+ type: 'extension';
19
+ extension: string;
20
+ password?: string;
21
+ sipDomain?: string;
22
+ }
23
+ type AuthConfig = ApiTokenAuth | DirectCredentialsAuth | ExtensionAuth;
18
24
  interface DoraCellConfig {
19
25
  auth: AuthConfig;
20
26
  sipServer?: string;
@@ -54,6 +60,7 @@ interface Call {
54
60
  unmute(): void;
55
61
  hangup(): void;
56
62
  isMuted(): boolean;
63
+ getRemoteStream(): MediaStream | null;
57
64
  }
58
65
  type ConnectionStatus = 'disconnected' | 'connecting' | 'connected' | 'registered' | 'registrationFailed';
59
66
  interface ConnectionState {
@@ -107,6 +114,7 @@ declare class DoraCell {
107
114
  * Initialize the SDK - authenticate and connect to SIP server
108
115
  */
109
116
  initialize(): Promise<void>;
117
+ private waitForRegistration;
110
118
  private initializeUserAgent;
111
119
  private setupUserAgentHandlers;
112
120
  private initializeCallManager;
package/dist/index.d.ts CHANGED
@@ -14,7 +14,13 @@ interface DirectCredentialsAuth {
14
14
  password: string;
15
15
  wsUrl: string;
16
16
  }
17
- type AuthConfig = ApiTokenAuth | DirectCredentialsAuth;
17
+ interface ExtensionAuth {
18
+ type: 'extension';
19
+ extension: string;
20
+ password?: string;
21
+ sipDomain?: string;
22
+ }
23
+ type AuthConfig = ApiTokenAuth | DirectCredentialsAuth | ExtensionAuth;
18
24
  interface DoraCellConfig {
19
25
  auth: AuthConfig;
20
26
  sipServer?: string;
@@ -54,6 +60,7 @@ interface Call {
54
60
  unmute(): void;
55
61
  hangup(): void;
56
62
  isMuted(): boolean;
63
+ getRemoteStream(): MediaStream | null;
57
64
  }
58
65
  type ConnectionStatus = 'disconnected' | 'connecting' | 'connected' | 'registered' | 'registrationFailed';
59
66
  interface ConnectionState {
@@ -107,6 +114,7 @@ declare class DoraCell {
107
114
  * Initialize the SDK - authenticate and connect to SIP server
108
115
  */
109
116
  initialize(): Promise<void>;
117
+ private waitForRegistration;
110
118
  private initializeUserAgent;
111
119
  private setupUserAgentHandlers;
112
120
  private initializeCallManager;