@tarunzyraclavis/zyra-twilio-wrapper 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/.eslint.json +15 -0
- package/README.md +2 -0
- package/dist/index.d.mts +156 -0
- package/dist/index.d.ts +156 -0
- package/dist/index.js +467 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +436 -0
- package/dist/index.mjs.map +1 -0
- package/eslint.config.js +21 -0
- package/package.json +44 -0
- package/src/index.ts +510 -0
- package/tsconfig.json +15 -0
- package/tsup.config.ts +25 -0
- package/types/interface.ts +162 -0
- package/utils/errorHandler.ts +37 -0
- package/utils/helper.ts +20 -0
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import axios2 from "axios";
|
|
3
|
+
import { Device } from "@twilio/voice-sdk";
|
|
4
|
+
|
|
5
|
+
// utils/errorHandler.ts
|
|
6
|
+
import axios from "axios";
|
|
7
|
+
function handleAxiosError(error, onErrorCallback, contextMessage = "Request failed") {
|
|
8
|
+
let finalError;
|
|
9
|
+
if (axios.isAxiosError(error)) {
|
|
10
|
+
const axiosError = error;
|
|
11
|
+
const status = axiosError.response?.status ?? "Unknown";
|
|
12
|
+
const statusText = axiosError.response?.statusText ?? "No status text";
|
|
13
|
+
const responseData = axiosError.response?.data ? JSON.stringify(axiosError.response.data) : "No response data";
|
|
14
|
+
finalError = new Error(
|
|
15
|
+
`[AxiosError] ${contextMessage}: ${status} ${statusText} | Response: ${responseData}`
|
|
16
|
+
);
|
|
17
|
+
} else if (error instanceof Error) {
|
|
18
|
+
finalError = new Error(`[Error] ${contextMessage}: ${error.message}`);
|
|
19
|
+
} else {
|
|
20
|
+
finalError = new Error(`[Unknown Error] ${contextMessage}: ${String(error)}`);
|
|
21
|
+
}
|
|
22
|
+
console.error(finalError);
|
|
23
|
+
onErrorCallback?.(finalError);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// utils/helper.ts
|
|
27
|
+
function createSuccessResult(message, data) {
|
|
28
|
+
return { success: true, message, data };
|
|
29
|
+
}
|
|
30
|
+
function createErrorResult(error) {
|
|
31
|
+
return {
|
|
32
|
+
success: false,
|
|
33
|
+
error: error instanceof Error ? error : new Error(error)
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// src/index.ts
|
|
38
|
+
var ZyraTwilioWrapper = class {
|
|
39
|
+
constructor(configObj) {
|
|
40
|
+
this.device = null;
|
|
41
|
+
this.activeConnection = null;
|
|
42
|
+
this.isInitialized = false;
|
|
43
|
+
this.isInitializing = false;
|
|
44
|
+
this.activeCallSid = null;
|
|
45
|
+
this.conferenceDetail = null;
|
|
46
|
+
this.participants = [];
|
|
47
|
+
this.waitUrl = "https://api.twilio.com/cowbell.mp3";
|
|
48
|
+
this.serverUrl = configObj.serverUrl;
|
|
49
|
+
this.identity = configObj.identity;
|
|
50
|
+
this.waitUrl = configObj.waitUrl || this.waitUrl;
|
|
51
|
+
this.conferenceName = `conf_${this.identity}`;
|
|
52
|
+
}
|
|
53
|
+
// /**
|
|
54
|
+
// * Initialize the Twilio device and get token
|
|
55
|
+
// */
|
|
56
|
+
/**
|
|
57
|
+
* Initialize the SDK. Can only be called once.
|
|
58
|
+
*
|
|
59
|
+
* @throws {Error} If already initialized or initialization fails
|
|
60
|
+
* @returns Promise that resolves when initialization is complete
|
|
61
|
+
*/
|
|
62
|
+
async init() {
|
|
63
|
+
if (this.isInitialized) {
|
|
64
|
+
throw new Error(
|
|
65
|
+
"SDK is already initialized. Call destroy() first to reinitialize."
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
if (this.isInitializing) {
|
|
69
|
+
throw new Error("SDK initialization is already in progress");
|
|
70
|
+
}
|
|
71
|
+
this.isInitializing = true;
|
|
72
|
+
try {
|
|
73
|
+
if (!this.serverUrl) {
|
|
74
|
+
throw new Error("serverUrl is required");
|
|
75
|
+
}
|
|
76
|
+
if (!this.identity) {
|
|
77
|
+
throw new Error("identity is required");
|
|
78
|
+
}
|
|
79
|
+
const token = await this.generateToken();
|
|
80
|
+
this.device = new Device(token, { logLevel: 3 });
|
|
81
|
+
this.setupDeviceEventHandlers();
|
|
82
|
+
await this.device.register();
|
|
83
|
+
this.isInitialized = true;
|
|
84
|
+
console.info("[init] Device registration completed");
|
|
85
|
+
} catch (error) {
|
|
86
|
+
handleAxiosError(error, this.onError, "Failed to fetch token");
|
|
87
|
+
throw error;
|
|
88
|
+
} finally {
|
|
89
|
+
this.isInitializing = false;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
// Private methods for get token for initialize the device
|
|
93
|
+
async generateToken() {
|
|
94
|
+
try {
|
|
95
|
+
const payload = {
|
|
96
|
+
identity: this.identity,
|
|
97
|
+
ttl: 3600,
|
|
98
|
+
incomingAllow: true
|
|
99
|
+
};
|
|
100
|
+
const res = await axios2.post(`${this.serverUrl}/voipSdk.generateToken`, payload);
|
|
101
|
+
const token = res.data.result.data.token;
|
|
102
|
+
if (!token) {
|
|
103
|
+
throw new Error("Token not found in server response");
|
|
104
|
+
}
|
|
105
|
+
return token;
|
|
106
|
+
} catch (error) {
|
|
107
|
+
handleAxiosError(error, this.onError, "Failed to generate Twilio token");
|
|
108
|
+
throw error;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
// Private methods for handling the event for device
|
|
112
|
+
setupDeviceEventHandlers() {
|
|
113
|
+
if (!this.device) return;
|
|
114
|
+
this.device.on("registered", () => {
|
|
115
|
+
console.info("[Device] Registered");
|
|
116
|
+
this.onReady?.();
|
|
117
|
+
});
|
|
118
|
+
this.device.on("incoming", (conn) => {
|
|
119
|
+
console.info("[Device] Incoming call detected");
|
|
120
|
+
conn.on("cancel", () => {
|
|
121
|
+
console.warn("[Device] Caller hung up before answer");
|
|
122
|
+
this.activeConnection = null;
|
|
123
|
+
this.onMissedCall?.();
|
|
124
|
+
});
|
|
125
|
+
conn.on("reject", () => {
|
|
126
|
+
console.warn("[Device] Call rejected");
|
|
127
|
+
this.activeConnection = null;
|
|
128
|
+
});
|
|
129
|
+
conn.on("accept", () => console.info("[Device] Call accepted"));
|
|
130
|
+
this.activeConnection = conn;
|
|
131
|
+
this.onIncoming?.(conn);
|
|
132
|
+
});
|
|
133
|
+
this.device.on("disconnect", () => {
|
|
134
|
+
console.info("[Device] Call disconnected");
|
|
135
|
+
this.activeConnection = null;
|
|
136
|
+
this.onDisconnect?.();
|
|
137
|
+
});
|
|
138
|
+
this.device.on("connect", (conn) => {
|
|
139
|
+
console.info("[Device] Call connected");
|
|
140
|
+
this.activeConnection = conn;
|
|
141
|
+
this.onConnect?.(conn);
|
|
142
|
+
});
|
|
143
|
+
this.device.on("error", (error) => {
|
|
144
|
+
handleAxiosError(error, this.onError, "Device encountered an error");
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Check if SDK is initialized
|
|
149
|
+
*/
|
|
150
|
+
get initialized() {
|
|
151
|
+
return this.isInitialized;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Destroy the SDK instance and clean up resources
|
|
155
|
+
*/
|
|
156
|
+
destroy() {
|
|
157
|
+
if (this.device) {
|
|
158
|
+
this.device.removeAllListeners();
|
|
159
|
+
this.device.on("error", (error) => {
|
|
160
|
+
handleAxiosError(error, this.onError, "Device encountered an error during destroy");
|
|
161
|
+
});
|
|
162
|
+
this.device.on("tokenWillExpire", async () => {
|
|
163
|
+
const token = await this.generateToken();
|
|
164
|
+
this.device?.updateToken(token);
|
|
165
|
+
});
|
|
166
|
+
this.device.destroy();
|
|
167
|
+
this.device = null;
|
|
168
|
+
}
|
|
169
|
+
this.isInitialized = false;
|
|
170
|
+
this.isInitializing = false;
|
|
171
|
+
this.activeConnection = null;
|
|
172
|
+
console.info("[destroy] Device destroyed and SDK state reset");
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Make an outgoing call or add participant to an existing call
|
|
176
|
+
*/
|
|
177
|
+
async makeCall(to) {
|
|
178
|
+
if (!this.device) {
|
|
179
|
+
return createErrorResult("Device not initialized");
|
|
180
|
+
}
|
|
181
|
+
if (!to) {
|
|
182
|
+
console.warn("[makeCall] 'to' parameter is required");
|
|
183
|
+
return createErrorResult("[makeCall] 'to' parameter is required");
|
|
184
|
+
}
|
|
185
|
+
if (!this.activeConnection) {
|
|
186
|
+
try {
|
|
187
|
+
const connection = await this.device.connect({
|
|
188
|
+
params: { To: to, conferenceName: this.conferenceName }
|
|
189
|
+
});
|
|
190
|
+
this.activeConnection = connection;
|
|
191
|
+
connection.on("accept", async (conn) => {
|
|
192
|
+
this.activeCallSid = connection?.parameters?.CallSid ?? null;
|
|
193
|
+
console.info(`[makeCall] Call accepted. Call SID: ${this.activeCallSid}`);
|
|
194
|
+
this.onAnswerOutGoing?.(conn);
|
|
195
|
+
await this.getConferenceId();
|
|
196
|
+
});
|
|
197
|
+
connection.on("error", (error) => {
|
|
198
|
+
console.error("[makeCall] Connection error:", error.message);
|
|
199
|
+
this.onError?.(error);
|
|
200
|
+
});
|
|
201
|
+
connection.on("disconnect", () => {
|
|
202
|
+
console.info("[makeCall] Call disconnected.");
|
|
203
|
+
this.activeConnection = null;
|
|
204
|
+
this.onDisconnect?.();
|
|
205
|
+
});
|
|
206
|
+
console.info(`[makeCall] Outgoing call initiated to: ${to}`);
|
|
207
|
+
return createSuccessResult(`[makeCall] Outgoing call initiated to: ${to}`, connection);
|
|
208
|
+
} catch (error) {
|
|
209
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
210
|
+
console.error("[makeCall] Failed to initiate call:", err.message);
|
|
211
|
+
this.onError?.(err);
|
|
212
|
+
return createErrorResult(`[makeCall] Failed to initiate call: ${err.message}`);
|
|
213
|
+
}
|
|
214
|
+
} else {
|
|
215
|
+
try {
|
|
216
|
+
console.info("[makeCall] Active call found. Holding and adding new participant...");
|
|
217
|
+
await this.holdAndAddParticipant(this.activeConnection.parameters.CallSid, to);
|
|
218
|
+
return createSuccessResult(`[makeCall] Outgoing participant ${to} added`, this.activeConnection);
|
|
219
|
+
} catch (error) {
|
|
220
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
221
|
+
console.error("[makeCall] Failed to add participant:", err.message);
|
|
222
|
+
this.onError?.(err);
|
|
223
|
+
return createErrorResult(`[makeCall] Failed to add participant: ${err.message}`);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Accept incoming call
|
|
229
|
+
*/
|
|
230
|
+
acceptCall() {
|
|
231
|
+
if (!this.device || !this.activeConnection) {
|
|
232
|
+
const msg = !this.device ? "Device not initialized." : "No active call to accept.";
|
|
233
|
+
console.warn(`[acceptCall] ${msg}`);
|
|
234
|
+
return createErrorResult(`[acceptCall] ${msg}`);
|
|
235
|
+
}
|
|
236
|
+
try {
|
|
237
|
+
this.activeConnection.accept();
|
|
238
|
+
console.info("[acceptCall] Call accepted successfully.");
|
|
239
|
+
return createSuccessResult("Call accepted successfully.", this.activeConnection);
|
|
240
|
+
} catch (error) {
|
|
241
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
242
|
+
console.error("[acceptCall] Failed:", err.message);
|
|
243
|
+
this.onError?.(err);
|
|
244
|
+
return createErrorResult(`[acceptCall] Failed: ${err.message}`);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Hang up active call
|
|
249
|
+
*/
|
|
250
|
+
hangup() {
|
|
251
|
+
if (!this.device || !this.activeConnection) {
|
|
252
|
+
const msg = !this.device ? "Device not initialized." : "No active call to hang up.";
|
|
253
|
+
console.warn(`[hangup] ${msg}`);
|
|
254
|
+
return createErrorResult(`[hangup] ${msg}`);
|
|
255
|
+
}
|
|
256
|
+
try {
|
|
257
|
+
this.device.disconnectAll();
|
|
258
|
+
this.activeConnection = null;
|
|
259
|
+
console.info("[hangup] Call hung up successfully.");
|
|
260
|
+
return createSuccessResult("Call hung up successfully.", this.activeConnection);
|
|
261
|
+
} catch (error) {
|
|
262
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
263
|
+
console.error("[hangup] Failed:", err.message);
|
|
264
|
+
this.onError?.(err);
|
|
265
|
+
return createErrorResult(`Failed to hang up: ${err.message}`);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Reject incoming call
|
|
270
|
+
*/
|
|
271
|
+
rejectCall() {
|
|
272
|
+
if (!this.device || !this.activeConnection) {
|
|
273
|
+
const msg = !this.device ? "Device not initialized." : "No active call to reject.";
|
|
274
|
+
console.warn(`[rejectCall] ${msg}`);
|
|
275
|
+
return createErrorResult(`[rejectCall] ${msg}`);
|
|
276
|
+
}
|
|
277
|
+
try {
|
|
278
|
+
this.activeConnection.reject();
|
|
279
|
+
this.activeConnection = null;
|
|
280
|
+
console.info("[rejectCall] Call rejected successfully.");
|
|
281
|
+
return createSuccessResult("[rejectCall] Call rejected successfully.", this.activeConnection);
|
|
282
|
+
} catch (error) {
|
|
283
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
284
|
+
console.error("[rejectCall] Failed:", err.message);
|
|
285
|
+
this.onError?.(err);
|
|
286
|
+
return createErrorResult(`Failed to reject call: ${err.message}`);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Toggle mute/unmute
|
|
291
|
+
*/
|
|
292
|
+
toggleMute(mute) {
|
|
293
|
+
if (!this.activeConnection) {
|
|
294
|
+
console.warn("[toggleMute] No active call to mute/unmute.");
|
|
295
|
+
return createErrorResult("[toggleMute] No active call to mute/unmute.");
|
|
296
|
+
}
|
|
297
|
+
try {
|
|
298
|
+
this.activeConnection.mute(mute);
|
|
299
|
+
console.info(`[toggleMute] Call ${mute ? "muted" : "unmuted"} successfully.`);
|
|
300
|
+
return createSuccessResult(`Call ${mute ? "muted" : "unmuted"} successfully.`, this.activeConnection);
|
|
301
|
+
} catch (error) {
|
|
302
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
303
|
+
console.error("[toggleMute] Failed:", err.message);
|
|
304
|
+
this.onError?.(err);
|
|
305
|
+
return createErrorResult(`Failed to toggle mute: ${err.message}`);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Hold a call
|
|
310
|
+
*/
|
|
311
|
+
async hold(callSid) {
|
|
312
|
+
if (!this.activeConnection) return createErrorResult("No active call to hold.");
|
|
313
|
+
if (!callSid) return createErrorResult("Please provide callSid.");
|
|
314
|
+
try {
|
|
315
|
+
const payload = { callSid, conferenceName: this.conferenceName, waitUrl: this.waitUrl };
|
|
316
|
+
await axios2.post(`${this.serverUrl}/outgoingCall.hold`, payload);
|
|
317
|
+
console.info("[hold] Call held successfully.");
|
|
318
|
+
return createSuccessResult("Call held successfully.", this.activeConnection);
|
|
319
|
+
} catch (error) {
|
|
320
|
+
handleAxiosError(error, this.onError, "Failed to hold call");
|
|
321
|
+
const errMessage = error instanceof Error ? error.message : String(error);
|
|
322
|
+
return createErrorResult(`Failed to hold call: ${errMessage}`);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Resume a held call
|
|
327
|
+
*/
|
|
328
|
+
async resume(callSid) {
|
|
329
|
+
if (!this.activeConnection) return createErrorResult("No active call to resume.");
|
|
330
|
+
if (!callSid) return createErrorResult("Please provide callSid.");
|
|
331
|
+
try {
|
|
332
|
+
const payload = { callSid, conferenceName: this.conferenceName };
|
|
333
|
+
await axios2.post(`${this.serverUrl}/outgoingCall.unhold`, payload);
|
|
334
|
+
console.info("[resume] Call resumed successfully.");
|
|
335
|
+
return createSuccessResult("Call resumed successfully.", this.activeConnection);
|
|
336
|
+
} catch (error) {
|
|
337
|
+
handleAxiosError(error, this.onError, "Failed to resume call");
|
|
338
|
+
const errMessage = error instanceof Error ? error.message : String(error);
|
|
339
|
+
return createErrorResult(`Failed to resume call: ${errMessage}`);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Hold active call and add a new participant
|
|
344
|
+
*/
|
|
345
|
+
async holdAndAddParticipant(callSid, newParticipantNo) {
|
|
346
|
+
if (!this.activeConnection) return createErrorResult("No active call.");
|
|
347
|
+
if (!callSid) return createErrorResult("Please provide callSid.");
|
|
348
|
+
if (!newParticipantNo) return createErrorResult("Please provide participant number.");
|
|
349
|
+
try {
|
|
350
|
+
const holdPayload = { conferenceName: this.conferenceName, callSid, waitUrl: this.waitUrl };
|
|
351
|
+
const holdRes = await axios2.post(`${this.serverUrl}/outgoingCall.hold`, holdPayload);
|
|
352
|
+
const addPayload = { conferenceName: this.conferenceName, newParticipantNo };
|
|
353
|
+
const addRes = await axios2.post(`${this.serverUrl}/outgoingCall.addNewCallee`, addPayload);
|
|
354
|
+
console.info("[holdAndAddParticipant] Call held and participant added successfully.");
|
|
355
|
+
return {
|
|
356
|
+
message: "Call held and participant added successfully.",
|
|
357
|
+
status: true,
|
|
358
|
+
holdResponse: holdRes.data,
|
|
359
|
+
addParticipantResponse: addRes.data
|
|
360
|
+
};
|
|
361
|
+
} catch (error) {
|
|
362
|
+
handleAxiosError(error, this.onError, "Failed to hold and add participant");
|
|
363
|
+
const errMessage = error instanceof Error ? error.message : String(error);
|
|
364
|
+
return createErrorResult(`Failed to hold/add participant: ${errMessage}`);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* Fetch conference details
|
|
369
|
+
*/
|
|
370
|
+
async getConferenceId() {
|
|
371
|
+
if (!this.activeConnection) return createErrorResult("No active call.");
|
|
372
|
+
const payload = { conferenceName: this.conferenceName };
|
|
373
|
+
try {
|
|
374
|
+
const res = await axios2.post(`${this.serverUrl}/outgoingCall.getConferenceId`, payload);
|
|
375
|
+
if (res?.data?.result?.data) {
|
|
376
|
+
const confDetails = {
|
|
377
|
+
conferenceSid: res.data.result.data.conferenceSid,
|
|
378
|
+
conferences: res.data.result.data.conferences
|
|
379
|
+
};
|
|
380
|
+
this.conferenceDetail = confDetails;
|
|
381
|
+
console.info("[getConferenceId] Conference details fetched successfully.");
|
|
382
|
+
return createSuccessResult("Call resumed successfully.", confDetails);
|
|
383
|
+
}
|
|
384
|
+
console.warn("[getConferenceId] No conference data returned from server.");
|
|
385
|
+
return { message: "No conference data returned.", status: false };
|
|
386
|
+
} catch (error) {
|
|
387
|
+
handleAxiosError(error, this.onError, "Failed to get conference ID");
|
|
388
|
+
const errMessage = error instanceof Error ? error.message : String(error);
|
|
389
|
+
return createErrorResult(`Failed to get conference ID: ${errMessage}`);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* Get participants of a conference
|
|
394
|
+
*/
|
|
395
|
+
async getParticipants(conferenceSid) {
|
|
396
|
+
if (!this.activeConnection) return createErrorResult("No active call.");
|
|
397
|
+
if (!conferenceSid) return createErrorResult("Please provide conferenceSid.");
|
|
398
|
+
try {
|
|
399
|
+
const payload = { conferenceSid };
|
|
400
|
+
const res = await axios2.post(`${this.serverUrl}/outgoingCall.getParticipants`, payload);
|
|
401
|
+
if (res?.data?.result?.data?.participants) {
|
|
402
|
+
this.participants = res.data.result.data.participants;
|
|
403
|
+
console.info("[getParticipants] Participants fetched successfully.");
|
|
404
|
+
return createSuccessResult("Participants fetched successfully.", this.participants);
|
|
405
|
+
}
|
|
406
|
+
console.warn("[getParticipants] No participants returned from server.");
|
|
407
|
+
return { message: "No participants returned.", status: false };
|
|
408
|
+
} catch (error) {
|
|
409
|
+
handleAxiosError(error, this.onError, "Failed to get participants");
|
|
410
|
+
const errMessage = error instanceof Error ? error.message : String(error);
|
|
411
|
+
return createErrorResult(`Failed to get participants: ${errMessage}`);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
/**
|
|
415
|
+
* Remove a participant from a conference
|
|
416
|
+
*/
|
|
417
|
+
async removeParticipant(conferenceSid, callSid) {
|
|
418
|
+
if (!this.activeConnection) return createErrorResult("No active call.");
|
|
419
|
+
if (!callSid) return createErrorResult("Please provide callSid.");
|
|
420
|
+
if (!conferenceSid) return createErrorResult("Please provide conferenceSid.");
|
|
421
|
+
try {
|
|
422
|
+
const payload = { callSid, conferenceSid };
|
|
423
|
+
const res = await axios2.post(`${this.serverUrl}/outgoingCall.removeParticipant`, payload);
|
|
424
|
+
console.info("[removeParticipant] Participant removed successfully.");
|
|
425
|
+
return createSuccessResult("Participant removed successfully.", res.data);
|
|
426
|
+
} catch (error) {
|
|
427
|
+
handleAxiosError(error, this.onError, "Failed to remove participant");
|
|
428
|
+
const errMessage = error instanceof Error ? error.message : String(error);
|
|
429
|
+
return createErrorResult(`Failed to remove participant: ${errMessage}`);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
};
|
|
433
|
+
export {
|
|
434
|
+
ZyraTwilioWrapper as default
|
|
435
|
+
};
|
|
436
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../utils/errorHandler.ts","../utils/helper.ts"],"sourcesContent":["import axios from \"axios\";\r\nimport { Device, Call } from \"@twilio/voice-sdk\";\r\nimport { handleAxiosError } from '../utils/errorHandler';\r\nimport {\r\n AddParticipantPayload,\r\n CallResponse,\r\n Config,\r\n GetConferencePayload,\r\n GetConferenceResult,\r\n GetParticipantsPayload,\r\n GetParticipantsResult,\r\n HoldAndAddResult,\r\n HoldCallPayload,\r\n HoldPayload,\r\n RemoveParticipantPayload,\r\n RemoveParticipantResult,\r\n ResumeCallPayload,\r\n TokenRequestPayload,\r\n TokenResponse,\r\n TwilioConference,\r\n TwilioConferenceParticipant,\r\n} from '../types/interface';\r\nimport { createSuccessResult, createErrorResult } from '../utils/helper'\r\n\r\nexport default class ZyraTwilioWrapper {\r\n private readonly serverUrl: string;\r\n private readonly identity: string;\r\n private device: Device | null = null;\r\n private activeConnection: Call | null = null;\r\n private isInitialized: boolean = false;\r\n private isInitializing: boolean = false;\r\n public activeCallSid: string | null = null;\r\n public conferenceName: string;\r\n public conferenceDetail: TwilioConference | null = null;\r\n public participants: TwilioConferenceParticipant[] = [];\r\n public waitUrl: string = \"https://api.twilio.com/cowbell.mp3\";\r\n\r\n // Optional event handlers\r\n public onReady?: () => void;\r\n public onIncoming?: (conn: Call) => void;\r\n public onDisconnect?: () => void;\r\n public onError?: (error: Error) => void;\r\n public onConnect?: (conn: Call) => void;\r\n public onMissedCall?: () => void;\r\n public onAnswerOutGoing?: (conn: Call) => void;\r\n\r\n constructor(configObj: Config) {\r\n this.serverUrl = configObj.serverUrl;\r\n this.identity = configObj.identity;\r\n this.waitUrl = configObj.waitUrl || this.waitUrl;\r\n this.conferenceName = `conf_${this.identity}`;\r\n }\r\n\r\n // /**\r\n // * Initialize the Twilio device and get token\r\n // */\r\n /**\r\n * Initialize the SDK. Can only be called once.\r\n * \r\n * @throws {Error} If already initialized or initialization fails\r\n * @returns Promise that resolves when initialization is complete\r\n */\r\npublic async init(): Promise<void> {\r\n if (this.isInitialized) {\r\n throw new Error(\r\n \"SDK is already initialized. Call destroy() first to reinitialize.\"\r\n );\r\n }\r\n\r\n if (this.isInitializing) {\r\n throw new Error(\"SDK initialization is already in progress\");\r\n }\r\n\r\n this.isInitializing = true;\r\n\r\n try {\r\n // Validate configuration\r\n if (!this.serverUrl) {\r\n throw new Error(\"serverUrl is required\");\r\n }\r\n if (!this.identity) {\r\n throw new Error(\"identity is required\");\r\n }\r\n\r\n // Generate token and create Device\r\n const token = await this.generateToken();\r\n this.device = new Device(token, { logLevel: 3 });\r\n\r\n // Setup event handlers\r\n this.setupDeviceEventHandlers();\r\n\r\n // Register the device\r\n await this.device.register();\r\n\r\n this.isInitialized = true;\r\n console.info(\"[init] Device registration completed\");\r\n } catch (error: unknown) {\r\n handleAxiosError(error, this.onError, \"Failed to fetch token\");\r\n throw error;\r\n } finally {\r\n // Reset initializing flag even if init fails\r\n this.isInitializing = false;\r\n }\r\n}\r\n\r\n // Private methods for get token for initialize the device\r\n private async generateToken(): Promise<string> {\r\n try {\r\n const payload: TokenRequestPayload = {\r\n identity: this.identity,\r\n ttl: 3600,\r\n incomingAllow: true,\r\n };\r\n\r\n const res = await axios.post<TokenResponse>(`${this.serverUrl}/voipSdk.generateToken`, payload);\r\n\r\n const token = res.data.result.data.token;\r\n\r\n if (!token) {\r\n throw new Error(\"Token not found in server response\");\r\n }\r\n\r\n return token;\r\n } catch (error : unknown) {\r\n handleAxiosError(error, this.onError, \"Failed to generate Twilio token\");\r\n throw error;\r\n }\r\n }\r\n\r\n // Private methods for handling the event for device\r\n private setupDeviceEventHandlers(): void {\r\n if (!this.device) return;\r\n\r\n this.device.on(\"registered\", () => {\r\n console.info(\"[Device] Registered\");\r\n this.onReady?.();\r\n });\r\n\r\n this.device.on(\"incoming\", (conn: Call) => {\r\n console.info(\"[Device] Incoming call detected\");\r\n conn.on(\"cancel\", () => {\r\n console.warn(\"[Device] Caller hung up before answer\");\r\n this.activeConnection = null;\r\n this.onMissedCall?.();\r\n });\r\n conn.on(\"reject\", () => {\r\n console.warn(\"[Device] Call rejected\");\r\n this.activeConnection = null;\r\n });\r\n conn.on(\"accept\", () => console.info(\"[Device] Call accepted\"));\r\n this.activeConnection = conn;\r\n this.onIncoming?.(conn);\r\n });\r\n\r\n this.device.on(\"disconnect\", () => {\r\n console.info(\"[Device] Call disconnected\");\r\n this.activeConnection = null;\r\n this.onDisconnect?.();\r\n });\r\n\r\n this.device.on(\"connect\", (conn: Call) => {\r\n console.info(\"[Device] Call connected\");\r\n this.activeConnection = conn;\r\n this.onConnect?.(conn);\r\n });\r\n\r\n this.device.on(\"error\", (error: Error) => {\r\n handleAxiosError(error, this.onError, \"Device encountered an error\");\r\n });\r\n}\r\n\r\n /**\r\n * Check if SDK is initialized\r\n */\r\n get initialized(): boolean {\r\n return this.isInitialized;\r\n }\r\n \r\n /**\r\n * Destroy the SDK instance and clean up resources\r\n */\r\n public destroy(): void {\r\n if (this.device) {\r\n // Remove all event listeners\r\n this.device.removeAllListeners();\r\n\r\n // Optionally, explicitly handle any final error events\r\n this.device.on(\"error\", (error: Error) => {\r\n handleAxiosError(error, this.onError, \"Device encountered an error during destroy\");\r\n });\r\n\r\n // When Token expires then get new and update with twilio\r\n this.device.on('tokenWillExpire', async () => {\r\n const token = await this.generateToken();\r\n this.device?.updateToken(token);\r\n });\r\n // Shutdown device\r\n this.device.destroy();\r\n this.device = null;\r\n }\r\n\r\n // Reset state flags\r\n this.isInitialized = false;\r\n this.isInitializing = false;\r\n this.activeConnection = null;\r\n\r\n console.info(\"[destroy] Device destroyed and SDK state reset\");\r\n}\r\n\r\n\r\n /**\r\n * Make an outgoing call or add participant to an existing call\r\n */\r\n public async makeCall(to: string): Promise<CallResponse<Call>> {\r\n if (!this.device) {\r\n return createErrorResult(\"Device not initialized\");\r\n }\r\n\r\n if (!to) {\r\n console.warn(\"[makeCall] 'to' parameter is required\");\r\n return createErrorResult(\"[makeCall] 'to' parameter is required\");\r\n }\r\n\r\n if (!this.activeConnection) {\r\n try {\r\n const connection = await this.device.connect({\r\n params: { To: to, conferenceName: this.conferenceName },\r\n });\r\n\r\n this.activeConnection = connection;\r\n\r\n connection.on(\"accept\", async (conn: Call) => {\r\n this.activeCallSid = connection?.parameters?.CallSid ?? null;\r\n console.info(`[makeCall] Call accepted. Call SID: ${this.activeCallSid}`);\r\n this.onAnswerOutGoing?.(conn);\r\n await this.getConferenceId();\r\n });\r\n\r\n connection.on(\"error\", (error: Error) => {\r\n console.error(\"[makeCall] Connection error:\", error.message);\r\n this.onError?.(error);\r\n });\r\n\r\n connection.on(\"disconnect\", () => {\r\n console.info(\"[makeCall] Call disconnected.\");\r\n this.activeConnection = null;\r\n this.onDisconnect?.();\r\n });\r\n\r\n console.info(`[makeCall] Outgoing call initiated to: ${to}`);\r\n return createSuccessResult(`[makeCall] Outgoing call initiated to: ${to}`, connection);\r\n } catch (error: unknown) {\r\n const err = error instanceof Error ? error : new Error(String(error));\r\n console.error(\"[makeCall] Failed to initiate call:\", err.message);\r\n this.onError?.(err);\r\n return createErrorResult(`[makeCall] Failed to initiate call: ${err.message}`);\r\n }\r\n } else {\r\n try {\r\n console.info(\"[makeCall] Active call found. Holding and adding new participant...\");\r\n await this.holdAndAddParticipant(this.activeConnection.parameters.CallSid, to);\r\n return createSuccessResult(`[makeCall] Outgoing participant ${to} added`, this.activeConnection);\r\n } catch (error: unknown) {\r\n const err = error instanceof Error ? error : new Error(String(error));\r\n console.error(\"[makeCall] Failed to add participant:\", err.message);\r\n this.onError?.(err);\r\n return createErrorResult(`[makeCall] Failed to add participant: ${err.message}`);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Accept incoming call\r\n */\r\n public acceptCall(): CallResponse<Call> {\r\n if (!this.device || !this.activeConnection) {\r\n const msg = !this.device\r\n ? \"Device not initialized.\"\r\n : \"No active call to accept.\";\r\n console.warn(`[acceptCall] ${msg}`);\r\n return createErrorResult(`[acceptCall] ${msg}`);\r\n }\r\n\r\n try {\r\n this.activeConnection.accept();\r\n console.info(\"[acceptCall] Call accepted successfully.\");\r\n return createSuccessResult(\"Call accepted successfully.\", this.activeConnection);\r\n } catch (error: unknown) {\r\n const err = error instanceof Error ? error : new Error(String(error));\r\n console.error(\"[acceptCall] Failed:\", err.message);\r\n this.onError?.(err);\r\n return createErrorResult(`[acceptCall] Failed: ${err.message}`);\r\n }\r\n }\r\n\r\n /**\r\n * Hang up active call\r\n */\r\n public hangup(): CallResponse<Call | null> {\r\n if (!this.device || !this.activeConnection) {\r\n const msg = !this.device\r\n ? \"Device not initialized.\"\r\n : \"No active call to hang up.\";\r\n console.warn(`[hangup] ${msg}`);\r\n return createErrorResult(`[hangup] ${msg}`);\r\n }\r\n\r\n try {\r\n this.device.disconnectAll();\r\n this.activeConnection = null;\r\n console.info(\"[hangup] Call hung up successfully.\");\r\n return createSuccessResult(\"Call hung up successfully.\", this.activeConnection);\r\n } catch (error: unknown) {\r\n const err = error instanceof Error ? error : new Error(String(error));\r\n console.error(\"[hangup] Failed:\", err.message);\r\n this.onError?.(err);\r\n return createErrorResult(`Failed to hang up: ${err.message}`);\r\n }\r\n }\r\n\r\n /**\r\n * Reject incoming call\r\n */\r\n public rejectCall(): CallResponse<Call | null> {\r\n if (!this.device || !this.activeConnection) {\r\n const msg = !this.device\r\n ? \"Device not initialized.\"\r\n : \"No active call to reject.\";\r\n console.warn(`[rejectCall] ${msg}`);\r\n return createErrorResult(`[rejectCall] ${msg}`);\r\n }\r\n\r\n try {\r\n this.activeConnection.reject();\r\n this.activeConnection = null;\r\n console.info(\"[rejectCall] Call rejected successfully.\");\r\n return createSuccessResult(\"[rejectCall] Call rejected successfully.\", this.activeConnection);\r\n } catch (error: unknown) {\r\n const err = error instanceof Error ? error : new Error(String(error));\r\n console.error(\"[rejectCall] Failed:\", err.message);\r\n this.onError?.(err);\r\n return createErrorResult(`Failed to reject call: ${err.message}`);\r\n }\r\n }\r\n\r\n /**\r\n * Toggle mute/unmute\r\n */\r\n public toggleMute(mute: boolean): CallResponse<Call> {\r\n if (!this.activeConnection) {\r\n console.warn(\"[toggleMute] No active call to mute/unmute.\");\r\n return createErrorResult(\"[toggleMute] No active call to mute/unmute.\");\r\n }\r\n\r\n try {\r\n this.activeConnection.mute(mute);\r\n console.info(`[toggleMute] Call ${mute ? \"muted\" : \"unmuted\"} successfully.`);\r\n return createSuccessResult(`Call ${mute ? \"muted\" : \"unmuted\"} successfully.`, this.activeConnection);\r\n } catch (error: unknown) {\r\n const err = error instanceof Error ? error : new Error(String(error));\r\n console.error(\"[toggleMute] Failed:\", err.message);\r\n this.onError?.(err);\r\n return createErrorResult(`Failed to toggle mute: ${err.message}`);\r\n }\r\n }\r\n\r\n /**\r\n * Hold a call\r\n */\r\n public async hold(callSid: string): Promise<CallResponse<Call>> {\r\n if (!this.activeConnection) return createErrorResult(\"No active call to hold.\");\r\n if (!callSid) return createErrorResult(\"Please provide callSid.\");\r\n\r\n try {\r\n const payload: HoldCallPayload = { callSid, conferenceName: this.conferenceName, waitUrl: this.waitUrl };\r\n await axios.post(`${this.serverUrl}/outgoingCall.hold`, payload);\r\n console.info(\"[hold] Call held successfully.\");\r\n return createSuccessResult(\"Call held successfully.\", this.activeConnection);\r\n\r\n } catch (error: unknown) {\r\n handleAxiosError(error, this.onError, \"Failed to hold call\");\r\n const errMessage = error instanceof Error ? error.message : String(error);\r\n return createErrorResult(`Failed to hold call: ${errMessage}`);\r\n }\r\n }\r\n\r\n /**\r\n * Resume a held call\r\n */\r\n public async resume(callSid: string): Promise<CallResponse<Call>> {\r\n if (!this.activeConnection) return createErrorResult(\"No active call to resume.\");\r\n if (!callSid) return createErrorResult(\"Please provide callSid.\");\r\n\r\n try {\r\n const payload: ResumeCallPayload = { callSid, conferenceName: this.conferenceName };\r\n await axios.post(`${this.serverUrl}/outgoingCall.unhold`, payload);\r\n console.info(\"[resume] Call resumed successfully.\");\r\n return createSuccessResult(\"Call resumed successfully.\", this.activeConnection);\r\n } catch (error: unknown) {\r\n handleAxiosError(error, this.onError, \"Failed to resume call\");\r\n const errMessage = error instanceof Error ? error.message : String(error);\r\n return createErrorResult(`Failed to resume call: ${errMessage}`);\r\n }\r\n }\r\n\r\n /**\r\n * Hold active call and add a new participant\r\n */\r\n public async holdAndAddParticipant(callSid: string, newParticipantNo: string): Promise<HoldAndAddResult | CallResponse> {\r\n if (!this.activeConnection) return createErrorResult(\"No active call.\");\r\n if (!callSid) return createErrorResult(\"Please provide callSid.\");\r\n if (!newParticipantNo) return createErrorResult(\"Please provide participant number.\");\r\n\r\n try {\r\n const holdPayload: HoldPayload = { conferenceName: this.conferenceName, callSid, waitUrl: this.waitUrl };\r\n const holdRes = await axios.post(`${this.serverUrl}/outgoingCall.hold`, holdPayload);\r\n\r\n const addPayload: AddParticipantPayload = { conferenceName: this.conferenceName, newParticipantNo };\r\n const addRes = await axios.post(`${this.serverUrl}/outgoingCall.addNewCallee`, addPayload);\r\n\r\n console.info(\"[holdAndAddParticipant] Call held and participant added successfully.\");\r\n return {\r\n message: \"Call held and participant added successfully.\",\r\n status: true,\r\n holdResponse: holdRes.data,\r\n addParticipantResponse: addRes.data,\r\n };\r\n } catch (error: unknown) {\r\n handleAxiosError(error, this.onError, \"Failed to hold and add participant\");\r\n const errMessage = error instanceof Error ? error.message : String(error);\r\n return createErrorResult(`Failed to hold/add participant: ${errMessage}`);\r\n }\r\n }\r\n\r\n /**\r\n * Fetch conference details\r\n */\r\n public async getConferenceId(): Promise<GetConferenceResult | CallResponse<TwilioConference>> {\r\n if (!this.activeConnection) return createErrorResult(\"No active call.\");\r\n\r\n const payload: GetConferencePayload = { conferenceName: this.conferenceName };\r\n\r\n try {\r\n const res = await axios.post(`${this.serverUrl}/outgoingCall.getConferenceId`, payload);\r\n\r\n if (res?.data?.result?.data) {\r\n const confDetails: TwilioConference = {\r\n conferenceSid: res.data.result.data.conferenceSid,\r\n conferences: res.data.result.data.conferences,\r\n };\r\n this.conferenceDetail = confDetails;\r\n console.info(\"[getConferenceId] Conference details fetched successfully.\");\r\n return createSuccessResult(\"Call resumed successfully.\", confDetails);\r\n }\r\n\r\n console.warn(\"[getConferenceId] No conference data returned from server.\");\r\n return { message: \"No conference data returned.\", status: false };\r\n } catch (error: unknown) {\r\n handleAxiosError(error, this.onError, \"Failed to get conference ID\");\r\n const errMessage = error instanceof Error ? error.message : String(error);\r\n return createErrorResult(`Failed to get conference ID: ${errMessage}`);\r\n }\r\n }\r\n\r\n /**\r\n * Get participants of a conference\r\n */\r\n public async getParticipants(conferenceSid: string): Promise<GetParticipantsResult | CallResponse<TwilioConferenceParticipant[]>> {\r\n if (!this.activeConnection) return createErrorResult(\"No active call.\");\r\n if (!conferenceSid) return createErrorResult(\"Please provide conferenceSid.\");\r\n\r\n try {\r\n const payload: GetParticipantsPayload = { conferenceSid };\r\n const res = await axios.post(`${this.serverUrl}/outgoingCall.getParticipants`, payload);\r\n\r\n if (res?.data?.result?.data?.participants) {\r\n this.participants = res.data.result.data.participants;\r\n console.info(\"[getParticipants] Participants fetched successfully.\");\r\n return createSuccessResult(\"Participants fetched successfully.\", this.participants);\r\n }\r\n\r\n console.warn(\"[getParticipants] No participants returned from server.\");\r\n return { message: \"No participants returned.\", status: false };\r\n } catch (error: unknown) {\r\n handleAxiosError(error, this.onError, \"Failed to get participants\");\r\n const errMessage = error instanceof Error ? error.message : String(error);\r\n return createErrorResult(`Failed to get participants: ${errMessage}`);\r\n }\r\n }\r\n\r\n /**\r\n * Remove a participant from a conference\r\n */\r\n public async removeParticipant(conferenceSid: string, callSid: string): Promise<RemoveParticipantResult | CallResponse> {\r\n if (!this.activeConnection) return createErrorResult(\"No active call.\");\r\n if (!callSid) return createErrorResult(\"Please provide callSid.\");\r\n if (!conferenceSid) return createErrorResult(\"Please provide conferenceSid.\");\r\n\r\n try {\r\n const payload: RemoveParticipantPayload = { callSid, conferenceSid };\r\n const res = await axios.post(`${this.serverUrl}/outgoingCall.removeParticipant`, payload);\r\n console.info(\"[removeParticipant] Participant removed successfully.\");\r\n return createSuccessResult(\"Participant removed successfully.\", res.data);\r\n } catch (error: unknown) {\r\n handleAxiosError(error, this.onError, \"Failed to remove participant\");\r\n const errMessage = error instanceof Error ? error.message : String(error);\r\n return createErrorResult(`Failed to remove participant: ${errMessage}`);\r\n }\r\n }\r\n}","import axios, { AxiosError } from \"axios\";\r\n\r\n/**\r\n * Handles errors from Axios requests in a consistent way.\r\n * \r\n * @param error - The error thrown by Axios or any other source.\r\n * @param onErrorCallback - Optional callback to handle the error externally.\r\n * @param contextMessage - Optional custom message to provide context for the error.\r\n */\r\nexport function handleAxiosError(\r\n error: unknown,\r\n onErrorCallback?: (error: Error) => void,\r\n contextMessage = \"Request failed\"\r\n): void {\r\n let finalError: Error;\r\n\r\n if (axios.isAxiosError(error)) {\r\n const axiosError = error as AxiosError;\r\n const status = axiosError.response?.status ?? \"Unknown\";\r\n const statusText = axiosError.response?.statusText ?? \"No status text\";\r\n const responseData = axiosError.response?.data\r\n ? JSON.stringify(axiosError.response.data)\r\n : \"No response data\";\r\n\r\n finalError = new Error(\r\n `[AxiosError] ${contextMessage}: ${status} ${statusText} | Response: ${responseData}`\r\n );\r\n } else if (error instanceof Error) {\r\n finalError = new Error(`[Error] ${contextMessage}: ${error.message}`);\r\n } else {\r\n finalError = new Error(`[Unknown Error] ${contextMessage}: ${String(error)}`);\r\n }\r\n\r\n console.error(finalError); // Optional: log for debugging\r\n onErrorCallback?.(finalError);\r\n}\r\n\r\n","// src/utils/helper.ts\r\n\r\nimport type { CallResponse } from \"../types/interface\"; // adjust path if needed\r\n\r\n/**\r\n * Helper to create success result\r\n */\r\nexport function createSuccessResult<T>(message: string, data: T): CallResponse<T> {\r\n return { success : true, message : message, data };\r\n}\r\n\r\n/**\r\n * Helper to create error result\r\n */\r\nexport function createErrorResult<T = void>(error: Error | string): CallResponse<T> {\r\n return {\r\n success: false,\r\n error: error instanceof Error ? error : new Error(error),\r\n };\r\n}"],"mappings":"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","names":["axios","axios"]}
|
package/eslint.config.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// eslint.config.js
|
|
2
|
+
export default [
|
|
3
|
+
{
|
|
4
|
+
files: ["**/*.js"],
|
|
5
|
+
languageOptions: {
|
|
6
|
+
ecmaVersion: "latest",
|
|
7
|
+
sourceType: "module",
|
|
8
|
+
globals: {
|
|
9
|
+
console: "readonly",
|
|
10
|
+
module: "readonly",
|
|
11
|
+
require: "readonly",
|
|
12
|
+
__dirname: "readonly"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
rules: {
|
|
16
|
+
semi: ["error", "always"],
|
|
17
|
+
quotes: ["error", "double"]
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
];
|
|
21
|
+
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@tarunzyraclavis/zyra-twilio-wrapper",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Twilio Voice SDK Wrapper for browser app",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "./dist/index.mjs",
|
|
7
|
+
"types": "./dist/index/d.ts",
|
|
8
|
+
"scripts": {
|
|
9
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
10
|
+
"build": "tsup",
|
|
11
|
+
"dev": "tsup --watch",
|
|
12
|
+
"clean": "rm -rf dist",
|
|
13
|
+
"lint": "eslint ."
|
|
14
|
+
},
|
|
15
|
+
"author": "",
|
|
16
|
+
"license": "ISC",
|
|
17
|
+
"keywords": [
|
|
18
|
+
"twilio",
|
|
19
|
+
"voice",
|
|
20
|
+
"sdk",
|
|
21
|
+
"typescript",
|
|
22
|
+
"wrapper"
|
|
23
|
+
],
|
|
24
|
+
"exports": {
|
|
25
|
+
".": {
|
|
26
|
+
"require": "./dist/index.js",
|
|
27
|
+
"import": "./dist/index.mjs",
|
|
28
|
+
"types": "./dist/index.d.ts"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"@twilio/voice-sdk": "^2.16.0",
|
|
33
|
+
"axios": "^1.12.2",
|
|
34
|
+
"dotenv": "^17.2.3",
|
|
35
|
+
"eslint": "^9.37.0",
|
|
36
|
+
"tsup": "^8.5.0",
|
|
37
|
+
"typescript": "^5.9.3",
|
|
38
|
+
"winston": "^3.18.3",
|
|
39
|
+
"winston-daily-rotate-file": "^5.0.0"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@types/node": "^24.7.2"
|
|
43
|
+
}
|
|
44
|
+
}
|