@similie/hyphen-command-server-types 1.0.0

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.
Files changed (60) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/LICENSE +21 -0
  3. package/README.md +1 -0
  4. package/dist/index.d.ts +5 -0
  5. package/dist/index.d.ts.map +1 -0
  6. package/dist/index.js +5 -0
  7. package/dist/index.js.map +1 -0
  8. package/dist/models/base-model.d.ts +13 -0
  9. package/dist/models/base-model.d.ts.map +1 -0
  10. package/dist/models/base-model.js +2 -0
  11. package/dist/models/base-model.js.map +1 -0
  12. package/dist/models/index.d.ts +2 -0
  13. package/dist/models/index.d.ts.map +1 -0
  14. package/dist/models/index.js +2 -0
  15. package/dist/models/index.js.map +1 -0
  16. package/dist/modules/index.d.ts +3 -0
  17. package/dist/modules/index.d.ts.map +1 -0
  18. package/dist/modules/index.js +3 -0
  19. package/dist/modules/index.js.map +1 -0
  20. package/dist/modules/loader.d.ts +4 -0
  21. package/dist/modules/loader.d.ts.map +1 -0
  22. package/dist/modules/loader.js +53 -0
  23. package/dist/modules/loader.js.map +1 -0
  24. package/dist/modules/types.d.ts +29 -0
  25. package/dist/modules/types.d.ts.map +1 -0
  26. package/dist/modules/types.js +2 -0
  27. package/dist/modules/types.js.map +1 -0
  28. package/dist/services/index.d.ts +3 -0
  29. package/dist/services/index.d.ts.map +1 -0
  30. package/dist/services/index.js +3 -0
  31. package/dist/services/index.js.map +1 -0
  32. package/dist/services/leader-lock.d.ts +31 -0
  33. package/dist/services/leader-lock.d.ts.map +1 -0
  34. package/dist/services/leader-lock.js +103 -0
  35. package/dist/services/leader-lock.js.map +1 -0
  36. package/dist/services/redis.d.ts +27 -0
  37. package/dist/services/redis.d.ts.map +1 -0
  38. package/dist/services/redis.js +62 -0
  39. package/dist/services/redis.js.map +1 -0
  40. package/dist/tools/index.d.ts +2 -0
  41. package/dist/tools/index.d.ts.map +1 -0
  42. package/dist/tools/index.js +2 -0
  43. package/dist/tools/index.js.map +1 -0
  44. package/dist/tools/utils.d.ts +44 -0
  45. package/dist/tools/utils.d.ts.map +1 -0
  46. package/dist/tools/utils.js +283 -0
  47. package/dist/tools/utils.js.map +1 -0
  48. package/package.json +34 -0
  49. package/src/index.ts +4 -0
  50. package/src/models/base-model.ts +13 -0
  51. package/src/models/index.ts +1 -0
  52. package/src/modules/index.ts +2 -0
  53. package/src/modules/loader.ts +67 -0
  54. package/src/modules/types.ts +40 -0
  55. package/src/services/index.ts +2 -0
  56. package/src/services/leader-lock.ts +113 -0
  57. package/src/services/redis.ts +69 -0
  58. package/src/tools/index.ts +1 -0
  59. package/src/tools/utils.ts +349 -0
  60. package/tsconfig.json +46 -0
@@ -0,0 +1,349 @@
1
+ import type { UUID } from "../models";
2
+ import CryptoJS from "crypto-js";
3
+ import { v4 } from "uuid";
4
+ export type MQTTFunctionalResponse = {
5
+ value: any;
6
+ key: string;
7
+ id: string;
8
+ request: string;
9
+ };
10
+
11
+ export const mqttMessageIdentity = (
12
+ payload: Buffer<ArrayBufferLike>,
13
+ ): string => {
14
+ try {
15
+ const value = JSON.parse(payload.toString());
16
+ value._uid = generateUniqueUUID();
17
+ return JSON.stringify(value);
18
+ } catch {
19
+ return payload.toString();
20
+ }
21
+ };
22
+
23
+ export const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
24
+
25
+ export const wrapModelSet = <T>(
26
+ models: T[],
27
+ wrapOn: keyof T = "uid" as keyof T,
28
+ ) => {
29
+ const map = new Map<keyof T, T>();
30
+ models.forEach((m) => map.set(m[wrapOn] as keyof T, m));
31
+
32
+ return (key: keyof T) => {
33
+ if (!map.has(key)) {
34
+ return null;
35
+ }
36
+ return map.get(key);
37
+ };
38
+ };
39
+
40
+ export const URL_HOST_PATTERN_FOR_INPUT =
41
+ /^(https?:\/\/)?((([a-z0-9]([a-z0-9\-]*[a-z0-9])*)\.)+[a-z]{2,}|(([0-9]{1,3}\.){3}[0-9]{1,3}))(:[0-9]+)?(\/[\-a-z0-9%_.~+]*)*(\?[;&a-z0-9%_.~+=\-]*)?(#[-a-z0-9_]*)?$/;
42
+ export const DOMAIN_PATTERN =
43
+ /^(?:\*\.)?(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,}$/i;
44
+ export function isNumeric(str: string): boolean {
45
+ if (typeof str !== "string") return false; // we only process strings
46
+ const trimmed = str.trim();
47
+ if (trimmed === "") return false;
48
+ return !isNaN(Number(trimmed));
49
+ }
50
+
51
+ export const generateUniqueUUID = () => {
52
+ return v4() as UUID;
53
+ };
54
+
55
+ export function formatDate(
56
+ date: Date | string,
57
+ locale = "en-AU",
58
+ options: Intl.DateTimeFormatOptions = {
59
+ year: "numeric",
60
+ month: "2-digit",
61
+ day: "2-digit",
62
+ },
63
+ ): string {
64
+ if (typeof date === "string") {
65
+ date = new Date(date);
66
+ }
67
+ return date.toLocaleDateString(locale, options);
68
+ }
69
+
70
+ export function formatMoney(value: number, currencySymbol: string = "$") {
71
+ let formattedValue = value.toString();
72
+ if (value.toString().includes(".")) {
73
+ formattedValue = value.toFixed(2);
74
+ } else {
75
+ formattedValue = value.toString() + ".00";
76
+ }
77
+ return `${currencySymbol}${formattedValue}`;
78
+ }
79
+
80
+ export const siteMoneyFormatConfig = (
81
+ value: number,
82
+ currencyDivisor: number = 100,
83
+ currencySymbol: string = "$",
84
+ ): string => {
85
+ if (typeof value !== "number" && isNaN(value)) {
86
+ return "0.00";
87
+ }
88
+ const divisor = currencyDivisor;
89
+ const formattedValue = (value / divisor).toFixed(2);
90
+ return `${currencySymbol}${formattedValue}`;
91
+ };
92
+
93
+ export const errorMessageWithCode = (message: string) => {
94
+ if (!message) {
95
+ return { code: 500, message: message };
96
+ }
97
+ const errorCode = message.split(":");
98
+ if (errorCode.length > 1) {
99
+ const code = errorCode[0] || "500";
100
+ const intValue = parseInt(code);
101
+ return {
102
+ code: Number.isNaN(intValue) ? 500 : intValue,
103
+ message: errorCode[1],
104
+ };
105
+ }
106
+ return { code: 500, message: message };
107
+ };
108
+
109
+ export const isDomainPattern = (str: string): boolean => {
110
+ if (!str || typeof str !== "string") return false;
111
+ return DOMAIN_PATTERN.test(str);
112
+ };
113
+
114
+ export const extractFormToJson = <T extends Record<string, any> = {}>(
115
+ form: FormData,
116
+ ) => {
117
+ const asObject = Object.fromEntries(form.entries());
118
+ const data: any = {};
119
+ for (const key of Object.keys(asObject)) {
120
+ try {
121
+ data[key] = JSON.parse(asObject[key] as string);
122
+ } catch {
123
+ data[key] = asObject[key];
124
+ }
125
+ }
126
+ return data as T;
127
+ };
128
+
129
+ export const delay = (timeout = 1000) =>
130
+ new Promise((resolve) => setTimeout(resolve, timeout));
131
+
132
+ export const generateRandomInt = (min: number, max: number): number => {
133
+ return Math.floor(Math.random() * (max - min + 1)) + min;
134
+ };
135
+
136
+ export const generateUniqueId = (numBytes: number = 16): string => {
137
+ const wordArray = CryptoJS.lib.WordArray.random(numBytes);
138
+ // Convert the WordArray to a hexadecimal string
139
+ return wordArray.toString(CryptoJS.enc.Hex);
140
+ };
141
+
142
+ export const isUUID = (value: string | UUID) => {
143
+ const regex =
144
+ /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}/i;
145
+ return regex.test(value);
146
+ };
147
+
148
+ export const validateEmail = (email: string): boolean => {
149
+ const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
150
+ return emailRegex.test(email);
151
+ };
152
+
153
+ export const generateRandomPassword = (length: number): string => {
154
+ const characters =
155
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()_+[]{}|;:,.<>?";
156
+ let password = "";
157
+
158
+ for (let i = 0; i < length; i++) {
159
+ const randomIndex = Math.floor(Math.random() * characters.length);
160
+ password += characters[randomIndex];
161
+ }
162
+
163
+ return password;
164
+ };
165
+
166
+ export const fileToUint8Array = (file: File): Promise<Uint8Array> => {
167
+ return new Promise((resolve, reject) => {
168
+ const reader = new FileReader();
169
+ reader.onload = () => {
170
+ const arrayBuffer = reader.result as ArrayBuffer;
171
+ const uint8Array = new Uint8Array(arrayBuffer);
172
+ resolve(uint8Array);
173
+ };
174
+ reader.onerror = () => {
175
+ reject(new Error("Error reading file as ArrayBuffer"));
176
+ };
177
+ reader.readAsArrayBuffer(file);
178
+ });
179
+ };
180
+
181
+ function readFileAsArrayBuffer(file: File): Promise<ArrayBuffer> {
182
+ return new Promise<ArrayBuffer>((resolve, reject) => {
183
+ const reader = new FileReader();
184
+
185
+ reader.onload = function (event) {
186
+ const arrayBuffer = event.target?.result as ArrayBuffer;
187
+ resolve(arrayBuffer);
188
+ };
189
+
190
+ reader.onerror = function () {
191
+ reject(new Error("Error reading file"));
192
+ };
193
+
194
+ reader.readAsArrayBuffer(file);
195
+ });
196
+ }
197
+
198
+ async function sha256Fallback(arrayBuffer: ArrayBuffer) {
199
+ const wordArray = CryptoJS.lib.WordArray.create(arrayBuffer);
200
+ const hash = CryptoJS.SHA256(wordArray);
201
+ return hash.toString(CryptoJS.enc.Hex);
202
+ }
203
+
204
+ async function sha256(arrayBuffer: ArrayBuffer) {
205
+ if (crypto.subtle) {
206
+ const hashBuffer = await crypto.subtle.digest("SHA-256", arrayBuffer);
207
+ return Array.from(new Uint8Array(hashBuffer))
208
+ .map((b) => b.toString(16).padStart(2, "0"))
209
+ .join("");
210
+ } else {
211
+ // Use fallback if crypto.subtle isn't available
212
+ return sha256Fallback(arrayBuffer);
213
+ }
214
+ }
215
+
216
+ export function sha256String(values: string) {
217
+ const encoder = new TextEncoder();
218
+ const uint8Array = encoder.encode(values);
219
+ const wordArray = CryptoJS.lib.WordArray.create(uint8Array);
220
+ const hash = CryptoJS.SHA256(wordArray);
221
+ return hash.toString(CryptoJS.enc.Hex);
222
+ }
223
+
224
+ export const ParseSocketMessage = <T>(message: string): T => {
225
+ try {
226
+ return JSON.parse(message) as unknown as T;
227
+ } catch {
228
+ return message as unknown as T;
229
+ }
230
+ };
231
+
232
+ export const stripStateFromObject = (obj: any) => {
233
+ try {
234
+ return JSON.parse(JSON.stringify(obj));
235
+ } catch {
236
+ return obj;
237
+ }
238
+ };
239
+
240
+ export const buildShaValueString = (data: any) => {
241
+ return sha256String(JSON.stringify(data));
242
+ };
243
+
244
+ async function computeHash(arrayBuffer: ArrayBuffer): Promise<string> {
245
+ const hashBuffer = await sha256(arrayBuffer);
246
+ return hashBuffer;
247
+ }
248
+
249
+ export const hashFileContents = async (file: File): Promise<string> => {
250
+ const arrayBuffer = await readFileAsArrayBuffer(file);
251
+ return computeHash(arrayBuffer);
252
+ };
253
+
254
+ export const fileListToFile = async (file: File): Promise<File> => {
255
+ const uint8Array = await fileToUint8Array(file);
256
+ return new File([uint8Array as BlobPart], file.name, {
257
+ type: file.type,
258
+ lastModified: file.lastModified,
259
+ });
260
+ };
261
+
262
+ export const formatMessageServerMessage = (message: string) => {
263
+ const backup = "Failed to send verification email";
264
+ if (!message) {
265
+ return backup;
266
+ }
267
+
268
+ try {
269
+ const errMessage = JSON.parse(message);
270
+ if (errMessage?.error) {
271
+ return errMessage.error;
272
+ }
273
+ if (errMessage?.message) {
274
+ return errMessage.message;
275
+ }
276
+ throw new Error("Not known json");
277
+ } catch {
278
+ return message;
279
+ }
280
+ };
281
+
282
+ export const isOlderThanInDays = (created_at: Date, days: number): boolean => {
283
+ // Get the current date and time
284
+ const currentDate = new Date();
285
+
286
+ // Calculate the target date by subtracting `days` from the current date
287
+ const targetDate = new Date();
288
+ targetDate.setDate(currentDate.getDate() - days);
289
+
290
+ // Compare created_at with the target date
291
+ return created_at < targetDate;
292
+ };
293
+
294
+ export const removeDoubleSpaces = (text: string) => {
295
+ return text.replace(/\s\s+/g, " ");
296
+ };
297
+
298
+ export const removeContentSpace = (text: string) => {
299
+ return removeDoubleSpaces(text.replace(/[\n\t]/g, " ")); // new lines and tabs
300
+ };
301
+
302
+ export const removeHtmlEntities = (text: string) => {
303
+ return text.replace(/(?:&#x[a-f0-9]{2};|&#[0-9]+;)/g, " ");
304
+ };
305
+
306
+ export function getLast30DaysLabels(locale = "en-US"): string[] {
307
+ const labels: string[] = [];
308
+ const today = new Date();
309
+
310
+ for (let daysAgo = 30; daysAgo >= 0; daysAgo--) {
311
+ const d = new Date(today);
312
+ d.setDate(d.getDate() - daysAgo);
313
+
314
+ // e.g. "Jan"
315
+ const month = d.toLocaleString(locale, { month: "short" });
316
+ // day of month, no leading zero: "1", "31", etc.
317
+ const day = d.getDate();
318
+
319
+ labels.push(`${month}, ${day}`);
320
+ }
321
+
322
+ return labels;
323
+ }
324
+
325
+ export function humanizeNumber(value: number, precision = 1): string {
326
+ if (value === 0) return "0";
327
+ const suffixes = [
328
+ "",
329
+ " thousand",
330
+ " million",
331
+ " billion",
332
+ " trillion",
333
+ " quadrillion",
334
+ ];
335
+ const abs = Math.abs(value);
336
+ const tier = Math.floor(Math.log10(abs) / 3);
337
+
338
+ // if in the ones (no suffix)
339
+ if (tier === 0) {
340
+ return value.toString();
341
+ }
342
+
343
+ const scale = 10 ** (tier * 3);
344
+ const scaled = value / scale;
345
+ // format to `precision` decimals, then drop any trailing “.0”
346
+ const formatted = scaled.toFixed(precision).replace(/\.0+$/, "");
347
+
348
+ return `${formatted}${suffixes[tier]}`;
349
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ // Visit https://aka.ms/tsconfig to read more about this file
3
+ "compilerOptions": {
4
+ // File Layout
5
+ "rootDir": "./src",
6
+ "outDir": "./dist",
7
+ "moduleResolution": "Node",
8
+
9
+ // Environment Settings
10
+ // See also https://aka.ms/tsconfig/module
11
+ "module": "ESNext",
12
+ "target": "ES2022",
13
+ "types": [],
14
+ // For nodejs:
15
+ // "lib": ["esnext"],
16
+ // "types": ["node"],
17
+ // and npm install -D @types/node
18
+
19
+ // Other Outputs
20
+ "sourceMap": true,
21
+ "declaration": true,
22
+ "declarationMap": true,
23
+
24
+ // Stricter Typechecking Options
25
+ "noUncheckedIndexedAccess": true,
26
+ "exactOptionalPropertyTypes": true,
27
+ "esModuleInterop": true,
28
+ // Style Options
29
+ // "noImplicitReturns": true,
30
+ // "noImplicitOverride": true,
31
+ // "noUnusedLocals": true,
32
+ // "noUnusedParameters": true,
33
+ // "noFallthroughCasesInSwitch": true,
34
+ // "noPropertyAccessFromIndexSignature": true,
35
+
36
+ // Recommended Options
37
+ "strict": true,
38
+ "jsx": "react-jsx",
39
+ "verbatimModuleSyntax": true,
40
+ "isolatedModules": true,
41
+ "noUncheckedSideEffectImports": true,
42
+ "moduleDetection": "force",
43
+ "skipLibCheck": true
44
+ },
45
+ "include": ["src"]
46
+ }