@kidus.dev/flowdb 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.
- package/README.md +15 -0
- package/dist/core/blob/blob.d.ts +25 -0
- package/dist/core/blob/blob.d.ts.map +1 -0
- package/dist/core/blob/blob.js +57 -0
- package/dist/core/blob/blob_disk_driver.d.ts +27 -0
- package/dist/core/blob/blob_disk_driver.d.ts.map +1 -0
- package/dist/core/blob/blob_disk_driver.js +179 -0
- package/dist/core/blob/blob_storage.d.ts +90 -0
- package/dist/core/blob/blob_storage.d.ts.map +1 -0
- package/dist/core/blob/blob_storage.js +248 -0
- package/dist/core/collection/collection.d.ts +99 -0
- package/dist/core/collection/collection.d.ts.map +1 -0
- package/dist/core/collection/collection.js +226 -0
- package/dist/core/collection/document.d.ts +24 -0
- package/dist/core/collection/document.d.ts.map +1 -0
- package/dist/core/collection/document.js +86 -0
- package/dist/core/collection/driver/collection_file_driver.d.ts +20 -0
- package/dist/core/collection/driver/collection_file_driver.d.ts.map +1 -0
- package/dist/core/collection/driver/collection_file_driver.js +90 -0
- package/dist/core/collection/driver/collection_operations.d.ts +43 -0
- package/dist/core/collection/driver/collection_operations.d.ts.map +1 -0
- package/dist/core/collection/driver/collection_operations.js +278 -0
- package/dist/core/collection/query/compares.d.ts +90 -0
- package/dist/core/collection/query/compares.d.ts.map +1 -0
- package/dist/core/collection/query/compares.js +362 -0
- package/dist/core/collection/query/filtering.d.ts +14 -0
- package/dist/core/collection/query/filtering.d.ts.map +1 -0
- package/dist/core/collection/query/filtering.js +176 -0
- package/dist/core/collection/query/query_builder.d.ts +145 -0
- package/dist/core/collection/query/query_builder.d.ts.map +1 -0
- package/dist/core/collection/query/query_builder.js +196 -0
- package/dist/core/collection/query/query_executor.d.ts +87 -0
- package/dist/core/collection/query/query_executor.d.ts.map +1 -0
- package/dist/core/collection/query/query_executor.js +348 -0
- package/dist/core/collection/query/relation.d.ts +29 -0
- package/dist/core/collection/query/relation.d.ts.map +1 -0
- package/dist/core/collection/query/relation.js +40 -0
- package/dist/core/database/backup.d.ts +26 -0
- package/dist/core/database/backup.d.ts.map +1 -0
- package/dist/core/database/backup.js +114 -0
- package/dist/core/database/database.d.ts +57 -0
- package/dist/core/database/database.d.ts.map +1 -0
- package/dist/core/database/database.js +179 -0
- package/dist/core/database/database_file_driver.d.ts +27 -0
- package/dist/core/database/database_file_driver.d.ts.map +1 -0
- package/dist/core/database/database_file_driver.js +135 -0
- package/dist/core/store/store.d.ts +24 -0
- package/dist/core/store/store.d.ts.map +1 -0
- package/dist/core/store/store.js +54 -0
- package/dist/core/store/store_file_driver.d.ts +26 -0
- package/dist/core/store/store_file_driver.d.ts.map +1 -0
- package/dist/core/store/store_file_driver.js +87 -0
- package/dist/tools/encryptor.d.ts +17 -0
- package/dist/tools/encryptor.d.ts.map +1 -0
- package/dist/tools/encryptor.js +80 -0
- package/dist/tools/format.d.ts +10 -0
- package/dist/tools/format.d.ts.map +1 -0
- package/dist/tools/format.js +40 -0
- package/dist/tools/index.d.ts +7 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +6 -0
- package/dist/tools/json.d.ts +19 -0
- package/dist/tools/json.d.ts.map +1 -0
- package/dist/tools/json.js +232 -0
- package/dist/tools/performance.d.ts +20 -0
- package/dist/tools/performance.d.ts.map +1 -0
- package/dist/tools/performance.js +53 -0
- package/dist/tools/print_colored.d.ts +47 -0
- package/dist/tools/print_colored.d.ts.map +1 -0
- package/dist/tools/print_colored.js +119 -0
- package/dist/tools/random.d.ts +46 -0
- package/dist/tools/random.d.ts.map +1 -0
- package/dist/tools/random.js +214 -0
- package/package.json +40 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
type AnyObject = {
|
|
2
|
+
[key: string]: any;
|
|
3
|
+
};
|
|
4
|
+
export default class StoreFileStorage {
|
|
5
|
+
private readonly _encrypted;
|
|
6
|
+
private readonly _file;
|
|
7
|
+
private readonly _encryptor;
|
|
8
|
+
constructor({ path, encrypted, secretKey, }: {
|
|
9
|
+
path: string;
|
|
10
|
+
encrypted?: boolean;
|
|
11
|
+
secretKey?: string;
|
|
12
|
+
});
|
|
13
|
+
create(): void;
|
|
14
|
+
delete(): void;
|
|
15
|
+
get size(): number;
|
|
16
|
+
readAll(): Record<string, any>;
|
|
17
|
+
writeAll(data: AnyObject): void;
|
|
18
|
+
set(key: string, value: any): any;
|
|
19
|
+
setFrom(key: string, func: (data: any) => any, fallback?: any): any;
|
|
20
|
+
get(key: string): any;
|
|
21
|
+
remove(key: string): AnyObject;
|
|
22
|
+
has(key: string): boolean;
|
|
23
|
+
clear(): void;
|
|
24
|
+
}
|
|
25
|
+
export {};
|
|
26
|
+
//# sourceMappingURL=store_file_driver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store_file_driver.d.ts","sourceRoot":"","sources":["../../../src/core/store/store_file_driver.ts"],"names":[],"mappings":"AAIA,KAAK,SAAS,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;CAAE,CAAC;AAExC,MAAM,CAAC,OAAO,OAAO,gBAAgB;IACnC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAU;IACrC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAY;gBAE3B,EACV,IAAI,EACJ,SAAS,EACT,SAAS,GACV,EAAE;QACD,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,CAAC,EAAE,OAAO,CAAC;QACpB,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB;IAMD,MAAM;IAUN,MAAM;IAMN,IAAI,IAAI,IAAI,MAAM,CAKjB;IAED,OAAO,IAAI,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IAc9B,QAAQ,CAAC,IAAI,EAAE,SAAS;IAMxB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,GAAG;IASjC,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,GAAG,EAAE,QAAQ,CAAC,EAAE,GAAG,GAAG,GAAG;IASnE,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG;IAIrB,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS;IAS9B,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAIzB,KAAK;CAGN"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import * as fs from "fs";
|
|
2
|
+
import * as path from "path";
|
|
3
|
+
import { Encryptor, Json } from "../../tools";
|
|
4
|
+
export default class StoreFileStorage {
|
|
5
|
+
_encrypted;
|
|
6
|
+
_file;
|
|
7
|
+
_encryptor;
|
|
8
|
+
constructor({ path, encrypted, secretKey, }) {
|
|
9
|
+
this._file = path;
|
|
10
|
+
this._encrypted = encrypted ?? false;
|
|
11
|
+
this._encryptor = new Encryptor({ round: 10, key: secretKey });
|
|
12
|
+
}
|
|
13
|
+
create() {
|
|
14
|
+
const dir = path.dirname(this._file);
|
|
15
|
+
if (!fs.existsSync(dir)) {
|
|
16
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
17
|
+
}
|
|
18
|
+
if (!fs.existsSync(this._file)) {
|
|
19
|
+
fs.writeFileSync(this._file, "");
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
delete() {
|
|
23
|
+
if (fs.existsSync(this._file)) {
|
|
24
|
+
fs.unlinkSync(this._file);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
get size() {
|
|
28
|
+
if (fs.existsSync(this._file)) {
|
|
29
|
+
return fs.statSync(this._file).size;
|
|
30
|
+
}
|
|
31
|
+
return 0;
|
|
32
|
+
}
|
|
33
|
+
readAll() {
|
|
34
|
+
if (!fs.existsSync(this._file))
|
|
35
|
+
return {};
|
|
36
|
+
const fileContents = fs.readFileSync(this._file, "utf-8");
|
|
37
|
+
const content = this._encrypted
|
|
38
|
+
? this._encryptor.dec(fileContents)
|
|
39
|
+
: fileContents;
|
|
40
|
+
if (!content || content.trim().length === 0)
|
|
41
|
+
return {};
|
|
42
|
+
try {
|
|
43
|
+
return Json.parse(content);
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return {};
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
writeAll(data) {
|
|
50
|
+
const jsonData = Json.stringify(data);
|
|
51
|
+
const content = this._encrypted ? this._encryptor.enc(jsonData) : jsonData;
|
|
52
|
+
fs.writeFileSync(this._file, content);
|
|
53
|
+
}
|
|
54
|
+
set(key, value) {
|
|
55
|
+
const content = this.readAll();
|
|
56
|
+
const updated = Json.update(content, key, value);
|
|
57
|
+
if (JSON.stringify(updated) !== JSON.stringify(content)) {
|
|
58
|
+
this.writeAll(updated);
|
|
59
|
+
}
|
|
60
|
+
return value;
|
|
61
|
+
}
|
|
62
|
+
setFrom(key, func, fallback) {
|
|
63
|
+
const content = this.readAll();
|
|
64
|
+
const oldData = Json.getNested(content, key);
|
|
65
|
+
const newValue = func(oldData !== undefined ? oldData : fallback);
|
|
66
|
+
const updated = Json.update(content, key, newValue);
|
|
67
|
+
this.writeAll(updated);
|
|
68
|
+
return newValue;
|
|
69
|
+
}
|
|
70
|
+
get(key) {
|
|
71
|
+
return Json.getNested(this.readAll(), key);
|
|
72
|
+
}
|
|
73
|
+
remove(key) {
|
|
74
|
+
const content = this.readAll();
|
|
75
|
+
const updated = Json.remove(content, key);
|
|
76
|
+
if (JSON.stringify(updated) !== JSON.stringify(content)) {
|
|
77
|
+
this.writeAll(updated);
|
|
78
|
+
}
|
|
79
|
+
return updated;
|
|
80
|
+
}
|
|
81
|
+
has(key) {
|
|
82
|
+
return Json.getNested(this.readAll(), key) !== undefined;
|
|
83
|
+
}
|
|
84
|
+
clear() {
|
|
85
|
+
this.writeAll({});
|
|
86
|
+
}
|
|
87
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export default class Encryptor {
|
|
2
|
+
private _key;
|
|
3
|
+
private _round;
|
|
4
|
+
private static readonly _defaultKey;
|
|
5
|
+
constructor({ key, round }?: {
|
|
6
|
+
key?: string;
|
|
7
|
+
round?: number;
|
|
8
|
+
});
|
|
9
|
+
enc(data: string): string;
|
|
10
|
+
dec(data: string): string;
|
|
11
|
+
static encrypt(data: string, key?: string, round?: number): string;
|
|
12
|
+
static decrypt(encryptedData: string, key?: string, round?: number): string;
|
|
13
|
+
private static _deriveKey;
|
|
14
|
+
private static _encryptBytes;
|
|
15
|
+
private static _decryptBytes;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=encryptor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"encryptor.d.ts","sourceRoot":"","sources":["../../src/tools/encryptor.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,OAAO,OAAO,SAAS;IAC5B,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAsC;gBAE7D,EAAE,GAAG,EAAE,KAAK,EAAE,GAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAO;IAKjE,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAIzB,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAIzB,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,KAAK,GAAE,MAAe,GAAG,MAAM;IAW1E,MAAM,CAAC,OAAO,CACZ,aAAa,EAAE,MAAM,EACrB,GAAG,CAAC,EAAE,MAAM,EACZ,KAAK,GAAE,MAAe,GACrB,MAAM;IAwBT,OAAO,CAAC,MAAM,CAAC,UAAU;IAazB,OAAO,CAAC,MAAM,CAAC,aAAa;IAc5B,OAAO,CAAC,MAAM,CAAC,aAAa;CAiB7B"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import * as crypto from "crypto";
|
|
2
|
+
export default class Encryptor {
|
|
3
|
+
_key;
|
|
4
|
+
_round;
|
|
5
|
+
static _defaultKey = "535d260689feff3b45afb004190505ab";
|
|
6
|
+
constructor({ key, round } = {}) {
|
|
7
|
+
this._key = key ?? Encryptor._defaultKey;
|
|
8
|
+
this._round = round ?? 10_000;
|
|
9
|
+
}
|
|
10
|
+
enc(data) {
|
|
11
|
+
return Encryptor.encrypt(data, this._key, this._round);
|
|
12
|
+
}
|
|
13
|
+
dec(data) {
|
|
14
|
+
return Encryptor.decrypt(data, this._key, this._round);
|
|
15
|
+
}
|
|
16
|
+
static encrypt(data, key, round = 10_000) {
|
|
17
|
+
const encryptionKey = key ?? Encryptor._defaultKey;
|
|
18
|
+
const keyBytes = Buffer.from(encryptionKey, "utf8");
|
|
19
|
+
const dataBytes = Buffer.from(data, "utf8");
|
|
20
|
+
const iv = crypto.randomBytes(16);
|
|
21
|
+
const derivedKey = Encryptor._deriveKey(keyBytes, iv, round);
|
|
22
|
+
const encryptedBytes = Encryptor._encryptBytes(dataBytes, derivedKey, iv);
|
|
23
|
+
const combined = Buffer.concat([iv, encryptedBytes]);
|
|
24
|
+
return combined.toString("base64");
|
|
25
|
+
}
|
|
26
|
+
static decrypt(encryptedData, key, round = 10_000) {
|
|
27
|
+
try {
|
|
28
|
+
const encryptionKey = key ?? Encryptor._defaultKey;
|
|
29
|
+
const keyBytes = Buffer.from(encryptionKey, "utf8");
|
|
30
|
+
const combined = Buffer.from(encryptedData, "base64");
|
|
31
|
+
if (combined.length < 16)
|
|
32
|
+
return "";
|
|
33
|
+
const iv = combined.subarray(0, 16);
|
|
34
|
+
const encryptedBytes = combined.subarray(16);
|
|
35
|
+
const derivedKey = Encryptor._deriveKey(keyBytes, iv, round);
|
|
36
|
+
const decryptedBytes = Encryptor._decryptBytes(encryptedBytes, derivedKey, iv);
|
|
37
|
+
return Buffer.from(decryptedBytes).toString("utf8");
|
|
38
|
+
}
|
|
39
|
+
catch (e) {
|
|
40
|
+
throw new Error(`Error decrypting data: ${e}, May be the key is incorrect or the data is corrupted`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
// Derive a key from a key and a salt
|
|
44
|
+
static _deriveKey(key, salt, round) {
|
|
45
|
+
let derivedKey = crypto.createHmac("sha256", key).update(salt).digest();
|
|
46
|
+
for (let i = 0; i < round; i++) {
|
|
47
|
+
derivedKey = crypto
|
|
48
|
+
.createHmac("sha256", derivedKey)
|
|
49
|
+
.update(derivedKey)
|
|
50
|
+
.digest();
|
|
51
|
+
}
|
|
52
|
+
return derivedKey;
|
|
53
|
+
}
|
|
54
|
+
static _encryptBytes(data, key, iv) {
|
|
55
|
+
const result = Buffer.alloc(data.length);
|
|
56
|
+
for (let i = 0; i < data.length; i++) {
|
|
57
|
+
const keyByte = key[i % key.length];
|
|
58
|
+
const ivByte = iv[i % iv.length];
|
|
59
|
+
const dataByte = data[i];
|
|
60
|
+
let encrypted = dataByte ^ keyByte ^ ivByte;
|
|
61
|
+
encrypted = ((encrypted << 3) | (encrypted >> 5)) & 0xff;
|
|
62
|
+
encrypted = encrypted ^ ((keyByte + ivByte) % 256);
|
|
63
|
+
result[i] = encrypted;
|
|
64
|
+
}
|
|
65
|
+
return result;
|
|
66
|
+
}
|
|
67
|
+
static _decryptBytes(encryptedData, key, iv) {
|
|
68
|
+
const result = Buffer.alloc(encryptedData.length);
|
|
69
|
+
for (let i = 0; i < encryptedData.length; i++) {
|
|
70
|
+
const keyByte = key[i % key.length];
|
|
71
|
+
const ivByte = iv[i % iv.length];
|
|
72
|
+
const encryptedByte = encryptedData[i];
|
|
73
|
+
let decrypted = encryptedByte ^ ((keyByte + ivByte) % 256);
|
|
74
|
+
decrypted = ((decrypted >> 3) | (decrypted << 5)) & 0xff;
|
|
75
|
+
decrypted = decrypted ^ keyByte ^ ivByte;
|
|
76
|
+
result[i] = decrypted;
|
|
77
|
+
}
|
|
78
|
+
return result;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export default class Format {
|
|
2
|
+
static suffixes: string[];
|
|
3
|
+
static dateToYMD(date: Date): string;
|
|
4
|
+
static dateToYMDHMS(date: Date): string;
|
|
5
|
+
static dateToHMS(date: Date): string;
|
|
6
|
+
static sizeToHumanReadable(size: number): string;
|
|
7
|
+
static durationToHumanReadable(duration: number): string;
|
|
8
|
+
static numberToHumanReadable(number: number): string;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=format.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../src/tools/format.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,OAAO,OAAO,MAAM;IACzB,MAAM,CAAC,QAAQ,WAAyD;IACxE,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM;IAIpC,MAAM,CAAC,YAAY,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM;IAIvC,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM;IAIpC,MAAM,CAAC,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAehD,MAAM,CAAC,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;IAUxD,MAAM,CAAC,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;CAQrD"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export default class Format {
|
|
2
|
+
static suffixes = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
|
|
3
|
+
static dateToYMD(date) {
|
|
4
|
+
return date.toISOString().split("T")[0];
|
|
5
|
+
}
|
|
6
|
+
static dateToYMDHMS(date) {
|
|
7
|
+
return date.toISOString().replace("T", " ").split(".")[0];
|
|
8
|
+
}
|
|
9
|
+
static dateToHMS(date) {
|
|
10
|
+
return date.toISOString().split("T")[1].split(".")[0];
|
|
11
|
+
}
|
|
12
|
+
static sizeToHumanReadable(size) {
|
|
13
|
+
const suffixes = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
|
|
14
|
+
if (size <= 0 || isNaN(size))
|
|
15
|
+
return "0 B";
|
|
16
|
+
let i = size > 0 ? Math.floor(Math.log(size) / Math.log(1024)) : 0;
|
|
17
|
+
i = Math.max(0, Math.min(i, suffixes.length - 1));
|
|
18
|
+
const displaySize = size / Math.pow(1024, i);
|
|
19
|
+
if (!isFinite(displaySize) || isNaN(displaySize)) {
|
|
20
|
+
return "0 B";
|
|
21
|
+
}
|
|
22
|
+
return `${displaySize.toFixed(2)} ${suffixes[i]}`;
|
|
23
|
+
}
|
|
24
|
+
static durationToHumanReadable(duration) {
|
|
25
|
+
// duration is assumed to be in milliseconds
|
|
26
|
+
const microseconds = duration * 1000;
|
|
27
|
+
const milliseconds = duration;
|
|
28
|
+
const seconds = duration / 1000;
|
|
29
|
+
const minutes = duration / (1000 * 60);
|
|
30
|
+
return `[ ${microseconds} µs | ${milliseconds} ms | ${seconds} s | ${minutes} mn ]`;
|
|
31
|
+
}
|
|
32
|
+
static numberToHumanReadable(number) {
|
|
33
|
+
let s = number.toFixed(2);
|
|
34
|
+
// Add commas for thousands
|
|
35
|
+
s = s.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
36
|
+
// Remove ".00" at end if present
|
|
37
|
+
s = s.replace(/\.00$/, "");
|
|
38
|
+
return s;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { default as Json } from "./json";
|
|
2
|
+
export { default as Random } from "./random";
|
|
3
|
+
export { default as Format } from "./format";
|
|
4
|
+
export { default as PrintColored } from "./print_colored";
|
|
5
|
+
export { default as Encryptor } from "./encryptor";
|
|
6
|
+
export { default as Performance } from "./performance";
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,QAAQ,CAAC;AACzC,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC1D,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { default as Json } from "./json";
|
|
2
|
+
export { default as Random } from "./random";
|
|
3
|
+
export { default as Format } from "./format";
|
|
4
|
+
export { default as PrintColored } from "./print_colored";
|
|
5
|
+
export { default as Encryptor } from "./encryptor";
|
|
6
|
+
export { default as Performance } from "./performance";
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
type JsonObject = {
|
|
2
|
+
[key: string]: any;
|
|
3
|
+
};
|
|
4
|
+
export default class Json {
|
|
5
|
+
static isNull(v: string): boolean;
|
|
6
|
+
static isNumber(v: string): boolean;
|
|
7
|
+
static isDouble(v: string): boolean;
|
|
8
|
+
static isBoolean(v: string): boolean;
|
|
9
|
+
static isDate(v: string): boolean;
|
|
10
|
+
static isMap(v: string): boolean;
|
|
11
|
+
static parse(value: string): any;
|
|
12
|
+
static stringify(map: JsonObject): string;
|
|
13
|
+
static update(json: Record<string, any>, path: string, newValue: any): any;
|
|
14
|
+
static getNested(input: any, path: string): any;
|
|
15
|
+
static remove(input: any, path: string): any;
|
|
16
|
+
static mapToCSV(rows: JsonObject[]): string;
|
|
17
|
+
}
|
|
18
|
+
export {};
|
|
19
|
+
//# sourceMappingURL=json.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json.d.ts","sourceRoot":"","sources":["../../src/tools/json.ts"],"names":[],"mappings":"AAAA,KAAK,UAAU,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;CAAE,CAAC;AAEzC,MAAM,CAAC,OAAO,OAAO,IAAI;IACvB,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO;IAIjC,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO;IAInC,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO;IAInC,MAAM,CAAC,SAAS,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO;IAIpC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO;IAKjC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO;IAIhC,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG;IAuDhC,MAAM,CAAC,SAAS,CAAC,GAAG,EAAE,UAAU,GAAG,MAAM;IA2BzC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,GAAG,GAAG;IAyC1E,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,GAAG,GAAG;IAoC/C,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,GAAG,GAAG;IA4C5C,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,MAAM;CAkB5C"}
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
export default class Json {
|
|
2
|
+
static isNull(v) {
|
|
3
|
+
return v === "null" || v === "" || v === undefined || v === null;
|
|
4
|
+
}
|
|
5
|
+
static isNumber(v) {
|
|
6
|
+
return /^-?\d+$/.test(v);
|
|
7
|
+
}
|
|
8
|
+
static isDouble(v) {
|
|
9
|
+
return /^-?\d*\.\d+(e[+-]?\d+)?$/i.test(v);
|
|
10
|
+
}
|
|
11
|
+
static isBoolean(v) {
|
|
12
|
+
return v === "true" || v === "false";
|
|
13
|
+
}
|
|
14
|
+
static isDate(v) {
|
|
15
|
+
return /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:[Zz]|[+-]\d{2}:\d{2})?$/.test(v);
|
|
16
|
+
}
|
|
17
|
+
static isMap(v) {
|
|
18
|
+
return /^\s*{[\s\S]*}\s*$/.test(v);
|
|
19
|
+
}
|
|
20
|
+
static parse(value) {
|
|
21
|
+
if (typeof value === "string") {
|
|
22
|
+
const v = value.trim();
|
|
23
|
+
if (Json.isNull(v))
|
|
24
|
+
return null;
|
|
25
|
+
if (Json.isNumber(v))
|
|
26
|
+
return parseInt(v, 10);
|
|
27
|
+
if (Json.isDouble(v))
|
|
28
|
+
return parseFloat(v);
|
|
29
|
+
if (Json.isBoolean(v.toLowerCase()))
|
|
30
|
+
return v.toLowerCase() === "true";
|
|
31
|
+
if (Json.isDate(v)) {
|
|
32
|
+
const d = new Date(v);
|
|
33
|
+
if (!isNaN(d.valueOf()))
|
|
34
|
+
return d;
|
|
35
|
+
}
|
|
36
|
+
if (Json.isMap(v)) {
|
|
37
|
+
try {
|
|
38
|
+
let quoted = v;
|
|
39
|
+
quoted = quoted.replace(/([,{]\s*)([A-Za-z0-9_]+)\s*:/g, '$1"$2":');
|
|
40
|
+
quoted = quoted.replace(/:\s*([A-Za-z_][A-Za-z0-9_\s]*)/g, (m, val) => {
|
|
41
|
+
val = val.trim();
|
|
42
|
+
if (Json.isNumber(val) ||
|
|
43
|
+
Json.isDouble(val) ||
|
|
44
|
+
Json.isBoolean(val) ||
|
|
45
|
+
Json.isNull(val)) {
|
|
46
|
+
return ": " + val;
|
|
47
|
+
}
|
|
48
|
+
if (val.startsWith('"') || val.startsWith("'"))
|
|
49
|
+
return ": " + val.replace(/^'/, '"').replace(/'$/, '"');
|
|
50
|
+
return ': "' + val.replace(/"/g, '\\"') + '"';
|
|
51
|
+
});
|
|
52
|
+
const jsonObj = JSON.parse(quoted);
|
|
53
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
54
|
+
// @ts-ignore
|
|
55
|
+
function convert(obj) {
|
|
56
|
+
if (Array.isArray(obj))
|
|
57
|
+
return obj.map(convert);
|
|
58
|
+
if (obj && typeof obj === "object") {
|
|
59
|
+
let result = {};
|
|
60
|
+
for (let k in obj)
|
|
61
|
+
result[k] = convert(obj[k]);
|
|
62
|
+
return result;
|
|
63
|
+
}
|
|
64
|
+
if (typeof obj === "string")
|
|
65
|
+
return Json.parse(obj);
|
|
66
|
+
return obj;
|
|
67
|
+
}
|
|
68
|
+
return convert(jsonObj);
|
|
69
|
+
}
|
|
70
|
+
catch (_) { }
|
|
71
|
+
}
|
|
72
|
+
return value;
|
|
73
|
+
}
|
|
74
|
+
return value;
|
|
75
|
+
}
|
|
76
|
+
static stringify(map) {
|
|
77
|
+
function encodeValue(value) {
|
|
78
|
+
if (value == null || value === undefined) {
|
|
79
|
+
return "null";
|
|
80
|
+
}
|
|
81
|
+
else if (typeof value === "number" || typeof value === "boolean") {
|
|
82
|
+
return value.toString();
|
|
83
|
+
}
|
|
84
|
+
else if (value instanceof Date) {
|
|
85
|
+
return `"${value.toISOString()}"`;
|
|
86
|
+
}
|
|
87
|
+
else if (Array.isArray(value)) {
|
|
88
|
+
return "[" + value.map(encodeValue).join(", ") + "]";
|
|
89
|
+
}
|
|
90
|
+
else if (typeof value === "object" && value !== null) {
|
|
91
|
+
return Json.stringify(value);
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
let str = value.toString().replace(/"/g, '\\"');
|
|
95
|
+
return `"${str}"`;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return ("{" +
|
|
99
|
+
Object.entries(map)
|
|
100
|
+
.map(([key, val]) => `"${key}": ${encodeValue(val)}`)
|
|
101
|
+
.join(", ") +
|
|
102
|
+
"}");
|
|
103
|
+
}
|
|
104
|
+
static update(json, path, newValue) {
|
|
105
|
+
json = json || {};
|
|
106
|
+
if (!path)
|
|
107
|
+
return newValue;
|
|
108
|
+
const parts = path.split(".");
|
|
109
|
+
if (!parts.length)
|
|
110
|
+
return newValue;
|
|
111
|
+
const key = parts[0];
|
|
112
|
+
if (!key)
|
|
113
|
+
return newValue;
|
|
114
|
+
const restPath = parts.slice(1).join(".");
|
|
115
|
+
const index = /^[0-9]+$/.test(key) ? parseInt(key, 10) : undefined;
|
|
116
|
+
// Map/object case (or create a map)
|
|
117
|
+
if (index === undefined) {
|
|
118
|
+
let updated = typeof json === "object" && json !== null ? { ...json } : {};
|
|
119
|
+
if (!restPath) {
|
|
120
|
+
updated[key] = newValue;
|
|
121
|
+
return updated;
|
|
122
|
+
}
|
|
123
|
+
updated[key] = Json.update(updated.hasOwnProperty(key) ? updated[key] : null, restPath, newValue);
|
|
124
|
+
return updated;
|
|
125
|
+
}
|
|
126
|
+
// List/array case
|
|
127
|
+
else if (index >= 0) {
|
|
128
|
+
let list = Array.isArray(json) ? [...json] : [];
|
|
129
|
+
while (list.length <= index)
|
|
130
|
+
list.push(null);
|
|
131
|
+
if (!restPath) {
|
|
132
|
+
list[index] = newValue;
|
|
133
|
+
return list;
|
|
134
|
+
}
|
|
135
|
+
list[index] = Json.update(list[index], restPath, newValue);
|
|
136
|
+
return list;
|
|
137
|
+
}
|
|
138
|
+
return json;
|
|
139
|
+
}
|
|
140
|
+
static getNested(input, path) {
|
|
141
|
+
if (!path)
|
|
142
|
+
return input;
|
|
143
|
+
const parts = path.split(".");
|
|
144
|
+
if (!parts.length)
|
|
145
|
+
return input;
|
|
146
|
+
const key = parts[0];
|
|
147
|
+
if (!key)
|
|
148
|
+
return null;
|
|
149
|
+
const restPath = parts.slice(1).join(".");
|
|
150
|
+
const index = /^[0-9]+$/.test(key) ? parseInt(key, 10) : undefined;
|
|
151
|
+
if (input == null)
|
|
152
|
+
return null;
|
|
153
|
+
// Map/object case
|
|
154
|
+
if (typeof input === "object" &&
|
|
155
|
+
!Array.isArray(input) &&
|
|
156
|
+
index === undefined) {
|
|
157
|
+
if (!(key in input))
|
|
158
|
+
return null;
|
|
159
|
+
return restPath ? Json.getNested(input[key], restPath) : input[key];
|
|
160
|
+
}
|
|
161
|
+
// List/array case
|
|
162
|
+
else if (Array.isArray(input) &&
|
|
163
|
+
index !== undefined &&
|
|
164
|
+
index >= 0 &&
|
|
165
|
+
index < input.length) {
|
|
166
|
+
return restPath ? Json.getNested(input[index], restPath) : input[index];
|
|
167
|
+
}
|
|
168
|
+
return null; // leaf or invalid
|
|
169
|
+
}
|
|
170
|
+
static remove(input, path) {
|
|
171
|
+
if (!path)
|
|
172
|
+
return input;
|
|
173
|
+
const parts = path.split(".");
|
|
174
|
+
if (!parts.length)
|
|
175
|
+
return input;
|
|
176
|
+
const key = parts[0];
|
|
177
|
+
const restPath = parts.slice(1).join(".");
|
|
178
|
+
if (input == null)
|
|
179
|
+
return input;
|
|
180
|
+
const index = /^[0-9]+$/.test(key ?? "")
|
|
181
|
+
? parseInt(key ?? "", 10)
|
|
182
|
+
: undefined;
|
|
183
|
+
if (!key)
|
|
184
|
+
return null;
|
|
185
|
+
// Map/object
|
|
186
|
+
if (typeof input === "object" && !Array.isArray(input) && key in input) {
|
|
187
|
+
if (!restPath) {
|
|
188
|
+
let copy = { ...input };
|
|
189
|
+
delete copy[key];
|
|
190
|
+
return copy;
|
|
191
|
+
}
|
|
192
|
+
let copy = { ...input };
|
|
193
|
+
copy[key] = Json.remove(copy[key], restPath);
|
|
194
|
+
return copy;
|
|
195
|
+
}
|
|
196
|
+
// List/array
|
|
197
|
+
if (Array.isArray(input) &&
|
|
198
|
+
index !== undefined &&
|
|
199
|
+
index >= 0 &&
|
|
200
|
+
index < input.length) {
|
|
201
|
+
let copy = [...input];
|
|
202
|
+
if (!restPath) {
|
|
203
|
+
copy.splice(index, 1);
|
|
204
|
+
return copy;
|
|
205
|
+
}
|
|
206
|
+
copy[index] = Json.remove(copy[index], restPath);
|
|
207
|
+
return copy;
|
|
208
|
+
}
|
|
209
|
+
return input;
|
|
210
|
+
}
|
|
211
|
+
// Map to CSV
|
|
212
|
+
static mapToCSV(rows) {
|
|
213
|
+
if (!rows.length)
|
|
214
|
+
return "";
|
|
215
|
+
if (!rows[0])
|
|
216
|
+
return "";
|
|
217
|
+
const headers = Object.keys(rows[0]);
|
|
218
|
+
const csvRows = rows.map((row) => headers
|
|
219
|
+
.map((k) => {
|
|
220
|
+
let cell = row[k];
|
|
221
|
+
if (cell == null)
|
|
222
|
+
return "";
|
|
223
|
+
if (cell instanceof Date)
|
|
224
|
+
return cell.toISOString();
|
|
225
|
+
if (typeof cell === "object")
|
|
226
|
+
return JSON.stringify(cell);
|
|
227
|
+
return String(cell).replace(/"/g, '""');
|
|
228
|
+
})
|
|
229
|
+
.join(","));
|
|
230
|
+
return headers.join(",") + "\n" + csvRows.join("\n");
|
|
231
|
+
}
|
|
232
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export type PerformanceResult<T> = {
|
|
2
|
+
name: string;
|
|
3
|
+
duration: number;
|
|
4
|
+
durationFormatted: string;
|
|
5
|
+
data: T;
|
|
6
|
+
};
|
|
7
|
+
export default class Performance {
|
|
8
|
+
private stopwatchStart;
|
|
9
|
+
private stopwatchEnd;
|
|
10
|
+
readonly name: string;
|
|
11
|
+
constructor(name: string);
|
|
12
|
+
static test<T>(name: string, func: () => Promise<T> | T): Promise<PerformanceResult<T>>;
|
|
13
|
+
start(): void;
|
|
14
|
+
stop(): void;
|
|
15
|
+
printIt(): void;
|
|
16
|
+
get duration(): number;
|
|
17
|
+
get durationFormatted(): string;
|
|
18
|
+
toString(): string;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=performance.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"performance.d.ts","sourceRoot":"","sources":["../../src/tools/performance.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,iBAAiB,CAAC,CAAC,IAAI;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,IAAI,EAAE,CAAC,CAAC;CACT,CAAC;AAEF,MAAM,CAAC,OAAO,OAAO,WAAW;IAC9B,OAAO,CAAC,cAAc,CAAuB;IAC7C,OAAO,CAAC,YAAY,CAAuB;IAC3C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBAEV,IAAI,EAAE,MAAM;WAIX,IAAI,CAAC,CAAC,EACjB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,GACzB,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC;IAgBhC,KAAK,IAAI,IAAI;IAKb,IAAI,IAAI,IAAI;IAMZ,OAAO,IAAI,IAAI;IAIf,IAAI,QAAQ,IAAI,MAAM,CAQrB;IAED,IAAI,iBAAiB,IAAI,MAAM,CAO9B;IAED,QAAQ,IAAI,MAAM;CAGnB"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
export default class Performance {
|
|
2
|
+
stopwatchStart = null;
|
|
3
|
+
stopwatchEnd = null;
|
|
4
|
+
name;
|
|
5
|
+
constructor(name) {
|
|
6
|
+
this.name = name;
|
|
7
|
+
}
|
|
8
|
+
static async test(name, func) {
|
|
9
|
+
const performance = new Performance(name);
|
|
10
|
+
performance.start();
|
|
11
|
+
const result = await func();
|
|
12
|
+
performance.stop();
|
|
13
|
+
performance.printIt();
|
|
14
|
+
return {
|
|
15
|
+
name,
|
|
16
|
+
duration: performance.duration,
|
|
17
|
+
durationFormatted: performance.durationFormatted,
|
|
18
|
+
data: result,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
start() {
|
|
22
|
+
this.stopwatchStart = Date.now();
|
|
23
|
+
this.stopwatchEnd = null;
|
|
24
|
+
}
|
|
25
|
+
stop() {
|
|
26
|
+
if (this.stopwatchStart !== null) {
|
|
27
|
+
this.stopwatchEnd = Date.now();
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
printIt() {
|
|
31
|
+
console.log(this.durationFormatted);
|
|
32
|
+
}
|
|
33
|
+
get duration() {
|
|
34
|
+
if (this.stopwatchStart !== null && this.stopwatchEnd !== null) {
|
|
35
|
+
return this.stopwatchEnd - this.stopwatchStart;
|
|
36
|
+
}
|
|
37
|
+
if (this.stopwatchStart !== null && this.stopwatchEnd === null) {
|
|
38
|
+
return Date.now() - this.stopwatchStart;
|
|
39
|
+
}
|
|
40
|
+
return 0;
|
|
41
|
+
}
|
|
42
|
+
get durationFormatted() {
|
|
43
|
+
const durationMs = this.duration;
|
|
44
|
+
const microseconds = durationMs * 1000;
|
|
45
|
+
const milliseconds = durationMs;
|
|
46
|
+
const seconds = durationMs / 1000;
|
|
47
|
+
const minutes = seconds / 60;
|
|
48
|
+
return `${this.name} [${microseconds.toFixed(0)} µs | ${milliseconds.toFixed(0)} ms | ${seconds.toFixed(3)} s | ${minutes.toFixed(2)} mn]`;
|
|
49
|
+
}
|
|
50
|
+
toString() {
|
|
51
|
+
return this.durationFormatted;
|
|
52
|
+
}
|
|
53
|
+
}
|