@ermis-network/ermis-chat-sdk 1.0.1 → 1.0.3
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/bin/init-call.js +52 -0
- package/dist/index.browser.cjs +174 -95
- package/dist/index.browser.cjs.map +1 -1
- package/dist/index.browser.full-bundle.min.js +15 -15
- package/dist/index.browser.full-bundle.min.js.map +1 -1
- package/dist/index.browser.mjs +173 -95
- package/dist/index.browser.mjs.map +1 -1
- package/dist/index.cjs +174 -95
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +29 -9
- package/dist/index.d.ts +29 -9
- package/dist/index.mjs +173 -95
- package/dist/index.mjs.map +1 -1
- package/package.json +7 -2
- package/public/call_incoming.mp3 +0 -0
- package/public/call_outgoing.mp3 +0 -0
- package/public/ermis_call_node_wasm_bg.wasm +0 -0
- package/src/client.ts +17 -6
- package/src/ermis_call_node.ts +77 -47
- package/src/index.ts +2 -1
- package/src/signal_message.ts +121 -71
package/bin/init-call.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
|
|
5
|
+
// Absolute path to the files inside the installed package
|
|
6
|
+
const sourceWasm = path.join(__dirname, '../public/ermis_call_node_wasm_bg.wasm');
|
|
7
|
+
const sourceIncomingMp3 = path.join(__dirname, '../public/call_incoming.mp3');
|
|
8
|
+
const sourceOutgoingMp3 = path.join(__dirname, '../public/call_outgoing.mp3');
|
|
9
|
+
|
|
10
|
+
// Execution directory (always the root of the consumer's project)
|
|
11
|
+
const targetDir = path.join(process.cwd(), 'public');
|
|
12
|
+
const targetWasm = path.join(targetDir, 'ermis_call_node_wasm_bg.wasm');
|
|
13
|
+
const targetIncomingMp3 = path.join(targetDir, 'call_incoming.mp3');
|
|
14
|
+
const targetOutgoingMp3 = path.join(targetDir, 'call_outgoing.mp3');
|
|
15
|
+
|
|
16
|
+
console.log('🔄 Configuring WebAssembly & Audio files for Ermis Direct Call feature...');
|
|
17
|
+
|
|
18
|
+
if (!fs.existsSync(sourceWasm)) {
|
|
19
|
+
console.error('❌ Error: Could not find the original Wasm file in the SDK package.');
|
|
20
|
+
console.error('Search path:', sourceWasm);
|
|
21
|
+
process.exit(1);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Create the public directory if it doesn't exist in the consumer project
|
|
25
|
+
if (!fs.existsSync(targetDir)) {
|
|
26
|
+
console.log('Creating public directory...');
|
|
27
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
try {
|
|
31
|
+
fs.copyFileSync(sourceWasm, targetWasm);
|
|
32
|
+
console.log('✅ Successfully copied ermis_call_node_wasm_bg.wasm to your public/ directory!');
|
|
33
|
+
|
|
34
|
+
if (fs.existsSync(sourceIncomingMp3)) {
|
|
35
|
+
fs.copyFileSync(sourceIncomingMp3, targetIncomingMp3);
|
|
36
|
+
console.log('✅ Successfully copied call_incoming.mp3 to your public/ directory!');
|
|
37
|
+
} else {
|
|
38
|
+
console.warn('⚠️ Warning: call_incoming.mp3 not found in SDK, skipping copy.');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (fs.existsSync(sourceOutgoingMp3)) {
|
|
42
|
+
fs.copyFileSync(sourceOutgoingMp3, targetOutgoingMp3);
|
|
43
|
+
console.log('✅ Successfully copied call_outgoing.mp3 to your public/ directory!');
|
|
44
|
+
} else {
|
|
45
|
+
console.warn('⚠️ Warning: call_outgoing.mp3 not found in SDK, skipping copy.');
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
console.log('You can now enable the Direct Call feature in your application.');
|
|
49
|
+
} catch (error) {
|
|
50
|
+
console.error('❌ An error occurred while copying the file:', error.message);
|
|
51
|
+
process.exit(1);
|
|
52
|
+
}
|
package/dist/index.browser.cjs
CHANGED
|
@@ -32,6 +32,7 @@ var index_exports = {};
|
|
|
32
32
|
__export(index_exports, {
|
|
33
33
|
CallAction: () => CallAction,
|
|
34
34
|
CallStatus: () => CallStatus,
|
|
35
|
+
CallType: () => CallType,
|
|
35
36
|
Channel: () => Channel,
|
|
36
37
|
ChannelState: () => ChannelState,
|
|
37
38
|
ClientState: () => ClientState,
|
|
@@ -3606,17 +3607,24 @@ var ErmisChat = class _ErmisChat {
|
|
|
3606
3607
|
async unpinChannel(channelType, channelId) {
|
|
3607
3608
|
return await this.post(this.baseURL + `/channels/${channelType}/${channelId}/unpin`);
|
|
3608
3609
|
}
|
|
3609
|
-
channel(channelType,
|
|
3610
|
+
channel(channelType, channelIDOrCustom, custom) {
|
|
3610
3611
|
if (!this.userID) {
|
|
3611
3612
|
throw Error("Call connectUser before creating a channel");
|
|
3612
3613
|
}
|
|
3613
3614
|
if (~channelType.indexOf(":")) {
|
|
3614
3615
|
throw Error(`Invalid channel group ${channelType}, can't contain the : character`);
|
|
3615
3616
|
}
|
|
3616
|
-
|
|
3617
|
+
let channelID = void 0;
|
|
3618
|
+
let customData = custom || {};
|
|
3619
|
+
if (typeof channelIDOrCustom === "string") {
|
|
3620
|
+
channelID = channelIDOrCustom;
|
|
3621
|
+
} else if (typeof channelIDOrCustom === "object" && channelIDOrCustom !== null) {
|
|
3622
|
+
customData = channelIDOrCustom;
|
|
3623
|
+
}
|
|
3624
|
+
return this.getChannelById(channelType, channelID, customData);
|
|
3617
3625
|
}
|
|
3618
3626
|
getChannelById = (channelType, channelID, custom) => {
|
|
3619
|
-
const cid = `${channelType}:${channelID}`;
|
|
3627
|
+
const cid = `${channelType}:${channelID || ""}`;
|
|
3620
3628
|
if (cid in this.activeChannels && !this.activeChannels[cid].disconnected) {
|
|
3621
3629
|
const channel2 = this.activeChannels[cid];
|
|
3622
3630
|
if (Object.keys(custom).length > 0) {
|
|
@@ -3659,7 +3667,7 @@ var ErmisChat = class _ErmisChat {
|
|
|
3659
3667
|
return pinExpires;
|
|
3660
3668
|
}
|
|
3661
3669
|
getUserAgent() {
|
|
3662
|
-
return this.userAgent || `ermis-chat-sdk-javascript-client-${this.node ? "node" : "browser"}-${"1.0.
|
|
3670
|
+
return this.userAgent || `ermis-chat-sdk-javascript-client-${this.node ? "node" : "browser"}-${"1.0.3"}`;
|
|
3663
3671
|
}
|
|
3664
3672
|
setUserAgent(userAgent) {
|
|
3665
3673
|
this.userAgent = userAgent;
|
|
@@ -6369,21 +6377,38 @@ var ErmisCallNode = class {
|
|
|
6369
6377
|
const mediaConstraints = await this.getMediaConstraints();
|
|
6370
6378
|
try {
|
|
6371
6379
|
const stream = await navigator.mediaDevices.getUserMedia(mediaConstraints);
|
|
6372
|
-
|
|
6373
|
-
|
|
6374
|
-
|
|
6375
|
-
|
|
6380
|
+
return this.applyLocalStream(stream);
|
|
6381
|
+
} catch (error) {
|
|
6382
|
+
console.warn("Error getting user media:", error?.message);
|
|
6383
|
+
if (this.callType === "video" && mediaConstraints.video) {
|
|
6384
|
+
try {
|
|
6385
|
+
const audioOnlyStream = await navigator.mediaDevices.getUserMedia({
|
|
6386
|
+
audio: mediaConstraints.audio,
|
|
6387
|
+
video: false
|
|
6388
|
+
});
|
|
6389
|
+
this.setConnectionMessage("Camera not available, using audio only");
|
|
6390
|
+
return this.applyLocalStream(audioOnlyStream);
|
|
6391
|
+
} catch {
|
|
6392
|
+
}
|
|
6376
6393
|
}
|
|
6377
|
-
if (this.
|
|
6378
|
-
this.
|
|
6394
|
+
if (typeof this.onError === "function") {
|
|
6395
|
+
this.onError("No microphone or camera found. Please check your device.");
|
|
6379
6396
|
}
|
|
6380
|
-
this.localStream = stream;
|
|
6381
|
-
return stream;
|
|
6382
|
-
} catch (error) {
|
|
6383
|
-
console.error("Error getting user media:", error);
|
|
6384
6397
|
return null;
|
|
6385
6398
|
}
|
|
6386
6399
|
}
|
|
6400
|
+
applyLocalStream(stream) {
|
|
6401
|
+
if (this.callStatus === "ended" /* ENDED */) {
|
|
6402
|
+
stream.getTracks().forEach((track) => track.stop());
|
|
6403
|
+
this.destroy();
|
|
6404
|
+
return;
|
|
6405
|
+
}
|
|
6406
|
+
if (this.onLocalStream) {
|
|
6407
|
+
this.onLocalStream(stream);
|
|
6408
|
+
}
|
|
6409
|
+
this.localStream = stream;
|
|
6410
|
+
return stream;
|
|
6411
|
+
}
|
|
6387
6412
|
setConnectionMessage(message) {
|
|
6388
6413
|
if (typeof this.onConnectionMessageChange === "function") {
|
|
6389
6414
|
this.onConnectionMessageChange(message);
|
|
@@ -6428,20 +6453,10 @@ var ErmisCallNode = class {
|
|
|
6428
6453
|
this.isDestroyed = false;
|
|
6429
6454
|
this.callStatus = "";
|
|
6430
6455
|
this.callType = is_video ? "video" : "audio";
|
|
6431
|
-
await this.startLocalStream();
|
|
6432
|
-
if (this.callStatus === "ended" /* ENDED */) return;
|
|
6433
6456
|
this.setUserInfo(cid, eventUserId);
|
|
6434
6457
|
this.setCallStatus("ringing" /* RINGING */);
|
|
6435
6458
|
this.cid = cid || "";
|
|
6436
6459
|
this.metadata = metadata || {};
|
|
6437
|
-
console.log("----metadata---", metadata);
|
|
6438
|
-
if (eventUserId !== this.userID) {
|
|
6439
|
-
await this.initialize();
|
|
6440
|
-
}
|
|
6441
|
-
if (this.localStream && this.mediaSender && this.mediaReceiver) {
|
|
6442
|
-
this.mediaSender?.initEncoders(this.localStream);
|
|
6443
|
-
this.mediaReceiver?.initDecoders(this.callType);
|
|
6444
|
-
}
|
|
6445
6460
|
if (typeof this.onCallEvent === "function") {
|
|
6446
6461
|
this.onCallEvent({
|
|
6447
6462
|
type: eventUserId !== this.userID ? "incoming" : "outgoing",
|
|
@@ -6452,6 +6467,15 @@ var ErmisCallNode = class {
|
|
|
6452
6467
|
metadata: this.metadata
|
|
6453
6468
|
});
|
|
6454
6469
|
}
|
|
6470
|
+
await this.startLocalStream();
|
|
6471
|
+
if (this.callStatus === "ended" /* ENDED */) return;
|
|
6472
|
+
if (eventUserId !== this.userID) {
|
|
6473
|
+
await this.initialize();
|
|
6474
|
+
}
|
|
6475
|
+
if (this.localStream && this.mediaSender && this.mediaReceiver) {
|
|
6476
|
+
this.mediaSender?.initEncoders(this.localStream);
|
|
6477
|
+
this.mediaReceiver?.initDecoders(this.callType);
|
|
6478
|
+
}
|
|
6455
6479
|
if (eventUserId === this.userID) {
|
|
6456
6480
|
if (this.missCallTimeout) clearTimeout(this.missCallTimeout);
|
|
6457
6481
|
this.missCallTimeout = setTimeout(async () => {
|
|
@@ -6712,21 +6736,30 @@ var ErmisCallNode = class {
|
|
|
6712
6736
|
}
|
|
6713
6737
|
async stopScreenShare() {
|
|
6714
6738
|
const mediaConstraints = await this.getMediaConstraints();
|
|
6715
|
-
|
|
6716
|
-
|
|
6717
|
-
|
|
6718
|
-
|
|
6719
|
-
|
|
6720
|
-
|
|
6721
|
-
|
|
6722
|
-
|
|
6723
|
-
|
|
6724
|
-
|
|
6725
|
-
|
|
6726
|
-
|
|
6727
|
-
|
|
6728
|
-
|
|
6729
|
-
|
|
6739
|
+
try {
|
|
6740
|
+
const cameraStream = await navigator.mediaDevices.getUserMedia({
|
|
6741
|
+
video: mediaConstraints.video,
|
|
6742
|
+
audio: false
|
|
6743
|
+
});
|
|
6744
|
+
const cameraTrack = cameraStream.getVideoTracks()[0];
|
|
6745
|
+
if (this.localStream) {
|
|
6746
|
+
this.localStream.getVideoTracks().forEach((track) => {
|
|
6747
|
+
track.stop();
|
|
6748
|
+
this.localStream?.removeTrack(track);
|
|
6749
|
+
});
|
|
6750
|
+
this.localStream.addTrack(cameraTrack);
|
|
6751
|
+
} else {
|
|
6752
|
+
this.localStream = cameraStream;
|
|
6753
|
+
}
|
|
6754
|
+
if (this.onLocalStream) {
|
|
6755
|
+
this.onLocalStream(this.localStream);
|
|
6756
|
+
this.mediaSender?.replaceVideoTrack(this.localStream.getVideoTracks()[0]);
|
|
6757
|
+
}
|
|
6758
|
+
if (typeof this.onScreenShareChange === "function") {
|
|
6759
|
+
this.onScreenShareChange(false);
|
|
6760
|
+
}
|
|
6761
|
+
} catch (error) {
|
|
6762
|
+
console.error("Error stopping screen share and reverting to camera:", error);
|
|
6730
6763
|
}
|
|
6731
6764
|
}
|
|
6732
6765
|
async toggleMic(enabled) {
|
|
@@ -6993,7 +7026,7 @@ var ErmisAuthProvider = class {
|
|
|
6993
7026
|
return data;
|
|
6994
7027
|
}
|
|
6995
7028
|
getUserAgent() {
|
|
6996
|
-
return this.userAgent || `ermis-chat-sdk-javascript-client-${this.node ? "node" : "browser"}-${"1.0.
|
|
7029
|
+
return this.userAgent || `ermis-chat-sdk-javascript-client-${this.node ? "node" : "browser"}-${"1.0.3"}`;
|
|
6997
7030
|
}
|
|
6998
7031
|
setUserAgent(userAgent) {
|
|
6999
7032
|
this.userAgent = userAgent;
|
|
@@ -7226,71 +7259,117 @@ function parseSystemMessage(value, userMap) {
|
|
|
7226
7259
|
}
|
|
7227
7260
|
|
|
7228
7261
|
// src/signal_message.ts
|
|
7229
|
-
|
|
7230
|
-
|
|
7231
|
-
|
|
7232
|
-
|
|
7233
|
-
|
|
7234
|
-
|
|
7235
|
-
|
|
7236
|
-
|
|
7237
|
-
|
|
7262
|
+
var CallType = {
|
|
7263
|
+
AUDIO: "audio",
|
|
7264
|
+
VIDEO: "video"
|
|
7265
|
+
};
|
|
7266
|
+
function formatDuration(durationMs) {
|
|
7267
|
+
if (!durationMs) return "";
|
|
7268
|
+
const ms = parseInt(durationMs, 10);
|
|
7269
|
+
if (isNaN(ms) || ms <= 0) return "";
|
|
7270
|
+
const totalSeconds = Math.floor(ms / 1e3);
|
|
7271
|
+
const minutes = Math.floor(totalSeconds / 60);
|
|
7272
|
+
const seconds = totalSeconds % 60;
|
|
7273
|
+
return `${minutes} min, ${seconds} sec`;
|
|
7238
7274
|
}
|
|
7239
|
-
function parseSignalMessage(value,
|
|
7240
|
-
if (!value || typeof value !== "string") return
|
|
7275
|
+
function parseSignalMessage(value, myUserId) {
|
|
7276
|
+
if (!value || typeof value !== "string") return null;
|
|
7241
7277
|
const trimmed = value.trim();
|
|
7242
|
-
if (!trimmed) return
|
|
7278
|
+
if (!trimmed) return null;
|
|
7243
7279
|
const parts = trimmed.split(" ");
|
|
7244
|
-
const
|
|
7245
|
-
const
|
|
7246
|
-
const
|
|
7247
|
-
|
|
7248
|
-
|
|
7249
|
-
|
|
7250
|
-
|
|
7251
|
-
|
|
7252
|
-
|
|
7253
|
-
|
|
7254
|
-
|
|
7255
|
-
|
|
7256
|
-
|
|
7257
|
-
|
|
7258
|
-
|
|
7259
|
-
|
|
7260
|
-
|
|
7261
|
-
|
|
7262
|
-
case
|
|
7263
|
-
|
|
7264
|
-
|
|
7265
|
-
|
|
7266
|
-
|
|
7267
|
-
|
|
7268
|
-
|
|
7269
|
-
|
|
7270
|
-
|
|
7271
|
-
|
|
7272
|
-
|
|
7273
|
-
|
|
7274
|
-
|
|
7275
|
-
|
|
7276
|
-
|
|
7277
|
-
|
|
7278
|
-
|
|
7279
|
-
|
|
7280
|
-
|
|
7281
|
-
case
|
|
7282
|
-
|
|
7283
|
-
|
|
7284
|
-
|
|
7285
|
-
|
|
7280
|
+
const number = parseInt(parts[0], 10);
|
|
7281
|
+
const callerId = parts[1] ?? "";
|
|
7282
|
+
const isMe = myUserId === callerId;
|
|
7283
|
+
let enderId = "";
|
|
7284
|
+
let duration = "";
|
|
7285
|
+
let callType = "";
|
|
7286
|
+
let color = "";
|
|
7287
|
+
if (number === 3 || number === 6) {
|
|
7288
|
+
enderId = parts[2] ?? "";
|
|
7289
|
+
duration = parts[3] === "0" ? "" : parts[3] ?? "";
|
|
7290
|
+
}
|
|
7291
|
+
let text;
|
|
7292
|
+
switch (number) {
|
|
7293
|
+
case 1:
|
|
7294
|
+
text = isMe ? "Calling..." : "Incoming audio call...";
|
|
7295
|
+
callType = CallType.AUDIO;
|
|
7296
|
+
color = "#54D62C";
|
|
7297
|
+
break;
|
|
7298
|
+
case 2:
|
|
7299
|
+
text = isMe ? "Outgoing audio call" : "You missed audio call";
|
|
7300
|
+
callType = CallType.AUDIO;
|
|
7301
|
+
color = "#FF4842";
|
|
7302
|
+
break;
|
|
7303
|
+
case 3:
|
|
7304
|
+
if (duration) {
|
|
7305
|
+
text = isMe ? "Outgoing audio call" : "Incoming audio call";
|
|
7306
|
+
color = "#54D62C";
|
|
7307
|
+
} else {
|
|
7308
|
+
if (enderId === myUserId) {
|
|
7309
|
+
text = "You cancel audio call";
|
|
7310
|
+
} else {
|
|
7311
|
+
text = "You missed audio call";
|
|
7312
|
+
}
|
|
7313
|
+
color = "#FF4842";
|
|
7314
|
+
}
|
|
7315
|
+
callType = CallType.AUDIO;
|
|
7316
|
+
break;
|
|
7317
|
+
case 4:
|
|
7318
|
+
text = isMe ? "Calling..." : "Incoming video call...";
|
|
7319
|
+
callType = CallType.VIDEO;
|
|
7320
|
+
color = "#54D62C";
|
|
7321
|
+
break;
|
|
7322
|
+
case 5:
|
|
7323
|
+
text = isMe ? "Outgoing video call" : "You missed video call";
|
|
7324
|
+
callType = CallType.VIDEO;
|
|
7325
|
+
color = "#FF4842";
|
|
7326
|
+
break;
|
|
7327
|
+
case 6:
|
|
7328
|
+
if (duration) {
|
|
7329
|
+
text = isMe ? "Outgoing video call" : "Incoming video call";
|
|
7330
|
+
color = "#54D62C";
|
|
7331
|
+
} else {
|
|
7332
|
+
if (enderId === myUserId) {
|
|
7333
|
+
text = "You cancel video call";
|
|
7334
|
+
} else {
|
|
7335
|
+
text = "You missed video call";
|
|
7336
|
+
}
|
|
7337
|
+
color = "#FF4842";
|
|
7338
|
+
}
|
|
7339
|
+
callType = CallType.VIDEO;
|
|
7340
|
+
break;
|
|
7341
|
+
case 7:
|
|
7342
|
+
text = isMe ? "Recipient rejected audio call" : "You rejected audio call";
|
|
7343
|
+
callType = CallType.AUDIO;
|
|
7344
|
+
color = "#FF4842";
|
|
7345
|
+
break;
|
|
7346
|
+
case 8:
|
|
7347
|
+
text = isMe ? "Recipient rejected video call" : "You rejected video call";
|
|
7348
|
+
callType = CallType.VIDEO;
|
|
7349
|
+
color = "#FF4842";
|
|
7350
|
+
break;
|
|
7351
|
+
case 9:
|
|
7352
|
+
text = isMe ? "Recipient was busy" : "You missed audio call";
|
|
7353
|
+
callType = CallType.AUDIO;
|
|
7354
|
+
color = "#FF4842";
|
|
7355
|
+
break;
|
|
7356
|
+
case 10:
|
|
7357
|
+
text = isMe ? "Recipient was busy" : "You missed video call";
|
|
7358
|
+
callType = CallType.VIDEO;
|
|
7359
|
+
color = "#FF4842";
|
|
7360
|
+
break;
|
|
7286
7361
|
default:
|
|
7287
|
-
|
|
7362
|
+
text = trimmed;
|
|
7363
|
+
callType = "";
|
|
7364
|
+
color = "";
|
|
7288
7365
|
}
|
|
7366
|
+
return { text, duration: formatDuration(duration), callType, color };
|
|
7289
7367
|
}
|
|
7290
7368
|
// Annotate the CommonJS export names for ESM import in node:
|
|
7291
7369
|
0 && (module.exports = {
|
|
7292
7370
|
CallAction,
|
|
7293
7371
|
CallStatus,
|
|
7372
|
+
CallType,
|
|
7294
7373
|
Channel,
|
|
7295
7374
|
ChannelState,
|
|
7296
7375
|
ClientState,
|