@trap_stevo/filetide 0.0.84 → 0.0.86

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,228 @@
1
+ # SCL-1.0-Universal — Steven Compton Universal License v1.0
2
+ (Source-Available, No Redistribution, No Reverse Engineering)
3
+
4
+ **Effective Date:** September 10, 2024
5
+ **Licensor:** Hassan Steven Compton (Steven Compton) (“Licensor”)
6
+ **Package:** @trap_stevo/filetide (“Package”)
7
+ **Licensee:** Any individual or entity installing, using, referencing, or integrating the “Package”
8
+
9
+ **SPDX Identifier:** SCL-1.0-Universal
10
+
11
+ ---
12
+
13
+ ## 1. Definitions
14
+
15
+ ### **1.1 “Package”**
16
+ Refers to the software identified as @trap_stevo/filetide, including its source code, object code, binaries, compiled outputs, metadata, and documentation.
17
+
18
+ ### **1.2 “Source Code”**
19
+ Human-readable implementation of the “Package”, whether distributed or not.
20
+
21
+ ### **1.3 “Dependent System”**
22
+ Means any system, software, hardware, firmware, service, device, environment, runtime, application, platform, embedded implementation, virtual machine, cloud service, or any other construct that uses, integrates, links to, or depends upon the “Package”, directly or indirectly, without including or exposing the “Package’s” code or internal structure.
23
+
24
+ ### **1.4 “Derivative Work”**
25
+ Any software, product, service, system, or implementation based on or derived from the “Package’s” source code, object code, architecture, structure, behavior, or design, in part or in whole.
26
+
27
+ ---
28
+
29
+ ## 2. Ownership
30
+
31
+ The “Licensor” retains exclusive ownership of all rights, title, and interest in and to the “Package”, including all associated intellectual property.
32
+
33
+ This Agreement transfers no ownership rights to the “Licensee”.
34
+
35
+ ---
36
+
37
+ ## 3. Grant of License
38
+
39
+ Subject to all terms of this Agreement, the “Licensor” grants the “Licensee” a limited, non-exclusive, revocable, non-transferable, and non-sublicensable license to:
40
+
41
+ 1. Use the “Package” as a dependency in “Dependent Systems” created by the “Licensee”.
42
+ 2. Distribute “Dependent Systems”, provided the “Package” is **never** included, exposed, modified, redistributed, or replicated in any form.
43
+
44
+ Nothing in this Agreement grants the “Licensee” permission to:
45
+
46
+ - modify the “Package”
47
+ - redistribute the “Package”
48
+ - fork the “Package”
49
+ - repackage the “Package”
50
+ - host the “Package”
51
+ - analyze the “Package”
52
+ - expose internal behavior of the “Package”
53
+ - create derivative or competing software based on the “Package”
54
+
55
+ ---
56
+
57
+ ## 4. Prohibited Uses
58
+
59
+ Without the express written permission of the “Licensor”, the “Licensee” shall not:
60
+
61
+ 1. Modify, decompile, reverse-engineer, or disassemble the “Package” in any way.
62
+ 2. Include the “Package’s” source code or object code in any distributed software, service, or application.
63
+ 3. Use the “Package” to create a competing product or service that replicates the functionality of the “Package”.
64
+ 4. Make the “Package” publicly available, including uploading it to public repositories or including it in distributed software bundles.
65
+ 5. Attempt to extract or analyze the functionality, structure, or behavior of the “Package” through runtime inspection, instrumentation, reflection, or behavioral analysis.
66
+ 6. Privately share, sublicense, or distribute the “Package” or any portion thereof, whether internally within an organization or externally to any third party, without written authorization.
67
+ 7. Remove, obscure, obfuscate, or alter any attribution, copyright notices, proprietary labels, or identifiers included in the “Package”.
68
+ 8. Re-upload, rename, fork, or redistribute the “Package” or any portion thereof on any registry, platform, or namespace other than that explicitly maintained or authorized by the “Licensor”.
69
+ 9. Use the “Package” in any way that violates applicable laws, infringes on third-party rights, or breaches this Agreement.
70
+
71
+ Any attempt to bypass or circumvent these restrictions constitutes a material breach.
72
+
73
+ ### 4.A. No Competitive Re-implementation
74
+
75
+ “Licensee” shall not create, develop, train, test, benchmark, or distribute any software, system, service, model, or method that uses, incorporates, is derived from, or is based upon the “Package’s” source code, object code, algorithms, data structures, interfaces, protocols, internal behavior, design, architecture, or execution characteristics for the purpose of creating a product or service that provides substantially similar functionality to the “Package”, competes with the “Package”, or reproduces its core operations.
76
+
77
+ “Licensee” shall not directly or indirectly analyze, observe, measure, study, or evaluate the behavior, performance, outputs, or internal characteristics of the “Package” for the purpose of creating, validating, training, improving, or assisting any competing or functionally similar software, system, service, or model.
78
+
79
+ Any such activity shall constitute creation of an unauthorized derivative work and is strictly prohibited.
80
+
81
+ ---
82
+
83
+ ## 5. Dependent System Requirements
84
+
85
+ The “Licensee” may create and distribute “Dependent Systems” only if all of the following conditions are met:
86
+
87
+ 1. The “Dependent System” does **not** include or expose any portion of the “Package’s” source code or object code.
88
+ 2. The “Dependent System” identifies the “Package” as a dependency in its documentation.
89
+ 3. The “Dependent System” provides substantial original functionality.
90
+ 4. The “Dependent System” does not replicate, emulate, reimplement, or mimic any significant part of the “Package’s” behavior or design.
91
+ 5. The “Dependent System” complies fully with this Agreement.
92
+
93
+ ---
94
+
95
+ ## 6. Request for Additional Permissions
96
+
97
+ The “Licensee” may request additional rights by contacting:
98
+
99
+ **h.steven.compton13@gmail.com**
100
+
101
+ Requests must:
102
+
103
+ 1. Be submitted in writing
104
+ 2. Describe purpose, scope, and distribution method
105
+
106
+ The “Licensor” may:
107
+
108
+ - approve or deny at sole discretion
109
+ - impose additional terms
110
+ - revoke previously granted permissions with written notice
111
+
112
+ All permissions must be explicit and in writing.
113
+
114
+ ---
115
+
116
+ ## 7. Violation of Terms (Termination)
117
+
118
+ 1. Any violation of this Agreement results in immediate termination of all licensed rights.
119
+ 2. Upon termination, the “Licensee” must:
120
+ - cease all use of the “Package”
121
+ - remove the “Package” from all systems and environments
122
+ - destroy all copies, including caches and build artifacts
123
+ - confirm destruction in writing if requested
124
+ 3. The “Licensor” may pursue damages, injunctive relief, or any other legal remedy.
125
+
126
+ ---
127
+
128
+ ## 8. No Warranty
129
+
130
+ The “Package” is provided **“AS IS”**, without any warranty, express or implied, including but not limited to merchantability, fitness for a particular purpose, or non-infringement.
131
+
132
+ The “Licensee” assumes all risk associated with use.
133
+
134
+ ---
135
+
136
+ ## 9. Intellectual Property Limitations
137
+
138
+ Nothing in this Agreement grants the “Licensee” any rights under any patent, whether by implication, estoppel, exhaustion, or otherwise. Any use of the “Package” that would require a patent license must receive separate written permission from the “Licensor”.
139
+
140
+ This Agreement also grants no rights to use the “Licensor’s” trademarks, service marks, branding, logos, product names, or organizational names. Any such use requires separate written permission.
141
+
142
+ No patent rights, trademark rights, or branding rights are provided or implied by this license.
143
+
144
+ ---
145
+
146
+ ## 10. Patent Rights and Restrictions
147
+
148
+ ### 10.1 No Implied Patent License
149
+
150
+ Except as expressly stated in this Section, the “Licensor” grants no license, covenant, immunity, or right under any patent or patent application owned, controlled, or licensable by the “Licensor”. All such rights are expressly reserved.
151
+
152
+ ### 10.2 Patent Grant for Non-Competitive Use
153
+
154
+ Subject to full compliance with this Agreement, the “Licensor” grants the “Licensee” a limited, non-exclusive, non-transferable, revocable, royalty-free patent license to use any patent claims embodied in the “Package” solely to the extent necessary to use the unmodified “Package” as permitted under Section 3.
155
+
156
+ This grant does not extend to:
157
+
158
+ - derivative works
159
+
160
+ - competing software
161
+
162
+ - re-implementations
163
+
164
+ - architectural replications
165
+
166
+ - alternative implementations of patented methods
167
+
168
+ - any use not directly involving the unmodified “Package”
169
+
170
+ ### 10.3 Patent Restriction for Competing Systems
171
+
172
+ No patent license is granted for any software, system, service, or model that:
173
+
174
+ - competes with the “Package”,
175
+
176
+ - provides substantially similar core functionality,
177
+
178
+ - implements any patented algorithm, method, design, architecture, or process used by the Package, or
179
+
180
+ - is a re-implementation or functional substitute of the “Package”.
181
+
182
+ Any such use constitutes patent infringement and is prohibited.
183
+
184
+ ### 10.4 Termination of Patent Rights
185
+
186
+ Any violation of this Agreement immediately terminates all patent licenses granted herein. Upon termination, Licensee must cease all uses of the patented subject matter and destroy any implementations utilizing such technology.
187
+
188
+ ---
189
+
190
+ ## 11. Indemnification
191
+
192
+ The “Licensee” agrees to indemnify and hold harmless the “Licensor” from any claims, damages, liabilities, losses, or expenses arising from:
193
+
194
+ - violation of this Agreement
195
+ - misuse of the “Package”
196
+ - unlawful or infringing use
197
+
198
+ ---
199
+
200
+ ## 12. Governing Law & Dispute Resolution
201
+
202
+ This Agreement is governed by the laws of **Georgia, United States**, without regard to conflict-of-law principles.
203
+
204
+ All disputes shall be resolved exclusively through binding arbitration in **Georgia, United States**.
205
+
206
+ ---
207
+
208
+ ## 13. Amendments
209
+
210
+ The “Licensor” may modify this Agreement at any time.
211
+
212
+ Changes take effect 30 days after posting at:
213
+
214
+ **https://www.npmjs.com/package/@trap_stevo/filetide**
215
+
216
+ Continued use of the “Package” constitutes acceptance of the updated terms.
217
+
218
+ ---
219
+
220
+ ## 14. Applicability to All Versions
221
+
222
+ This Agreement applies to **all versions** of the “Package” downloaded, installed, or used on or after the Effective Date.
223
+
224
+ Use of any version after this date constitutes acceptance of this License unless explicitly overridden by the “Licensor”.
225
+
226
+ ---
227
+
228
+ **SPDX-License-Identifier: SCL-1.0-Universal**
@@ -6,6 +6,7 @@ function _assertClassBrand(e, t, n) { if ("function" == typeof e ? e === t : e.h
6
6
  const {
7
7
  HUDIoTide
8
8
  } = require("@trap_stevo/iotide-client");
9
+ const LogicTide = require("@trap_stevo/logictide");
9
10
  const chalk = require("chalk");
10
11
  const path = require("path");
11
12
  const fs = require("fs");
@@ -14,6 +15,9 @@ const {
14
15
  significantMessageColors,
15
16
  errorMessageColors
16
17
  } = require("./HUDManagers/FileTideDebugUtilityManager");
18
+ const {
19
+ STATES: NETWORK_TRAFFIC_STATES
20
+ } = require("./HUDManagers/FileTideNetworkTrafficManager.js");
17
21
  const {
18
22
  FileTransferTrackingManager
19
23
  } = require("./HUDManagers/FileTransferTrackingManager.js");
@@ -41,25 +45,39 @@ class FileMessagerClient {
41
45
  maxReconnectionAttempts = 15,
42
46
  reconnectionAttempts = 15,
43
47
  maxReconnectionDelay = 10000,
48
+ tideDurationMs: _tideDurationMs = 125,
49
+ minTideBytes = 512 * 1024,
50
+ maxTideBytes = 8 * 1024 * 1024,
44
51
  ...messagerConfigurations
45
52
  } = messagerSettings;
46
53
  this.clientOptions = FileMessagerConfigManager.getClientOptions(_options);
47
54
  this.transporter = new FileTransferManager(transportOptions);
55
+ this.tideDurationMs = Math.max(25, _tideDurationMs);
56
+ this.minTideBytes = Math.max(512 * 1024, minTideBytes);
57
+ this.maxTideBytes = Math.max(this.minTideBytes, maxTideBytes);
48
58
  this.activeTransferTypes = new Map();
49
59
  this.clientTide = new HUDIoTide(maxReconnectionAttempts, reconnectionAttempts, maxReconnectionDelay, {
50
60
  persistentTideIDs: true,
51
61
  persistentTideID: true,
52
- ...messagerConfigurations
62
+ ...messagerConfigurations,
63
+ tideIDsPath: LogicTide.runSync("tide-session-ids-path"),
64
+ tideIDPath: LogicTide.runSync("tide-session-id-path")
53
65
  });
54
66
  this.clients = new Map();
55
67
  }
68
+ recordNetworkThroughput(throughputBps) {
69
+ return this.transporter.recordNetworkThroughput(throughputBps);
70
+ }
71
+ getNetworkTrafficStatus() {
72
+ return this.transporter.getNetworkTrafficStatus();
73
+ }
56
74
  joinRoom(userID, roomName, options = {}, headers = {}, onConnect = null, onDisconnect = null, authURL = "", authHeaders = {}, useAuthentication = false, queryAuthToken = false) {
57
75
  const socketName = _assertClassBrand(_FileMessagerClient_brand, this, _createClientInstance).call(this, userID, {
58
76
  url: this.clientOptions.url
59
77
  }, options, headers, onConnect, onDisconnect, authURL, authHeaders, useAuthentication, queryAuthToken);
60
78
  return () => {
61
79
  this.clientTide.joinChannel(socketName, roomName, userID, () => {
62
- FileTideDebugUtilityManager.outputGradient(`\n[FileTide ~ File Messager] ~ Client ~ ${userID} joined room ${roomName} successfully!`, significantMessageColors);
80
+ FileTideDebugUtilityManager.outputGradient(`\n[FileTide ~ Tider] ~ Client ~ ${userID} joined room ${roomName} successfully!`, significantMessageColors);
63
81
  this.clients.set(userID, {
64
82
  roomName
65
83
  });
@@ -108,18 +126,18 @@ class FileMessagerClient {
108
126
  transferType
109
127
  }, transferExpirationTime);
110
128
  if (!transferAccepted) {
111
- FileTideDebugUtilityManager.outputGradient(`[FileTide ~ File Messager] ${recipientID} denied your transfer.`, errorMessageColors);
129
+ FileTideDebugUtilityManager.outputGradient(`[FileTide ~ Tider] ${recipientID} denied your transfer.`, errorMessageColors);
112
130
  return false;
113
131
  } else if (transferAccepted) {
114
- FileTideDebugUtilityManager.outputGradient(`[FileTide ~ File Messager] ${recipientID} accepted your transfer!`, significantMessageColors);
132
+ FileTideDebugUtilityManager.outputGradient(`[FileTide ~ Tider] ${recipientID} accepted your transfer!`, significantMessageColors);
115
133
  return true;
116
134
  }
117
135
  } catch (error) {
118
136
  if (error.message.startsWith("Timeout: No response")) {
119
- FileTideDebugUtilityManager.outputGradient("[FileTide ~ File Messager] Transfer approval timed out.", errorMessageColors);
137
+ FileTideDebugUtilityManager.outputGradient("[FileTide ~ Tider] Transfer approval timed out.", errorMessageColors);
120
138
  return false;
121
139
  }
122
- FileTideDebugUtilityManager.outputGradient(`[FileTide ~ File Messager] Transfer approval refused.\n${error}`, errorMessageColors);
140
+ FileTideDebugUtilityManager.outputGradient(`[FileTide ~ Tider] Transfer approval refused.\n${error}`, errorMessageColors);
123
141
  return false;
124
142
  }
125
143
  }
@@ -163,7 +181,7 @@ class FileMessagerClient {
163
181
  });
164
182
  Promise.all(sendFilePromises).then(() => console.log("\nAll files in directory transferred successfully!")).catch(error => console.error("Did not transfer directory: ", error));
165
183
  } catch (error) {
166
- FileTideDebugUtilityManager.outputGradient(`[FileTide ~ File Messager] ~ Refused directory transfer: ${error}`, errorMessageColors);
184
+ FileTideDebugUtilityManager.outputGradient(`[FileTide ~ Tider] ~ Refused directory transfer: ${error}`, errorMessageColors);
167
185
  }
168
186
  }
169
187
  async sendDirectoryLargeFile(clientID, recipientId, fileName, filePath = process.cwd(), destinationPath = null, fileSize, index = 0, tideSize = 500, minTideSize = 10, maxTideSize = 2000, transferRequestExpirationTime = 30000, metadata = {}) {
@@ -193,7 +211,7 @@ class FileMessagerClient {
193
211
  }
194
212
  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, metadata = {}) {
195
213
  const destinationPath = FileUtilityManager.normalizePath(path.join(destination, fileName));
196
- FileTideDebugUtilityManager.outputGradient(largeFile ? `[FileTide ~ File Messager] ~ Requesting to transfer large file ~ ${destinationPath} to ${recipientId}!` : `[FileTide ~ File Messager] ~ Requesting to transfer ~ ${destinationPath} to ${recipientId}!`, significantMessageColors);
214
+ FileTideDebugUtilityManager.outputGradient(largeFile ? `[FileTide ~ Tider] ~ Requesting to transfer large file ~ ${destinationPath} to ${recipientId}!` : `[FileTide ~ Tider] ~ Requesting to transfer ~ ${destinationPath} to ${recipientId}!`, significantMessageColors);
197
215
  const incomingType = this.activeTransferTypes.get(filePath);
198
216
  if (!inDirectory && initiatingTransfer) {
199
217
  const transferAllowed = incomingType && incomingType === "requestedTransfer" ? true : await this.allowedTransfer(clientID, recipientId, destinationPath, filePath, fileSize, 1, "file", "send", transferRequestExpirationTime);
@@ -224,12 +242,39 @@ class FileMessagerClient {
224
242
  size: fileSize
225
243
  };
226
244
  try {
227
- let lastSendTime = Date.now();
228
- const maxBatchSize = maxTideSize;
229
- const minBatchSize = minTideSize;
230
- let batchSize = tideSize > maxBatchSize || tideSize > minBatchSize ? tideSize : tideSize <= minBatchSize ? minBatchSize : 10;
231
245
  let transferInitiated = false;
232
- const chunkBatch = [];
246
+ const currentTide = [];
247
+ const flushTide = () => {
248
+ if (currentTide.length <= 0) {
249
+ return;
250
+ }
251
+ const outgoingChunks = currentTide.splice(0, currentTide.length);
252
+ const firstChunk = outgoingChunks[0];
253
+ const lastChunk = outgoingChunks[outgoingChunks.length - 1];
254
+ const tideBytes = outgoingChunks.reduce((total, chunk) => total + chunk.chunkSize, 0);
255
+ this.clientTide.emitEvent(clientID, "client-to-client-transfer", {
256
+ tide: {
257
+ transferId: firstChunk.transferId,
258
+ senderID: firstChunk.senderID,
259
+ recipientId: firstChunk.recipientId,
260
+ fileName: firstChunk.fileName,
261
+ filePath: firstChunk.filePath,
262
+ fileSize: firstChunk.fileSize,
263
+ totalChunks: firstChunk.totalChunks,
264
+ firstChunkIndex: firstChunk.chunkIndex,
265
+ lastChunkIndex: lastChunk.chunkIndex,
266
+ completedChunks: lastChunk.completedChunks,
267
+ tideChunkCount: outgoingChunks.length,
268
+ tideBytes,
269
+ chunks: outgoingChunks.map(chunk => ({
270
+ chunkIndex: chunk.chunkIndex,
271
+ chunkSize: chunk.chunkSize,
272
+ fileChunk: chunk.fileChunk
273
+ })),
274
+ metadata: firstChunk.metadata
275
+ }
276
+ });
277
+ };
233
278
  await this.transporter.sendLargeFile(fileHandle, {
234
279
  recipientID: recipientId,
235
280
  originDetails: {
@@ -237,61 +282,48 @@ class FileMessagerClient {
237
282
  senderID: clientID
238
283
  },
239
284
  fileDetails,
240
- onSendChunk: (transferId, chunkIndex, chunkSize, chunkData, totalChunks, completedChunks) => {
241
- return new Promise(resolve => {
242
- chunkBatch.push({
243
- senderID: clientID,
244
- recipientId,
245
- fileName,
246
- fileChunk: chunkData,
247
- completedChunks,
248
- totalChunks,
249
- chunkIndex,
250
- chunkSize,
251
- filePath: destination,
252
- fileSize,
253
- metadata
254
- });
255
- if (!transferInitiated) {
256
- this.clientTide.emitEvent(clientID, "client-to-client-transfer", {
257
- chunkBatch
258
- });
259
- transferInitiated = true;
260
- chunkBatch.length = 0;
261
- }
262
- if (chunkBatch.length >= batchSize) {
263
- const now = Date.now();
264
- const rtt = now - lastSendTime;
265
- lastSendTime = now;
266
- this.clientTide.emitEvent(clientID, "client-to-client-transfer", {
267
- chunkBatch
268
- });
269
- chunkBatch.length = 0;
270
- if (rtt >= 200 && batchSize < maxBatchSize) {
271
- batchSize = Math.min(batchSize + 50, maxBatchSize);
272
- } else if (rtt < 200 && batchSize > minBatchSize) {
273
- batchSize = Math.max(batchSize - 50, minBatchSize);
274
- }
275
- }
276
- resolve();
285
+ onSendChunk: async (transferId, chunkIndex, chunkSize, chunkData, totalChunks, completedChunks) => {
286
+ currentTide.push({
287
+ transferId,
288
+ senderID: clientID,
289
+ recipientId,
290
+ fileName,
291
+ fileChunk: chunkData,
292
+ completedChunks,
293
+ totalChunks,
294
+ chunkIndex,
295
+ chunkSize,
296
+ filePath: destination,
297
+ fileSize,
298
+ metadata
277
299
  });
300
+ if (!transferInitiated) {
301
+ flushTide();
302
+ transferInitiated = true;
303
+ return;
304
+ }
305
+ const adaptiveTideSize = _assertClassBrand(_FileMessagerClient_brand, this, _getAdaptiveTideSize).call(this, chunkSize, tideSize, minTideSize, maxTideSize);
306
+ if (currentTide.length >= adaptiveTideSize) {
307
+ flushTide();
308
+ }
309
+ },
310
+ onComplete: async () => {
311
+ flushTide();
278
312
  },
279
- onComplete: transferId => {
280
- return new Promise(resolve => {
281
- if (chunkBatch.length > 0) {
282
- this.clientTide.emitEvent(clientID, "client-to-client-transfer", {
283
- chunkBatch
284
- });
285
- chunkBatch.length = 0;
286
- }
287
- this.clientTide.emitEvent(clientID, "transfer-complete", {
288
- senderID: clientID,
289
- recipientId,
290
- fileName,
291
- filePath: destination,
292
- metadata
293
- });
294
- resolve();
313
+ onFailure: async (transferId, error) => {
314
+ /*
315
+ * Do not flush an unfinished Tide after
316
+ * the transfer has already failed.
317
+ */
318
+ currentTide.length = 0;
319
+ this.clientTide.emitEvent(clientID, "transfer-failed", {
320
+ transferId,
321
+ senderID: clientID,
322
+ recipientId,
323
+ fileName,
324
+ filePath: destination,
325
+ reason: error.message,
326
+ metadata
295
327
  });
296
328
  },
297
329
  onTiding: () => {
@@ -301,9 +333,10 @@ class FileMessagerClient {
301
333
  });
302
334
  }
303
335
  }, this.clientTide);
304
- FileTideDebugUtilityManager.outputGradient(largeFile ? `[FileTide ~ File Messager] ~ Large file ~ ${fileName} transfer complete!` : `[FileTide ~ File Messager] ~ File ~ ${fileName} transfer complete!`, significantMessageColors);
336
+ FileTideDebugUtilityManager.outputGradient(largeFile ? `[FileTide ~ Tider] ~ Large file ~ ${fileName} transfer complete!` : `[FileTide ~ Tider] ~ File ~ ${fileName} transfer complete!`, significantMessageColors);
305
337
  } catch (error) {
306
- FileTideDebugUtilityManager.outputGradient(largeFile ? `[FileTide ~ File Messager] ~ Error transferring large file: ${error.message}` : `[FileTide ~ File Messager] ~ Error transferring file ~ ${error.message}`, errorMessageColors);
338
+ FileTideDebugUtilityManager.outputGradient(largeFile ? `[FileTide ~ Tider] ~ Error transferring large file: ${error.message}` : `[FileTide ~ Tider] ~ Error transferring file ~ ${error.message}`, errorMessageColors);
339
+ throw error;
307
340
  } finally {
308
341
  await fileHandle.close();
309
342
  }
@@ -313,14 +346,48 @@ function _createClientInstance(clientID, clientOptions, options = {}, headers =
313
346
  this.clientTide.createIO(clientID, clientOptions.url, {
314
347
  transports: ["websocket"],
315
348
  ...options
316
- }, headers, authURL, authHeaders, useAuthentication, queryAuthToken, onConnect, async () => {
349
+ }, headers, authURL, authHeaders, useAuthentication, queryAuthToken, (...connectionArguments) => {
350
+ this.transporter.updateNetworkTraffic({
351
+ online: true,
352
+ success: true
353
+ });
354
+ if (onConnect) {
355
+ return onConnect(...connectionArguments);
356
+ }
357
+ }, async (...disconnectArguments) => {
358
+ this.transporter.updateNetworkTraffic({
359
+ online: false
360
+ });
317
361
  FileTransferTrackingManager.outputCurrentTransfers();
318
362
  if (onDisconnect) {
319
- await onDisconnect();
363
+ await onDisconnect(...disconnectArguments);
320
364
  }
321
365
  });
322
- FileTideDebugUtilityManager.outputGradient(`\n[FileTide ~ File Messager] ~ Created client with ID ${clientID} and socket ${clientID}!`, significantMessageColors);
366
+ FileTideDebugUtilityManager.outputGradient(`\n[FileTide ~ Tider] ~ Created client with ID ${clientID} and socket ${clientID}!`, significantMessageColors);
323
367
  return clientID;
324
368
  }
369
+ function _getAdaptiveTideSize(chunkSize, tideSize = 500, minTideSize = 10, maxTideSize = 2000) {
370
+ const networkStatus = this.transporter.getNetworkTrafficStatus();
371
+ const sendRateBps = Math.max(networkStatus.sendRateBps || chunkSize, chunkSize);
372
+ let tideDurationMs = this.tideDurationMs;
373
+ if (networkStatus.state === NETWORK_TRAFFIC_STATES.CONGESTED) {
374
+ tideDurationMs *= 0.50;
375
+ }
376
+
377
+ /*
378
+ * Determine how many chunks current network conditions
379
+ * can reasonably support during one Tide duration.
380
+ */
381
+ const networkTideBytes = Math.max(sendRateBps * (tideDurationMs / 1000), chunkSize);
382
+ const networkTideSize = Math.max(1, Math.floor(networkTideBytes / chunkSize));
383
+ const normalizedMinTideSize = Math.max(1, minTideSize);
384
+ const normalizedMaxTideSize = Math.max(normalizedMinTideSize, maxTideSize);
385
+ const preferredTideSize = Math.min(Math.max(tideSize, normalizedMinTideSize), normalizedMaxTideSize);
386
+ const adaptiveTideSize = Math.min(networkTideSize, preferredTideSize);
387
+ const minTideChunkSize = Math.max(1, Math.floor(this.minTideBytes / chunkSize));
388
+ const maxTideChunkSize = Math.max(1, Math.floor(this.maxTideBytes / chunkSize));
389
+ const optimizedTideSize = adaptiveTideSize >= minTideChunkSize ? adaptiveTideSize : Math.min(networkTideSize, preferredTideSize);
390
+ return Math.max(1, Math.min(optimizedTideSize, maxTideChunkSize, normalizedMaxTideSize));
391
+ }
325
392
  ;
326
393
  module.exports = FileMessagerClient;