@trap_stevo/filetide 0.0.70 → 0.0.71

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.
@@ -64,6 +64,13 @@ class FileMessager {
64
64
  }
65
65
  onDisconnect(connectionRes, socket) {
66
66
  console.log(`Client disconnected ~ ${socket.id}`);
67
+ const currentOnlineClient = FileNetClientManager.getOnlineClientByConnectionID(socket.id);
68
+ if (currentOnlineClient) {
69
+ this.handleClientOffline({}, {
70
+ connectionID: currentOnlineClient.id,
71
+ ...currentOnlineClient
72
+ });
73
+ }
67
74
  this.onlineClients.delete(socket.id);
68
75
  return;
69
76
  }
@@ -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
  HUDIoTide
5
8
  } = require("@trap_stevo/iotide-client");
@@ -24,8 +27,9 @@ const {
24
27
  const {
25
28
  FileUtilityManager
26
29
  } = require("./HUDManagers/FileUtilityManager");
30
+ var _FileMessagerClient_brand = /*#__PURE__*/new WeakSet();
27
31
  class FileMessagerClient {
28
- constructor(options = {}, transportOptions = {
32
+ constructor(_options = {}, transportOptions = {
29
33
  parallelChunks: 3,
30
34
  maxRetries: 3
31
35
  }, messagerSettings = {
@@ -33,13 +37,14 @@ class FileMessagerClient {
33
37
  reconnectionAttempts: 15,
34
38
  maxReconnectionDelay: 10000
35
39
  }) {
40
+ _classPrivateMethodInitSpec(this, _FileMessagerClient_brand);
36
41
  const {
37
42
  maxReconnectionAttempts = 15,
38
43
  reconnectionAttempts = 15,
39
44
  maxReconnectionDelay = 10000,
40
45
  ...messagerConfigurations
41
46
  } = messagerSettings;
42
- this.clientOptions = FileMessagerConfigManager.getClientOptions(options);
47
+ this.clientOptions = FileMessagerConfigManager.getClientOptions(_options);
43
48
  this.transporter = new FileTransferManager(transportOptions);
44
49
  this.activeTransferTypes = new Map();
45
50
  this.clientTide = new HUDIoTide(maxReconnectionAttempts, reconnectionAttempts, maxReconnectionDelay, {
@@ -49,22 +54,8 @@ class FileMessagerClient {
49
54
  });
50
55
  this.clients = new Map();
51
56
  }
52
- createClientInstance(clientID, clientOptions, options = {}, headers = {}, onConnect = null, onDisconnect = null, authURL = "", authHeaders = {}, useAuthentication = false, queryAuthToken = false) {
53
- this.clientTide.createIO(clientID, clientOptions.url, {
54
- transports: ["websocket"],
55
- ...options
56
- }, headers, authURL, authHeaders, useAuthentication, queryAuthToken, onConnect, async () => {
57
- FileTransferTrackingManager.outputCurrentTransfers();
58
- FileTransferRecoveryManager.flushToDisk();
59
- if (onDisconnect) {
60
- await onDisconnect();
61
- }
62
- });
63
- FileTideDebugUtilityManager.outputGradient(`\n[FileTide ~ File Messager] ~ Created client with ID ${clientID} and socket ${clientID}!`, significantMessageColors);
64
- return clientID;
65
- }
66
57
  joinRoom(userID, roomName, options = {}, headers = {}, onConnect = null, onDisconnect = null, authURL = "", authHeaders = {}, useAuthentication = false, queryAuthToken = false) {
67
- const socketName = this.createClientInstance(userID, {
58
+ const socketName = _assertClassBrand(_FileMessagerClient_brand, this, _createClientInstance).call(this, userID, {
68
59
  url: this.clientOptions.url
69
60
  }, options, headers, onConnect, onDisconnect, authURL, authHeaders, useAuthentication, queryAuthToken);
70
61
  return () => {
@@ -315,5 +306,19 @@ class FileMessagerClient {
315
306
  }
316
307
  }
317
308
  }
309
+ function _createClientInstance(clientID, clientOptions, options = {}, headers = {}, onConnect = null, onDisconnect = null, authURL = "", authHeaders = {}, useAuthentication = false, queryAuthToken = false) {
310
+ this.clientTide.createIO(clientID, clientOptions.url, {
311
+ transports: ["websocket"],
312
+ ...options
313
+ }, headers, authURL, authHeaders, useAuthentication, queryAuthToken, onConnect, async () => {
314
+ FileTransferTrackingManager.outputCurrentTransfers();
315
+ FileTransferRecoveryManager.flushToDisk();
316
+ if (onDisconnect) {
317
+ await onDisconnect();
318
+ }
319
+ });
320
+ FileTideDebugUtilityManager.outputGradient(`\n[FileTide ~ File Messager] ~ Created client with ID ${clientID} and socket ${clientID}!`, significantMessageColors);
321
+ return clientID;
322
+ }
318
323
  ;
319
324
  module.exports = FileMessagerClient;
@@ -11,11 +11,18 @@ const chalk = require("chalk");
11
11
  const path = require("path");
12
12
  const fs = require("fs");
13
13
  const os = require("os");
14
+ require("./HUDComponents/FileTideCommunicationConfigurations.js");
15
+ require("./HUDComponents/FileTideEnvironment.js");
14
16
  const {
15
17
  FileTideDebugUtilityManager,
16
18
  significantMessageColors,
17
19
  errorMessageColors
18
20
  } = require("./HUDManagers/FileTideDebugUtilityManager.js");
21
+ const {
22
+ displayFileTideAuthor,
23
+ displayFileTideTitle,
24
+ displayFileTideLogo
25
+ } = require("./HUDManagers/FileTideUniversalUtilityManager.js");
19
26
  const {
20
27
  FileTransferTrackingManager
21
28
  } = require("./HUDManagers/FileTransferTrackingManager.js");
@@ -23,20 +30,22 @@ const {
23
30
  FileTransferReceiverManager
24
31
  } = require("./HUDManagers/FileTransferReceiverManager.js");
25
32
  const FileTransferRecoveryManager = require("./HUDManagers/FileTransferRecoveryManager.js");
33
+ const TideTokenEnforcer = require("./HUDManagers/TideTokenEnforcementManager.js");
26
34
  const {
27
35
  FileNetConfigManager
28
36
  } = require("./HUDManagers/FileNetConfigManager.js");
29
37
  const {
30
38
  FileUtilityManager
31
39
  } = require("./HUDManagers/FileUtilityManager.js");
32
- const ConsoleProgressBarManager = require("./HUDComponents/ConsoleProgressBarManager");
40
+ const ConsoleProgressBarManager = require("./HUDComponents/ConsoleProgressBarManager.js");
33
41
  const ChunkCapacitor = require("./HUDComponents/ChunkCapacitor.js");
34
42
  const ConsoleTable = require("./HUDComponents/ConsoleTable.js");
35
- const FileMessagerClient = require("./FileMessagerClient");
36
- const FileMessager = require("./FileMessager");
43
+ const FileMessagerClient = require("./FileMessagerClient.js");
44
+ const FileMessager = require("./FileMessager.js");
37
45
  var _FileTide_brand = /*#__PURE__*/new WeakSet();
38
46
  class FileTide {
39
47
  constructor(debugMode = true) {
48
+ // --- FileTide Event Management ---
40
49
  /**
41
50
  * Set up file transfer event listeners natively.
42
51
  * Automatically checks and creates directories as needed.
@@ -60,6 +69,23 @@ class FileTide {
60
69
  return;
61
70
  }
62
71
 
72
+ // --- FileTide TideToken Enforcement Management ---
73
+
74
+ updateTideTokenEnforcementCallbackConfigurations(updatedConfigurations = {}) {
75
+ TideTokenEnforcer.updateTideTokenEnforcementCallbackConfigurations(updatedConfigurations);
76
+ }
77
+ async registerTideToken(tideToken, meta = {}) {
78
+ return await TideTokenEnforcer.seal(tideToken, meta);
79
+ }
80
+ async inspectTideToken(tideToken) {
81
+ return await TideTokenEnforcer.inspect(tideToken);
82
+ }
83
+ getTideToken(scope = "default") {
84
+ return TideTokenEnforcer.getKey(scope);
85
+ }
86
+
87
+ // --- FileTide Gateway Management ---
88
+
63
89
  /**
64
90
  * Initialize and start the server.
65
91
  * @param {Object} serverOptions - Configuration for server (e.g., port, useCors, useHTTPS)
@@ -67,12 +93,14 @@ class FileTide {
67
93
  * @param {...any} tideConfigurations - Additional configuration objects for customizing FileTide behavior
68
94
  */
69
95
  launchFileTide(serverOptions = {}, onLaunch, ...tideConfigurations) {
70
- this.fileNet = new FileMessager(serverOptions, ...tideConfigurations);
71
- this.fileNet.start();
72
- FileTide.outputGradient("[FileTide] ~ FileNet launched successfully!", significantMessageColors);
73
- if (onLaunch) {
74
- onLaunch(this.fileNet);
75
- }
96
+ TideTokenEnforcer.protect(() => {
97
+ this.fileNet = new FileMessager(serverOptions, ...tideConfigurations);
98
+ this.fileNet.start();
99
+ FileTide.outputGradient("[FileTide] ~ FileNet launched successfully!", significantMessageColors);
100
+ if (onLaunch) {
101
+ onLaunch(this.fileNet);
102
+ }
103
+ }, "default")();
76
104
  return;
77
105
  }
78
106
 
@@ -107,39 +135,43 @@ class FileTide {
107
135
  reconnectionAttempts: 15,
108
136
  maxReconnectionDelay: 10000
109
137
  }, roomName, userID, onLaunch, onIncomingFile, onIncomingTransfer, onTransferBarrier, onTransferProgress, enableTransferBarrier = true, options = {}, headers = {}, onConnect = null, onDisconnect = null, authURL = "", authHeaders = {}, useAuthentication = false, queryAuthToken = false) {
110
- if (this.clients.has(userID)) {
111
- this.stopMessager(userID);
112
- }
113
- const currentClientDetails = this.clientDetails.get(userID);
114
- if (currentClientDetails && currentClientDetails.unauthorized) {
115
- const {
116
- onCurrentClientUnauthorized
117
- } = options;
118
- FileTide.outputGradient(`[FileTide ~ FileNet] ~ Unauthorized access detected.`, errorMessageColors);
119
- if (onCurrentClientUnauthorized) {
120
- onCurrentClientUnauthorized({
121
- ...currentClientDetails,
122
- userID
123
- });
138
+ TideTokenEnforcer.protect(() => {
139
+ if (this.clients.has(userID)) {
140
+ this.stopMessager(userID);
124
141
  }
125
- return;
126
- }
127
- const newClient = new FileMessagerClient(clientOptions, transportOptions, messagerSettings);
128
- const enterRoom = newClient.joinRoom(userID, roomName, connectionOptions, headers, onConnect, onDisconnect, authURL, authHeaders, useAuthentication, queryAuthToken);
129
- this.transferBarrier = enableTransferBarrier;
130
- this.clientShorePolicies.set(userID, [FileUtilityManager.getTidePath(">Downloads"), FileUtilityManager.getTidePath(">Documents"), FileUtilityManager.getTidePath(">Desktop"), FileUtilityManager.getTidePath(">Photos"), FileUtilityManager.getTidePath(">Videos"), FileUtilityManager.getTidePath(">Music")]);
131
- this.clients.set(userID, newClient);
132
- this.clientDetails.set(userID, {
133
- unauthorized: false,
134
- userID
135
- });
136
- FileTide.outputGradient(`[FileTide] ~ Messager launched successfully for client ~ ${userID}!`, significantMessageColors);
137
- _assertClassBrand(_FileTide_brand, this, _setupFileEventListeners).call(this, userID, newClient, onTransferProgress, onIncomingTransfer, onIncomingFile, onTransferBarrier, options);
138
- if (onLaunch) {
139
- onLaunch(newClient, enterRoom);
140
- }
142
+ const currentClientDetails = this.clientDetails.get(userID);
143
+ if (currentClientDetails && currentClientDetails.unauthorized) {
144
+ const {
145
+ onCurrentClientUnauthorized
146
+ } = options;
147
+ FileTide.outputGradient(`[FileTide ~ FileNet] ~ Unauthorized access detected.`, errorMessageColors);
148
+ if (onCurrentClientUnauthorized) {
149
+ onCurrentClientUnauthorized({
150
+ ...currentClientDetails,
151
+ userID
152
+ });
153
+ }
154
+ return;
155
+ }
156
+ const newClient = new FileMessagerClient(clientOptions, transportOptions, messagerSettings);
157
+ const enterRoom = newClient.joinRoom(userID, roomName, connectionOptions, headers, onConnect, onDisconnect, authURL, authHeaders, useAuthentication, queryAuthToken);
158
+ this.transferBarrier = enableTransferBarrier;
159
+ this.clientShorePolicies.set(userID, [FileUtilityManager.getTidePath(">Downloads"), FileUtilityManager.getTidePath(">Documents"), FileUtilityManager.getTidePath(">Desktop"), FileUtilityManager.getTidePath(">Photos"), FileUtilityManager.getTidePath(">Videos"), FileUtilityManager.getTidePath(">Music")]);
160
+ this.clients.set(userID, newClient);
161
+ this.clientDetails.set(userID, {
162
+ unauthorized: false,
163
+ userID
164
+ });
165
+ FileTide.outputGradient(`[FileTide] ~ Messager launched successfully for client ~ ${userID}!`, significantMessageColors);
166
+ _assertClassBrand(_FileTide_brand, this, _setupFileEventListeners).call(this, userID, newClient, onTransferProgress, onIncomingTransfer, onIncomingFile, onTransferBarrier, options);
167
+ if (onLaunch) {
168
+ onLaunch(newClient, enterRoom);
169
+ }
170
+ }, "default")();
141
171
  return;
142
172
  }
173
+ // --- FileTide Path Management ---
174
+
143
175
  async getDirectoryData(directoryPath) {
144
176
  return await FileUtilityManager.getDirectoryData(directoryPath);
145
177
  }
@@ -152,12 +184,6 @@ class FileTide {
152
184
  getTidePath(inputPath) {
153
185
  return FileUtilityManager.getTidePath(inputPath);
154
186
  }
155
- getTidingTransferStates() {
156
- return FileTransferRecoveryManager.memoryStorage;
157
- }
158
- saveTransferStates() {
159
- FileTransferRecoveryManager.flushToDisk();
160
- }
161
187
  filterFilesAndDirectories(dirPath, filterContent = [], callback) {
162
188
  FileUtilityManager.filterFilesAndDirectories(dirPath, filterContent, (files, error) => {
163
189
  if (callback) {
@@ -165,46 +191,73 @@ class FileTide {
165
191
  }
166
192
  });
167
193
  }
168
- listFilesFromClient(recipientID, depth = 1) {
169
- const clientID = this.currentUserID;
170
- const clientMessager = this.clients.get(clientID);
171
- if (!clientMessager) {
172
- FileTide.outputGradient(`[FileTide] Client ~ ${clientID} not found.`, errorMessageColors);
173
- return;
174
- }
175
- clientMessager.clientTide.emitEvent(clientID, "check-client-banned", {
176
- clientID,
177
- tideID: clientMessager.clientTide.sockets[clientID].tideID
178
- });
179
- clientMessager.listFiles(clientID, recipientID, depth);
180
- }
181
194
  async listFiles(directories, depth = 1, onDirectory) {
182
195
  return await FileUtilityManager.listFiles(directories, depth, onDirectory);
183
196
  }
184
- clearShorePolicies(clientID, shores = []) {
185
- let clientShorePolicies = this.clientShorePolicies.get(clientID);
186
- if (!shores || shores.length <= 0 || !clientShorePolicies || !clientID) {
187
- FileTide.outputGradient(`[FileTide] Did not clear from client ~ ${clientID} shore policies.`, errorMessageColors);
188
- return false;
189
- }
190
- const shorePolicies = Array.from(clientShorePolicies.values());
191
- const currentShores = new Set(clientShorePolicies);
192
- this.clientShorePolicies.set(clientID, shorePolicies.filter(shorePolicy => !currentShores.has(shorePolicy)));
193
- return true;
197
+
198
+ // --- FileTide Transfer State Management ---
199
+
200
+ async getTidingTransferStates() {
201
+ return await TideTokenEnforcer.protect(() => FileTransferRecoveryManager.memoryStorage, "default")();
194
202
  }
195
- addShorePolicies(clientID, shores = []) {
196
- const clientShorePolicies = this.clientShorePolicies.get(clientID);
197
- if (!shores || shores.length <= 0 || !clientShorePolicies || !clientID) {
198
- FileTide.outputGradient(`[FileTide] Did not add to client ~ ${clientID} shore policies.`, errorMessageColors);
199
- return false;
200
- }
201
- this.clientShorePolicies.set(clientID, [...new Set([...clientShorePolicies, ...shores])]);
202
- return true;
203
+ saveTransferStates() {
204
+ TideTokenEnforcer.protect(() => {
205
+ FileTransferRecoveryManager.flushToDisk();
206
+ }, "default")();
207
+ }
208
+
209
+ // --- FileTide Remote Files Management ---
210
+
211
+ listFilesFromClient(recipientID, depth = 1) {
212
+ TideTokenEnforcer.protect(() => {
213
+ const clientID = this.currentUserID;
214
+ const clientMessager = this.clients.get(clientID);
215
+ if (!clientMessager) {
216
+ FileTide.outputGradient(`[FileTide] Client ~ ${clientID} not found.`, errorMessageColors);
217
+ return;
218
+ }
219
+ clientMessager.clientTide.emitEvent(clientID, "check-client-banned", {
220
+ clientID,
221
+ tideID: clientMessager.clientTide.sockets[clientID].tideID
222
+ });
223
+ clientMessager.listFiles(clientID, recipientID, depth);
224
+ }, "default")();
225
+ }
226
+
227
+ // --- FileTide Shore Policy Management ---
228
+
229
+ async clearShorePolicies(clientID, shores = []) {
230
+ return await TideTokenEnforcer.protect(() => {
231
+ let clientShorePolicies = this.clientShorePolicies.get(clientID);
232
+ if (!shores || shores.length <= 0 || !clientShorePolicies || !clientID) {
233
+ FileTide.outputGradient(`[FileTide] Did not clear from client ~ ${clientID} shore policies.`, errorMessageColors);
234
+ return false;
235
+ }
236
+ const shorePolicies = Array.from(clientShorePolicies.values());
237
+ const currentShores = new Set(clientShorePolicies);
238
+ this.clientShorePolicies.set(clientID, shorePolicies.filter(shorePolicy => !currentShores.has(shorePolicy)));
239
+ return true;
240
+ }, "default")();
241
+ }
242
+ async addShorePolicies(clientID, shores = []) {
243
+ return await TideTokenEnforcer.protect(() => {
244
+ const clientShorePolicies = this.clientShorePolicies.get(clientID);
245
+ if (!shores || shores.length <= 0 || !clientShorePolicies || !clientID) {
246
+ FileTide.outputGradient(`[FileTide] Did not add to client ~ ${clientID} shore policies.`, errorMessageColors);
247
+ return false;
248
+ }
249
+ this.clientShorePolicies.set(clientID, [...new Set([...clientShorePolicies, ...shores])]);
250
+ return true;
251
+ }, "default")();
203
252
  }
204
- getShorePolicies(clientID) {
205
- return this.clientShorePolicies.get(clientID);
253
+ async getShorePolicies(clientID) {
254
+ return await TideTokenEnforcer.protect(() => {
255
+ return this.clientShorePolicies.get(clientID);
256
+ }, "default")();
206
257
  }
207
258
 
259
+ // --- FileTide Transfer Management ---
260
+
208
261
  /**
209
262
  * Send files / directories directly to a device.
210
263
  * @param {String} recipientID - The ID of the client device to send the data to.
@@ -218,73 +271,81 @@ class FileTide {
218
271
  * @param {Number} transferRequestExpirationTime - The maximum time until the transfer barrier times out the transfer request.
219
272
  */
220
273
  async sendToDevice(recipientID, filePath, destinationPath, filterDirectoryContent = [], tideSize = 200, tidalSize = 500, minTideSize = 10, maxTideSize = 2000, transferRequestExpirationTime = 30000) {
221
- const clientID = this.currentUserID;
222
- const clientMessager = this.clients.get(clientID);
223
- if (!clientMessager) {
224
- FileTide.outputGradient(`[FileTide] Client ~ ${clientID} not found.`, errorMessageColors);
225
- return false;
226
- }
227
- clientMessager.clientTide.emitEvent(clientID, "check-client-banned", {
228
- clientID,
229
- tideID: clientMessager.clientTide.sockets[clientID].tideID
230
- });
231
- const recipientOnline = await clientMessager.clientTide.emitEventWithResponse(clientID, "check-client-online", "retrieved-client-online", {
232
- clientID: recipientID
233
- }, 5000);
234
- if (!recipientOnline || !recipientOnline.online) {
235
- FileTide.outputGradient(`[FileTide] ${recipientID} currently not tiding.`, errorMessageColors);
236
- return false;
237
- }
238
- const fileDetails = await this.getPathData(filePath, filterDirectoryContent);
239
- if (!fileDetails) {
240
- FileTide.outputGradient(`[${clientID}] File at path ${filePath} not found.`, errorMessageColors);
241
- return false;
242
- }
243
- if (fileDetails.type === "file") {
244
- if (fileDetails.largeFile) {
245
- FileTide.outputGradient(`[${clientID}] Sending large file ~ ${fileDetails.fileName} to client ~ ${recipientID}...`, significantMessageColors);
246
- await clientMessager.sendFile(clientID, recipientID, fileDetails.fileName, fileDetails.filePath, destinationPath, fileDetails.fileSize, tidalSize, minTideSize, maxTideSize, true, false, true, transferRequestExpirationTime);
274
+ return await TideTokenEnforcer.protect(async () => {
275
+ const clientID = this.currentUserID;
276
+ const clientMessager = this.clients.get(clientID);
277
+ if (!clientMessager) {
278
+ FileTide.outputGradient(`[FileTide] Client ~ ${clientID} not found.`, errorMessageColors);
279
+ return false;
280
+ }
281
+ clientMessager.clientTide.emitEvent(clientID, "check-client-banned", {
282
+ clientID,
283
+ tideID: clientMessager.clientTide.sockets[clientID].tideID
284
+ });
285
+ const recipientOnline = await clientMessager.clientTide.emitEventWithResponse(clientID, "check-client-online", "retrieved-client-online", {
286
+ clientID: recipientID
287
+ }, 5000);
288
+ if (!recipientOnline || !recipientOnline.online) {
289
+ FileTide.outputGradient(`[FileTide] ${recipientID} currently not tiding.`, errorMessageColors);
290
+ return false;
291
+ }
292
+ const fileDetails = await this.getPathData(filePath, filterDirectoryContent);
293
+ if (!fileDetails) {
294
+ FileTide.outputGradient(`[${clientID}] File at path ${filePath} not found.`, errorMessageColors);
295
+ return false;
296
+ }
297
+ if (fileDetails.type === "file") {
298
+ if (fileDetails.largeFile) {
299
+ FileTide.outputGradient(`[${clientID}] Sending large file ~ ${fileDetails.fileName} to client ~ ${recipientID}...`, significantMessageColors);
300
+ await clientMessager.sendFile(clientID, recipientID, fileDetails.fileName, fileDetails.filePath, destinationPath, fileDetails.fileSize, tidalSize, minTideSize, maxTideSize, true, false, true, transferRequestExpirationTime);
301
+ return true;
302
+ }
303
+ FileTide.outputGradient(`[${clientID}] Sending file ~ ${fileDetails.content.fileName} to client ~ ${recipientID}...`, significantMessageColors);
304
+ await clientMessager.sendFile(clientID, recipientID, fileDetails.content.fileName, fileDetails.content.filePath, destinationPath, fileDetails.content.size, tideSize, minTideSize, maxTideSize, transferRequestExpirationTime);
247
305
  return true;
248
306
  }
249
- FileTide.outputGradient(`[${clientID}] Sending file ~ ${fileDetails.content.fileName} to client ~ ${recipientID}...`, significantMessageColors);
250
- await clientMessager.sendFile(clientID, recipientID, fileDetails.content.fileName, fileDetails.content.filePath, destinationPath, fileDetails.content.size, tideSize, minTideSize, maxTideSize, transferRequestExpirationTime);
251
- return true;
252
- }
253
- if (fileDetails.type === "directory") {
254
- FileTide.outputGradient(`[${clientID}] Sending ${fileDetails.content.length} files in directory ~ ${path.basename(filePath)} to client ~ ${recipientID}...`, significantMessageColors);
255
- await clientMessager.sendDirectoryFiles(clientID, recipientID, fileDetails.content, this.getTidePath(filePath), destinationPath, tideSize, minTideSize, maxTideSize, transferRequestExpirationTime);
256
- return true;
257
- }
258
- FileTide.outputGradient(`[FileTide] ~ No active client ~ ${recipientID} found.`, errorMessageColors);
259
- return false;
307
+ if (fileDetails.type === "directory") {
308
+ FileTide.outputGradient(`[${clientID}] Sending ${fileDetails.content.length} files in directory ~ ${path.basename(filePath)} to client ~ ${recipientID}...`, significantMessageColors);
309
+ await clientMessager.sendDirectoryFiles(clientID, recipientID, fileDetails.content, this.getTidePath(filePath), destinationPath, tideSize, minTideSize, maxTideSize, transferRequestExpirationTime);
310
+ return true;
311
+ }
312
+ FileTide.outputGradient(`[FileTide] ~ No active client ~ ${recipientID} found.`, errorMessageColors);
313
+ return false;
314
+ }, "default")();
260
315
  }
261
316
 
317
+ // --- FileTide Operational Status Management ---
318
+
262
319
  /**
263
320
  * Check if running in server mode.
264
- * @returns {Boolean} - True if running as a server
321
+ * @returns {Boolean} - True if server running
265
322
  */
266
- fileTideOperational() {
267
- return this.fileNet !== null;
323
+ async fileTideOperational() {
324
+ return await TideTokenEnforcer.protect(() => this.fileNet !== null, "default")();
268
325
  }
269
326
 
270
327
  /**
271
328
  * Check if running in client mode.
272
- * @returns {Boolean} - True if any client is active
329
+ * @returns {Boolean} - True if any connected clients found
273
330
  */
274
- messagerOperational() {
275
- return this.clients.size > 0;
331
+ async messagerOperational() {
332
+ return await TideTokenEnforcer.protect(() => this.clients.size > 0, "default")();
276
333
  }
277
334
 
335
+ // --- FileTide Cleanup Management ---
336
+
278
337
  /**
279
338
  * Stop the server if running.
280
339
  */
281
340
  stopFileTide() {
282
- if (this.fileNet) {
283
- FileTide.outputGradient("Stopping FileTide...", significantMessageColors);
284
- this.fileNet.close();
285
- this.fileNet = null;
286
- FileTide.outputGradient("Stopped FileTide.", significantMessageColors);
287
- }
341
+ TideTokenEnforcer.protect(() => {
342
+ if (this.fileNet) {
343
+ FileTide.outputGradient("Stopping FileTide...", significantMessageColors);
344
+ this.fileNet.close();
345
+ this.fileNet = null;
346
+ FileTide.outputGradient("Stopped FileTide.", significantMessageColors);
347
+ }
348
+ }, "default")();
288
349
  return;
289
350
  }
290
351
 
@@ -296,33 +357,35 @@ class FileTide {
296
357
  * @param {Function} onCompletion - Executes upon messager disconnection completion
297
358
  */
298
359
  async stopMessager(userID, onBeforeDisconnect, onDisconnect, onCompletion) {
299
- if (this.clients.has(userID)) {
300
- FileTide.outputGradient(`Stopping messager for user ${userID}...`, significantMessageColors);
301
- const connectionOrigin = this.clients.get(userID);
302
- if (typeof onBeforeDisconnect === "function") {
303
- await onBeforeDisconnect(this, userID, connectionOrigin);
304
- }
305
- if (connectionOrigin?.clientTide?.closeSocket) {
306
- const result = connectionOrigin.clientTide.closeSocket(userID);
307
- if (result instanceof Promise) {
308
- try {
309
- await result;
310
- } catch (error) {
311
- FileTide.outputGradient(`Did not disconnect ~ ${userID} ~ ${error.message}`, errorMessageColors);
360
+ TideTokenEnforcer.protect(async () => {
361
+ if (this.clients.has(userID)) {
362
+ FileTide.outputGradient(`Stopping messager for user ${userID}...`, significantMessageColors);
363
+ const connectionOrigin = this.clients.get(userID);
364
+ if (typeof onBeforeDisconnect === "function") {
365
+ await onBeforeDisconnect(this, userID, connectionOrigin);
366
+ }
367
+ if (connectionOrigin?.clientTide?.closeSocket) {
368
+ const result = connectionOrigin.clientTide.closeSocket(userID);
369
+ if (result instanceof Promise) {
370
+ try {
371
+ await result;
372
+ } catch (error) {
373
+ FileTide.outputGradient(`Did not disconnect ~ ${userID} ~ ${error.message}`, errorMessageColors);
374
+ }
375
+ }
376
+ if (typeof onDisconnect === "function") {
377
+ await onDisconnect(this, userID, connectionOrigin);
312
378
  }
313
379
  }
314
- if (typeof onDisconnect === "function") {
315
- await onDisconnect(this, userID, connectionOrigin);
380
+ this.clients.delete(userID);
381
+ FileTide.outputGradient(`Stopped messager for user ${userID}.`, significantMessageColors);
382
+ if (typeof onCompletion === "function") {
383
+ await onCompletion(this, userID, connectionOrigin);
316
384
  }
385
+ return;
317
386
  }
318
- this.clients.delete(userID);
319
- FileTide.outputGradient(`Stopped messager for user ${userID}.`, significantMessageColors);
320
- if (typeof onCompletion === "function") {
321
- await onCompletion(this, userID, connectionOrigin);
322
- }
323
- return;
324
- }
325
- FileTide.outputGradient(`No active messager found for user ${userID}.`, errorMessageColors);
387
+ FileTide.outputGradient(`No active messager found for user ${userID}.`, errorMessageColors);
388
+ }, "default")();
326
389
  return;
327
390
  }
328
391
 
@@ -333,38 +396,52 @@ class FileTide {
333
396
  * @param {Function} onCompletion - Executes upon all messager disconnection
334
397
  */
335
398
  async stopAllMessagers(onBeforeClientDisconnect, onClientDisconnect, onCompletion) {
336
- FileTide.outputGradient("Stopping all messagers...", significantMessageColors);
337
- const disconnectTasks = [];
338
- for (let [userID, connectionOrigin] of this.clients.entries()) {
339
- if (typeof onBeforeClientDisconnect === "function") {
340
- await onBeforeClientDisconnect(this, userID, connectionOrigin);
341
- }
342
- if (connectionOrigin?.clientTide?.closeSocket) {
343
- const task = async () => {
344
- try {
345
- const result = connectionOrigin.clientTide.closeSocket(userID);
346
- if (result instanceof Promise) {
347
- await result;
348
- }
349
- if (typeof onClientDisconnect === "function") {
350
- await onClientDisconnect(this, userID, connectionOrigin);
399
+ TideTokenEnforcer.protect(async () => {
400
+ FileTide.outputGradient("Stopping all messagers...", significantMessageColors);
401
+ const disconnectTasks = [];
402
+ for (let [userID, connectionOrigin] of this.clients.entries()) {
403
+ if (typeof onBeforeClientDisconnect === "function") {
404
+ await onBeforeClientDisconnect(this, userID, connectionOrigin);
405
+ }
406
+ if (connectionOrigin?.clientTide?.closeSocket) {
407
+ const task = async () => {
408
+ try {
409
+ const result = connectionOrigin.clientTide.closeSocket(userID);
410
+ if (result instanceof Promise) {
411
+ await result;
412
+ }
413
+ if (typeof onClientDisconnect === "function") {
414
+ await onClientDisconnect(this, userID, connectionOrigin);
415
+ }
416
+ FileTide.outputGradient(`Disconnected ~ ${userID}`, significantMessageColors);
417
+ } catch (error) {
418
+ FileTide.outputGradient(`Did not disconnect ~ ${userID} - ${error.message}`, errorMessageColors);
351
419
  }
352
- FileTide.outputGradient(`Disconnected ~ ${userID}`, significantMessageColors);
353
- } catch (error) {
354
- FileTide.outputGradient(`Did not disconnect ~ ${userID} - ${error.message}`, errorMessageColors);
355
- }
356
- };
357
- disconnectTasks.push(task());
420
+ };
421
+ disconnectTasks.push(task());
422
+ }
358
423
  }
359
- }
360
- await Promise.all(disconnectTasks);
361
- this.clients.clear();
362
- FileTide.outputGradient("All messagers stopped.", significantMessageColors);
363
- if (typeof onCompletion === "function") {
364
- await onCompletion(this);
365
- }
424
+ await Promise.all(disconnectTasks);
425
+ this.clients.clear();
426
+ FileTide.outputGradient("All messagers stopped.", significantMessageColors);
427
+ if (typeof onCompletion === "function") {
428
+ await onCompletion(this);
429
+ }
430
+ }, "default")();
366
431
  return;
367
432
  }
433
+
434
+ // --- FileTide Display Management ---
435
+
436
+ static displayFileTideLogo() {
437
+ displayFileTideLogo();
438
+ }
439
+ static displayFileTideTitle(cli = false) {
440
+ displayFileTideTitle(cli);
441
+ }
442
+ static displayFileTideAuthor() {
443
+ displayFileTideAuthor();
444
+ }
368
445
  }
369
446
  _FileTide = FileTide;
370
447
  function _setupFileEventListeners(userID, client, onTransferProgress, onIncomingTransfer, onIncomingFile, onTransferBarrier, options = {}) {
@@ -701,7 +778,7 @@ function _setupFileEventListeners(userID, client, onTransferProgress, onIncoming
701
778
  });
702
779
  client.clientTide.onEvent(userID, "list-files", async data => {
703
780
  _FileTide.outputGradient(`[${userID}] Sending file list to ${data.senderID}...!`, significantMessageColors);
704
- const currentClientShorePolicies = this.getShorePolicies(userID);
781
+ const currentClientShorePolicies = await this.getShorePolicies(userID);
705
782
  let totalFilesSent = 0;
706
783
  const listedFiles = await this.listFiles(currentClientShorePolicies || [">Downloads"], data.depth || 1, (totalItems, directoryContents) => {
707
784
  const capacitor = new ChunkCapacitor(directoryContents, 100);
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+
3
+ const LogicTide = require("@trap_stevo/logictide");
4
+
5
+ // ~ Universal FileTide Environment Mode ~
6
+
7
+ const productionMode = true;
8
+ LogicTide.setMode(productionMode ? "production" : "development");
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+
3
+ const LogicTide = require("@trap_stevo/logictide");
4
+
5
+ // ~ Universal FileTide Communication Configurations ~
6
+
7
+ LogicTide.defineLogic("filetide-api-origin-url", "development", () => {
8
+ return "http://localhost:19269";
9
+ });
10
+ LogicTide.defineLogic("filetide-api-origin-url", "production", () => {
11
+ return "https://api.filetide.com";
12
+ });
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+
3
+ const LogicTide = require("@trap_stevo/logictide");
4
+
5
+ // ~ Universal FileTide Environment Mode ~
6
+
7
+ const productionMode = true;
8
+ LogicTide.setMode(productionMode ? "production" : "development");
@@ -33,6 +33,14 @@ class FileNetClientManager {
33
33
  currentOnlineClients.delete(clientID);
34
34
  return currentOnlineClients;
35
35
  }
36
+ static getOnlineClientByConnectionID(connectionID) {
37
+ for (const clientData of currentOnlineClients.values()) {
38
+ if (clientData.id === connectionID) {
39
+ return clientData;
40
+ }
41
+ }
42
+ return null;
43
+ }
36
44
  static getOnlineClient(clientID) {
37
45
  return currentOnlineClients.get(clientID);
38
46
  }
@@ -6,6 +6,7 @@ const {
6
6
  const chalk = require("chalk");
7
7
  const significantMessageColors = ["#00C897", "#00E0FF"];
8
8
  const noticeMessageColors = ["#4A90E2", "#A3D8F4"];
9
+ const infoAccentMessageColors = ["#6B768F", "#8D99AB"];
9
10
  const errorMessageColors = ["#F94144", "#F3722C"];
10
11
  const infoMessageColors = ["#028090", "#56cfe1"];
11
12
  const logHandler = {
@@ -26,14 +27,29 @@ const logHandler = {
26
27
  outputGradient(log + message.join(" "), infoMessageColors);
27
28
  }
28
29
  };
29
- function outputGradient(text, colors) {
30
+ function gradientText(text, colors, options = {
31
+ underline: false
32
+ }) {
30
33
  const gradient = HUDUtilityManager.generateGradientColors(colors, text.length);
31
34
  let coloredText = "";
35
+ const underlineRange = Array.isArray(options.underline) ? options.underline : null;
36
+ const underlineNone = options.underline === false;
37
+ const underlineAll = options.underline === true;
32
38
  for (let i = 0; i < text.length; i++) {
33
39
  const [r, g, b] = gradient[i];
34
- coloredText += chalk.rgb(r, g, b)(text[i]);
40
+ let styledChar = chalk.rgb(r, g, b);
41
+ if (underlineAll || underlineRange && i >= underlineRange[0] && i < underlineRange[1]) {
42
+ styledChar = styledChar.underline;
43
+ }
44
+ coloredText += styledChar(text[i]);
35
45
  }
36
- console.log(coloredText);
46
+ return coloredText;
47
+ }
48
+ ;
49
+ function outputGradient(text, colors, options = {
50
+ underline: false
51
+ }) {
52
+ console.log(gradientText(text, colors, options));
37
53
  return;
38
54
  }
39
55
  ;
@@ -45,13 +61,35 @@ class FileTideDebugUtilityManager {
45
61
  this.debugMode = false;
46
62
  FileTideDebugUtilityManager.instance = this;
47
63
  }
48
- outputGradient(text, colors) {
49
- outputGradient(text, colors);
64
+ outputGradient(text, colors, options = {
65
+ underline: false
66
+ }) {
67
+ outputGradient(text, colors, options);
50
68
  return;
51
69
  }
70
+ gradientText(text, colors, options = {
71
+ underline: false
72
+ }) {
73
+ return gradientText(text, colors, options);
74
+ }
75
+ createHyperlink(text, url) {
76
+ const ESC = "\u001b";
77
+ const BEL = "\u0007";
78
+ return `${ESC}]8;;${url}${BEL}${text}${ESC}]8;;${BEL}`;
79
+ }
52
80
  setDebugMode(mode) {
53
81
  this.debugMode = mode;
54
82
  }
83
+ logLink(displayText, url, prefix = "➜", colors = noticeMessageColors.slice(0)) {
84
+ const styledText = gradientText(displayText, colors, {
85
+ underline: true
86
+ });
87
+ const link = this.createHyperlink(styledText, url);
88
+ const styledPrefix = gradientText(prefix, colors);
89
+ process.stdout.write(`${styledPrefix} `);
90
+ process.stdout.write(link);
91
+ process.stdout.write("\n");
92
+ }
55
93
  log(type = "info", includeDate = false, ...message) {
56
94
  if (!this.debugMode && type !== "error") {
57
95
  return;
@@ -69,5 +107,6 @@ module.exports = {
69
107
  significantMessageColors,
70
108
  noticeMessageColors,
71
109
  errorMessageColors,
110
+ infoAccentMessageColors,
72
111
  infoMessageColors
73
112
  };
@@ -0,0 +1,109 @@
1
+ "use strict";
2
+
3
+ const {
4
+ FileTideDebugUtilityManager
5
+ } = require("./FileTideDebugUtilityManager.js");
6
+ function displayFileTideLogo() {
7
+ FileTideDebugUtilityManager.outputGradient(`
8
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
11
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
12
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
13
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
14
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
15
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
16
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
17
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
18
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
19
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
20
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::::::;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
21
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:;:::::;;;;:::::::;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
22
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::::;+?%%%%%%%?*;::::::::::::;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
23
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;:::;*%%?+;:,,,::+?S?;:::::::::::::::::;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
24
+ ;;;;;;;;;;;;;;;;;;;;;;;;::::;*S?;,,,,::::::,,;SS;:::;+++++++++;;:::::::;;;;;;:::::::;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
25
+ ;;;;;;;;;;;;;;;;;;;;;;;;:::+S%:.,::;::;;+++;::*@+:*SSS%%%%%%%%SS%+:::::::::::::::::::::;::;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
26
+ ;;;;;;;;;;;;;;;;;;;;;;;;;:+#*,,:;;::+?SSSSS#?+SS+SS;:,,,,,,,,,,;S#?;::::::::::::::::::::::::;;;;;;;;;;;;;;;;;;;;;;;;;;;;
27
+ ;;;;;;;;;;;;;;;;;;;;;;;;:;S?.,;;;:;%#%*+;*S##SS%S*,:;;;;;;;;;;;:,+S#%%%%%%%%%%%%%%%%%%%%%?+::::;;;;;;;;;;;;;;;;;;;;;;;;;
28
+ ;;;;;;;;;;;;;;;;;;;;;;;;:?#:,;;;:;S#*;::?#%+++%#*.:;;;;;;;;;;;;;;::;++++++++++++++++++++*?#S+::;;;;;;;;;;;;;;;;;;;;;;;;;
29
+ ;;;;;;;;;;;;;;;;;;;;;;;;;S%,;;;;;%#*;::*#?:::;S#+;+++++++++++++++++++++++++;;;;;;;;;;;;;;;;##;:;;;;;;;;;;;;;;;;;;;;;;;;;
30
+ ;;;;;;;;;;;;;;;;;;;;;;;:;#%:;;;;*#?+::;#S:::::S#*%%SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS?S#;::;;;;;;;;;;;;;;;;;;;;;;;;
31
+ ;;;;;;;;;;;;;;;;;;;;;;;:;S%;+;;;%#*+::+#%:::::S#S?+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+%##;::;;;;;;;;;;;;;;;;;;;;;;;;
32
+ ;;;;;;;;;;;;;;;;;;;;;;;:;SS++;;;%#**::+#?::::;#S:,,:::::::::::::::::::::::::::::::::::::::,+#%::;;;;;;;;;;;;;;;;;;;;;;;;
33
+ ;;;;;;;;;;;;;;;;;;;;;;::;SS?*+;;%#?*;:;#S::::+#?,;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;,S#;:::::;;;;;;;;;;;;;;;;;;;;
34
+ ;;;;;;;;;;;;;;;;;;;;;;;:;S#S*+;;*#%*+::?#*:::+#?,;;;;;;;;;**;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:S#;::::;;;;;;;;;;;;;;;;;;;;;
35
+ ;;;;;;;;;;;;;;;;;;;;;;::;S##?*;;;SS**;::%#*::+#?,;;;;;;;;;++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:S#;::::;;;;;;;;;;;;;;;;;;;;;
36
+ ;;;;;;;;;;;;;;;;;;;;;;::;S##S**;;*#%**;;:?#?:;#?,+++++++++;;+++++++++++++++++++++++++++++++;S#;:::::;;;;;;;;;;;;;;;;;;;;
37
+ ;;;;;;;;;;;;;;;;;;;;;;::;S%?#?*+;;?#%**;;:*#S?#%:*++++++++++++++++++++++++++++++++++++++++*+S#;:::;;;;;;;;;;;;;;;;;;;;;;
38
+ ;;;;;;;;;;;;;;;;;;;;;;::;S%:SS?*+;;?#%**+;;;?##S;******************************************+S#;::::;;;;;;;;;;;;;;;;;;;;;
39
+ ;;;;;;;;;;;;;;;;;;;;;:::;SS,;#S??+;;*#S?*+;;:;?##%?******??%%SSSSSSS%%??********************##;::::::;;;;;;;;;;;;;;;;;;;
40
+ ;;;;;;;;;;;;;;;;;;;;;;::;SS;,;#S??+;;;%#S?*+;;;;?S#S%??%SS?*+;:::::;+*%SSS%%????????????????##;::::::;;;;;;;;;;;;;;;;;;;
41
+ ;;;;;;;;;;;;;;;;;;;;;;::;SS;;,:S#??*+;;+%#S%?*++;;+?##S*;,,,,:::::::,,,,;?##SSSS%%%???????%%##;::::;;;;;;;;;;;;;;;;;;;;;
42
+ ;;;;;;;;;;;;;;;;;;;;;;::;SS*+;:,*#S??*+;;+?S#S%?**?SS+,,::;;;;;::::;;;;::,:?#%**?%SSSSSSSSS%%S;:::;;;;;;;;;;;;;;;;;;;;;;
43
+ ;;;;;;;;;;;;;;;;;;;;;;::;S#%**+;,:?SS%?**+;;+?S###%+,,:;;;;;;+**???**;;;;;:,;%#S*;;;;;;;;;::?S;:::;;;;;;;;;;;;;;;;;;;;;;
44
+ ;;;;;;;;;;;;;;;;;;;;;;::;S##S?*++;::*%SSSSS%%%S%*:,,:;;;;;;*%SS%???%SSS?*+;;:,;%##%?**+++++*S#;:::;;;;;;;;;;;;;;;;;;;;;;
45
+ ;;;;;;;;;;;;;;;;;;;;;;;:;SS;%#%?*++;:::;++**+;:,,:;;;;;;;;%#?+;;;;;;;;*%SS?*+;;::+?%SSSSSSSSS#;:::;;;;;;;;;;;;;;;;;;;;;;
46
+ ;;;;;;;;;;;;;;;;;;;;;;::;SS;:+S#S?**++;;;:::::;;;;;+*+++;*S?+++++++;;;;;;*S#%**+;;:::;;;;;;:*S;:::;;;;;;;;;;;;;;;;;;;;;;
47
+ ;;;;;;;;;;;;;;;;;;;;;;;:;SS*+;;+?SSS%?**+++++++**?%S%+;;?#?*???????**++;;;;*%SS%?**++;;;;;;;%S;:::;;;;;;;;;;;;;;;;;;;;;;
48
+ ;;;;;;;;;;;;;;;;;;;;;;;::?#%?*++;;+*%SSSSS%%%%SSS%?+;;+%#SSSSSSSSSSS%%?**++;;;*%SSSS%%????%%#S;:::;;;;;;;;;;;;;;;;;;;;;;
49
+ ;;;;;;;;;;;;;;;;;;;;;;;;::%#%??**++;;;;+**???**++;;;+?S#S%%???**++*?%SSS%?**+++;;++*?%%%%%%##+:::;;;;;;;;;;;;;;;;;;;;;;;
50
+ ;;;;;;;;;;;;;;;;;;;;;;;;;::*##%???****+++;;;;;;+++*?S#S%??????***+++++*%SSS%??****+++++++*%S+:::;;;;;;;;;;;;;;;;;;;;;;;;
51
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;::;?S#SS%?????******??%%SSS%%%%SSSS%%%%????****?%SSSS%%??????%S#?;::::;;;;;;;;;;;;;;;;;;;;;;;;
52
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;:::;+?%S##SSSSSSSSS#####SSSSS#SS#######SSSSSSSSSSS#######SSS%*;::::;;;;;;;;;;;;;;;;;;;;;;;;;;
53
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::;+++********************************************+++;;::::::;;;;;;;;;;;;;;;;;;;;;;;;;;;
54
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::::::::::::::::::::::::::::::::::::::::::::::::::::::;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
55
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::::::::::::::::::::::::::;;;::::::::::::;;;;;;;;:;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
56
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::::;::::::::::;;:;;;;;;;;;;::;;:::;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
57
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::::::;;;;;:;;;;;;;;;;;;;;;::;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
58
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
59
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
60
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
61
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
62
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
63
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
64
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
65
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
66
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
67
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
68
+ `, ["#0077B6", "#00B4D8"]);
69
+ }
70
+ ;
71
+ function displayFileTideTitle(cli = false) {
72
+ if (cli) {
73
+ FileTideDebugUtilityManager.outputGradient(`
74
+ \t\t _______ ___ ___ _______ _______ ___ ______ _______ _______ ___ ___
75
+ \t\t| || | | | | || || | | | | | | || | | |
76
+ \t\t| ___|| | | | | ___||_ _|| | | _ || ___| | || | | |
77
+ \t\t| |___ | | | | | |___ | | | | | | | || |___ | || | | |
78
+ \t\t| ___|| | | |___ | ___| | | | | | |_| || ___| | _|| |___ | |
79
+ \t\t| | | | | || |___ | | | | | || |___ | |_ | || |
80
+ \t\t|___| |___| |_______||_______| |___| |___| |______| |_______| |_______||_______||___|
81
+ `, ["#028090", "#56cfe1"]);
82
+ return;
83
+ }
84
+ FileTideDebugUtilityManager.outputGradient(`
85
+ \t\t\t\t _______ ___ ___ _______ _______ ___ ______ _______
86
+ \t\t\t\t| || | | | | || || | | | | |
87
+ \t\t\t\t| ___|| | | | | ___||_ _|| | | _ || ___|
88
+ \t\t\t\t| |___ | | | | | |___ | | | | | | | || |___
89
+ \t\t\t\t| ___|| | | |___ | ___| | | | | | |_| || ___|
90
+ \t\t\t\t| | | | | || |___ | | | | | || |___
91
+ \t\t\t\t|___| |___| |_______||_______| |___| |___| |______| |_______|
92
+ `, ["#028090", "#56cfe1"]);
93
+ }
94
+ ;
95
+ function displayFileTideAuthor() {
96
+ FileTideDebugUtilityManager.outputGradient(`
97
+ ▄▄· ▄▄▄ ▄▄▄ . ▄▄▄· ▄▄▄▄▄▄▄▄ .·▄▄▄▄ ▄▄▄▄· ▄· ▄▌ .▄▄ · ▄▄▄▄▄▄▄▄ . ▌ ▐·▄▄▄ . ▐ ▄ ▄▄· • ▌ ▄ ·. ▄▄▄·▄▄▄▄▄ ▐ ▄
98
+ ▐█ ▌▪▀▄ █·▀▄.▀·▐█ ▀█ •██ ▀▄.▀·██▪ ██ ▐█ ▀█▪▐█▪██▌ ▐█ ▀. •██ ▀▄.▀·▪█·█▌▀▄.▀·•█▌▐█ ▐█ ▌▪▪ ·██ ▐███▪▐█ ▄█•██ ▪ •█▌▐█
99
+ ██ ▄▄▐▀▀▄ ▐▀▀▪▄▄█▀▀█ ▐█.▪▐▀▀▪▄▐█· ▐█▌ ▐█▀▀█▄▐█▌▐█▪ ▄▀▀▀█▄ ▐█.▪▐▀▀▪▄▐█▐█•▐▀▀▪▄▐█▐▐▌ ██ ▄▄ ▄█▀▄ ▐█ ▌▐▌▐█· ██▀· ▐█.▪ ▄█▀▄ ▐█▐▐▌
100
+ ▐███▌▐█•█▌▐█▄▄▌▐█ ▪▐▌ ▐█▌·▐█▄▄▌██. ██ ██▄▪▐█ ▐█▀·. ▐█▄▪▐█ ▐█▌·▐█▄▄▌ ███ ▐█▄▄▌██▐█▌ ▐███▌▐█▌.▐▌██ ██▌▐█▌▐█▪·• ▐█▌·▐█▌.▐▌██▐█▌
101
+ ·▀▀▀ .▀ ▀ ▀▀▀ ▀ ▀ ▀▀▀ ▀▀▀ ▀▀▀▀▀• ·▀▀▀▀ ▀ • ▀▀▀▀ ▀▀▀ ▀▀▀ . ▀ ▀▀▀ ▀▀ █▪ ·▀▀▀ ▀█▄▀▪▀▀ █▪▀▀▀.▀ ▀▀▀ ▀█▄▀▪▀▀ █▪
102
+ `, ["#1a73e8", "#a0c4ff"]);
103
+ }
104
+ ;
105
+ module.exports = {
106
+ displayFileTideAuthor,
107
+ displayFileTideTitle,
108
+ displayFileTideLogo
109
+ };
@@ -0,0 +1,149 @@
1
+ "use strict";
2
+
3
+ const LogicTide = require("@trap_stevo/logictide");
4
+ const Lockline = require("@trap_stevo/lockline");
5
+ const axios = require("axios");
6
+ const {
7
+ FileTideDebugUtilityManager,
8
+ significantMessageColors,
9
+ noticeMessageColors,
10
+ infoMessageColors,
11
+ infoAccentMessageColors,
12
+ errorMessageColors
13
+ } = require("./FileTideDebugUtilityManager.js");
14
+ const {
15
+ displayFileTideAuthor,
16
+ displayFileTideTitle,
17
+ displayFileTideLogo
18
+ } = require("./FileTideUniversalUtilityManager.js");
19
+ class TideTokenEnforcementManager {
20
+ constructor(options = {}) {
21
+ const {
22
+ tideTokenEnforcementCallbackConfigurations = {},
23
+ onDidNotLoadRecentTideTokens
24
+ } = options;
25
+ this.tideTokenEnforcementCallbackConfigurations = tideTokenEnforcementCallbackConfigurations;
26
+ this.tideTokenEnforcementComplianceHandlers = this.generateTideTokenEnforcementHandlers();
27
+ this.lock = new Lockline();
28
+ this.lock.setStorage(Lockline.lockbox("./lockbox", {
29
+ namespace: "tide-tokens",
30
+ encrypt: true
31
+ }));
32
+ this.lock.registerValidator("tide-token-authorization", async ({
33
+ key
34
+ }) => {
35
+ const fileTideAPIURL = await LogicTide.run("filetide-api-origin-url");
36
+ const response = await axios.get(`${fileTideAPIURL}/tide-token-auth/authorized-tide-token`, {
37
+ params: {
38
+ inputTideToken: key
39
+ }
40
+ });
41
+ return {
42
+ valid: response.data.authorizedTideToken,
43
+ raw: response.data.details,
44
+ reason: response.data.message
45
+ };
46
+ });
47
+ this.lock.setDefaultValidator("tide-token-authorization");
48
+ this.loadedRecentLicenseKeys = this.lock.loadRecentLicenseKeys().catch(error => {
49
+ if (typeof onDidNotLoadRecentTideTokens === "function") {
50
+ onDidNotLoadRecentTideTokens(error);
51
+ }
52
+ });
53
+ this.enforcerOverviewMetrics = {
54
+ "tide-token-authorized": 0,
55
+ "tide-token-blocked": 0,
56
+ "tide-token-missing": 0,
57
+ "tide-token-invalid": 0
58
+ };
59
+ }
60
+ updateTideTokenEnforcementCallbackConfigurations(updatedConfigurations = {}) {
61
+ this.tideTokenEnforcementCallbackConfigurations = {
62
+ ...this.tideTokenEnforcementCallbackConfigurations,
63
+ ...updatedConfigurations
64
+ };
65
+ this.tideTokenEnforcementComplianceHandlers = this.generateTideTokenEnforcementHandlers();
66
+ }
67
+ generateTideTokenEnforcementHandlers() {
68
+ const {
69
+ onLicenseBlocked,
70
+ onMissingLicense,
71
+ onInvalidLicense,
72
+ onSuccess
73
+ } = this.tideTokenEnforcementCallbackConfigurations;
74
+ const url = "https://filetide.com/tider-portal";
75
+ return {
76
+ onLicenseBlocked: enforcedDetails => {
77
+ FileTideDebugUtilityManager.outputGradient(`[FileTide | ${new Date().toLocaleString()}] ~ ❌ TideToken Blocked\n`, errorMessageColors);
78
+ FileTideDebugUtilityManager.outputGradient(`\t→ Visit ~ ${url} to configure / create TideTokens.\n`, infoAccentMessageColors);
79
+ FileTideDebugUtilityManager.outputGradient(`| ${new Date().toLocaleString()} |`, infoAccentMessageColors);
80
+ FileTideDebugUtilityManager.outputGradient(`${"-".repeat(130)}\n`, infoAccentMessageColors);
81
+ this.enforcerOverviewMetrics["tide-token-blocked"] += 1;
82
+ onLicenseBlocked?.(enforcedDetails);
83
+ },
84
+ onMissingKey: enforcedDetails => {
85
+ displayFileTideLogo();
86
+ displayFileTideTitle();
87
+ FileTideDebugUtilityManager.outputGradient(`[FileTide] ~ Welcome!\n`, significantMessageColors);
88
+ FileTideDebugUtilityManager.outputGradient("\t~ No TideToken(s) Detected\n", significantMessageColors);
89
+ FileTideDebugUtilityManager.outputGradient(`\t→ Visit ~ ${url} to create TideTokens.\n`, infoMessageColors);
90
+ FileTideDebugUtilityManager.outputGradient(`| ${new Date().toLocaleString()} |`, infoAccentMessageColors);
91
+ FileTideDebugUtilityManager.outputGradient(`${"-".repeat(130)}\n`, infoAccentMessageColors);
92
+ this.enforcerOverviewMetrics["tide-token-missing"] += 1;
93
+ onMissingLicense?.(enforcedDetails);
94
+ },
95
+ onInvalidKey: enforcedDetails => {
96
+ FileTideDebugUtilityManager.outputGradient(`[FileTide | ${new Date().toLocaleString()}] ~ ❌ TideToken Unauthorized\n`, errorMessageColors);
97
+ FileTideDebugUtilityManager.outputGradient(`\t→ Visit ~ ${url} to configure / create TideTokens.\n`, infoAccentMessageColors);
98
+ FileTideDebugUtilityManager.outputGradient(`| ${new Date().toLocaleString()} |`, infoAccentMessageColors);
99
+ FileTideDebugUtilityManager.outputGradient(`${"-".repeat(130)}\n`, infoAccentMessageColors);
100
+ this.enforcerOverviewMetrics["tide-token-invalid"] += 1;
101
+ onInvalidLicense?.(enforcedDetails);
102
+ },
103
+ onSuccess: enforcedDetails => {
104
+ FileTideDebugUtilityManager.outputGradient(`[FileTide | ${new Date().toLocaleString()}] ~ ✅ TideToken Authorized\n`, significantMessageColors);
105
+ if (this.enforcerOverviewMetrics["tide-token-authorized"] <= 0) {
106
+ FileTideDebugUtilityManager.outputGradient(`\t→ Configure TideTokens at ${url}\n`, noticeMessageColors);
107
+ }
108
+ FileTideDebugUtilityManager.outputGradient(`| ${new Date().toLocaleString()} |`, infoAccentMessageColors);
109
+ FileTideDebugUtilityManager.outputGradient(`${"-".repeat(130)}\n`, infoAccentMessageColors);
110
+ this.enforcerOverviewMetrics["tide-token-authorized"] += 1;
111
+ onSuccess?.(enforcedDetails);
112
+ }
113
+ };
114
+ }
115
+ protect(handler, scope, options = {}) {
116
+ return async (...args) => {
117
+ await this.loadedRecentLicenseKeys;
118
+ const protectedHandler = this.lock.withLicenseProtection(handler, scope, {
119
+ ...(options ?? {}),
120
+ ...this.tideTokenEnforcementComplianceHandlers
121
+ });
122
+ return await protectedHandler(...args);
123
+ };
124
+ }
125
+ getKey(scope = "default") {
126
+ return this.lock.getCurrentLicenseKey(scope);
127
+ }
128
+ async seal(key, meta = {}) {
129
+ return await this.lock.sealKey(key, {
130
+ validators: [{
131
+ name: "tide-token-authorization"
132
+ }],
133
+ meta
134
+ }, {
135
+ assumePreviouslyValid: true,
136
+ fallbackIfOffline: true,
137
+ autoRemoveExpired: true,
138
+ storeInvalid: true
139
+ });
140
+ }
141
+ async validate(key) {
142
+ return await this.lock.validate(key);
143
+ }
144
+ async inspect(key) {
145
+ return await this.lock.inspectKey(key);
146
+ }
147
+ }
148
+ ;
149
+ module.exports = new TideTokenEnforcementManager();
package/package.json CHANGED
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "@trap_stevo/filetide",
3
- "version": "0.0.70",
3
+ "version": "0.0.71",
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-tide-token-server": "node demos/tideTokenServerDemo.js",
8
9
  "start-file-generation": "node demos/FileGenerator.js",
9
10
  "start-messager": "node demos/FileTideClientDemo.js",
10
11
  "start-net": "node demos/FileTideNetDemo.js",
@@ -37,6 +38,8 @@
37
38
  "@trap_stevo/iotide": "^0.0.44",
38
39
  "@trap_stevo/iotide-client": "^0.0.26",
39
40
  "@trap_stevo/legendarybuilderpronodejs-utilities": "^1.0.49",
41
+ "@trap_stevo/lockline": "^0.0.11",
42
+ "@trap_stevo/logictide": "^0.0.1",
40
43
  "@trap_stevo/metrictide": "^0.0.4",
41
44
  "@trap_stevo/timelyst": "^0.0.6",
42
45
  "chalk": "^4.1.2",