@trap_stevo/filetide 0.0.51 → 0.0.53

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.
@@ -1,5 +1,8 @@
1
1
  "use strict";
2
2
 
3
+ function _classPrivateMethodInitSpec(e, a) { _checkPrivateRedeclaration(e, a), a.add(e); }
4
+ function _checkPrivateRedeclaration(e, t) { if (t.has(e)) throw new TypeError("Cannot initialize the same private elements twice on an object"); }
5
+ function _assertClassBrand(e, t, n) { if ("function" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n; throw new TypeError("Private element is not present on this object"); }
3
6
  const {
4
7
  OmniMap
5
8
  } = require("@trap_stevo/legendarybuilderpronodejs-utilities/HUDStructs");
@@ -7,6 +10,9 @@ const IoTide = require("@trap_stevo/iotide");
7
10
  const {
8
11
  FileMessagerConfigManager
9
12
  } = require("./HUDManagers/FileMessagerConfigManager");
13
+ const {
14
+ FileNetUtilityManager
15
+ } = require("./HUDManagers/FileNetUtilityManager");
10
16
  const {
11
17
  FileNetClientManager
12
18
  } = require("./HUDManagers/FileNetClientManager");
@@ -14,6 +20,7 @@ const {
14
20
  FileTransferManager
15
21
  } = require("./HUDManagers/FileTransferManager");
16
22
  const HUDTargetQueue = require("./HUDManagers/HUDTargetQueueManager");
23
+ var _FileMessager_brand = /*#__PURE__*/new WeakSet();
17
24
  class FileMessager {
18
25
  constructor(options = {
19
26
  pingTimeout: 3600000,
@@ -21,7 +28,8 @@ class FileMessager {
21
28
  }, transportOptions = {
22
29
  parallelChunks: 3,
23
30
  maxRetries: 3
24
- }) {
31
+ }, debugMode = false) {
32
+ _classPrivateMethodInitSpec(this, _FileMessager_brand);
25
33
  const serverOptions = FileMessagerConfigManager.getServerOptions(options);
26
34
  this.transporter = new FileTransferManager(transportOptions);
27
35
  this.transferQueue = new HUDTargetQueue();
@@ -30,6 +38,7 @@ class FileMessager {
30
38
  this.currentTidingTransfers = new Map();
31
39
  this.fileNet = new IoTide(serverOptions.port, serverOptions, true, this.onConnect.bind(this), this.onDisconnect.bind(this));
32
40
  this.onlineClients = new OmniMap();
41
+ this.debugMode = debugMode;
33
42
  return;
34
43
  }
35
44
  onConnect(socket) {
@@ -46,6 +55,7 @@ class FileMessager {
46
55
  this.fileNet.on("get-client-transfer-barrier-response", this.handleClientTransferBarrierResponse.bind(this));
47
56
  this.fileNet.on("get-client-transfer-state", this.handleGetClientTransferState.bind(this));
48
57
  this.fileNet.on("get-client", this.handleGetClient.bind(this));
58
+ this.fileNet.on("acknowledge-transfer-tide", this.handleAcknowledgeTransferTide.bind(this));
49
59
  this.fileNet.on("notify-transfer-barrier", this.handleNotifyTransferBarrier.bind(this));
50
60
  this.fileNet.on("send-current-transfer-state", this.handleSendCurrentTransferState.bind(this));
51
61
  this.fileNet.on("sent-file-list-to-client", this.handleSentFileListToClient.bind(this));
@@ -121,11 +131,13 @@ class FileMessager {
121
131
  path: filePath,
122
132
  fileSize
123
133
  });
124
- console.log(`[FileTide ~ File Messager] ~ Sent chunk ${chunkIndex} of ${fileName} to client ~ ${clientData.userID}!`);
134
+ _assertClassBrand(_FileMessager_brand, this, _log).call(this, `[FileTide ~ File Messager] ~ Sent chunk ${chunkIndex} of ${fileName} to client ~ ${clientData.userID}!`);
125
135
  if (senderClient) {
126
136
  this.fileNet.emitToTide(senderClient.tideID, "transfer-status", {
127
137
  status: `Chunk ${chunkIndex} of ${fileName} sent to client ${clientData.userID}!`,
128
138
  recipientID: clientData.userID,
139
+ senderName: senderData.userID,
140
+ senderID: senderData.id,
129
141
  success: true,
130
142
  fileName,
131
143
  chunkIndex,
@@ -136,7 +148,7 @@ class FileMessager {
136
148
  });
137
149
  }
138
150
  }
139
- handleRequestTransferFromClient(transferData) {
151
+ handleRequestTransferFromClient(senderTide, transferData) {
140
152
  const {
141
153
  requesterID,
142
154
  senderID,
@@ -145,7 +157,7 @@ class FileMessager {
145
157
  } = transferData;
146
158
  this.requestFromClient(requesterID, senderID, filePath, destinationPath);
147
159
  }
148
- handleSentFileListToClient(listData) {
160
+ handleSentFileListToClient(senderTide, listData) {
149
161
  const {
150
162
  totalItemsSent,
151
163
  recipientID,
@@ -164,10 +176,11 @@ class FileMessager {
164
176
  totalItemsSent
165
177
  });
166
178
  } catch (error) {
179
+ console.error(`[FileTide ~ Net Scanner] ~ `, error);
167
180
  return;
168
181
  }
169
182
  }
170
- handleSendFileListToClient(listData) {
183
+ handleSendFileListToClient(senderTide, listData) {
171
184
  const {
172
185
  listedFiles,
173
186
  totalItems,
@@ -188,10 +201,11 @@ class FileMessager {
188
201
  listedFiles
189
202
  });
190
203
  } catch (error) {
204
+ console.error(`[FileTide ~ Net Scanner] ~ `, error);
191
205
  return;
192
206
  }
193
207
  }
194
- handleListClientFiles(clientData) {
208
+ handleListClientFiles(senderTide, clientData) {
195
209
  const {
196
210
  requesterID,
197
211
  recipientID,
@@ -211,10 +225,11 @@ class FileMessager {
211
225
  depth
212
226
  });
213
227
  } catch (error) {
228
+ console.error(`[FileTide ~ Net Scanner] ~ `, error);
214
229
  return;
215
230
  }
216
231
  }
217
- handleClientToClientTransfer(transferData) {
232
+ handleClientToClientTransfer(senderTide, transferData) {
218
233
  try {
219
234
  const {
220
235
  chunkBatch
@@ -233,7 +248,7 @@ class FileMessager {
233
248
  completedChunks,
234
249
  totalChunks
235
250
  } = chunkData;
236
- console.log(`[FileTide ~ File Messager] ~ Transferring file ~ ${fileName} | chunk ${chunkIndex + 1} >> ${completedChunks} of ${totalChunks} to client (${recipientId})`);
251
+ _assertClassBrand(_FileMessager_brand, this, _log).call(this, `[FileTide ~ File Messager] ~ Transferring file ~ ${fileName} | chunk ${chunkIndex + 1} >> ${completedChunks} of ${totalChunks} to client (${recipientId})`);
237
252
  const recipientClient = FileNetClientManager.getOnlineClient(recipientId);
238
253
  const senderClient = FileNetClientManager.getOnlineClient(senderID);
239
254
  this.sendFileChunkToClient({
@@ -277,7 +292,7 @@ class FileMessager {
277
292
  completedChunks,
278
293
  totalChunks
279
294
  } = transferData;
280
- console.log(`[FileTide ~ File Messager] ~ Transferring file ~ ${fileName} | chunk ${chunkIndex + 1} >> ${completedChunks} of ${totalChunks} to client (${recipientId})`);
295
+ _assertClassBrand(_FileMessager_brand, this, _log).call(this, `[FileTide ~ File Messager] ~ Transferring file ~ ${fileName} | chunk ${chunkIndex + 1} >> ${completedChunks} of ${totalChunks} to client (${recipientId})`);
281
296
  const recipientClient = FileNetClientManager.getOnlineClient(recipientId);
282
297
  const senderClient = FileNetClientManager.getOnlineClient(senderID);
283
298
  this.sendFileChunkToClient({
@@ -307,11 +322,11 @@ class FileMessager {
307
322
  }
308
323
  }
309
324
  } catch (error) {
310
- console.log(error);
325
+ console.error(`[FileTide ~ Net Transporter] ~ `, error);
311
326
  return;
312
327
  }
313
328
  }
314
- handleClientTransferBarrierResponse(data) {
329
+ handleClientTransferBarrierResponse(senderTide, data) {
315
330
  console.log(`[FileTide ~ Net] Checking ${data.recipientID}'s transfer barrier for transfer ~ ${data.transferID}...`);
316
331
  try {
317
332
  const recipientConnectionID = FileNetClientManager.getOnlineClient(data.recipientID).id;
@@ -319,6 +334,7 @@ class FileMessager {
319
334
  const senderClient = this.getClientFromID(senderConnectionID);
320
335
  const client = this.getClientFromID(recipientConnectionID);
321
336
  if (!client || !senderClient) {
337
+ console.log(`[FileTide ~ Net Barrier] ~ Both, recipient and sender connection authorization required.`);
322
338
  return;
323
339
  }
324
340
  this.fileNet.emitToTide(client.tideID, "queue-incoming-transfer", {
@@ -341,18 +357,20 @@ class FileMessager {
341
357
  ...data
342
358
  });
343
359
  }).catch(error => {
344
- console.error(error.message);
360
+ console.error(`[FileTide ~ Net Barrier] ~ ${error.message}`);
345
361
  });
346
362
  return;
347
363
  } catch (error) {
364
+ console.error(`[FileTide ~ Net Barrier] ~ `, error);
348
365
  return;
349
366
  }
350
367
  }
351
- handleSendCurrentTransferState(data) {
368
+ handleSendCurrentTransferState(senderTide, data) {
352
369
  try {
353
370
  const senderConnectionID = FileNetClientManager.getOnlineClient(data.senderID).id;
354
371
  const senderClient = this.getClientFromID(senderConnectionID);
355
372
  if (!senderClient) {
373
+ console.log(`[FileTide ~ Net Transfers] ~ Sender ~ ${senderConnectionID.truncate(0, senderConnectionID.length / 2)}... not found.`);
356
374
  return;
357
375
  }
358
376
  this.fileNet.emitToTide(senderClient.tideID, "sent-current-transfer-state", data.transferState || {
@@ -360,10 +378,11 @@ class FileMessager {
360
378
  lastChunkSent: 0
361
379
  });
362
380
  } catch (error) {
381
+ console.error(`[FileTide ~ Net Transfers] ~ `, error);
363
382
  return;
364
383
  }
365
384
  }
366
- handleGetClientTransferState(data) {
385
+ handleGetClientTransferState(senderTide, data) {
367
386
  const filePath = data.filePath || data.path;
368
387
  console.log(`[FileTide ~ Net] ~ Getting ${data.recipientID}'s transfer state for ~ ${filePath}...`);
369
388
  try {
@@ -378,10 +397,11 @@ class FileMessager {
378
397
  filePath
379
398
  });
380
399
  } catch (error) {
400
+ console.error(`[FileTide ~ Net Transfers] ~ `, error);
381
401
  return;
382
402
  }
383
403
  }
384
- handleGetClient(data) {
404
+ handleGetClient(senderTide, data) {
385
405
  console.log(`[FileTide ~ Net] ~ Getting client ~ ${data.clientID}...`);
386
406
  try {
387
407
  const senderConnectionID = FileNetClientManager.getOnlineClient(data.senderID).id;
@@ -394,15 +414,23 @@ class FileMessager {
394
414
  console.log(`[FileTide ~ Net] Got client ~ ${data.clientID}!`);
395
415
  this.fileNet.emitToTide(senderClient.tideID, "retrieved-current-client", client);
396
416
  } catch (error) {
417
+ console.error(`[FileTide ~ Net Activity] ~ `, error);
397
418
  return;
398
419
  }
399
420
  }
400
- handleNotifyTransferBarrier(data, emitToChannel) {
421
+ handleAcknowledgeTransferTide(senderTide, data) {
422
+ try {
423
+ console.log(`[FileTide ~ Net Activity] ~ ${data.recipientName} acknowledged tide transfer from ${data.senderName}.\n\n\t~ [${data.fileName}-${data.transferStats.startTime}] ~\n\n\t\tFile Name ~ ${data.fileName}\n\t\tDestination ~ ${data.path}\n\n\t\t\tProgress ~ ${data.transferStats.progress.toFixed(2)}%\n\t\t\tETA ~ ${data.transferStats.timeLeft <= 0 ? "Now" : FileNetUtilityManager.convertSeconds(data.transferStats.timeLeft.toFixed(2))}\n\t\t\tSpeed ~ ${FileNetUtilityManager.getFormattedSize(data.transferStats.speed, true)}/s\n\t\t\tSize ~ ${FileNetUtilityManager.getFormattedSize(data.transferStats.totalSize, true)}\n\t\t\tTransferred ~ ${FileNetUtilityManager.getFormattedSize(data.transferStats.current, true)}\n`);
424
+ } catch (error) {
425
+ console.error(`[FileTide ~ Net Activity] ~ ${data.recipientName} acknowledged tide transfer from ${data.senderName}.\n\n${error}`);
426
+ }
427
+ }
428
+ handleNotifyTransferBarrier(senderTide, data, emitToChannel) {
401
429
  const accepted = data.accepted;
402
430
  const transferID = data.data.transferID;
403
431
  this.currentTransferBarrierTransfers.set(transferID, accepted);
404
432
  }
405
- handleFileTransferStart(data, emitToChannel) {
433
+ handleFileTransferStart(senderTide, data, emitToChannel) {
406
434
  console.log(`[FileTide ~ File Messager] ~ Alerting client of incoming transfer from ${data.senderID}...`);
407
435
  try {
408
436
  const recipientConnectionID = FileNetClientManager.getOnlineClient(data.recipientID).id;
@@ -417,7 +445,7 @@ class FileMessager {
417
445
  ...data,
418
446
  currentSender: data.senderID
419
447
  });
420
- if (!this.currentTidingTransfers.get(senderID) || this.currentTidingTransfers.get(senderID).length <= 0) {
448
+ if (!this.currentTidingTransfers.get(data.senderID) || this.currentTidingTransfers.get(data.senderID).length <= 0) {
421
449
  const tidingTransfers = new Map();
422
450
  tidingTransfers.set(data.recipientID, {
423
451
  recipientID: data.recipientID,
@@ -428,23 +456,24 @@ class FileMessager {
428
456
  this.currentTidingTransfers.set(data.senderID, tidingTransfers);
429
457
  return;
430
458
  }
431
- this.currentTidingTransfers.get(senderID).set(data.recipientID, {
459
+ this.currentTidingTransfers.get(data.senderID).set(data.recipientID, {
432
460
  recipientID: data.recipientID,
433
461
  startedOn: new Date(),
434
462
  size: data.fileSize,
435
463
  path: data.path
436
464
  });
437
465
  } catch (error) {
466
+ console.error(`[FileTide ~ Net Transfers] ~ `, error);
438
467
  return;
439
468
  }
440
469
  }
441
- handleFileTransferProgress(data, emitToChannel) {
470
+ handleFileTransferProgress(senderTide, data, emitToChannel) {
442
471
  console.log(`Progress: ${data.progress}`);
443
472
  }
444
- handleFileTransferComplete(data) {
473
+ handleFileTransferComplete(senderTide, data) {
445
474
  console.log(`File transfer completed: ${data.fileName}`);
446
475
  }
447
- handleCheckClientOnline(data) {
476
+ handleCheckClientOnline(senderTide, data) {
448
477
  console.log(`[FileTide ~ Net Activity] ~ Checking if client ~ ${data.clientID} online...`);
449
478
  try {
450
479
  const client = FileNetClientManager.getOnlineClient(data.clientID);
@@ -468,7 +497,7 @@ class FileMessager {
468
497
  return;
469
498
  }
470
499
  }
471
- handleClientsOnline(clientID) {
500
+ handleClientsOnline(senderTide, clientID) {
472
501
  const connectionDetails = FileNetClientManager.getOnlineClient(clientID);
473
502
  if (!connectionDetails) {
474
503
  console.log(`[FileTide ~ Net Activity] ~ Client ~ ${clientID} not authorized.`);
@@ -482,13 +511,21 @@ class FileMessager {
482
511
  this.fileNet.emitToTide(connectionDetails.tideID, "current-online-clients", Object.fromEntries(FileNetClientManager.getOnlineClients()));
483
512
  return;
484
513
  }
485
- handleClientOnline(clientID, tideID, pClientID, connectionID, activeTransferBarrier) {
514
+ handleClientOnline(senderTide, clientID, tideID, pClientID, connectionID, activeTransferBarrier) {
486
515
  if (!this.onlineClients.contains(connectionID)) {
487
516
  return;
488
517
  }
489
518
  if (FileNetClientManager.getOnlineClient(clientID) && this.onlineClients.get(connectionID)) {
490
- clientID = `${clientID}_${connectionID.slice(0, 4)}`;
519
+ const nClientID = `${clientID}_${connectionID.slice(0, 4)}`;
520
+ const currentClientID = clientID;
521
+ clientID = nClientID;
491
522
  this.fileNet.emitToTide(tideID, "current-client-id-already-online", clientID);
523
+ FileNetClientManager.updateOnlineClient(nClientID, {
524
+ pClientID: currentClientID,
525
+ clientID: nClientID,
526
+ tideID: senderTide.tideID,
527
+ id: senderTide.id
528
+ });
492
529
  return;
493
530
  }
494
531
  FileNetClientManager.addOnlineClient(clientID, pClientID, tideID, connectionID);
@@ -501,7 +538,7 @@ class FileMessager {
501
538
  this.fileNet.emit("current-clients", currentOnlineClients);
502
539
  return;
503
540
  }
504
- handleClientOffline(clientData) {
541
+ handleClientOffline(senderTide, clientData) {
505
542
  console.log(`[FileTide ~ Net Activity] ~ Client ~ ${clientData.clientID} | connection origin ~ ${clientData.connectionID} going offline...`);
506
543
  try {
507
544
  const clientDetails = FileNetClientManager.getOnlineClient(clientData.clientID);
@@ -535,7 +572,7 @@ class FileMessager {
535
572
  }
536
573
  return;
537
574
  }
538
- handleClientTiding(data) {
575
+ handleClientTiding(senderTide, data) {
539
576
  try {
540
577
  const senderConnectionID = FileNetClientManager.getOnlineClient(data.senderID).id;
541
578
  const senderClient = this.getClientFromID(senderConnectionID);
@@ -548,9 +585,16 @@ class FileMessager {
548
585
  });
549
586
  return;
550
587
  } catch (error) {
588
+ console.error(`[FileTide ~ Net Activity] ~ `, error);
551
589
  return;
552
590
  }
553
591
  }
554
592
  }
593
+ function _log(...message) {
594
+ if (!this.debugMode) {
595
+ return;
596
+ }
597
+ console.log(...message);
598
+ }
555
599
  ;
556
600
  module.exports = FileMessager;
@@ -7,10 +7,13 @@ const chalk = require("chalk");
7
7
  const path = require("path");
8
8
  const fs = require("fs");
9
9
  const {
10
- FileNetUtilityManager,
10
+ FileTideDebugUtilityManager,
11
11
  significantMessageColors,
12
12
  errorMessageColors
13
- } = require("./HUDManagers/FileNetUtilityManager");
13
+ } = require("./HUDManagers/FileTideDebugUtilityManager");
14
+ const {
15
+ FileTransferTrackingManager
16
+ } = require("./HUDManagers/FileTransferTrackingManager.js");
14
17
  const FileTransferRecoveryManager = require("./HUDManagers/FileTransferRecoveryManager");
15
18
  const {
16
19
  FileMessagerConfigManager
@@ -46,12 +49,13 @@ class FileMessagerClient {
46
49
  transports: ["websocket"],
47
50
  ...options
48
51
  }, headers, authURL, authHeaders, useAuthentication, queryAuthToken, onConnect, () => {
52
+ FileTransferTrackingManager.outputCurrentTransfers();
49
53
  FileTransferRecoveryManager.flushToDisk();
50
54
  if (onDisconnect) {
51
55
  onDisconnect();
52
56
  }
53
57
  });
54
- FileNetUtilityManager.outputGradient(`\n[FileTide ~ File Messager] ~ Created client with ID ${clientID} and socket ${clientID}!`, significantMessageColors);
58
+ FileTideDebugUtilityManager.outputGradient(`\n[FileTide ~ File Messager] ~ Created client with ID ${clientID} and socket ${clientID}!`, significantMessageColors);
55
59
  return clientID;
56
60
  }
57
61
  joinRoom(userID, roomName, options = {}, headers = {}, onConnect = null, onDisconnect = null, authURL = "", authHeaders = {}, useAuthentication = false, queryAuthToken = false) {
@@ -60,7 +64,7 @@ class FileMessagerClient {
60
64
  }, options, headers, onConnect, onDisconnect, authURL, authHeaders, useAuthentication, queryAuthToken);
61
65
  return () => {
62
66
  this.clientTide.joinChannel(socketName, roomName, userID, () => {
63
- FileNetUtilityManager.outputGradient(`\n[FileTide ~ File Messager] ~ Client ~ ${userID} joined room ${roomName} successfully!`, significantMessageColors);
67
+ FileTideDebugUtilityManager.outputGradient(`\n[FileTide ~ File Messager] ~ Client ~ ${userID} joined room ${roomName} successfully!`, significantMessageColors);
64
68
  this.clients.set(userID, {
65
69
  roomName
66
70
  });
@@ -109,18 +113,18 @@ class FileMessagerClient {
109
113
  transferType
110
114
  }, transferExpirationTime);
111
115
  if (!transferAccepted) {
112
- FileNetUtilityManager.outputGradient(`[FileTide ~ File Messager] ${recipientID} denied your transfer.`, errorMessageColors);
116
+ FileTideDebugUtilityManager.outputGradient(`[FileTide ~ File Messager] ${recipientID} denied your transfer.`, errorMessageColors);
113
117
  return false;
114
118
  } else if (transferAccepted) {
115
- FileNetUtilityManager.outputGradient(`[FileTide ~ File Messager] ${recipientID} accepted your transfer!`, significantMessageColors);
119
+ FileTideDebugUtilityManager.outputGradient(`[FileTide ~ File Messager] ${recipientID} accepted your transfer!`, significantMessageColors);
116
120
  return true;
117
121
  }
118
122
  } catch (error) {
119
123
  if (error.message.startsWith("Timeout: No response")) {
120
- FileNetUtilityManager.outputGradient("[FileTide ~ File Messager] Transfer approval timed out.", errorMessageColors);
124
+ FileTideDebugUtilityManager.outputGradient("[FileTide ~ File Messager] Transfer approval timed out.", errorMessageColors);
121
125
  return false;
122
126
  }
123
- FileNetUtilityManager.outputGradient(`[FileTide ~ File Messager] Transfer approval refused.\n${error}`, errorMessageColors);
127
+ FileTideDebugUtilityManager.outputGradient(`[FileTide ~ File Messager] Transfer approval refused.\n${error}`, errorMessageColors);
124
128
  return false;
125
129
  }
126
130
  }
@@ -163,7 +167,7 @@ class FileMessagerClient {
163
167
  });
164
168
  Promise.all(sendFilePromises).then(() => console.log("\nAll files in directory transferred successfully!")).catch(error => console.error("Did not transfer directory: ", error));
165
169
  } catch (error) {
166
- FileNetUtilityManager.outputGradient(`[FileTide ~ File Messager] ~ Refused directory transfer: ${error}`, errorMessageColors);
170
+ FileTideDebugUtilityManager.outputGradient(`[FileTide ~ File Messager] ~ Refused directory transfer: ${error}`, errorMessageColors);
167
171
  }
168
172
  }
169
173
  async sendDirectoryLargeFile(clientID, recipientId, fileName, filePath = process.cwd(), destinationPath = null, fileSize, index = 0, tideSize = 500, minTideSize = 10, maxTideSize = 2000, transferRequestExpirationTime = 30000) {
@@ -192,7 +196,7 @@ class FileMessagerClient {
192
196
  }
193
197
  async sendFile(clientID, recipientId, fileName, filePath = process.cwd(), destination = process.cwd(), fileSize, tideSize = 500, minTideSize = 10, maxTideSize = 2000, initiatingTransfer = true, inDirectory = false, largeFile = false, transferRequestExpirationTime = 30000) {
194
198
  const destinationPath = FileUtilityManager.normalizePath(path.join(destination, fileName));
195
- FileNetUtilityManager.outputGradient(largeFile ? `[FileTide ~ File Messager] ~ Requesting to transfer large file ~ ${destinationPath} to ${recipientId}!` : `[FileTide ~ File Messager] ~ Requesting to transfer ~ ${destinationPath} to ${recipientId}!`, significantMessageColors);
199
+ FileTideDebugUtilityManager.outputGradient(largeFile ? `[FileTide ~ File Messager] ~ Requesting to transfer large file ~ ${destinationPath} to ${recipientId}!` : `[FileTide ~ File Messager] ~ Requesting to transfer ~ ${destinationPath} to ${recipientId}!`, significantMessageColors);
196
200
  const incomingType = this.activeTransferTypes.get(filePath);
197
201
  if (!inDirectory && initiatingTransfer) {
198
202
  const transferAllowed = incomingType && incomingType === "requestedTransfer" ? true : await this.allowedTransfer(clientID, recipientId, destinationPath, filePath, fileSize, 1, "file", "send", transferRequestExpirationTime);
@@ -298,9 +302,9 @@ class FileMessagerClient {
298
302
  });
299
303
  }
300
304
  }, this.clientTide);
301
- FileNetUtilityManager.outputGradient(largeFile ? `[FileTide ~ File Messager] ~ Large file ~ ${fileName} transfer complete!` : `[FileTide ~ File Messager] ~ File ~ ${fileName} transfer complete!`, significantMessageColors);
305
+ FileTideDebugUtilityManager.outputGradient(largeFile ? `[FileTide ~ File Messager] ~ Large file ~ ${fileName} transfer complete!` : `[FileTide ~ File Messager] ~ File ~ ${fileName} transfer complete!`, significantMessageColors);
302
306
  } catch (error) {
303
- FileNetUtilityManager.outputGradient(largeFile ? `[FileTide ~ File Messager] ~ Error transferring large file: ${error.message}` : `[FileTide ~ File Messager] ~ Error transferring file ~ ${error.message}`, errorMessageColors);
307
+ FileTideDebugUtilityManager.outputGradient(largeFile ? `[FileTide ~ File Messager] ~ Error transferring large file: ${error.message}` : `[FileTide ~ File Messager] ~ Error transferring file ~ ${error.message}`, errorMessageColors);
304
308
  } finally {
305
309
  await fileHandle.close();
306
310
  }
@@ -11,10 +11,13 @@ const chalk = require("chalk");
11
11
  const path = require("path");
12
12
  const fs = require("fs");
13
13
  const {
14
- FileNetUtilityManager,
14
+ FileTideDebugUtilityManager,
15
15
  significantMessageColors,
16
16
  errorMessageColors
17
- } = require("./HUDManagers/FileNetUtilityManager.js");
17
+ } = require("./HUDManagers/FileTideDebugUtilityManager.js");
18
+ const {
19
+ FileTransferTrackingManager
20
+ } = require("./HUDManagers/FileTransferTrackingManager.js");
18
21
  const {
19
22
  FileTransferReceiverManager
20
23
  } = require("./HUDManagers/FileTransferReceiverManager.js");
@@ -32,7 +35,7 @@ const FileMessagerClient = require("./FileMessagerClient");
32
35
  const FileMessager = require("./FileMessager");
33
36
  var _FileTide_brand = /*#__PURE__*/new WeakSet();
34
37
  class FileTide {
35
- constructor() {
38
+ constructor(debugMode = true) {
36
39
  /**
37
40
  * Set up file transfer event listeners natively.
38
41
  * Automatically checks and creates directories as needed.
@@ -45,10 +48,12 @@ class FileTide {
45
48
  this.transferBarrier = false;
46
49
  this.clients = new Map();
47
50
  this.currentUserID = "";
51
+ this.inDebugMode = debugMode;
52
+ FileTideDebugUtilityManager.setDebugMode(debugMode);
48
53
  return;
49
54
  }
50
55
  static outputGradient(text, colors) {
51
- FileNetUtilityManager.outputGradient(text, colors);
56
+ FileTideDebugUtilityManager.outputGradient(text, colors);
52
57
  return;
53
58
  }
54
59
 
@@ -104,7 +109,7 @@ class FileTide {
104
109
  const newClient = new FileMessagerClient(clientOptions, transportOptions, messagerSettings);
105
110
  const enterRoom = newClient.joinRoom(userID, roomName, connectionOptions, headers, onConnect, onDisconnect, authURL, authHeaders, useAuthentication, queryAuthToken);
106
111
  this.transferBarrier = enableTransferBarrier;
107
- this.clientShorePolicies.set(userID, [FileUtilityManager.getTidePath(">CurrentUser"), FileUtilityManager.getTidePath(">Downloads"), FileUtilityManager.getTidePath(">Documents")]);
112
+ this.clientShorePolicies.set(userID, [FileUtilityManager.getTidePath(">Downloads"), FileUtilityManager.getTidePath(">Documents"), FileUtilityManager.getTidePath(">Pictures"), FileUtilityManager.getTidePath(">Desktop"), FileUtilityManager.getTidePath(">Videos"), FileUtilityManager.getTidePath(">Music")]);
108
113
  this.clients.set(userID, newClient);
109
114
  FileTide.outputGradient(`[FileTide] ~ Messager launched successfully for client ~ ${userID}!`, significantMessageColors);
110
115
  _assertClassBrand(_FileTide_brand, this, _setupFileEventListeners).call(this, userID, newClient, onTransferProgress, onIncomingTransfer, onIncomingFile, onTransferBarrier, options);
@@ -142,7 +147,7 @@ class FileTide {
142
147
  const clientID = this.currentUserID;
143
148
  const clientMessager = this.clients.get(clientID);
144
149
  if (!clientMessager) {
145
- FileTide.outputGradient(`[FileTide] Client ~ ${clientID} not found.`, ["#F94144", "#F3722C"]);
150
+ FileTide.outputGradient(`[FileTide] Client ~ ${clientID} not found.`, errorMessageColors);
146
151
  return;
147
152
  }
148
153
  clientMessager.listFiles(clientID, recipientID, depth);
@@ -153,7 +158,7 @@ class FileTide {
153
158
  clearShorePolicies(clientID, shores = []) {
154
159
  let clientShorePolicies = this.clientShorePolicies.get(clientID);
155
160
  if (!shores || shores.length <= 0 || !clientShorePolicies || !clientID) {
156
- FileTide.outputGradient(`[FileTide] Did not clear from client ~ ${clientID} shore policies.`, ["#F94144", "#F3722C"]);
161
+ FileTide.outputGradient(`[FileTide] Did not clear from client ~ ${clientID} shore policies.`, errorMessageColors);
157
162
  return false;
158
163
  }
159
164
  const shorePolicies = Array.from(clientShorePolicies.values());
@@ -164,7 +169,7 @@ class FileTide {
164
169
  addShorePolicies(clientID, shores = []) {
165
170
  const clientShorePolicies = this.clientShorePolicies.get(clientID);
166
171
  if (!shores || shores.length <= 0 || !clientShorePolicies || !clientID) {
167
- FileTide.outputGradient(`[FileTide] Did not add to client ~ ${clientID} shore policies.`, ["#F94144", "#F3722C"]);
172
+ FileTide.outputGradient(`[FileTide] Did not add to client ~ ${clientID} shore policies.`, errorMessageColors);
168
173
  return false;
169
174
  }
170
175
  this.clientShorePolicies.set(clientID, [...new Set([...clientShorePolicies, ...shores])]);
@@ -190,33 +195,33 @@ class FileTide {
190
195
  const clientID = this.currentUserID;
191
196
  const clientMessager = this.clients.get(clientID);
192
197
  if (!clientMessager) {
193
- FileTide.outputGradient(`[FileTide] Client ~ ${clientID} not found.`, ["#F94144", "#F3722C"]);
198
+ FileTide.outputGradient(`[FileTide] Client ~ ${clientID} not found.`, errorMessageColors);
194
199
  return false;
195
200
  }
196
201
  const recipientOnline = await clientMessager.clientTide.emitEventWithResponse(clientID, "check-client-online", "retrieved-client-online", {
197
202
  clientID: recipientID
198
203
  }, 5000);
199
204
  if (!recipientOnline || !recipientOnline.online) {
200
- FileTide.outputGradient(`[FileTide] ${recipientID} currently not tiding.`, ["#F94144", "#F3722C"]);
205
+ FileTide.outputGradient(`[FileTide] ${recipientID} currently not tiding.`, errorMessageColors);
201
206
  return false;
202
207
  }
203
208
  const fileDetails = await this.getPathData(filePath, filterDirectoryContent);
204
209
  if (!fileDetails) {
205
- FileTide.outputGradient(`[${clientID}] File at path ${filePath} not found.`, ["#F94144", "#F3722C"]);
210
+ FileTide.outputGradient(`[${clientID}] File at path ${filePath} not found.`, errorMessageColors);
206
211
  return false;
207
212
  }
208
213
  if (fileDetails.type === "file") {
209
214
  if (fileDetails.largeFile) {
210
- FileTide.outputGradient(`[${clientID}] Sending large file ~ ${fileDetails.fileName} to client ~ ${recipientID}...`, ["#00C897", "#00E0FF"]);
215
+ FileTide.outputGradient(`[${clientID}] Sending large file ~ ${fileDetails.fileName} to client ~ ${recipientID}...`, significantMessageColors);
211
216
  await clientMessager.sendFile(clientID, recipientID, fileDetails.fileName, fileDetails.filePath, destinationPath, fileDetails.fileSize, tidalSize, minTideSize, maxTideSize, true, false, true, transferRequestExpirationTime);
212
217
  return true;
213
218
  }
214
- FileTide.outputGradient(`[${clientID}] Sending file ~ ${fileDetails.content.fileName} to client ~ ${recipientID}...`, ["#00C897", "#00E0FF"]);
219
+ FileTide.outputGradient(`[${clientID}] Sending file ~ ${fileDetails.content.fileName} to client ~ ${recipientID}...`, significantMessageColors);
215
220
  await clientMessager.sendFile(clientID, recipientID, fileDetails.content.fileName, fileDetails.content.filePath, destinationPath, fileDetails.content.size, tideSize, minTideSize, maxTideSize, transferRequestExpirationTime);
216
221
  return true;
217
222
  }
218
223
  if (fileDetails.type === "directory") {
219
- FileTide.outputGradient(`[${clientID}] Sending ${fileDetails.content.length} files in directory ~ ${path.basename(filePath)} to client ~ ${recipientID}...`, ["#00C897", "#00E0FF"]);
224
+ FileTide.outputGradient(`[${clientID}] Sending ${fileDetails.content.length} files in directory ~ ${path.basename(filePath)} to client ~ ${recipientID}...`, significantMessageColors);
220
225
  await clientMessager.sendDirectoryFiles(clientID, recipientID, fileDetails.content, this.getTidePath(filePath), destinationPath, tideSize, minTideSize, maxTideSize, transferRequestExpirationTime);
221
226
  return true;
222
227
  }
@@ -439,7 +444,7 @@ function _setupFileEventListeners(userID, client, onTransferProgress, onIncoming
439
444
  onIncomingFile(verifiedSender, {
440
445
  ...data,
441
446
  stats: taskBarStats
442
- }, fileTransferReceiver.activeTransfers);
447
+ }, FileTransferTrackingManager.activeTransfers);
443
448
  }
444
449
  if (verifiedSender && !fs.existsSync(saveDir)) {
445
450
  fs.mkdirSync(saveDir, {
@@ -465,6 +470,8 @@ function _setupFileEventListeners(userID, client, onTransferProgress, onIncoming
465
470
  });
466
471
  client.clientTide.onEvent(userID, "transfer-progress", async data => {
467
472
  if (!data || data.fileChunk === undefined || data.fileChunk === null) {
473
+ FileTideDebugUtilityManager.log("notice", true, `Received invalid data chunk from ~ ${data.senderName} in transfer progress ~ ${data.fileName}`);
474
+ FileTransferTrackingManager.outputCurrentTransfers();
468
475
  return;
469
476
  }
470
477
  await fileTransferReceiver.handleTransferProgress(data);
@@ -474,8 +481,16 @@ function _setupFileEventListeners(userID, client, onTransferProgress, onIncoming
474
481
  };
475
482
  currentTransferState.transferredSize += data.chunkSize || 512 * 1024;
476
483
  FileTransferRecoveryManager.saveTransferState(userID, data.senderName, `${data.path}-${data.fileName}`, data.chunkIndex, currentTransferState.transferredSize);
484
+ const taskBarStats = this.progressBarManager.getTaskBar(data.fileName);
485
+ client.clientTide.emitEvent(userID, "acknowledge-transfer-tide", {
486
+ fileName: data.fileName,
487
+ senderName: data.senderName,
488
+ recipientName: userID,
489
+ transferStateID: `${data.path}-${data.fileName}`,
490
+ path: data.path,
491
+ transferStats: taskBarStats
492
+ });
477
493
  if (onTransferProgress) {
478
- const taskBarStats = this.progressBarManager.getTaskBar(data.fileName);
479
494
  onTransferProgress({
480
495
  ...data,
481
496
  stats: taskBarStats
@@ -490,12 +505,15 @@ function _setupFileEventListeners(userID, client, onTransferProgress, onIncoming
490
505
  fileSize
491
506
  } = data;
492
507
  if (chunkIndex === 0) {
508
+ FileTransferTrackingManager.trackTransfer(data);
493
509
  this.progressBarManager.addTask({
494
510
  name: fileName,
495
511
  size: fileSize
496
512
  });
513
+ } else if (chunkIndex > 0) {
514
+ FileTransferTrackingManager.updateTransfer(data);
515
+ this.progressBarManager.updateTaskProgress(fileName, chunkSize);
497
516
  }
498
- this.progressBarManager.updateTaskProgress(fileName, chunkSize);
499
517
  if (onTransferStatus) {
500
518
  const taskBarStats = this.progressBarManager.getTaskBar(fileName);
501
519
  onTransferStatus({
@@ -508,35 +526,61 @@ function _setupFileEventListeners(userID, client, onTransferProgress, onIncoming
508
526
  client.clientTide.onEvent(userID, "transfer-complete", data => {
509
527
  const savePath = FileUtilityManager.getTidePath(path.join(data.filePath, data.fileName));
510
528
  try {
511
- _FileTide.outputGradient(`[${userID}] File transfer complete : ${data.fileName}`, significantMessageColors);
512
- const transferState = fileTransferReceiver.activeTransfers.get(data.fileName);
529
+ _FileTide.outputGradient(`[${userID}] File transfer complete ~ ${data.fileName}`, significantMessageColors);
530
+ const transferState = FileTransferTrackingManager.getTransfer(data.fileName);
531
+ FileTideDebugUtilityManager.log("notice", true, `Transfer state ~ ${data.fileName} active | ${transferState !== null && transferState !== undefined ? true : false}`);
513
532
  if (!transferState) {
514
533
  return;
515
534
  }
516
- fileTransferReceiver.completeTransfer(data, (transferData, transfers, success, error) => {
517
- if (success) {
518
- FileTransferRecoveryManager.clearTransferState(userID, data.senderID, `${data.filePath}-${data.fileName}`);
519
- _FileTide.outputGradient(`[${userID}] File saved at : ${savePath}\n`, significantMessageColors);
520
- } else if (!success) {
521
- _FileTide.outputGradient(`[${userID}] Did not save file at : ${savePath}\n\t${error}\n`, errorMessageColors);
522
- }
523
- if (onTransferComplete) {
524
- const taskBarStats = this.progressBarManager.getTaskBar(data.fileName);
525
- onTransferComplete({
526
- ...data,
527
- stats: taskBarStats
528
- }, fileTransferReceiver.activeTransfers, success);
529
- }
530
- });
535
+ if (transferState.fileStream) {
536
+ fileTransferReceiver.completeTransfer(data, (transferData, transfers, success, error) => {
537
+ if (success) {
538
+ FileTransferRecoveryManager.clearTransferState(userID, data.senderID, `${data.filePath}-${data.fileName}`);
539
+ _FileTide.outputGradient(`[${userID}] File saved at ~ ${savePath}\n`, significantMessageColors);
540
+ } else if (!success) {
541
+ _FileTide.outputGradient(`[${userID}] Did not save file at ~ ${savePath}\n\t${error}\n`, errorMessageColors);
542
+ }
543
+ if (onTransferComplete) {
544
+ const taskBarStats = this.progressBarManager.getTaskBar(data.fileName);
545
+ onTransferComplete({
546
+ ...data,
547
+ stats: taskBarStats
548
+ }, FileTransferTrackingManager.activeTransfers, success);
549
+ }
550
+ setTimeout(() => {
551
+ FileTransferTrackingManager.outputCurrentTransfers();
552
+ this.progressBarManager.clearTaskBar(data.fileName);
553
+ }, this.progressBarManager.completionTimeout);
554
+ });
555
+ return;
556
+ }
557
+ FileTransferRecoveryManager.clearTransferState(userID, data.senderID, `${data.filePath}-${data.fileName}`);
558
+ FileTransferTrackingManager.untrackTransfer(data.fileName);
559
+ _FileTide.outputGradient(`[${userID}] Transfer successfully sent to ~ ${data.recipientId} and saved at ~ ${path.join(data.filePath, data.fileName)}\n`, significantMessageColors);
560
+ if (onTransferComplete) {
561
+ const taskBarStats = this.progressBarManager.getTaskBar(data.fileName);
562
+ onTransferComplete({
563
+ ...data,
564
+ stats: taskBarStats
565
+ }, FileTransferTrackingManager.activeTransfers, true);
566
+ }
567
+ setTimeout(() => {
568
+ FileTransferTrackingManager.outputCurrentTransfers();
569
+ this.progressBarManager.clearTaskBar(data.fileName);
570
+ }, this.progressBarManager.completionTimeout);
531
571
  } catch (error) {
532
- _FileTide.outputGradient(`[${userID}] Did not save file at : ${savePath}\n${error}`, errorMessageColors);
572
+ _FileTide.outputGradient(`[${userID}] Did not save file at ~ ${savePath}\n${error}`, errorMessageColors);
533
573
  if (onTransferComplete) {
534
574
  const taskBarStats = this.progressBarManager.getTaskBar(data.fileName);
535
575
  onTransferComplete({
536
576
  ...data,
537
577
  stats: taskBarStats
538
- }, fileTransferReceiver.activeTransfers, false);
578
+ }, FileTransferTrackingManager.activeTransfers, false);
539
579
  }
580
+ setTimeout(() => {
581
+ FileTransferTrackingManager.outputCurrentTransfers();
582
+ this.progressBarManager.clearTaskBar(data.fileName);
583
+ }, this.progressBarManager.completionTimeout);
540
584
  }
541
585
  });
542
586
  client.clientTide.onEvent(userID, "transfer-requested", async data => {
@@ -2,6 +2,12 @@
2
2
 
3
3
  const readline = require("readline");
4
4
  const chalk = require("chalk");
5
+ const {
6
+ FileTideDebugUtilityManager
7
+ } = require("../HUDManagers/FileTideDebugUtilityManager.js");
8
+ const {
9
+ FileNetUtilityManager
10
+ } = require("../HUDManagers/FileNetUtilityManager");
5
11
  class ConsoleProgressBarManager {
6
12
  constructor(tasks = [], options = {}) {
7
13
  const rows = process.stdout.rows || 24;
@@ -20,41 +26,6 @@ class ConsoleProgressBarManager {
20
26
  this.allTasksCompleted = false;
21
27
  this.taskBars = tasks.map((task, index) => this.createTaskBar(task, index));
22
28
  }
23
- convertSeconds(seconds) {
24
- if (seconds === 0) return "0 s";
25
- const units = [{
26
- name: "y",
27
- seconds: 60 * 60 * 24 * 365
28
- }, {
29
- name: "mo",
30
- seconds: 60 * 60 * 24 * 30
31
- }, {
32
- name: "w",
33
- seconds: 60 * 60 * 24 * 7
34
- }, {
35
- name: "d",
36
- seconds: 60 * 60 * 24
37
- }, {
38
- name: "h",
39
- seconds: 60 * 60
40
- }, {
41
- name: "m",
42
- seconds: 60
43
- }, {
44
- name: "s",
45
- seconds: 1
46
- }];
47
- let remainingSeconds = seconds;
48
- let result = "";
49
- for (const unit of units) {
50
- const count = Math.floor(remainingSeconds / unit.seconds);
51
- if (count > 0) {
52
- result += `${count}${unit.name} `;
53
- remainingSeconds %= unit.seconds;
54
- }
55
- }
56
- return result.trim();
57
- }
58
29
  createTaskBar(task, index) {
59
30
  const defaultOptions = {
60
31
  barLength: 40,
@@ -81,32 +52,6 @@ class ConsoleProgressBarManager {
81
52
  startTime: Date.now(),
82
53
  taskIndex: index,
83
54
  completed: false,
84
- getFormattedSize: size => {
85
- if (!settings.dynamicUnits) return `${size.toFixed(1)} B`;
86
- const units = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
87
- let unitIndex = 0;
88
- while (size >= 1024 && unitIndex < units.length - 1) {
89
- size /= 1024;
90
- unitIndex++;
91
- }
92
- return `${size.toFixed(2)} ${units[unitIndex]}`;
93
- },
94
- getUnitData: size => {
95
- if (!settings.dynamicUnits) return {
96
- current: size.toFixed(1),
97
- unit: "B"
98
- };
99
- const units = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
100
- let unitIndex = 0;
101
- while (size >= 1024 && unitIndex < units.length - 1) {
102
- size /= 1024;
103
- unitIndex++;
104
- }
105
- return {
106
- current: size.toFixed(2),
107
- unit: units[unitIndex]
108
- };
109
- },
110
55
  redraw: () => {
111
56
  if (!isNaN(newBar.taskIndex) && !isNaN(this.barsPerPage) && process.stdout.isTTY) {
112
57
  readline.cursorTo(process.stdout, 0, newBar.taskIndex % this.barsPerPage);
@@ -119,7 +64,7 @@ class ConsoleProgressBarManager {
119
64
  const percentage = newBar.current / newBar.totalSize * 100;
120
65
  const elapsedTime = (Date.now() - newBar.startTime) / 1000;
121
66
  const speed = newBar.current / elapsedTime;
122
- const speedData = newBar.getUnitData(speed);
67
+ const speedData = FileNetUtilityManager.getFormattedSize(speed, settings.dynamicUnits);
123
68
  const timeLeft = (newBar.totalSize - newBar.current) / (speed || 1);
124
69
  newBar.progress = percentage;
125
70
  newBar.timeLeft = timeLeft;
@@ -127,7 +72,7 @@ class ConsoleProgressBarManager {
127
72
  const filledLength = Math.round(settings.barLength * (newBar.current / newBar.totalSize));
128
73
  const bar = settings.barColor(settings.filledChar.repeat(filledLength)) + settings.unfilledChar.repeat(settings.barLength - filledLength);
129
74
  try {
130
- process.stdout.write(`${settings.taskNameColor(newBar.taskName)} > ${settings.totalSizeColor(newBar.getFormattedSize(newBar.totalSize))} | ${settings.sizeTransferredColor(newBar.getFormattedSize(newBar.current))} ${settings.speedColor(`${speedData.current} ${speedData.unit}/s`)} | ${settings.taskETAColor(this.convertSeconds(timeLeft.toFixed(2)))} [${bar}] ${settings.percentageColor(percentage.toFixed(2) + "%")}`);
75
+ process.stdout.write(`${settings.taskNameColor(newBar.taskName)} > ${settings.totalSizeColor(FileNetUtilityManager.getFormattedSize(newBar.totalSize, settings.dynamicUnits))} | ${settings.sizeTransferredColor(FileNetUtilityManager.getFormattedSize(newBar.current, settings.dynamicUnits))} ${settings.speedColor(`${speedData}/s`)} | ${settings.taskETAColor(FileNetUtilityManager.convertSeconds(timeLeft.toFixed(2)))} [${bar}] ${settings.percentageColor(percentage.toFixed(2) + "%")}`);
131
76
  } catch (error) {
132
77
  console.log(error);
133
78
  }
@@ -165,7 +110,9 @@ class ConsoleProgressBarManager {
165
110
  setTimeout(() => {
166
111
  this.completionFeed = this.completionFeed.filter(task => task !== newBar.taskName);
167
112
  }, this.completionTimeout);
113
+ FileTideDebugUtilityManager.log("notice", true, `Tasks Completion Status ~\n\n\tTasks ~ (${this.completedTasksCount}/${this.totalTasks})`);
168
114
  if (this.completedTasksCount === this.totalTasks) {
115
+ FileTideDebugUtilityManager.log("notice", true, `All Tasks Complete!`);
169
116
  this.allTasksCompleted = true;
170
117
  this.exitInputListener();
171
118
  this.displayPage();
@@ -211,7 +158,7 @@ class ConsoleProgressBarManager {
211
158
  getCurrentStats() {
212
159
  const completedTasks = this.taskBars.filter(bar => bar.completed).length;
213
160
  const totalTasks = this.taskBars.length;
214
- const overallProgress = this.taskBars.reduce((acc, bar) => acc + bar.current / bar.totalSize * 100, 0) / totalTasks;
161
+ const overallProgress = totalTasks === 0 ? 0 : this.taskBars.reduce((acc, bar) => acc + bar.current / bar.totalSize * 100, 0) / totalTasks;
215
162
  const stats = {
216
163
  completedTasks,
217
164
  totalTasks,
@@ -220,10 +167,10 @@ class ConsoleProgressBarManager {
220
167
  taskName: bar.taskName,
221
168
  progress: `${(bar.current / bar.totalSize * 100).toFixed(2)}%`,
222
169
  completed: bar.completed,
223
- currentSize: bar.getFormattedSize(bar.current),
224
- totalSize: bar.getFormattedSize(bar.totalSize),
225
- speed: `${bar.getUnitData(bar.speed).current} ${bar.getUnitData(bar.speed).unit}/s`,
226
- timeLeft: this.convertSeconds(bar.timeLeft.toFixed(2))
170
+ currentSize: FileNetUtilityManager.getFormattedSize(bar.current, true),
171
+ totalSize: FileNetUtilityManager.getFormattedSize(bar.totalSize, true),
172
+ speed: `${FileNetUtilityManager.getUnitData(bar.speed, true).current} ${FileNetUtilityManager.getUnitData(bar.speed, true).unit}/s`,
173
+ timeLeft: FileNetUtilityManager.convertSeconds(bar.timeLeft.toFixed(2))
227
174
  }))
228
175
  };
229
176
  return stats;
@@ -317,14 +264,20 @@ class ConsoleProgressBarManager {
317
264
  }
318
265
  exitInputListener() {
319
266
  process.stdin.removeListener("data", this.inputListener);
267
+ FileTideDebugUtilityManager.log("notice", true, `Exiting input listener...`);
268
+ FileTideDebugUtilityManager.log("notice", true, `Process TTY ~ ${process.stdout.isTTY}`);
320
269
  if (process.stdout.isTTY) {
321
270
  process.stdin.setRawMode(false);
322
271
  process.stdin.resume();
272
+ FileTideDebugUtilityManager.log("notice", true, `Resumed process.`);
323
273
  }
274
+ FileTideDebugUtilityManager.log("notice", true, `Exited input listener.`);
324
275
  }
325
276
  displayCompletionMessage() {
326
277
  const lastLine = Math.min(this.taskBars.length, this.barsPerPage);
327
278
  readline.cursorTo(process.stdout, 0, lastLine);
279
+ FileTideDebugUtilityManager.log("notice", true, `Displaying task completion message...`);
280
+ FileTideDebugUtilityManager.log("notice", true, `Process TTY ~ ${process.stdout.isTTY}`);
328
281
  if (process.stdout.isTTY) {
329
282
  process.stdout.clearLine();
330
283
  }
@@ -14,6 +14,17 @@ class FileNetClientManager {
14
14
  });
15
15
  return currentOnlineClients;
16
16
  }
17
+ static updateOnlineClient(clientID, data) {
18
+ const onlineClient = currentOnlineClients.get(clientID);
19
+ if (!onlineClient) {
20
+ return false;
21
+ }
22
+ currentOnlineClients.set(clientID, {
23
+ ...onlineClient,
24
+ ...data
25
+ });
26
+ return true;
27
+ }
17
28
  static clearOnlineClient(clientID) {
18
29
  if (!currentOnlineClients.get(clientID)) {
19
30
  return currentOnlineClients;
@@ -3,23 +3,69 @@
3
3
  const {
4
4
  HUDUtilityManager
5
5
  } = require("@trap_stevo/legendarybuilderpronodejs-utilities");
6
- const chalk = require("chalk");
7
- const significantMessageColors = ["#00C897", "#00E0FF"];
8
- const errorMessageColors = ["#F94144", "#F3722C"];
9
6
  class FileNetUtilityManager {
10
- static outputGradient(text, colors) {
11
- const gradient = HUDUtilityManager.generateGradientColors(colors, text.length);
12
- let coloredText = "";
13
- for (let i = 0; i < text.length; i++) {
14
- const [r, g, b] = gradient[i];
15
- coloredText += chalk.rgb(r, g, b)(text[i]);
7
+ static convertSeconds(seconds) {
8
+ if (seconds === 0) return "0 s";
9
+ const units = [{
10
+ name: "y",
11
+ seconds: 60 * 60 * 24 * 365
12
+ }, {
13
+ name: "mo",
14
+ seconds: 60 * 60 * 24 * 30
15
+ }, {
16
+ name: "w",
17
+ seconds: 60 * 60 * 24 * 7
18
+ }, {
19
+ name: "d",
20
+ seconds: 60 * 60 * 24
21
+ }, {
22
+ name: "h",
23
+ seconds: 60 * 60
24
+ }, {
25
+ name: "m",
26
+ seconds: 60
27
+ }, {
28
+ name: "s",
29
+ seconds: 1
30
+ }];
31
+ let remainingSeconds = seconds;
32
+ let result = "";
33
+ for (const unit of units) {
34
+ const count = Math.floor(remainingSeconds / unit.seconds);
35
+ if (count > 0) {
36
+ result += `${count}${unit.name} `;
37
+ remainingSeconds %= unit.seconds;
38
+ }
16
39
  }
17
- console.log(coloredText);
18
- return;
40
+ return result.trim();
41
+ }
42
+ static getFormattedSize(size, dynamicUnits = true) {
43
+ if (!dynamicUnits) return `${size.toFixed(1)} B`;
44
+ const units = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
45
+ let unitIndex = 0;
46
+ while (size >= 1024 && unitIndex < units.length - 1) {
47
+ size /= 1024;
48
+ unitIndex++;
49
+ }
50
+ return `${size.toFixed(2)} ${units[unitIndex]}`;
51
+ }
52
+ static getUnitData(size, dynamicUnits = true) {
53
+ if (!dynamicUnits) return {
54
+ current: size.toFixed(1),
55
+ unit: "B"
56
+ };
57
+ const units = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
58
+ let unitIndex = 0;
59
+ while (size >= 1024 && unitIndex < units.length - 1) {
60
+ size /= 1024;
61
+ unitIndex++;
62
+ }
63
+ return {
64
+ current: size.toFixed(2),
65
+ unit: units[unitIndex]
66
+ };
19
67
  }
20
68
  }
21
69
  module.exports = {
22
- FileNetUtilityManager,
23
- significantMessageColors,
24
- errorMessageColors
70
+ FileNetUtilityManager
25
71
  };
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+
3
+ const {
4
+ HUDUtilityManager
5
+ } = require("@trap_stevo/legendarybuilderpronodejs-utilities");
6
+ const chalk = require("chalk");
7
+ const significantMessageColors = ["#00C897", "#00E0FF"];
8
+ const noticeMessageColors = ["#4A90E2", "#A3D8F4"];
9
+ const errorMessageColors = ["#F94144", "#F3722C"];
10
+ const infoMessageColors = ["#028090", "#56cfe1"];
11
+ const logHandler = {
12
+ "significant": function (includeDate = false, ...message) {
13
+ const log = includeDate ? `[${new Date().toLocaleString()}] ~ ` : "";
14
+ outputGradient(log + message.join(" "), significantMessageColors);
15
+ },
16
+ "notice": function (includeDate = false, ...message) {
17
+ const log = includeDate ? `[${new Date().toLocaleString()}] ~ ` : "";
18
+ outputGradient(log + message.join(" "), noticeMessageColors);
19
+ },
20
+ "error": function (includeDate = false, ...message) {
21
+ const log = includeDate ? `[${new Date().toLocaleString()}] ~ ` : "";
22
+ outputGradient(log + message.join(" "), errorMessageColors);
23
+ },
24
+ "info": function (includeDate = false, ...message) {
25
+ const log = includeDate ? `[${new Date().toLocaleString()}] ~ ` : "";
26
+ outputGradient(log + message.join(" "), infoMessageColors);
27
+ }
28
+ };
29
+ function outputGradient(text, colors) {
30
+ const gradient = HUDUtilityManager.generateGradientColors(colors, text.length);
31
+ let coloredText = "";
32
+ for (let i = 0; i < text.length; i++) {
33
+ const [r, g, b] = gradient[i];
34
+ coloredText += chalk.rgb(r, g, b)(text[i]);
35
+ }
36
+ console.log(coloredText);
37
+ return;
38
+ }
39
+ ;
40
+ class FileTideDebugUtilityManager {
41
+ constructor() {
42
+ if (FileTideDebugUtilityManager.instance) {
43
+ return FileTideDebugUtilityManager.instance;
44
+ }
45
+ this.debugMode = false;
46
+ FileTideDebugUtilityManager.instance = this;
47
+ }
48
+ outputGradient(text, colors) {
49
+ outputGradient(text, colors);
50
+ return;
51
+ }
52
+ setDebugMode(mode) {
53
+ this.debugMode = mode;
54
+ }
55
+ log(type = "info", includeDate = false, ...message) {
56
+ if (!this.debugMode && type !== "error") {
57
+ return;
58
+ }
59
+ if (logHandler[type]) {
60
+ logHandler[type](includeDate, ...message);
61
+ return;
62
+ }
63
+ console.log(new Date().toLocaleString(), chalk.gray("Unknown log type ~ "), type, ...message);
64
+ }
65
+ }
66
+ const instance = new FileTideDebugUtilityManager();
67
+ module.exports = {
68
+ FileTideDebugUtilityManager: instance,
69
+ significantMessageColors,
70
+ noticeMessageColors,
71
+ errorMessageColors,
72
+ infoMessageColors
73
+ };
@@ -77,16 +77,23 @@ class FileTransferManager {
77
77
  } = await fileHandle.read(Buffer.alloc(end - start), 0, end - start, start);
78
78
  const transferState = this.activeTransfers.get(transferId);
79
79
  chunkBuffer.set(chunkIndex, buffer);
80
- while (chunkBuffer.has(nextExpectedChunk)) {
81
- const nextChunkBuffer = chunkBuffer.get(nextExpectedChunk);
82
- await onSendChunk(transferId, nextExpectedChunk, this.chunkSize, nextChunkBuffer, totalChunks, this.activeTransfers.get(transferId).completedChunks + 1);
83
- chunkBuffer.delete(nextExpectedChunk);
84
- nextExpectedChunk++;
85
- transferState.transferredSize += this.chunkSize;
86
- transferState.completedChunks++;
87
- updateProgress();
88
- }
89
- if (transferState.completedChunks === transferState.totalChunks) {
80
+ try {
81
+ while (chunkBuffer.has(nextExpectedChunk)) {
82
+ const nextChunkBuffer = chunkBuffer.get(nextExpectedChunk);
83
+ await onSendChunk(transferId, nextExpectedChunk, this.chunkSize, nextChunkBuffer, totalChunks, this.activeTransfers.get(transferId).completedChunks + 1);
84
+ chunkBuffer.delete(nextExpectedChunk);
85
+ nextExpectedChunk++;
86
+ transferState.transferredSize += this.chunkSize;
87
+ transferState.completedChunks++;
88
+ updateProgress();
89
+ }
90
+ if (transferState.completedChunks === transferState.totalChunks) {
91
+ return onComplete(transferId).then(() => {
92
+ this.activeTransfers.delete(transferId);
93
+ });
94
+ }
95
+ } catch (error) {
96
+ console.error(`[FileTide ~ Transporter] ~ Did not send chunk ${chunkIndex} ~ ${error.message}`);
90
97
  return onComplete(transferId).then(() => {
91
98
  this.activeTransfers.delete(transferId);
92
99
  });
@@ -1,21 +1,25 @@
1
1
  "use strict";
2
2
 
3
- const fs = require("fs");
4
3
  const path = require("path");
4
+ const fs = require("fs");
5
+ const {
6
+ FileTransferTrackingManager
7
+ } = require("./FileTransferTrackingManager.js");
8
+ const {
9
+ FileTideDebugUtilityManager
10
+ } = require("./FileTideDebugUtilityManager.js");
5
11
  const {
6
12
  FileUtilityManager
7
13
  } = require("./FileUtilityManager.js");
8
14
  class FileTransferReceiverManager {
9
- constructor() {
10
- this.activeTransfers = new Map();
11
- }
15
+ constructor() {}
12
16
  async initializeTransfer(data, onError) {
13
17
  const savePath = FileUtilityManager.getTidePath(path.join(data.path || data.filePath, data.fileName));
14
- if (this.activeTransfers.has(data.fileName)) {
18
+ FileTideDebugUtilityManager.log("notice", true, `Initializing transfer ~ ${data.fileName} | ${savePath}...`);
19
+ if (FileTransferTrackingManager.containsTransfer(data.fileName)) {
20
+ FileTideDebugUtilityManager.log("notice", true, `Transfer ~ ${data.fileName} | ${savePath} already initialized.`);
15
21
  return;
16
22
  }
17
- const totalChunks = data.totalChunks || Math.ceil(data.fileSize / (data.chunkSize || 512 * 1024));
18
- const chunkSize = data.chunkSize || 512 * 1024;
19
23
  try {
20
24
  const dir = path.dirname(savePath);
21
25
  if (!fs.existsSync(dir)) {
@@ -26,53 +30,58 @@ class FileTransferReceiverManager {
26
30
  const fileStream = fs.createWriteStream(savePath, {
27
31
  flags: "w"
28
32
  });
29
- this.activeTransfers.set(data.fileName, {
30
- receivedChunks: new Set(),
31
- fileInfo: data,
32
- totalChunks,
33
- fileStream,
34
- chunkSize
35
- });
33
+ FileTransferTrackingManager.trackTransfer(data, fileStream);
34
+ FileTideDebugUtilityManager.log("notice", true, `Initialized transfer ~ ${data.fileName} | ${savePath}!`);
36
35
  } catch (error) {
36
+ FileTideDebugUtilityManager.log("error", true, `Did not initialize transfer ~ ${data.fileName} | ${savePath}.\n\t\t${error}`);
37
37
  if (onError) {
38
38
  onError(`[${data.fileName}] Did not initialize transfer ~ ${error.message}`);
39
39
  }
40
40
  }
41
41
  }
42
42
  async handleTransferProgress(data, onError) {
43
- let transferState = this.activeTransfers.get(data.fileName);
43
+ let transferState = FileTransferTrackingManager.getTransfer(data.fileName);
44
44
  if (!transferState) {
45
45
  await this.initializeTransfer(data);
46
- transferState = this.activeTransfers.get(data.fileName);
46
+ transferState = tFileTransferTrackingManager.getTransfer(data.fileName);
47
47
  }
48
48
  const chunkBuffer = Buffer.from(data.fileChunk);
49
49
  try {
50
50
  transferState.fileStream.write(chunkBuffer);
51
51
  transferState.receivedChunks.add(data.chunkIndex);
52
52
  } catch (error) {
53
+ FileTideDebugUtilityManager.log("error", true, `Did not write chunk ${data.chunkIndex} ~ ${data.fileName}.\n\t\t${error}`);
53
54
  if (onError) {
54
55
  onError(`[${data.fileName}] Did not write chunk ${data.chunkIndex} ~ ${error.message}`);
55
56
  }
56
57
  }
57
58
  }
58
59
  async completeTransfer(data, onComplete) {
59
- let transferState = this.activeTransfers.get(data.fileName);
60
+ let transferState = FileTransferTrackingManager.getTransfer(data.fileName);
61
+ FileTideDebugUtilityManager.log("notice", true, `Completing transfer ~ ${data.fileName}...`);
60
62
  if (!transferState) {
63
+ FileTideDebugUtilityManager.log("notice", true, `Did not get transfer state ~ ${data.fileName}...re-initializing....`);
61
64
  await this.initializeTransfer(data);
62
- transferState = this.activeTransfers.get(data.fileName);
65
+ transferState = FileTransferTrackingManager.getTransfer(data.fileName);
63
66
  }
64
67
  try {
68
+ FileTideDebugUtilityManager.log("notice", true, `Verifying transfer state ~ ${data.fileName} completion (${transferState.receivedChunks.size}/${transferState.totalChunks})...`);
69
+ FileTideDebugUtilityManager.log("notice", true, `Transfer state ~ ${data.fileName} completed ~ (${transferState.receivedChunks.size === transferState.totalChunks}).`);
65
70
  if (transferState.receivedChunks.size === transferState.totalChunks) {
66
71
  transferState.fileStream.end();
67
72
  console.log(`[${data.fileName}] Transfer complete. All chunks received and file written.`);
68
- this.activeTransfers.delete(data.fileName);
69
- if (onComplete) onComplete(data, this.activeTransfers, true);
73
+ FileTransferTrackingManager.untrackTransfer(data.fileName);
74
+ FileTideDebugUtilityManager.log("notice", true, `Cleared transfer state ~ ${data.fileName}.`);
75
+ FileTransferTrackingManager.outputCurrentTransfers();
76
+ if (onComplete) onComplete(data, FileTransferTrackingManager.activeTransfers, true);
70
77
  } else {
78
+ FileTideDebugUtilityManager.log("error", true, `Transfer incomplete. Received ${transferState.receivedChunks.size}/${transferState.totalChunks} chunks.`);
71
79
  throw new Error(`[${data.fileName}] Transfer incomplete. Received ${transferState.receivedChunks.size}/${transferState.totalChunks} chunks.`);
72
80
  }
73
81
  } catch (error) {
82
+ FileTideDebugUtilityManager.log("error", true, `Transfer incomplete.\n\t\t${error}`);
74
83
  if (onComplete) {
75
- onComplete(data, this.activeTransfers, false, error);
84
+ onComplete(data, FileTransferTrackingManager.activeTransfers, false, error);
76
85
  }
77
86
  }
78
87
  }
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+
3
+ const {
4
+ FileTideDebugUtilityManager
5
+ } = require("./FileTideDebugUtilityManager.js");
6
+ class FileTransferTrackingManager {
7
+ constructor() {
8
+ if (FileTransferTrackingManager.instance) {
9
+ return FileTransferTrackingManager.instance;
10
+ }
11
+ this.activeTransfers = new Map();
12
+ FileTransferTrackingManager.instance = this;
13
+ }
14
+ trackTransfer(data, fileStream) {
15
+ FileTideDebugUtilityManager.log("notice", true, `Tracking transfer ~ ${data.fileName} | ${data.senderName}...`);
16
+ if (this.containsTransfer(data.fileName)) {
17
+ FileTideDebugUtilityManager.log("notice", true, `Transfer ~ ${data.fileName} | ${data.senderName} already tracked.`);
18
+ return;
19
+ }
20
+ const totalChunks = data.totalChunks || Math.ceil(data.fileSize / (data.chunkSize || 512 * 1024));
21
+ const chunkSize = data.chunkSize || 512 * 1024;
22
+ this.activeTransfers.set(data.fileName, {
23
+ receivedChunks: new Set(),
24
+ fileInfo: data,
25
+ totalChunks,
26
+ fileStream,
27
+ chunkSize
28
+ });
29
+ FileTideDebugUtilityManager.log("notice", true, `Tracked transfer ~ ${data.fileName} | ${data.senderName}!`);
30
+ }
31
+ updateTransfer(data) {
32
+ FileTideDebugUtilityManager.log("notice", true, `Updating tracked transfer ~ ${data.fileName} | ${data.senderName}...`);
33
+ if (!this.containsTransfer(data.fileName)) {
34
+ FileTideDebugUtilityManager.log("notice", true, `Transfer ~ ${data.fileName} | ${data.senderName} not tracked.`);
35
+ return;
36
+ }
37
+ const transferState = this.getTransfer(data.fileName);
38
+ transferState.receivedChunks.add(data.chunkIndex);
39
+ FileTideDebugUtilityManager.log("notice", true, `Updated tracked transfer ~ ${data.fileName} | ${data.senderName}!`);
40
+ }
41
+ containsTransfer(transferID) {
42
+ return this.activeTransfers.has(transferID);
43
+ }
44
+ getTransfer(transferID) {
45
+ return this.activeTransfers.get(transferID);
46
+ }
47
+ untrackTransfer(transferID) {
48
+ FileTideDebugUtilityManager.log("notice", true, `Untracking transfer ~ ${transferID}...`);
49
+ if (this.containsTransfer(transferID)) {
50
+ this.activeTransfers.delete(transferID);
51
+ FileTideDebugUtilityManager.log("notice", true, `Transfer ~ ${transferID} untracked!`);
52
+ return;
53
+ }
54
+ FileTideDebugUtilityManager.log("notice", true, `Transfer ~ ${transferID} already untracked.`);
55
+ }
56
+ outputCurrentTransfers() {
57
+ if (this.activeTransfers.size === 0) {
58
+ FileTideDebugUtilityManager.log("notice", true, "No active file transfers.");
59
+ return;
60
+ }
61
+ FileTideDebugUtilityManager.log("notice", true, "Ongoing Transfers ~\n");
62
+ this.activeTransfers.forEach((transfer, fileName) => {
63
+ const {
64
+ totalChunks,
65
+ receivedChunks,
66
+ fileInfo
67
+ } = transfer;
68
+ const percentage = (receivedChunks.size / totalChunks * 100).toFixed(2);
69
+ FileTideDebugUtilityManager.log("notice", false, `\nFile Name ~ ${fileName}`);
70
+ FileTideDebugUtilityManager.log("notice", false, `File Path ~ ${fileInfo.path || fileInfo.filePath}`);
71
+ FileTideDebugUtilityManager.log("notice", false, `File Size ~ ${fileInfo.fileSize} bytes`);
72
+ FileTideDebugUtilityManager.log("notice", false, `Chunk Size ~ ${transfer.chunkSize} bytes`);
73
+ FileTideDebugUtilityManager.log("notice", false, `Total Chunks ~ ${totalChunks}`);
74
+ FileTideDebugUtilityManager.log("notice", false, `Received Chunks ~ ${receivedChunks.size}`);
75
+ FileTideDebugUtilityManager.log("notice", false, `Progress ~ ${percentage}%`);
76
+ });
77
+ FileTideDebugUtilityManager.log("notice", false, "=================================\n");
78
+ }
79
+ }
80
+ ;
81
+ const instance = new FileTransferTrackingManager();
82
+ module.exports = {
83
+ FileTransferTrackingManager: instance
84
+ };
package/package.json CHANGED
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "@trap_stevo/filetide",
3
- "version": "0.0.51",
3
+ "version": "0.0.53",
4
4
  "description": "Revolutionizing real-time file transfer with seamless, instant communication across any device. Deliver files instantly, regardless of platform, and experience unparalleled speed and control in managing transfers. Elevate your file-sharing capabilities with a tool designed for precision, efficiency, and effortless connectivity.",
5
5
  "main": "dist/cjs/FileTide.js",
6
6
  "scripts": {
7
7
  "build": "babel src -d dist/cjs --env-name cjs",
8
+ "start-file-generation": "node demos/FileGenerator.js",
8
9
  "start-messager": "node demos/FileTideClientDemo.js",
9
10
  "start-net": "node demos/FileTideNetDemo.js",
10
11
  "start": "node dist/cjs/FileTide.js"
@@ -33,7 +34,7 @@
33
34
  "author": "Steven Compton",
34
35
  "license": "See License in LICENSE.md",
35
36
  "dependencies": {
36
- "@trap_stevo/iotide": "^0.0.37",
37
+ "@trap_stevo/iotide": "^0.0.41",
37
38
  "@trap_stevo/iotide-client": "^0.0.23",
38
39
  "@trap_stevo/legendarybuilderpronodejs-utilities": "^1.0.43",
39
40
  "chalk": "^4.1.2",