@trap_stevo/filetide 0.0.37 → 0.0.39

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.
@@ -84,7 +84,7 @@ class FileMessager {
84
84
  * @param {String} fileName - The name of the file
85
85
  * @param {Number} chunkIndex - The index of the current chunk
86
86
  */
87
- sendFileChunkToClient(senderData, clientData, fileChunk, fileName, chunkIndex, totalChunks, filePath = process.cwd(), fileSize = 100) {
87
+ sendFileChunkToClient(senderData, clientData, fileChunk, fileName, chunkIndex, chunkSize, totalChunks, filePath = process.cwd(), fileSize = 100) {
88
88
  const senderClient = this.getClientFromID(senderData.id);
89
89
  const client = this.getClientFromID(clientData.id);
90
90
  if (!client) {
@@ -106,6 +106,7 @@ class FileMessager {
106
106
  fileName,
107
107
  fileChunk,
108
108
  chunkIndex,
109
+ chunkSize,
109
110
  path: filePath,
110
111
  fileSize
111
112
  });
@@ -173,6 +174,7 @@ class FileMessager {
173
174
  fileSize,
174
175
  filePath,
175
176
  chunkIndex,
177
+ chunkSize,
176
178
  totalChunks
177
179
  } = transferData;
178
180
  console.log(`Transferring file ~ ${fileName} | chunk ${chunkIndex + 1} of ${totalChunks} to client (${recipientId})`);
@@ -182,7 +184,7 @@ class FileMessager {
182
184
  }, {
183
185
  userID: recipientId,
184
186
  id: FileNetClientManager.getOnlineClient(recipientId).id
185
- }, fileChunk, fileName, chunkIndex, totalChunks, filePath, fileSize);
187
+ }, fileChunk, fileName, chunkIndex, chunkSize, totalChunks, filePath, fileSize);
186
188
  if (chunkIndex + 1 === totalChunks) {
187
189
  this.fileNet.emit("transfer-complete", {
188
190
  senderID,
@@ -270,10 +272,12 @@ class FileMessager {
270
272
  activeTransferBarrier
271
273
  });
272
274
  this.fileNet.emitToTide(tideID, "current-online-clients", Object.fromEntries(FileNetClientManager.getOnlineClients()));
275
+ this.fileNet.emit("current-clients", Object.fromEntries(FileNetClientManager.getOnlineClients()));
273
276
  return;
274
277
  }
275
278
  handleClientOffline(clientID) {
276
279
  FileNetClientManager.clearOnlineClient(clientID);
280
+ this.fileNet.emit("current-clients", Object.fromEntries(FileNetClientManager.getOnlineClients()));
277
281
  return;
278
282
  }
279
283
  }
@@ -154,7 +154,7 @@ class FileMessagerClient {
154
154
  });
155
155
  }
156
156
  this.transporter.sendFile(file, {
157
- onSendChunk: (transferId, chunkIndex, chunkData, totalChunks) => {
157
+ onSendChunk: (transferId, chunkIndex, chunkSize, chunkData, totalChunks) => {
158
158
  if (chunkIndex === 0) {
159
159
  this.progressBarManager.addTask({
160
160
  name: fileName,
@@ -169,6 +169,7 @@ class FileMessagerClient {
169
169
  fileChunk: chunkData,
170
170
  totalChunks,
171
171
  chunkIndex,
172
+ chunkSize,
172
173
  filePath,
173
174
  fileSize
174
175
  });
@@ -186,8 +187,8 @@ class FileMessagerClient {
186
187
  resolve();
187
188
  });
188
189
  },
189
- onProgress: progress => {
190
- this.progressBarManager.updateTaskProgress(fileName, 512 * 1024);
190
+ onProgress: (progress, chunkSize) => {
191
+ this.progressBarManager.updateTaskProgress(fileName, chunkSize);
191
192
  },
192
193
  originDetails: {
193
194
  recipientID: recipientId,
@@ -224,7 +225,7 @@ class FileMessagerClient {
224
225
  path: filePath
225
226
  });
226
227
  this.transporter.sendFile(file, {
227
- onSendChunk: (transferId, chunkIndex, chunkData, totalChunks) => {
228
+ onSendChunk: (transferId, chunkIndex, chunkSize, chunkData, totalChunks) => {
228
229
  if (chunkIndex === 0) {
229
230
  this.progressBarManager.addTask({
230
231
  name: fileName,
@@ -239,6 +240,7 @@ class FileMessagerClient {
239
240
  fileChunk: chunkData,
240
241
  totalChunks,
241
242
  chunkIndex,
243
+ chunkSize,
242
244
  filePath,
243
245
  fileSize
244
246
  });
@@ -256,8 +258,8 @@ class FileMessagerClient {
256
258
  resolve();
257
259
  });
258
260
  },
259
- onProgress: progress => {
260
- this.progressBarManager.updateTaskProgress(fileName, 512 * 1024);
261
+ onProgress: (progress, chunkSize) => {
262
+ this.progressBarManager.updateTaskProgress(fileName, chunkSize);
261
263
  },
262
264
  originDetails: {
263
265
  recipientID: recipientId,
@@ -12,6 +12,9 @@ const {
12
12
  significantMessageColors,
13
13
  errorMessageColors
14
14
  } = require("./HUDManagers/FileNetUtilityManager.js");
15
+ const {
16
+ FileTransferReceiverManager
17
+ } = require("./HUDManagers/FileTransferReceiverManager.js");
15
18
  const {
16
19
  FileNetConfigManager
17
20
  } = require("./HUDManagers/FileNetConfigManager.js");
@@ -236,6 +239,7 @@ function _setupFileEventListeners(userID, client, onTransferProgress, onIncoming
236
239
  onTransferStart,
237
240
  onTransferComplete,
238
241
  onTransferRequested,
242
+ onTransferStatus,
239
243
  onListFiles,
240
244
  onCurrentOnlineClients
241
245
  } = options;
@@ -265,7 +269,7 @@ function _setupFileEventListeners(userID, client, onTransferProgress, onIncoming
265
269
  return content;
266
270
  }
267
271
  });
268
- let activeTransfers = new Map();
272
+ const fileTransferReceiver = new FileTransferReceiverManager();
269
273
  client.clientTide.onEvent(userID, "current-online-clients", data => {
270
274
  const currentClients = {};
271
275
  Object.keys(data).forEach(key => {
@@ -280,7 +284,22 @@ function _setupFileEventListeners(userID, client, onTransferProgress, onIncoming
280
284
  cliTable.setData(currentClients);
281
285
  console.log(`\n[FileTide ~ FileNet]\n\n`, cliTable.render(), "\n");
282
286
  if (onCurrentOnlineClients) {
283
- onCurrentOnlineClients(currentClients);
287
+ onCurrentOnlineClients(currentClients, true);
288
+ }
289
+ });
290
+ client.clientTide.onEvent(userID, "current-clients", data => {
291
+ const currentClients = {};
292
+ Object.keys(data).forEach(key => {
293
+ if (key !== userID) {
294
+ currentClients[key] = data[key];
295
+ }
296
+ });
297
+ if (Object.keys(currentClients).length <= 0) {
298
+ return;
299
+ }
300
+ _FileTide.outputGradient(`\n[FileTide ~ FileNet]\n\n✨ Current Clients >${Object.keys(currentClients).length}< ✨\n`, significantMessageColors);
301
+ if (onCurrentOnlineClients) {
302
+ onCurrentOnlineClients(currentClients, false);
284
303
  }
285
304
  });
286
305
  client.clientTide.onEvent(userID, "queue-incoming-transfer", async data => {
@@ -309,14 +328,10 @@ function _setupFileEventListeners(userID, client, onTransferProgress, onIncoming
309
328
  this.progressBarManager.displayPage("Page Number:", "Press 'n' for next page, 'p' for previous page.", chalk.blue, chalk.magenta);
310
329
  this.progressBarManager.listenForInput("Page Number:", "Press 'n' for next page, 'p' for previous page.", chalk.blue, chalk.magenta, chalk.yellow);
311
330
  });
312
- client.clientTide.onEvent(userID, "incoming-file", data => {
331
+ client.clientTide.onEvent(userID, "incoming-file", async data => {
313
332
  try {
314
333
  _FileTide.outputGradient(`[${userID}] Preparing to receive file : ${data.fileName}`, significantMessageColors);
315
- activeTransfers.set(data.fileName, {
316
- receivedChunks: [],
317
- totalChunks: data.totalChunks,
318
- fileInfo: data
319
- });
334
+ await fileTransferReceiver.initializeTransfer(data);
320
335
  const saveDir = FileUtilityManager.getTidePath(data.path);
321
336
  const verifiedSender = data.senderID && data.senderID !== userID;
322
337
  if (verifiedSender) {
@@ -326,7 +341,7 @@ function _setupFileEventListeners(userID, client, onTransferProgress, onIncoming
326
341
  });
327
342
  }
328
343
  if (onIncomingFile) {
329
- onIncomingFile(verifiedSender, data, activeTransfers);
344
+ onIncomingFile(verifiedSender, data, fileTransferReceiver.activeTransfers);
330
345
  }
331
346
  if (verifiedSender && !fs.existsSync(saveDir)) {
332
347
  fs.mkdirSync(saveDir, {
@@ -350,41 +365,44 @@ function _setupFileEventListeners(userID, client, onTransferProgress, onIncoming
350
365
  onTransferBarrier(data);
351
366
  }
352
367
  });
353
- client.clientTide.onEvent(userID, "transfer-progress", data => {
368
+ client.clientTide.onEvent(userID, "transfer-progress", async data => {
354
369
  if (!data || data.fileChunk === undefined || data.fileChunk === null) {
355
370
  return;
356
371
  }
357
- const transferState = activeTransfers.get(data.fileName);
358
- if (!transferState) {
359
- return;
360
- }
361
- transferState.receivedChunks[data.chunkIndex] = Buffer.from(data.fileChunk);
362
- const progress = (data.chunkIndex + 1) / transferState.totalChunks * 100;
363
- this.progressBarManager.updateTaskProgress(data.fileName, 512 * 1024);
372
+ await fileTransferReceiver.handleTransferProgress(data);
373
+ this.progressBarManager.updateTaskProgress(data.fileName, data.chunkSize || 512 * 1024);
364
374
  if (onTransferProgress) {
365
375
  onTransferProgress(data);
366
376
  }
367
377
  });
378
+ client.clientTide.onEvent(userID, "transfer-status", data => {
379
+ if (onTransferStatus) {
380
+ onTransferStatus(data);
381
+ }
382
+ return;
383
+ });
368
384
  client.clientTide.onEvent(userID, "transfer-complete", data => {
369
385
  const savePath = FileUtilityManager.getTidePath(path.join(data.filePath, data.fileName));
370
386
  try {
371
387
  _FileTide.outputGradient(`[${userID}] File transfer complete : ${data.fileName}`, significantMessageColors);
372
- const transferState = activeTransfers.get(data.fileName);
388
+ const transferState = fileTransferReceiver.activeTransfers.get(data.fileName);
373
389
  if (!transferState) {
374
390
  return;
375
391
  }
376
- const fullFile = Buffer.concat(transferState.receivedChunks);
377
- fs.writeFileSync(savePath, fullFile);
378
- _FileTide.outputGradient(`[${userID}] File saved at : ${savePath}`, significantMessageColors);
379
- activeTransfers.delete(data.fileName);
380
- if (onTransferComplete) {
381
- onTransferComplete(data, activeTransfers, true);
382
- }
392
+ fileTransferReceiver.completeTransfer(data, (transferData, transfers, success) => {
393
+ if (success) {
394
+ _FileTide.outputGradient(`[${userID}] File saved at : ${savePath}\n`, significantMessageColors);
395
+ } else if (!success) {
396
+ _FileTide.outputGradient(`[${userID}] Did not save file at : ${savePath}\n`, errorMessageColors);
397
+ }
398
+ if (onTransferComplete) {
399
+ onTransferComplete(data, fileTransferReceiver.activeTransfers, success);
400
+ }
401
+ });
383
402
  } catch (error) {
384
403
  _FileTide.outputGradient(`[${userID}] Did not save file at : ${savePath}\n${error}`, errorMessageColors);
385
- activeTransfers.delete(data.fileName);
386
404
  if (onTransferComplete) {
387
- onTransferComplete(data, activeTransfers, false);
405
+ onTransferComplete(data, fileTransferReceiver.activeTransfers, false);
388
406
  }
389
407
  }
390
408
  });
@@ -41,7 +41,7 @@ function _startTransfer(file, transferId, fileDetails, onSendChunk, onComplete,
41
41
  const updateProgress = () => {
42
42
  const transferState = this.activeTransfers.get(transferId);
43
43
  if (onProgress) {
44
- onProgress(transferState.completedChunks / transferState.totalChunks * 100);
44
+ onProgress(transferState.completedChunks / transferState.totalChunks * 100, this.chunkSize);
45
45
  }
46
46
  };
47
47
  return new Promise((resolve, reject) => {
@@ -60,7 +60,7 @@ function _startTransfer(file, transferId, fileDetails, onSendChunk, onComplete,
60
60
  });
61
61
  }
62
62
  transferState.activeChunks++;
63
- onSendChunk(transferId, chunkIndex, chunk, transferState.totalChunks).then(() => {
63
+ onSendChunk(transferId, chunkIndex, this.chunkSize, chunk, transferState.totalChunks).then(() => {
64
64
  transferState.completedChunks++;
65
65
  transferState.activeChunks--;
66
66
  updateProgress();
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+
3
+ const fs = require("fs");
4
+ const path = require("path");
5
+ const {
6
+ FileUtilityManager
7
+ } = require("./FileUtilityManager.js");
8
+ class FileTransferReceiverManager {
9
+ constructor() {
10
+ this.activeTransfers = new Map();
11
+ }
12
+ async initializeTransfer(data, onError) {
13
+ const savePath = FileUtilityManager.getTidePath(path.join(data.path || data.filePath, data.fileName));
14
+ if (this.activeTransfers.has(data.fileName)) {
15
+ return;
16
+ }
17
+ const totalChunks = data.totalChunks || Math.ceil(data.fileSize / (data.chunkSize || 512 * 1024));
18
+ const chunkSize = data.chunkSize || 512 * 1024;
19
+ try {
20
+ const dir = path.dirname(savePath);
21
+ if (!fs.existsSync(dir)) {
22
+ fs.mkdirSync(dir, {
23
+ recursive: true
24
+ });
25
+ }
26
+ const fileStream = fs.createWriteStream(savePath, {
27
+ flags: "w"
28
+ });
29
+ this.activeTransfers.set(data.fileName, {
30
+ receivedChunks: new Set(),
31
+ fileInfo: data,
32
+ totalChunks,
33
+ fileStream,
34
+ chunkSize
35
+ });
36
+ } catch (error) {
37
+ if (onError) {
38
+ onError(`[${data.fileName}] Did not initialize transfer ~ ${error.message}`);
39
+ }
40
+ }
41
+ }
42
+ async handleTransferProgress(data, onError) {
43
+ let transferState = this.activeTransfers.get(data.fileName);
44
+ if (!transferState) {
45
+ await this.initializeTransfer(data);
46
+ transferState = this.activeTransfers.get(data.fileName);
47
+ }
48
+ const chunkBuffer = Buffer.from(data.fileChunk);
49
+ try {
50
+ transferState.fileStream.write(chunkBuffer);
51
+ transferState.receivedChunks.add(data.chunkIndex);
52
+ } catch (error) {
53
+ if (onError) {
54
+ onError(`[${data.fileName}] Did not write chunk ${data.chunkIndex} ~ ${error.message}`);
55
+ }
56
+ }
57
+ }
58
+ async completeTransfer(data, onComplete) {
59
+ let transferState = this.activeTransfers.get(data.fileName);
60
+ if (!transferState) {
61
+ await this.initializeTransfer(data);
62
+ transferState = this.activeTransfers.get(data.fileName);
63
+ }
64
+ try {
65
+ if (transferState.receivedChunks.size === transferState.totalChunks) {
66
+ transferState.fileStream.end();
67
+ 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);
70
+ } else {
71
+ throw new Error(`[${data.fileName}] Transfer incomplete. Received ${transferState.receivedChunks.size}/${transferState.totalChunks} chunks.`);
72
+ }
73
+ } catch (error) {
74
+ if (onComplete) {
75
+ onComplete(data, this.activeTransfers, false);
76
+ }
77
+ }
78
+ }
79
+ }
80
+ module.exports = {
81
+ FileTransferReceiverManager
82
+ };
@@ -292,7 +292,7 @@ class FileUtilityManager {
292
292
  for (const file of files) {
293
293
  const stats = await fs.promises.stat(file.path);
294
294
  if (stats.isFile()) {
295
- const fileData = FileUtilityManager.getFileData(file.path);
295
+ const fileData = await FileUtilityManager.getFileData(file.path);
296
296
  if (fileData) {
297
297
  filesData.push(fileData);
298
298
  }
@@ -310,22 +310,33 @@ class FileUtilityManager {
310
310
  * @param {string} inputFilePath - The full path to the file.
311
311
  * @returns {Object|null} - An object containing file data, name, path, and size or null if the file doesn't exist.
312
312
  */
313
- static getFileData(inputFilePath) {
313
+ static async getFileData(inputFilePath) {
314
314
  const filePath = this.getTidePath(inputFilePath);
315
315
  if (!fs.existsSync(filePath)) {
316
316
  console.log(`File at path ${filePath} not found.`);
317
317
  return null;
318
318
  }
319
- const fileData = fs.readFileSync(filePath, {
320
- encoding: null
321
- });
322
319
  const fileName = path.basename(filePath);
323
- return {
324
- size: fileData.length,
325
- fileName,
326
- fileData,
327
- filePath
328
- };
320
+ return new Promise((resolve, reject) => {
321
+ const fileStream = fs.createReadStream(filePath);
322
+ const chunks = [];
323
+ fileStream.on("data", chunk => {
324
+ chunks.push(chunk);
325
+ });
326
+ fileStream.on("end", () => {
327
+ const fileData = Buffer.concat(chunks);
328
+ resolve({
329
+ size: fileData.length,
330
+ fileName,
331
+ fileData,
332
+ filePath
333
+ });
334
+ });
335
+ fileStream.on("error", error => {
336
+ console.error(`Did not read file ${filePath}: `, error);
337
+ resolve(null);
338
+ });
339
+ });
329
340
  }
330
341
 
331
342
  /**
@@ -343,7 +354,7 @@ class FileUtilityManager {
343
354
  const stats = fs.statSync(currentInputPath);
344
355
  if (stats.isFile()) {
345
356
  return {
346
- content: this.getFileData(currentInputPath),
357
+ content: await this.getFileData(currentInputPath),
347
358
  type: "file"
348
359
  };
349
360
  } else if (stats.isDirectory()) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trap_stevo/filetide",
3
- "version": "0.0.37",
3
+ "version": "0.0.39",
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": {