topsyde-utils 1.0.149 → 1.0.151
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.
- package/dist/application.js.map +1 -1
- package/dist/client/rxjs/index.js.map +1 -1
- package/dist/client/rxjs/rxjs.js.map +1 -1
- package/dist/client/rxjs/useRxjs.js.map +1 -1
- package/dist/client/vite/plugins/index.js.map +1 -1
- package/dist/client/vite/plugins/topsydeUtilsVitePlugin.js.map +1 -1
- package/dist/consts.js.map +1 -1
- package/dist/enums.js.map +1 -1
- package/dist/errors.js.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/initializable.js.map +1 -1
- package/dist/server/bun/index.js.map +1 -1
- package/dist/server/bun/router/controller-discovery.js.map +1 -1
- package/dist/server/bun/router/index.js.map +1 -1
- package/dist/server/bun/router/router.internal.js.map +1 -1
- package/dist/server/bun/router/router.js.map +1 -1
- package/dist/server/bun/router/routes.js.map +1 -1
- package/dist/server/bun/websocket/Channel.js.map +1 -1
- package/dist/server/bun/websocket/Client.js.map +1 -1
- package/dist/server/bun/websocket/Message.js.map +1 -1
- package/dist/server/bun/websocket/Websocket.js.map +1 -1
- package/dist/server/bun/websocket/index.js.map +1 -1
- package/dist/server/bun/websocket/websocket.enums.js.map +1 -1
- package/dist/server/bun/websocket/websocket.guards.js.map +1 -1
- package/dist/server/bun/websocket/websocket.types.js.map +1 -1
- package/dist/server/controller.js.map +1 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/service.js.map +1 -1
- package/dist/singleton.js.map +1 -1
- package/dist/throwable.js.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utils/Console.js.map +1 -1
- package/dist/utils/Guards.js.map +1 -1
- package/dist/utils/Lib.js.map +1 -1
- package/dist/utils/index.js.map +1 -1
- package/package.json +4 -3
- package/src/__tests__/app.test.ts +205 -0
- package/src/__tests__/singleton.test.ts +402 -0
- package/src/__tests__/type-inference.test.ts +60 -0
- package/src/application.ts +43 -0
- package/src/client/rxjs/index.ts +5 -0
- package/src/client/rxjs/rxjs.ts +122 -0
- package/src/client/rxjs/useRxjs.ts +111 -0
- package/src/client/vite/plugins/index.ts +5 -0
- package/src/client/vite/plugins/topsydeUtilsVitePlugin.ts +80 -0
- package/src/consts.ts +48 -0
- package/src/enums.ts +14 -0
- package/src/errors.ts +56 -0
- package/src/index.ts +81 -0
- package/src/initializable.ts +375 -0
- package/src/server/bun/index.ts +6 -0
- package/src/server/bun/router/controller-discovery.ts +94 -0
- package/src/server/bun/router/index.ts +9 -0
- package/src/server/bun/router/router.internal.ts +64 -0
- package/src/server/bun/router/router.ts +51 -0
- package/src/server/bun/router/routes.ts +7 -0
- package/src/server/bun/websocket/Channel.ts +157 -0
- package/src/server/bun/websocket/Client.ts +129 -0
- package/src/server/bun/websocket/Message.ts +106 -0
- package/src/server/bun/websocket/Websocket.ts +221 -0
- package/src/server/bun/websocket/index.ts +14 -0
- package/src/server/bun/websocket/websocket.enums.ts +22 -0
- package/src/server/bun/websocket/websocket.guards.ts +6 -0
- package/src/server/bun/websocket/websocket.types.ts +186 -0
- package/src/server/controller.ts +121 -0
- package/src/server/index.ts +7 -0
- package/src/server/service.ts +36 -0
- package/src/singleton.ts +28 -0
- package/src/throwable.ts +87 -0
- package/src/types.ts +10 -0
- package/src/utils/Console.ts +85 -0
- package/src/utils/Guards.ts +61 -0
- package/src/utils/Lib.ts +506 -0
- package/src/utils/index.ts +9 -0
package/src/utils/Lib.ts
ADDED
@@ -0,0 +1,506 @@
|
|
1
|
+
import * as fs from "fs";
|
2
|
+
import * as path from "path";
|
3
|
+
import { E_IS } from "../enums";
|
4
|
+
import Throwable from "../throwable";
|
5
|
+
|
6
|
+
class Lib {
|
7
|
+
public static Log(...args: any) {
|
8
|
+
const timestamp = new Date().toLocaleTimeString();
|
9
|
+
console.log(`[${timestamp}]:`, ...args);
|
10
|
+
}
|
11
|
+
|
12
|
+
public static LogObject(object: any, text?: string) {
|
13
|
+
const timestamp = new Date().toLocaleTimeString();
|
14
|
+
console.log(`[${timestamp}]:`, text ?? "", JSON.stringify(object, null, 2));
|
15
|
+
}
|
16
|
+
|
17
|
+
public static Warn(...args: any) {
|
18
|
+
const timestamp = new Date().toLocaleTimeString();
|
19
|
+
console.error(`[${timestamp}] Handled Error: `, ...args);
|
20
|
+
}
|
21
|
+
|
22
|
+
public static $Log(...args: any) {
|
23
|
+
const timestamp = new Date().toLocaleTimeString();
|
24
|
+
console.error(`[${timestamp}]`, ...args);
|
25
|
+
}
|
26
|
+
|
27
|
+
public static secondsToMilliseconds(seconds: number): number {
|
28
|
+
return seconds * 1000;
|
29
|
+
}
|
30
|
+
|
31
|
+
public static minutesToMilliseconds(minutes: number): number {
|
32
|
+
return minutes * 60 * 1000;
|
33
|
+
}
|
34
|
+
|
35
|
+
public static hoursToMilliseconds(hours: number): number {
|
36
|
+
return hours * 60 * 60 * 1000;
|
37
|
+
}
|
38
|
+
|
39
|
+
public static GetTimestamp(milliseconds_ago: number) {
|
40
|
+
const now = new Date();
|
41
|
+
return new Date(now.getTime() - milliseconds_ago);
|
42
|
+
}
|
43
|
+
|
44
|
+
public static GetDateTimestamp(date: string | Date, format = "DD/MM/YYYY HH:mm", isUTC = false): number {
|
45
|
+
if (typeof date === "string") {
|
46
|
+
const formatParts = format.split(/[-\/. :]/);
|
47
|
+
const dateParts = date.split(/[-\/. :]/);
|
48
|
+
|
49
|
+
let day: number | undefined;
|
50
|
+
let month: number | undefined;
|
51
|
+
let year: number | undefined;
|
52
|
+
let hours = 0;
|
53
|
+
let minutes = 0;
|
54
|
+
|
55
|
+
formatParts.forEach((part, index) => {
|
56
|
+
switch (part) {
|
57
|
+
case "DD":
|
58
|
+
case "dd":
|
59
|
+
day = parseInt(dateParts[index], 10);
|
60
|
+
break;
|
61
|
+
case "MM":
|
62
|
+
month = parseInt(dateParts[index], 10) - 1; // Months are 0-based in JavaScript Date
|
63
|
+
break;
|
64
|
+
case "YYYY":
|
65
|
+
case "yyyy":
|
66
|
+
year = parseInt(dateParts[index], 10);
|
67
|
+
break;
|
68
|
+
case "HH":
|
69
|
+
case "hh":
|
70
|
+
hours = parseInt(dateParts[index], 10);
|
71
|
+
break;
|
72
|
+
case "mm":
|
73
|
+
minutes = parseInt(dateParts[index], 10);
|
74
|
+
break;
|
75
|
+
}
|
76
|
+
});
|
77
|
+
|
78
|
+
if (day === undefined || month === undefined || year === undefined) {
|
79
|
+
throw new Error("Invalid date format or date string");
|
80
|
+
}
|
81
|
+
|
82
|
+
let dateObj;
|
83
|
+
if (isUTC) {
|
84
|
+
dateObj = new Date(Date.UTC(year, month, day, hours, minutes));
|
85
|
+
} else {
|
86
|
+
dateObj = new Date(year, month, day, hours, minutes);
|
87
|
+
}
|
88
|
+
return dateObj.getTime();
|
89
|
+
} else {
|
90
|
+
return date.getTime();
|
91
|
+
}
|
92
|
+
}
|
93
|
+
|
94
|
+
public static calculatePercentage(x: number, y: number): number {
|
95
|
+
if (y === 0) {
|
96
|
+
throw new Error("The denominator (y) cannot be zero.");
|
97
|
+
}
|
98
|
+
return x / y;
|
99
|
+
}
|
100
|
+
|
101
|
+
public static MYSQLTimestamp(): string {
|
102
|
+
const now = new Date();
|
103
|
+
const year = now.getFullYear();
|
104
|
+
const month = now.getMonth() + 1;
|
105
|
+
const day = now.getDate();
|
106
|
+
const hours = now.getHours();
|
107
|
+
const minutes = now.getMinutes();
|
108
|
+
const seconds = now.getSeconds();
|
109
|
+
|
110
|
+
const formattedDate = `${year}-${month.toString().padStart(2, "0")}-${day.toString().padStart(2, "0")}`;
|
111
|
+
const formattedTime = `${hours.toString().padStart(2, "0")}:${minutes.toString().padStart(2, "0")}:${seconds.toString().padStart(2, "0")}`;
|
112
|
+
|
113
|
+
return `${formattedDate} ${formattedTime}`;
|
114
|
+
}
|
115
|
+
|
116
|
+
public static FormatUnixToDate(unix_time_stamp: number, in_milliseconds = false): Date {
|
117
|
+
const date = new Date(unix_time_stamp * (in_milliseconds ? 1 : 1000));
|
118
|
+
return date;
|
119
|
+
}
|
120
|
+
|
121
|
+
public static FormatDate(date: Date | string, format = "MM/dd/yyyy"): string {
|
122
|
+
try {
|
123
|
+
const leadingZero = (value: number) => (value < 10 ? `0${value}` : `${value}`);
|
124
|
+
if (!date) throw new Error("Lib.FormatDate() Exception: Date is required");
|
125
|
+
if (typeof date === "string") {
|
126
|
+
date = new Date(date);
|
127
|
+
}
|
128
|
+
const day = leadingZero(date.getDate());
|
129
|
+
const month = leadingZero(date.getMonth() + 1);
|
130
|
+
const year = date.getFullYear();
|
131
|
+
const hours = leadingZero(date.getHours());
|
132
|
+
const minutes = leadingZero(date.getMinutes());
|
133
|
+
const seconds = leadingZero(date.getSeconds());
|
134
|
+
|
135
|
+
let result = format
|
136
|
+
.replace(/DD|dd/g, day)
|
137
|
+
.replace(/MM/g, month)
|
138
|
+
.replace(/yyyy|YYYY/g, year.toString());
|
139
|
+
|
140
|
+
if (format.includes("HH")) {
|
141
|
+
result = result.replace(/HH/g, hours);
|
142
|
+
}
|
143
|
+
if (format.toLowerCase().includes("mm")) {
|
144
|
+
result = result.replace(/mm/g, minutes);
|
145
|
+
}
|
146
|
+
if (format.includes("ss")) {
|
147
|
+
result = result.replace(/ss/g, seconds);
|
148
|
+
}
|
149
|
+
|
150
|
+
return result;
|
151
|
+
} catch (e) {
|
152
|
+
throw e;
|
153
|
+
}
|
154
|
+
}
|
155
|
+
|
156
|
+
public static DaysBetweenDates(startDate: Date | string | undefined, endDate: Date | string | undefined, format = "MM/dd/yyyy"): number {
|
157
|
+
if (startDate === null || startDate === undefined || endDate === null || endDate === undefined) {
|
158
|
+
throw new Error("Lib.DaysBetweenDates() Exception: Dates are required" + startDate + " " + endDate);
|
159
|
+
}
|
160
|
+
const start = new Date(this.FormatDate(startDate, format)).getTime();
|
161
|
+
const end = new Date(this.FormatDate(endDate, format)).getTime();
|
162
|
+
const difference = end - start;
|
163
|
+
const daysPassed = difference / (1000 * 3600 * 24);
|
164
|
+
return Math.floor(daysPassed);
|
165
|
+
}
|
166
|
+
|
167
|
+
public static IsPastDate(date: Date | string, format = "MM/dd/yyyy HH:mm:ss", debug = false, currentDate?: Date | string): boolean {
|
168
|
+
const truncateToSecond = (d: Date) => new Date(Math.floor(d.getTime() / 1000) * 1000);
|
169
|
+
|
170
|
+
const now = truncateToSecond(currentDate ? (typeof currentDate === "string" ? new Date(currentDate) : currentDate) : new Date());
|
171
|
+
const check = truncateToSecond(typeof date === "string" ? new Date(date) : date);
|
172
|
+
|
173
|
+
if (debug) {
|
174
|
+
Debug.Log("Now:", this.FormatDate(now, format));
|
175
|
+
Debug.Log("Check:", this.FormatDate(check, format));
|
176
|
+
}
|
177
|
+
|
178
|
+
return now.getTime() > check.getTime();
|
179
|
+
}
|
180
|
+
|
181
|
+
public static IsPastDateFrom(date: Date | string, from: Date | string, format = "MM/dd/yyyy"): boolean {
|
182
|
+
const now = this.FormatDate(from, format);
|
183
|
+
const check = this.FormatDate(date, format);
|
184
|
+
return new Date(now).getTime() > new Date(check).getTime();
|
185
|
+
}
|
186
|
+
|
187
|
+
public static addTimeFromDate(date: Date | string, milliseconds: number): Date {
|
188
|
+
const dateObj = new Date(typeof date === "string" ? new Date(date).getTime() : date.getTime() + milliseconds);
|
189
|
+
return dateObj;
|
190
|
+
}
|
191
|
+
|
192
|
+
public static UUID(minLength = 36): string {
|
193
|
+
const template = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx";
|
194
|
+
let uuid = template.replace(/[xy]/g, function (c) {
|
195
|
+
const r = (Math.random() * 16) | 0,
|
196
|
+
v = c === "x" ? r : (r & 0x3) | 0x8;
|
197
|
+
return v.toString(16);
|
198
|
+
});
|
199
|
+
|
200
|
+
// If the generated UUID is shorter than the minimum length, pad it with additional random characters
|
201
|
+
while (uuid.length < minLength) {
|
202
|
+
uuid += ((Math.random() * 16) | 0).toString(16);
|
203
|
+
}
|
204
|
+
|
205
|
+
return uuid.substring(0, minLength);
|
206
|
+
}
|
207
|
+
|
208
|
+
public static Debounce(callback: (...args: any[]) => void, delay = 500): (...args: any[]) => any {
|
209
|
+
let timeout: Timer;
|
210
|
+
return (...args: any[]) => {
|
211
|
+
clearTimeout(timeout);
|
212
|
+
timeout = setTimeout(() => {
|
213
|
+
return callback(...args);
|
214
|
+
}, delay);
|
215
|
+
};
|
216
|
+
}
|
217
|
+
|
218
|
+
public static IsNil(value: any): boolean {
|
219
|
+
return value === null || value === undefined;
|
220
|
+
}
|
221
|
+
|
222
|
+
public static IsPrimitive(value: any): boolean {
|
223
|
+
return this.IsNumber(value) || this.IsString(value) || this.IsBoolean(value);
|
224
|
+
}
|
225
|
+
|
226
|
+
public static EmptyObject(value: any): boolean {
|
227
|
+
let empty_object = true;
|
228
|
+
if (this.GetType(value) !== "object") {
|
229
|
+
empty_object = false;
|
230
|
+
return empty_object;
|
231
|
+
}
|
232
|
+
if (Object.keys(value).length === 0) {
|
233
|
+
empty_object = true;
|
234
|
+
return empty_object;
|
235
|
+
}
|
236
|
+
for (const k in value) {
|
237
|
+
if (!this.IsNil(value[k]) && value[k] !== "") {
|
238
|
+
empty_object = false;
|
239
|
+
}
|
240
|
+
}
|
241
|
+
return empty_object;
|
242
|
+
}
|
243
|
+
|
244
|
+
public static IsNumpty(value: any, _objectsOnly = false): boolean {
|
245
|
+
return typeof value === "number" ? false : this.IsNil(value) || this.IsEmpty(value, _objectsOnly);
|
246
|
+
}
|
247
|
+
|
248
|
+
public static IsEmpty(value: any, _objectsOnly = false): boolean {
|
249
|
+
return (
|
250
|
+
(this.GetType(value) === "array" && value.length === 0 && !_objectsOnly) ||
|
251
|
+
(this.GetType(value) === "object" && this.EmptyObject(value)) ||
|
252
|
+
(typeof value === "string" && value.trim().length === 0)
|
253
|
+
);
|
254
|
+
}
|
255
|
+
|
256
|
+
public static IsArray(variable: any): boolean {
|
257
|
+
return this.GetType(variable) === E_IS.ARRAY;
|
258
|
+
}
|
259
|
+
|
260
|
+
public static IsString(variable: any, as_typeof: boolean = false): boolean {
|
261
|
+
return this.GetType(variable, as_typeof) === E_IS.STRING;
|
262
|
+
}
|
263
|
+
|
264
|
+
public static IsNumber(variable: any, as_typeof: boolean = false): boolean {
|
265
|
+
return this.GetType(variable, as_typeof) === E_IS.NUMBER;
|
266
|
+
}
|
267
|
+
|
268
|
+
public static IsObject(variable: any): boolean {
|
269
|
+
return this.GetType(variable) === E_IS.OBJECT;
|
270
|
+
}
|
271
|
+
|
272
|
+
public static IsFunction(variable: any): boolean {
|
273
|
+
return this.GetType(variable) === E_IS.FUNCTION;
|
274
|
+
}
|
275
|
+
|
276
|
+
public static IsRegex(variable: any): boolean {
|
277
|
+
return this.GetType(variable) === E_IS.REGEX;
|
278
|
+
}
|
279
|
+
|
280
|
+
public static IsBoolean(variable: any): boolean {
|
281
|
+
return this.GetType(variable, true) === E_IS.BOOLEAN;
|
282
|
+
}
|
283
|
+
|
284
|
+
public static GetType(value: any, asTypeOf = false): null | string | boolean {
|
285
|
+
if (asTypeOf) {
|
286
|
+
return typeof value;
|
287
|
+
}
|
288
|
+
if (value === "0" || value === "1") {
|
289
|
+
return "number";
|
290
|
+
}
|
291
|
+
if (value === true) {
|
292
|
+
return true;
|
293
|
+
} else if (value === false) {
|
294
|
+
return false;
|
295
|
+
} else if (value === null || value === undefined) {
|
296
|
+
return null;
|
297
|
+
} else if (Array.isArray(value)) {
|
298
|
+
return "array";
|
299
|
+
} else if (value instanceof RegExp) {
|
300
|
+
return "regex";
|
301
|
+
} else if (!isNaN(Number(value))) {
|
302
|
+
return "number";
|
303
|
+
} else if (typeof value === "string") {
|
304
|
+
return "string";
|
305
|
+
} else if ({}.toString.call(value) === "[object Function]" || typeof value === "function") {
|
306
|
+
return "function";
|
307
|
+
} else {
|
308
|
+
return "object";
|
309
|
+
}
|
310
|
+
}
|
311
|
+
|
312
|
+
public static GetProjectRoot(startDir: string = __dirname, rootReference = "package.json"): string {
|
313
|
+
let currentDir = startDir;
|
314
|
+
|
315
|
+
while (!fs.existsSync(path.join(currentDir, rootReference))) {
|
316
|
+
const parentDir = path.resolve(currentDir, "..");
|
317
|
+
if (parentDir === currentDir) {
|
318
|
+
throw new Error("Unable to find project root");
|
319
|
+
}
|
320
|
+
currentDir = parentDir;
|
321
|
+
}
|
322
|
+
|
323
|
+
return currentDir;
|
324
|
+
}
|
325
|
+
|
326
|
+
public static async RunTaskWithTimeout(task: () => Promise<void>, timeout: number) {
|
327
|
+
return Promise.race([task(), new Promise((_, reject) => setTimeout(() => reject(new Error("Task timed out")), timeout))]);
|
328
|
+
}
|
329
|
+
|
330
|
+
public static GetFolderPath(folder: string): string {
|
331
|
+
return path.join(this.GetProjectRoot(), folder);
|
332
|
+
}
|
333
|
+
|
334
|
+
public static GetFilePath(folder: string, file: string): string {
|
335
|
+
return path.join(this.GetFolderPath(folder), file);
|
336
|
+
}
|
337
|
+
|
338
|
+
public static async CreateDirectory(folderToCreate: string) {
|
339
|
+
const directoryPath = Lib.GetFolderPath(folderToCreate);
|
340
|
+
await fs.promises.access(directoryPath, fs.constants.F_OK).catch(async () => {
|
341
|
+
await fs.promises.mkdir(directoryPath, { recursive: true });
|
342
|
+
});
|
343
|
+
return directoryPath;
|
344
|
+
}
|
345
|
+
|
346
|
+
public static async DeleteDirectory(folderToDelete: string) {
|
347
|
+
const directoryPath = path.join(this.GetProjectRoot(), folderToDelete);
|
348
|
+
await fs.promises.rm(directoryPath, { recursive: true, force: true });
|
349
|
+
}
|
350
|
+
|
351
|
+
public static async CreateFile(folderPath: string, filePath: string, content: string) {
|
352
|
+
await Lib.CreateDirectory(folderPath);
|
353
|
+
const file = Lib.GetFilePath(folderPath, filePath);
|
354
|
+
await fs.promises.writeFile(file, content, "utf8");
|
355
|
+
}
|
356
|
+
|
357
|
+
public static GetFile(filePathFromRoot: string) {
|
358
|
+
return fs.createReadStream(filePathFromRoot);
|
359
|
+
}
|
360
|
+
|
361
|
+
public static GetFilesInDirectory(directoryPath: string): string[] {
|
362
|
+
return fs.readdirSync(directoryPath);
|
363
|
+
}
|
364
|
+
|
365
|
+
public static async DeleteFile(filePathFromRoot: string) {
|
366
|
+
await fs.promises.unlink(filePathFromRoot);
|
367
|
+
}
|
368
|
+
|
369
|
+
public static Timestamp(log = false) {
|
370
|
+
const currentTime = new Date().toLocaleTimeString();
|
371
|
+
if (log) console.log(`[${currentTime}]`);
|
372
|
+
return currentTime;
|
373
|
+
}
|
374
|
+
|
375
|
+
public static RemoveWhitespace(value: string): string {
|
376
|
+
return value.replace(/\s/g, "");
|
377
|
+
}
|
378
|
+
|
379
|
+
public static msToString(ms: number): string {
|
380
|
+
if (ms === 0) return "0ms"; // Handle zero duration case
|
381
|
+
const seconds = Math.floor(ms / 1000);
|
382
|
+
const minutes = Math.floor(seconds / 60);
|
383
|
+
const hours = Math.floor(minutes / 60);
|
384
|
+
let output = hours > 0 ? `${hours}h ` : "";
|
385
|
+
output += minutes > 0 ? `${minutes % 60}m ` : "";
|
386
|
+
output += seconds % 60 > 0 ? `${seconds % 60}s ` : "";
|
387
|
+
output += ms % 1000 > 0 ? `${(ms % 1000).toFixed(2)}ms` : "";
|
388
|
+
return output.trim();
|
389
|
+
}
|
390
|
+
|
391
|
+
public static FormatPhone(phone_number: string): string {
|
392
|
+
let output: string = phone_number;
|
393
|
+
//remove all non-digit characters and whitespaces using regex
|
394
|
+
output = output.replace(/\D/g, "");
|
395
|
+
//if phone number doesn't start with + add +
|
396
|
+
if (!output.startsWith("+")) {
|
397
|
+
output = `+${output}`;
|
398
|
+
}
|
399
|
+
return output;
|
400
|
+
}
|
401
|
+
|
402
|
+
public static ToMB(bytes: number, as_KB = true, decimalPlaces = 2): string {
|
403
|
+
const kb = bytes / 1024;
|
404
|
+
return (as_KB ? kb : kb / 1024).toFixed(decimalPlaces);
|
405
|
+
}
|
406
|
+
|
407
|
+
public static ToGB(bytes: number, as_KB = true, decimalPlaces = 2): string {
|
408
|
+
const mb = this.ToMB(bytes, as_KB, decimalPlaces);
|
409
|
+
return (parseInt(mb) / 1024).toFixed(decimalPlaces);
|
410
|
+
}
|
411
|
+
|
412
|
+
public static async RetryHandler<T extends (...args: any[]) => any>(func: T, retries = 3, ...args: Parameters<T>): Promise<ReturnType<T>> {
|
413
|
+
let attempts = 0;
|
414
|
+
let toThrow;
|
415
|
+
|
416
|
+
while (attempts < retries) {
|
417
|
+
try {
|
418
|
+
return await func(...args);
|
419
|
+
} catch (e) {
|
420
|
+
attempts++;
|
421
|
+
toThrow = e;
|
422
|
+
if (attempts <= retries && !Throwable.IsThrowable(e)) {
|
423
|
+
Lib.$Log(`Attempt ${attempts} failed. Retrying...(${func.name})`);
|
424
|
+
if (attempts == 1) Lib.Warn(toThrow);
|
425
|
+
// Lib.Warn(toThrow, { hint: `Attempt ${attempts} failed. Retrying...(${func.name})`, data: JSON.stringify(args) });
|
426
|
+
// Wait for 1 second before retrying
|
427
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
428
|
+
}
|
429
|
+
}
|
430
|
+
}
|
431
|
+
|
432
|
+
throw toThrow;
|
433
|
+
}
|
434
|
+
|
435
|
+
public static Difference(x: any[], y: any[]) {
|
436
|
+
return x.filter((x) => !y.includes(x));
|
437
|
+
}
|
438
|
+
|
439
|
+
public static async ReadFileContent(filePath: string): Promise<string> {
|
440
|
+
return fs.promises.readFile(filePath, "utf8");
|
441
|
+
}
|
442
|
+
|
443
|
+
public static async measureExecutionTime<T extends (...args: any[]) => any, U extends ReturnType<T>>(
|
444
|
+
func: T,
|
445
|
+
...args: Parameters<T>
|
446
|
+
): Promise<{ result: Awaited<U>; time: number | string }> {
|
447
|
+
const start = performance.now();
|
448
|
+
const result = await func(...args);
|
449
|
+
const end = performance.now();
|
450
|
+
return { result, time: this.msToString(end - start) };
|
451
|
+
}
|
452
|
+
|
453
|
+
public static ToCamelCase(str: string): string {
|
454
|
+
return str.replace(/(?:^\w|[A-Z]|\b\w)/g, (word, index) => (index === 0 ? word.toLowerCase() : word.toUpperCase())).replace(/\s+/g, "");
|
455
|
+
}
|
456
|
+
|
457
|
+
public static ToSnakeCase(str: string): string {
|
458
|
+
return str.replace(/([a-z])([A-Z])/g, "$1_$2").toLowerCase();
|
459
|
+
}
|
460
|
+
|
461
|
+
public static ToKebebCase(str: string): string {
|
462
|
+
return str.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
|
463
|
+
}
|
464
|
+
|
465
|
+
public static ToPascalCase(str: string): string {
|
466
|
+
return str.replace(/(?:^\w|[A-Z]|\b\w)/g, (word, index) => (index === 0 ? word.toUpperCase() : word.toLowerCase())).replace(/\s+/g, "");
|
467
|
+
}
|
468
|
+
}
|
469
|
+
|
470
|
+
export default Lib;
|
471
|
+
|
472
|
+
export class Debug {
|
473
|
+
public static Log(...args: any) {
|
474
|
+
if (process.env.NODE_ENV === "production") return;
|
475
|
+
Lib.Log(...args);
|
476
|
+
}
|
477
|
+
|
478
|
+
public static $Log(...args: any) {
|
479
|
+
if (process.env.NODE_ENV === "production") return;
|
480
|
+
Lib.$Log(...args);
|
481
|
+
}
|
482
|
+
|
483
|
+
public static LogObject(object: any, text?: string) {
|
484
|
+
if (process.env.NODE_ENV === "production") return;
|
485
|
+
Lib.LogObject(object, text);
|
486
|
+
}
|
487
|
+
|
488
|
+
public static GetLocalIpAddress(): string {
|
489
|
+
try {
|
490
|
+
const { networkInterfaces } = require("os");
|
491
|
+
const nets = networkInterfaces();
|
492
|
+
|
493
|
+
for (const name of Object.keys(nets)) {
|
494
|
+
for (const net of nets[name]) {
|
495
|
+
// Skip internal and non-IPv4 addresses
|
496
|
+
if (!net.internal && net.family === "IPv4") {
|
497
|
+
return net.address;
|
498
|
+
}
|
499
|
+
}
|
500
|
+
}
|
501
|
+
return "127.0.0.1"; // Fallback to localhost
|
502
|
+
} catch (err) {
|
503
|
+
return "127.0.0.1"; // Fallback to localhost
|
504
|
+
}
|
505
|
+
}
|
506
|
+
}
|
@@ -0,0 +1,9 @@
|
|
1
|
+
// This file is auto-generated by scripts/generate-indexes.ts
|
2
|
+
// Do not edit this file directly
|
3
|
+
|
4
|
+
export * from './Guards';
|
5
|
+
export * from './Lib';
|
6
|
+
export * from './Console';
|
7
|
+
export { default as Guards } from './Guards';
|
8
|
+
export { default as Lib } from './Lib';
|
9
|
+
export { default as Console } from './Console';
|