@dora-cell/sdk 1.0.2 → 3.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/dist/index.d.mts +8 -1
- package/dist/index.d.ts +8 -1
- package/dist/index.js +140 -29
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +140 -29
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -79,6 +79,7 @@ type DoraCellEventMap = {
|
|
|
79
79
|
'call:connected': (call: Call) => void;
|
|
80
80
|
'call:ended': (call: Call, reason?: string) => void;
|
|
81
81
|
'call:failed': (call: Call, error: string) => void;
|
|
82
|
+
'call:stream': (call: Call, stream: MediaStream) => void;
|
|
82
83
|
'error': (error: Error) => void;
|
|
83
84
|
};
|
|
84
85
|
type DoraCellEvent = keyof DoraCellEventMap;
|
|
@@ -114,6 +115,7 @@ declare class DoraCell {
|
|
|
114
115
|
private connectionStatus;
|
|
115
116
|
private retryCount;
|
|
116
117
|
private maxRetries;
|
|
118
|
+
private userId;
|
|
117
119
|
constructor(config: DoraCellConfig);
|
|
118
120
|
/**
|
|
119
121
|
* Initialize the SDK - authenticate and connect to SIP server
|
|
@@ -130,7 +132,7 @@ declare class DoraCell {
|
|
|
130
132
|
/**
|
|
131
133
|
* Answer an incoming call
|
|
132
134
|
*/
|
|
133
|
-
answerCall(): void
|
|
135
|
+
answerCall(): Promise<void>;
|
|
134
136
|
/**
|
|
135
137
|
* Hangup the current call
|
|
136
138
|
*/
|
|
@@ -199,9 +201,14 @@ declare class CallSession implements Call {
|
|
|
199
201
|
private remoteStreamValue;
|
|
200
202
|
private durationInterval?;
|
|
201
203
|
private events;
|
|
204
|
+
private ssrcWatchInterval?;
|
|
205
|
+
private lastKnownSSRCs;
|
|
202
206
|
constructor(session: any, direction: CallDirection, remoteNumber: string, localExtension: string, events: EventEmitter);
|
|
203
207
|
private generateCallId;
|
|
204
208
|
private setupSessionHandlers;
|
|
209
|
+
private startSSRCWatch;
|
|
210
|
+
private stopSSRCWatch;
|
|
211
|
+
private reattachFromReceivers;
|
|
205
212
|
private handleCallEnd;
|
|
206
213
|
private startDurationTimer;
|
|
207
214
|
private stopDurationTimer;
|
package/dist/index.d.ts
CHANGED
|
@@ -79,6 +79,7 @@ type DoraCellEventMap = {
|
|
|
79
79
|
'call:connected': (call: Call) => void;
|
|
80
80
|
'call:ended': (call: Call, reason?: string) => void;
|
|
81
81
|
'call:failed': (call: Call, error: string) => void;
|
|
82
|
+
'call:stream': (call: Call, stream: MediaStream) => void;
|
|
82
83
|
'error': (error: Error) => void;
|
|
83
84
|
};
|
|
84
85
|
type DoraCellEvent = keyof DoraCellEventMap;
|
|
@@ -114,6 +115,7 @@ declare class DoraCell {
|
|
|
114
115
|
private connectionStatus;
|
|
115
116
|
private retryCount;
|
|
116
117
|
private maxRetries;
|
|
118
|
+
private userId;
|
|
117
119
|
constructor(config: DoraCellConfig);
|
|
118
120
|
/**
|
|
119
121
|
* Initialize the SDK - authenticate and connect to SIP server
|
|
@@ -130,7 +132,7 @@ declare class DoraCell {
|
|
|
130
132
|
/**
|
|
131
133
|
* Answer an incoming call
|
|
132
134
|
*/
|
|
133
|
-
answerCall(): void
|
|
135
|
+
answerCall(): Promise<void>;
|
|
134
136
|
/**
|
|
135
137
|
* Hangup the current call
|
|
136
138
|
*/
|
|
@@ -199,9 +201,14 @@ declare class CallSession implements Call {
|
|
|
199
201
|
private remoteStreamValue;
|
|
200
202
|
private durationInterval?;
|
|
201
203
|
private events;
|
|
204
|
+
private ssrcWatchInterval?;
|
|
205
|
+
private lastKnownSSRCs;
|
|
202
206
|
constructor(session: any, direction: CallDirection, remoteNumber: string, localExtension: string, events: EventEmitter);
|
|
203
207
|
private generateCallId;
|
|
204
208
|
private setupSessionHandlers;
|
|
209
|
+
private startSSRCWatch;
|
|
210
|
+
private stopSSRCWatch;
|
|
211
|
+
private reattachFromReceivers;
|
|
205
212
|
private handleCallEnd;
|
|
206
213
|
private startDurationTimer;
|
|
207
214
|
private stopDurationTimer;
|
package/dist/index.js
CHANGED
|
@@ -23015,7 +23015,6 @@ var ApiTokenAuthProvider = class {
|
|
|
23015
23015
|
}
|
|
23016
23016
|
const baseUrl = apiBaseUrl?.replace(/\/$/, "") || "https://api.cell.usedora.com/api";
|
|
23017
23017
|
try {
|
|
23018
|
-
console.log("SDK: Verifying keys at:", `${baseUrl}/sdk/v1/auth/session`);
|
|
23019
23018
|
const authResponse = await fetch(`${baseUrl}/sdk/v1/auth/session`, {
|
|
23020
23019
|
method: "POST",
|
|
23021
23020
|
headers: {
|
|
@@ -23037,7 +23036,29 @@ var ApiTokenAuthProvider = class {
|
|
|
23037
23036
|
if (!this.sessionToken) {
|
|
23038
23037
|
throw new AuthenticationError("No session token returned after key verification");
|
|
23039
23038
|
}
|
|
23040
|
-
|
|
23039
|
+
const origin = typeof window !== "undefined" ? window.location.origin : "";
|
|
23040
|
+
const validateResponse = await fetch(`${baseUrl}/sdk/v1/auth/validate`, {
|
|
23041
|
+
method: "GET",
|
|
23042
|
+
headers: {
|
|
23043
|
+
"Authorization": `Bearer ${this.sessionToken}`,
|
|
23044
|
+
"x-dora-public-key": this.publicKey,
|
|
23045
|
+
"Origin": origin,
|
|
23046
|
+
"Accept": "application/json"
|
|
23047
|
+
}
|
|
23048
|
+
});
|
|
23049
|
+
if (!validateResponse.ok) {
|
|
23050
|
+
throw new AuthenticationError(
|
|
23051
|
+
`Secondary validation failed: ${validateResponse.status}`,
|
|
23052
|
+
{ status: validateResponse.status }
|
|
23053
|
+
);
|
|
23054
|
+
}
|
|
23055
|
+
const validateData = await validateResponse.json();
|
|
23056
|
+
console.log(`Dora Cell SDK: Authenticated successfully`);
|
|
23057
|
+
if (validateData.features && !validateData.features.includes("voice")) {
|
|
23058
|
+
console.warn('Dora Cell SDK: App token does not have the "voice" feature enabled.');
|
|
23059
|
+
}
|
|
23060
|
+
const actualResponseData = authData.data && typeof authData.data === "object" ? authData.data : authData;
|
|
23061
|
+
this.credentials = this.parseCredentials(actualResponseData);
|
|
23041
23062
|
return this.credentials;
|
|
23042
23063
|
} catch (error) {
|
|
23043
23064
|
if (error instanceof AuthenticationError) {
|
|
@@ -23075,7 +23096,8 @@ var ApiTokenAuthProvider = class {
|
|
|
23075
23096
|
if (!sipUri && extensions.length > 0) {
|
|
23076
23097
|
const ext = extensions[0].extension;
|
|
23077
23098
|
sipUri = `sip:${ext}@${sipDomain}`;
|
|
23078
|
-
|
|
23099
|
+
} else if (!sipUri) {
|
|
23100
|
+
sipUri = "";
|
|
23079
23101
|
}
|
|
23080
23102
|
return {
|
|
23081
23103
|
wsUrl,
|
|
@@ -23176,6 +23198,7 @@ var CallSession = class {
|
|
|
23176
23198
|
// JsSIP RTCSession
|
|
23177
23199
|
this._isMuted = false;
|
|
23178
23200
|
this.remoteStreamValue = null;
|
|
23201
|
+
this.lastKnownSSRCs = /* @__PURE__ */ new Set();
|
|
23179
23202
|
this.id = this.generateCallId();
|
|
23180
23203
|
this.session = session;
|
|
23181
23204
|
this.direction = direction;
|
|
@@ -23193,6 +23216,9 @@ var CallSession = class {
|
|
|
23193
23216
|
if (code === 180 || code === 183) {
|
|
23194
23217
|
this.status = "ringing";
|
|
23195
23218
|
this.events.emit("call:ringing", this);
|
|
23219
|
+
if (this.session.connection) {
|
|
23220
|
+
setTimeout(() => this.reattachFromReceivers(this.session.connection), 200);
|
|
23221
|
+
}
|
|
23196
23222
|
}
|
|
23197
23223
|
});
|
|
23198
23224
|
this.session.on("confirmed", () => {
|
|
@@ -23200,28 +23226,79 @@ var CallSession = class {
|
|
|
23200
23226
|
this.startTime = Date.now();
|
|
23201
23227
|
this.startDurationTimer();
|
|
23202
23228
|
this.events.emit("call:connected", this);
|
|
23229
|
+
if (this.session.connection) {
|
|
23230
|
+
this.reattachFromReceivers(this.session.connection);
|
|
23231
|
+
this.startSSRCWatch(this.session.connection);
|
|
23232
|
+
}
|
|
23203
23233
|
});
|
|
23204
23234
|
this.session.on("peerconnection", (evt) => {
|
|
23205
|
-
evt.peerconnection
|
|
23235
|
+
const pc = evt.peerconnection;
|
|
23236
|
+
pc.addEventListener("track", (event) => {
|
|
23237
|
+
setTimeout(() => this.reattachFromReceivers(pc), 150);
|
|
23206
23238
|
if (event.streams && event.streams[0]) {
|
|
23207
23239
|
this.remoteStreamValue = event.streams[0];
|
|
23240
|
+
this.events.emit("call:stream", this, event.streams[0]);
|
|
23241
|
+
}
|
|
23242
|
+
});
|
|
23243
|
+
pc.oniceconnectionstatechange = () => {
|
|
23244
|
+
if (pc.iceConnectionState === "connected" || pc.iceConnectionState === "completed") {
|
|
23245
|
+
this.reattachFromReceivers(pc);
|
|
23208
23246
|
}
|
|
23209
23247
|
};
|
|
23210
23248
|
});
|
|
23211
23249
|
this.session.on("ended", (evt) => {
|
|
23250
|
+
console.log(`Dora Cell SDK: Call ended (${evt?.cause || "Normal"})`);
|
|
23212
23251
|
this.handleCallEnd(evt?.cause);
|
|
23213
23252
|
});
|
|
23214
23253
|
this.session.on("failed", (evt) => {
|
|
23254
|
+
console.warn(`Dora Cell SDK: Call failed (${evt?.cause || "Internal Error"})`);
|
|
23215
23255
|
this.handleCallEnd(evt?.cause || "Call failed");
|
|
23216
23256
|
});
|
|
23217
23257
|
this.session.on("rejected", (evt) => {
|
|
23258
|
+
console.warn(`SDK: Call rejected. Cause: ${evt?.cause || "Rejected"}`);
|
|
23218
23259
|
this.handleCallEnd(evt?.cause || "Call rejected");
|
|
23219
23260
|
});
|
|
23220
23261
|
}
|
|
23262
|
+
startSSRCWatch(pc) {
|
|
23263
|
+
this.stopSSRCWatch();
|
|
23264
|
+
this.lastKnownSSRCs.clear();
|
|
23265
|
+
this.ssrcWatchInterval = window.setInterval(async () => {
|
|
23266
|
+
try {
|
|
23267
|
+
if (!pc) return;
|
|
23268
|
+
const stats = await pc.getStats();
|
|
23269
|
+
stats.forEach((report) => {
|
|
23270
|
+
if (report.type === "inbound-rtp" && report.kind === "audio") {
|
|
23271
|
+
const ssrc = report.ssrc;
|
|
23272
|
+
if (ssrc && !this.lastKnownSSRCs.has(ssrc)) {
|
|
23273
|
+
this.lastKnownSSRCs.add(ssrc);
|
|
23274
|
+
setTimeout(() => this.reattachFromReceivers(pc), 200);
|
|
23275
|
+
}
|
|
23276
|
+
}
|
|
23277
|
+
});
|
|
23278
|
+
} catch (e) {
|
|
23279
|
+
}
|
|
23280
|
+
}, 1e3);
|
|
23281
|
+
}
|
|
23282
|
+
stopSSRCWatch() {
|
|
23283
|
+
if (this.ssrcWatchInterval) {
|
|
23284
|
+
clearInterval(this.ssrcWatchInterval);
|
|
23285
|
+
this.ssrcWatchInterval = void 0;
|
|
23286
|
+
}
|
|
23287
|
+
}
|
|
23288
|
+
reattachFromReceivers(pc) {
|
|
23289
|
+
if (!pc) return;
|
|
23290
|
+
const liveAudioTracks = pc.getReceivers().map((r) => r.track).filter((t) => t && t.kind === "audio" && t.readyState === "live");
|
|
23291
|
+
if (liveAudioTracks.length > 0) {
|
|
23292
|
+
const newStream = new MediaStream(liveAudioTracks);
|
|
23293
|
+
this.remoteStreamValue = newStream;
|
|
23294
|
+
this.events.emit("call:stream", this, newStream);
|
|
23295
|
+
}
|
|
23296
|
+
}
|
|
23221
23297
|
handleCallEnd(reason) {
|
|
23222
23298
|
this.status = "ended";
|
|
23223
23299
|
this.endTime = Date.now();
|
|
23224
23300
|
this.stopDurationTimer();
|
|
23301
|
+
this.stopSSRCWatch();
|
|
23225
23302
|
this.remoteStreamValue = null;
|
|
23226
23303
|
this._isMuted = false;
|
|
23227
23304
|
this.events.emit("call:ended", this, reason);
|
|
@@ -23302,6 +23379,7 @@ var CallManager = class {
|
|
|
23302
23379
|
const extension = options?.extension || this.getDefaultExtension();
|
|
23303
23380
|
const sipDomain = this.extractDomain(this.credentials.sipUri);
|
|
23304
23381
|
const sipTarget = formatPhoneToSIP(targetNumber, sipDomain);
|
|
23382
|
+
console.log(`Dora Cell SDK: Initiating call to ${targetNumber}...`);
|
|
23305
23383
|
const session = this.ua.call(sipTarget, {
|
|
23306
23384
|
mediaConstraints: options?.mediaConstraints || { audio: true },
|
|
23307
23385
|
pcConfig: this.callConfig.pcConfig
|
|
@@ -23328,12 +23406,13 @@ var CallManager = class {
|
|
|
23328
23406
|
* Answer the pending incoming call.
|
|
23329
23407
|
* Uses the stored pendingSession from handleIncomingCall.
|
|
23330
23408
|
*/
|
|
23331
|
-
answerCurrentCall() {
|
|
23409
|
+
async answerCurrentCall() {
|
|
23332
23410
|
const session = this.pendingSession;
|
|
23333
23411
|
if (!session) {
|
|
23334
23412
|
throw new CallError("No pending incoming call to answer");
|
|
23335
23413
|
}
|
|
23336
23414
|
try {
|
|
23415
|
+
await navigator.mediaDevices.getUserMedia({ audio: true });
|
|
23337
23416
|
session.answer({
|
|
23338
23417
|
mediaConstraints: { audio: true },
|
|
23339
23418
|
pcConfig: this.callConfig.pcConfig
|
|
@@ -23378,10 +23457,13 @@ var CallManager = class {
|
|
|
23378
23457
|
this.pendingSession = null;
|
|
23379
23458
|
}
|
|
23380
23459
|
getDefaultExtension() {
|
|
23460
|
+
if (this.credentials.sipUri) {
|
|
23461
|
+
return this.extractExtension(this.credentials.sipUri);
|
|
23462
|
+
}
|
|
23381
23463
|
if (this.credentials.extensions && this.credentials.extensions.length > 0) {
|
|
23382
23464
|
return this.credentials.extensions[0].extension;
|
|
23383
23465
|
}
|
|
23384
|
-
return
|
|
23466
|
+
return "unknown";
|
|
23385
23467
|
}
|
|
23386
23468
|
extractExtension(sipUri) {
|
|
23387
23469
|
const match = sipUri.match(/sip:([^@]+)@/);
|
|
@@ -23465,6 +23547,7 @@ var DoraCell = class {
|
|
|
23465
23547
|
this.connectionStatus = "disconnected";
|
|
23466
23548
|
this.retryCount = 0;
|
|
23467
23549
|
this.maxRetries = 3;
|
|
23550
|
+
this.userId = null;
|
|
23468
23551
|
this.config = {
|
|
23469
23552
|
autoSelectExtension: true,
|
|
23470
23553
|
debug: false,
|
|
@@ -23489,17 +23572,25 @@ var DoraCell = class {
|
|
|
23489
23572
|
);
|
|
23490
23573
|
if (this.authProvider instanceof ApiTokenAuthProvider) {
|
|
23491
23574
|
const token = this.authProvider.getSessionToken();
|
|
23492
|
-
if (token)
|
|
23575
|
+
if (token) {
|
|
23576
|
+
this.apiClient.setSessionToken(token);
|
|
23577
|
+
}
|
|
23578
|
+
}
|
|
23579
|
+
await this.getWallet().catch(() => {
|
|
23580
|
+
});
|
|
23581
|
+
if (!this.credentials?.extensions || this.credentials.extensions.length === 0) {
|
|
23582
|
+
await this.fetchExtensions();
|
|
23493
23583
|
}
|
|
23494
23584
|
if (this.config.autoSelectExtension && this.credentials?.extensions && this.credentials.extensions.length > 0) {
|
|
23495
23585
|
const primary = this.credentials.extensions.find((e) => e.isPrimary) || this.credentials.extensions[0];
|
|
23496
|
-
const domain = this.credentials.sipDomain || "
|
|
23586
|
+
const domain = this.credentials.sipDomain || "64.227.10.164";
|
|
23497
23587
|
this.credentials.sipUri = `sip:${primary.extension}@${domain}`;
|
|
23498
|
-
console.log(`SDK: Auto-selected extension ${primary.extension}`);
|
|
23499
23588
|
}
|
|
23500
|
-
|
|
23501
|
-
|
|
23502
|
-
|
|
23589
|
+
if (this.credentials?.sipUri) {
|
|
23590
|
+
await this.initializeUserAgent();
|
|
23591
|
+
this.initializeCallManager();
|
|
23592
|
+
await this.waitForRegistration();
|
|
23593
|
+
}
|
|
23503
23594
|
} catch (error) {
|
|
23504
23595
|
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
23505
23596
|
this.emitError(new ConnectionError(`Initialization failed: ${errorMessage}`));
|
|
@@ -23533,6 +23624,16 @@ var DoraCell = class {
|
|
|
23533
23624
|
if (!this.credentials) {
|
|
23534
23625
|
throw new ConnectionError("No credentials available");
|
|
23535
23626
|
}
|
|
23627
|
+
this.connectionStatus = "connecting";
|
|
23628
|
+
this.emitConnectionStatus();
|
|
23629
|
+
if (this.ua) {
|
|
23630
|
+
try {
|
|
23631
|
+
this.ua.stop();
|
|
23632
|
+
} catch (e) {
|
|
23633
|
+
}
|
|
23634
|
+
this.ua = null;
|
|
23635
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
23636
|
+
}
|
|
23536
23637
|
try {
|
|
23537
23638
|
const socket = new import_jssip.default.WebSocketInterface(this.credentials.wsUrl);
|
|
23538
23639
|
const pcConfig = {
|
|
@@ -23544,16 +23645,18 @@ var DoraCell = class {
|
|
|
23544
23645
|
sockets: [socket],
|
|
23545
23646
|
register: true,
|
|
23546
23647
|
display_name: this.getDisplayName(),
|
|
23547
|
-
sessionTimers:
|
|
23648
|
+
sessionTimers: true,
|
|
23649
|
+
session_timers_refresh_method: "UPDATE",
|
|
23548
23650
|
trickleIce: false,
|
|
23549
23651
|
pcConfig,
|
|
23550
23652
|
instance_id: this.generateInstanceId()
|
|
23551
23653
|
};
|
|
23552
|
-
console.log("SDK: Initializing UA with config:", { ...uaConfig, password: "***" });
|
|
23553
23654
|
this.ua = new import_jssip.default.UA(uaConfig);
|
|
23554
23655
|
this.setupUserAgentHandlers();
|
|
23555
|
-
console.log("SDK: Starting UA...");
|
|
23556
23656
|
this.ua.start();
|
|
23657
|
+
if (this.callManager) {
|
|
23658
|
+
this.callManager.setUserAgent(this.ua);
|
|
23659
|
+
}
|
|
23557
23660
|
} catch (error) {
|
|
23558
23661
|
throw new ConnectionError(
|
|
23559
23662
|
`Failed to initialize User Agent: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
@@ -23573,6 +23676,7 @@ var DoraCell = class {
|
|
|
23573
23676
|
this.ua.on("registered", () => {
|
|
23574
23677
|
this.connectionStatus = "registered";
|
|
23575
23678
|
this.retryCount = 0;
|
|
23679
|
+
console.log(`Dora Cell SDK: Connected (${this.getDisplayName()})`);
|
|
23576
23680
|
this.emitConnectionStatus();
|
|
23577
23681
|
});
|
|
23578
23682
|
this.ua.on("registrationFailed", (e) => {
|
|
@@ -23587,9 +23691,7 @@ var DoraCell = class {
|
|
|
23587
23691
|
});
|
|
23588
23692
|
this.ua.on("newRTCSession", (e) => {
|
|
23589
23693
|
const session = e.session;
|
|
23590
|
-
console.log(`SDK: New session detected (${session.direction}):`, session.remote_identity?.uri?.toString());
|
|
23591
23694
|
if (session.direction === "incoming") {
|
|
23592
|
-
console.log("SDK: Handling incoming call event");
|
|
23593
23695
|
this.callManager?.handleIncomingCall(session);
|
|
23594
23696
|
}
|
|
23595
23697
|
});
|
|
@@ -23623,7 +23725,7 @@ var DoraCell = class {
|
|
|
23623
23725
|
/**
|
|
23624
23726
|
* Answer an incoming call
|
|
23625
23727
|
*/
|
|
23626
|
-
answerCall() {
|
|
23728
|
+
async answerCall() {
|
|
23627
23729
|
const currentCall = this.callManager?.getCurrentCall();
|
|
23628
23730
|
if (!currentCall) {
|
|
23629
23731
|
throw new CallError("No incoming call to answer");
|
|
@@ -23631,7 +23733,7 @@ var DoraCell = class {
|
|
|
23631
23733
|
if (currentCall.direction !== "inbound") {
|
|
23632
23734
|
throw new CallError("Current call is not an incoming call");
|
|
23633
23735
|
}
|
|
23634
|
-
this.callManager.answerCurrentCall();
|
|
23736
|
+
await this.callManager.answerCurrentCall();
|
|
23635
23737
|
}
|
|
23636
23738
|
/**
|
|
23637
23739
|
* Hangup the current call
|
|
@@ -23659,7 +23761,6 @@ var DoraCell = class {
|
|
|
23659
23761
|
return { balance: 0, currency: "NGN" };
|
|
23660
23762
|
}
|
|
23661
23763
|
try {
|
|
23662
|
-
console.log("SDK: Fetching wallet balance...");
|
|
23663
23764
|
const response = await this.apiClient.get("/wallets");
|
|
23664
23765
|
const wallets = Array.isArray(response) ? response : response.data || [];
|
|
23665
23766
|
if (wallets.length === 0) {
|
|
@@ -23667,11 +23768,11 @@ var DoraCell = class {
|
|
|
23667
23768
|
return { balance: 0, currency: "NGN" };
|
|
23668
23769
|
}
|
|
23669
23770
|
const primary = wallets[0];
|
|
23771
|
+
this.userId = primary.user_id || null;
|
|
23670
23772
|
const result = {
|
|
23671
|
-
balance: parseFloat(primary.balance || "0"),
|
|
23773
|
+
balance: parseFloat(primary.balance || primary.amount || "0"),
|
|
23672
23774
|
currency: primary.currency || "NGN"
|
|
23673
23775
|
};
|
|
23674
|
-
console.log("SDK: Wallet balance fetched:", result);
|
|
23675
23776
|
return result;
|
|
23676
23777
|
} catch (error) {
|
|
23677
23778
|
console.error("SDK: Failed to fetch wallet:", error);
|
|
@@ -23692,14 +23793,14 @@ var DoraCell = class {
|
|
|
23692
23793
|
throw new Error("SDK not authenticated. Call initialize() first.");
|
|
23693
23794
|
}
|
|
23694
23795
|
try {
|
|
23695
|
-
const
|
|
23796
|
+
const path = this.userId ? `/user/${this.userId}/extensions` : "/extensions";
|
|
23797
|
+
const response = await this.apiClient.get(path);
|
|
23696
23798
|
const extensions = response.data || response.extensions || response;
|
|
23697
23799
|
if (this.credentials && Array.isArray(extensions)) {
|
|
23698
23800
|
this.credentials.extensions = extensions;
|
|
23699
23801
|
}
|
|
23700
23802
|
return Array.isArray(extensions) ? extensions : [];
|
|
23701
23803
|
} catch (error) {
|
|
23702
|
-
console.error("SDK: Failed to fetch extensions:", error);
|
|
23703
23804
|
return this.credentials?.extensions || [];
|
|
23704
23805
|
}
|
|
23705
23806
|
}
|
|
@@ -23713,11 +23814,11 @@ var DoraCell = class {
|
|
|
23713
23814
|
* Update active extension and re-initialize SIP connection
|
|
23714
23815
|
*/
|
|
23715
23816
|
async setExtension(extension) {
|
|
23716
|
-
console.log(`SDK: Switching to extension ${extension}...`);
|
|
23717
23817
|
if (this.credentials) {
|
|
23718
|
-
const domain = this.credentials.sipDomain || "
|
|
23818
|
+
const domain = this.credentials.sipDomain || "64.227.10.164";
|
|
23719
23819
|
this.credentials.sipUri = `sip:${extension}@${domain}`;
|
|
23720
23820
|
await this.initializeUserAgent();
|
|
23821
|
+
await this.waitForRegistration();
|
|
23721
23822
|
this.emitConnectionStatus(this.connectionStatus);
|
|
23722
23823
|
}
|
|
23723
23824
|
}
|
|
@@ -23751,10 +23852,14 @@ var DoraCell = class {
|
|
|
23751
23852
|
}
|
|
23752
23853
|
// Helper methods
|
|
23753
23854
|
emitConnectionStatus(error) {
|
|
23754
|
-
|
|
23855
|
+
let activeExt = this.credentials?.sipUri ? extractNumberFromSipUri(this.credentials.sipUri) : void 0;
|
|
23856
|
+
if (!activeExt && this.credentials?.extensions && this.credentials.extensions.length > 0) {
|
|
23857
|
+
const primary = this.credentials.extensions.find((e) => e.isPrimary) || this.credentials.extensions[0];
|
|
23858
|
+
activeExt = primary.extension;
|
|
23859
|
+
}
|
|
23755
23860
|
const state = {
|
|
23756
23861
|
status: this.connectionStatus,
|
|
23757
|
-
extension,
|
|
23862
|
+
extension: activeExt,
|
|
23758
23863
|
error
|
|
23759
23864
|
};
|
|
23760
23865
|
this.events.emit("connection:status", state);
|
|
@@ -23780,6 +23885,12 @@ var DoraCell = class {
|
|
|
23780
23885
|
];
|
|
23781
23886
|
}
|
|
23782
23887
|
getDisplayName() {
|
|
23888
|
+
const currentExt = this.credentials?.sipUri ? extractNumberFromSipUri(this.credentials.sipUri) : null;
|
|
23889
|
+
if (currentExt && this.credentials?.extensions) {
|
|
23890
|
+
const found = this.credentials.extensions.find((e) => e.extension === currentExt);
|
|
23891
|
+
if (found?.displayName) return found.displayName;
|
|
23892
|
+
if (found?.extension) return `Ext ${found.extension}`;
|
|
23893
|
+
}
|
|
23783
23894
|
if (this.credentials?.extensions?.[0]?.displayName) {
|
|
23784
23895
|
return this.credentials.extensions[0].displayName;
|
|
23785
23896
|
}
|
|
@@ -23802,7 +23913,7 @@ var DoraCell = class {
|
|
|
23802
23913
|
case "staging":
|
|
23803
23914
|
case "dev":
|
|
23804
23915
|
return "https://dev.api.cell.usedora.com/api";
|
|
23805
|
-
|
|
23916
|
+
default:
|
|
23806
23917
|
return "https://api.cell.usedora.com/api";
|
|
23807
23918
|
}
|
|
23808
23919
|
}
|