@ermis-network/ermis-chat-sdk 1.0.2 → 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.
@@ -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
+ }
@@ -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,
@@ -3666,7 +3667,7 @@ var ErmisChat = class _ErmisChat {
3666
3667
  return pinExpires;
3667
3668
  }
3668
3669
  getUserAgent() {
3669
- return this.userAgent || `ermis-chat-sdk-javascript-client-${this.node ? "node" : "browser"}-${"1.0.2"}`;
3670
+ return this.userAgent || `ermis-chat-sdk-javascript-client-${this.node ? "node" : "browser"}-${"1.0.3"}`;
3670
3671
  }
3671
3672
  setUserAgent(userAgent) {
3672
3673
  this.userAgent = userAgent;
@@ -6376,21 +6377,38 @@ var ErmisCallNode = class {
6376
6377
  const mediaConstraints = await this.getMediaConstraints();
6377
6378
  try {
6378
6379
  const stream = await navigator.mediaDevices.getUserMedia(mediaConstraints);
6379
- if (this.callStatus === "ended" /* ENDED */) {
6380
- stream.getTracks().forEach((track) => track.stop());
6381
- this.destroy();
6382
- return;
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
+ }
6383
6393
  }
6384
- if (this.onLocalStream) {
6385
- this.onLocalStream(stream);
6394
+ if (typeof this.onError === "function") {
6395
+ this.onError("No microphone or camera found. Please check your device.");
6386
6396
  }
6387
- this.localStream = stream;
6388
- return stream;
6389
- } catch (error) {
6390
- console.error("Error getting user media:", error);
6391
6397
  return null;
6392
6398
  }
6393
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
+ }
6394
6412
  setConnectionMessage(message) {
6395
6413
  if (typeof this.onConnectionMessageChange === "function") {
6396
6414
  this.onConnectionMessageChange(message);
@@ -6435,20 +6453,10 @@ var ErmisCallNode = class {
6435
6453
  this.isDestroyed = false;
6436
6454
  this.callStatus = "";
6437
6455
  this.callType = is_video ? "video" : "audio";
6438
- await this.startLocalStream();
6439
- if (this.callStatus === "ended" /* ENDED */) return;
6440
6456
  this.setUserInfo(cid, eventUserId);
6441
6457
  this.setCallStatus("ringing" /* RINGING */);
6442
6458
  this.cid = cid || "";
6443
6459
  this.metadata = metadata || {};
6444
- console.log("----metadata---", metadata);
6445
- if (eventUserId !== this.userID) {
6446
- await this.initialize();
6447
- }
6448
- if (this.localStream && this.mediaSender && this.mediaReceiver) {
6449
- this.mediaSender?.initEncoders(this.localStream);
6450
- this.mediaReceiver?.initDecoders(this.callType);
6451
- }
6452
6460
  if (typeof this.onCallEvent === "function") {
6453
6461
  this.onCallEvent({
6454
6462
  type: eventUserId !== this.userID ? "incoming" : "outgoing",
@@ -6459,6 +6467,15 @@ var ErmisCallNode = class {
6459
6467
  metadata: this.metadata
6460
6468
  });
6461
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
+ }
6462
6479
  if (eventUserId === this.userID) {
6463
6480
  if (this.missCallTimeout) clearTimeout(this.missCallTimeout);
6464
6481
  this.missCallTimeout = setTimeout(async () => {
@@ -6719,21 +6736,30 @@ var ErmisCallNode = class {
6719
6736
  }
6720
6737
  async stopScreenShare() {
6721
6738
  const mediaConstraints = await this.getMediaConstraints();
6722
- const cameraStream = await navigator.mediaDevices.getUserMedia(mediaConstraints);
6723
- const cameraTrack = cameraStream.getVideoTracks()[0];
6724
- if (this.localStream) {
6725
- this.localStream.getVideoTracks().forEach((track) => track.stop());
6726
- this.localStream.removeTrack(this.localStream.getVideoTracks()[0]);
6727
- this.localStream.addTrack(cameraTrack);
6728
- } else {
6729
- this.localStream = cameraStream;
6730
- }
6731
- if (this.onLocalStream) {
6732
- this.onLocalStream(this.localStream);
6733
- this.mediaSender?.replaceVideoTrack(this.localStream.getVideoTracks()[0]);
6734
- }
6735
- if (typeof this.onScreenShareChange === "function") {
6736
- this.onScreenShareChange(false);
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);
6737
6763
  }
6738
6764
  }
6739
6765
  async toggleMic(enabled) {
@@ -7000,7 +7026,7 @@ var ErmisAuthProvider = class {
7000
7026
  return data;
7001
7027
  }
7002
7028
  getUserAgent() {
7003
- return this.userAgent || `ermis-chat-sdk-javascript-client-${this.node ? "node" : "browser"}-${"1.0.2"}`;
7029
+ return this.userAgent || `ermis-chat-sdk-javascript-client-${this.node ? "node" : "browser"}-${"1.0.3"}`;
7004
7030
  }
7005
7031
  setUserAgent(userAgent) {
7006
7032
  this.userAgent = userAgent;
@@ -7233,71 +7259,117 @@ function parseSystemMessage(value, userMap) {
7233
7259
  }
7234
7260
 
7235
7261
  // src/signal_message.ts
7236
- function formatDuration(durationSec) {
7237
- const sec = parseInt(durationSec, 10);
7238
- if (isNaN(sec) || sec < 0) return durationSec;
7239
- const minutes = Math.floor(sec / 60);
7240
- const seconds = sec % 60;
7241
- return `${minutes}:${seconds.toString().padStart(2, "0")}`;
7242
- }
7243
- function resolveUser2(userId, userMap) {
7244
- return userMap[userId] ?? userId;
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`;
7245
7274
  }
7246
- function parseSignalMessage(value, userMap) {
7247
- if (!value || typeof value !== "string") return value ?? "";
7275
+ function parseSignalMessage(value, myUserId) {
7276
+ if (!value || typeof value !== "string") return null;
7248
7277
  const trimmed = value.trim();
7249
- if (!trimmed) return "";
7278
+ if (!trimmed) return null;
7250
7279
  const parts = trimmed.split(" ");
7251
- const formatId = parts[0];
7252
- const userId = parts[1] ?? "";
7253
- const userName = userId ? resolveUser2(userId, userMap) : "User";
7254
- switch (formatId) {
7255
- // 1: Audio call started
7256
- case "1":
7257
- return `\u{1F4DE} ${userName} started an audio call.`;
7258
- // 2: Audio call missed
7259
- case "2":
7260
- return `\u{1F4DE} Missed audio call from ${userName}.`;
7261
- // 3: Audio call ended (caller_id ender_id duration)
7262
- case "3": {
7263
- const enderId = parts[2] ?? "";
7264
- const duration = parts[3] ?? "0";
7265
- const enderName = enderId ? resolveUser2(enderId, userMap) : "User";
7266
- return `\u{1F4DE} Audio call by ${userName}, ended by ${enderName}. Duration: ${formatDuration(duration)}.`;
7267
- }
7268
- // 4: Video call started
7269
- case "4":
7270
- return `\u{1F4F9} ${userName} started a video call.`;
7271
- // 5: Video call missed
7272
- case "5":
7273
- return `\u{1F4F9} Missed video call from ${userName}.`;
7274
- // 6: Video call ended (caller_id ender_id duration)
7275
- case "6": {
7276
- const enderId = parts[2] ?? "";
7277
- const duration = parts[3] ?? "0";
7278
- const enderName = enderId ? resolveUser2(enderId, userMap) : "User";
7279
- return `\u{1F4F9} Video call by ${userName}, ended by ${enderName}. Duration: ${formatDuration(duration)}.`;
7280
- }
7281
- // 7: Audio call rejected
7282
- case "7":
7283
- return `\u{1F4DE} Audio call from ${userName} was rejected.`;
7284
- // 8: Video call rejected
7285
- case "8":
7286
- return `\u{1F4F9} Video call from ${userName} was rejected.`;
7287
- // 9: Audio call busy
7288
- case "9":
7289
- return `\u{1F4DE} Audio call from ${userName} \u2014 recipient was busy.`;
7290
- // 10: Video call busy
7291
- case "10":
7292
- return `\u{1F4F9} Video call from ${userName} \u2014 recipient was busy.`;
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;
7293
7361
  default:
7294
- return trimmed;
7362
+ text = trimmed;
7363
+ callType = "";
7364
+ color = "";
7295
7365
  }
7366
+ return { text, duration: formatDuration(duration), callType, color };
7296
7367
  }
7297
7368
  // Annotate the CommonJS export names for ESM import in node:
7298
7369
  0 && (module.exports = {
7299
7370
  CallAction,
7300
7371
  CallStatus,
7372
+ CallType,
7301
7373
  Channel,
7302
7374
  ChannelState,
7303
7375
  ClientState,