@keeex/utils 7.0.1
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/LICENSE +9 -0
- package/README.md +105 -0
- package/lib/array.d.ts +28 -0
- package/lib/array.js +36 -0
- package/lib/arraybuffer.d.ts +138 -0
- package/lib/arraybuffer.js +141 -0
- package/lib/async/asynctrigger.d.ts +50 -0
- package/lib/async/asynctrigger.js +108 -0
- package/lib/async/deferredpromise.d.ts +32 -0
- package/lib/async/deferredpromise.js +66 -0
- package/lib/async/keycache.d.ts +56 -0
- package/lib/async/keycache.js +103 -0
- package/lib/async/queues.d.ts +69 -0
- package/lib/async/queues.js +135 -0
- package/lib/async/timecache.d.ts +58 -0
- package/lib/async/timecache.js +118 -0
- package/lib/base58.d.ts +27 -0
- package/lib/base58.js +83 -0
- package/lib/base64.d.ts +51 -0
- package/lib/base64.js +126 -0
- package/lib/benchmark.d.ts +126 -0
- package/lib/benchmark.js +177 -0
- package/lib/bits/arraybuffer.d.ts +35 -0
- package/lib/bits/arraybuffer.js +64 -0
- package/lib/bits/base64.d.ts +35 -0
- package/lib/bits/base64.js +70 -0
- package/lib/bits/hex.d.ts +17 -0
- package/lib/bits/hex.js +30 -0
- package/lib/bits/uint8array.d.ts +28 -0
- package/lib/bits/uint8array.js +42 -0
- package/lib/bytebuffer.d.ts +27 -0
- package/lib/bytebuffer.js +29 -0
- package/lib/consts.d.ts +33 -0
- package/lib/consts.js +33 -0
- package/lib/cron/logger.d.ts +22 -0
- package/lib/cron/logger.js +31 -0
- package/lib/cron/scheduledtask.d.ts +71 -0
- package/lib/cron/scheduledtask.js +137 -0
- package/lib/cron/types.d.ts +53 -0
- package/lib/cron/types.js +31 -0
- package/lib/cron.d.ts +29 -0
- package/lib/cron.js +47 -0
- package/lib/dict.d.ts +56 -0
- package/lib/dict.js +74 -0
- package/lib/error.d.ts +25 -0
- package/lib/error.js +41 -0
- package/lib/global.d.ts +27 -0
- package/lib/global.js +53 -0
- package/lib/hex.d.ts +32 -0
- package/lib/hex.js +58 -0
- package/lib/idx.d.ts +51 -0
- package/lib/idx.js +81 -0
- package/lib/json.d.ts +57 -0
- package/lib/json.js +116 -0
- package/lib/marshalling/marshaller.d.ts +51 -0
- package/lib/marshalling/marshaller.js +155 -0
- package/lib/marshalling/unmarshaller.d.ts +53 -0
- package/lib/marshalling/unmarshaller.js +124 -0
- package/lib/marshalling/util.d.ts +25 -0
- package/lib/marshalling/util.js +25 -0
- package/lib/number.d.ts +17 -0
- package/lib/number.js +21 -0
- package/lib/path.d.ts +25 -0
- package/lib/path.js +29 -0
- package/lib/promise.d.ts +42 -0
- package/lib/promise.js +78 -0
- package/lib/starttime.d.ts +23 -0
- package/lib/starttime.js +29 -0
- package/lib/string.d.ts +65 -0
- package/lib/string.js +108 -0
- package/lib/types/array.d.ts +34 -0
- package/lib/types/array.js +64 -0
- package/lib/types/enum.d.ts +30 -0
- package/lib/types/enum.js +44 -0
- package/lib/types/predicateerror.d.ts +40 -0
- package/lib/types/predicateerror.js +107 -0
- package/lib/types/primitive.d.ts +23 -0
- package/lib/types/primitive.js +34 -0
- package/lib/types/record.d.ts +67 -0
- package/lib/types/record.js +235 -0
- package/lib/types/types.d.ts +64 -0
- package/lib/types/types.js +115 -0
- package/lib/types/utils.d.ts +18 -0
- package/lib/types/utils.js +67 -0
- package/lib/uint8array.d.ts +176 -0
- package/lib/uint8array.js +438 -0
- package/lib/units.d.ts +159 -0
- package/lib/units.js +290 -0
- package/lib/utils/buffer.d.ts +49 -0
- package/lib/utils/buffer.js +79 -0
- package/lib/utils/fourbytes.d.ts +29 -0
- package/lib/utils/fourbytes.js +45 -0
- package/package.json +1 -0
- package/web/array.d.ts +28 -0
- package/web/array.js +34 -0
- package/web/arraybuffer.d.ts +138 -0
- package/web/arraybuffer.js +141 -0
- package/web/async/asynctrigger.d.ts +50 -0
- package/web/async/asynctrigger.js +106 -0
- package/web/async/deferredpromise.d.ts +32 -0
- package/web/async/deferredpromise.js +65 -0
- package/web/async/keycache.d.ts +56 -0
- package/web/async/keycache.js +97 -0
- package/web/async/queues.d.ts +69 -0
- package/web/async/queues.js +131 -0
- package/web/async/timecache.d.ts +58 -0
- package/web/async/timecache.js +107 -0
- package/web/base58.d.ts +27 -0
- package/web/base58.js +78 -0
- package/web/base64.d.ts +51 -0
- package/web/base64.js +136 -0
- package/web/benchmark.d.ts +126 -0
- package/web/benchmark.js +183 -0
- package/web/bits/arraybuffer.d.ts +35 -0
- package/web/bits/arraybuffer.js +59 -0
- package/web/bits/base64.d.ts +35 -0
- package/web/bits/base64.js +67 -0
- package/web/bits/hex.d.ts +17 -0
- package/web/bits/hex.js +27 -0
- package/web/bits/uint8array.d.ts +28 -0
- package/web/bits/uint8array.js +41 -0
- package/web/bytebuffer.d.ts +27 -0
- package/web/bytebuffer.js +29 -0
- package/web/consts.d.ts +33 -0
- package/web/consts.js +33 -0
- package/web/cron/logger.d.ts +22 -0
- package/web/cron/logger.js +30 -0
- package/web/cron/scheduledtask.d.ts +71 -0
- package/web/cron/scheduledtask.js +136 -0
- package/web/cron/types.d.ts +53 -0
- package/web/cron/types.js +31 -0
- package/web/cron.d.ts +29 -0
- package/web/cron.js +47 -0
- package/web/dict.d.ts +56 -0
- package/web/dict.js +67 -0
- package/web/error.d.ts +25 -0
- package/web/error.js +39 -0
- package/web/global.d.ts +27 -0
- package/web/global.js +49 -0
- package/web/hex.d.ts +32 -0
- package/web/hex.js +52 -0
- package/web/idx.d.ts +51 -0
- package/web/idx.js +76 -0
- package/web/json.d.ts +57 -0
- package/web/json.js +98 -0
- package/web/marshalling/marshaller.d.ts +51 -0
- package/web/marshalling/marshaller.js +150 -0
- package/web/marshalling/unmarshaller.d.ts +53 -0
- package/web/marshalling/unmarshaller.js +115 -0
- package/web/marshalling/util.d.ts +25 -0
- package/web/marshalling/util.js +25 -0
- package/web/number.d.ts +17 -0
- package/web/number.js +21 -0
- package/web/path.d.ts +25 -0
- package/web/path.js +26 -0
- package/web/promise.d.ts +42 -0
- package/web/promise.js +74 -0
- package/web/starttime.d.ts +23 -0
- package/web/starttime.js +29 -0
- package/web/string.d.ts +65 -0
- package/web/string.js +101 -0
- package/web/types/array.d.ts +34 -0
- package/web/types/array.js +63 -0
- package/web/types/enum.d.ts +30 -0
- package/web/types/enum.js +40 -0
- package/web/types/predicateerror.d.ts +40 -0
- package/web/types/predicateerror.js +128 -0
- package/web/types/primitive.d.ts +23 -0
- package/web/types/primitive.js +33 -0
- package/web/types/record.d.ts +67 -0
- package/web/types/record.js +213 -0
- package/web/types/types.d.ts +64 -0
- package/web/types/types.js +123 -0
- package/web/types/utils.d.ts +18 -0
- package/web/types/utils.js +30 -0
- package/web/uint8array.d.ts +176 -0
- package/web/uint8array.js +412 -0
- package/web/units.d.ts +159 -0
- package/web/units.js +312 -0
- package/web/utils/buffer.d.ts +49 -0
- package/web/utils/buffer.js +76 -0
- package/web/utils/fourbytes.d.ts +29 -0
- package/web/utils/fourbytes.js +45 -0
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* @preserve
|
|
4
|
+
*
|
|
5
|
+
* MIT License
|
|
6
|
+
*
|
|
7
|
+
* Copyright (c) 2023 KeeeX SAS
|
|
8
|
+
*
|
|
9
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
10
|
+
*
|
|
11
|
+
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
12
|
+
*
|
|
13
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
14
|
+
*
|
|
15
|
+
*/
|
|
16
|
+
/* eslint-disable no-console */
|
|
17
|
+
// Heavily based on https://stackoverflow.com/a/34637436/2059163
|
|
18
|
+
/**
|
|
19
|
+
* Allows returning a promise and resolving it in another scope
|
|
20
|
+
*
|
|
21
|
+
* @public
|
|
22
|
+
*/
|
|
23
|
+
export class DeferredPromise {
|
|
24
|
+
/** The actual promise that can be awaited */
|
|
25
|
+
promise;
|
|
26
|
+
#resolveFunc;
|
|
27
|
+
#rejectFunc;
|
|
28
|
+
#resolved = false;
|
|
29
|
+
constructor() {
|
|
30
|
+
// eslint-disable-next-line @typescript-eslint/init-declarations
|
|
31
|
+
let resolveFunc;
|
|
32
|
+
// eslint-disable-next-line @typescript-eslint/init-declarations
|
|
33
|
+
let rejectFunc;
|
|
34
|
+
// eslint-disable-next-line promise/avoid-new
|
|
35
|
+
this.promise = new Promise((resolve, reject) => {
|
|
36
|
+
resolveFunc = resolve;
|
|
37
|
+
rejectFunc = reject;
|
|
38
|
+
});
|
|
39
|
+
if (!resolveFunc || !rejectFunc)
|
|
40
|
+
throw new Error("Unexpected state");
|
|
41
|
+
this.#resolveFunc = resolveFunc;
|
|
42
|
+
this.#rejectFunc = rejectFunc;
|
|
43
|
+
}
|
|
44
|
+
/** Indicate if the promise already resolved or rejected. */
|
|
45
|
+
get resolved() {
|
|
46
|
+
return this.#resolved;
|
|
47
|
+
}
|
|
48
|
+
/** Can be called from anywhere; will resolve the promise. */
|
|
49
|
+
resolve = (value) => {
|
|
50
|
+
if (this.#resolved) {
|
|
51
|
+
console.warn("Promise resolved multiple time; ignoring");
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
this.#resolved = true;
|
|
55
|
+
this.#resolveFunc(value);
|
|
56
|
+
};
|
|
57
|
+
/** Can be called from anywhere; will reject the promise. */
|
|
58
|
+
reject = (reason) => {
|
|
59
|
+
if (this.#resolved) {
|
|
60
|
+
console.warn("Promise resolved multiple time; ignoring");
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
this.#resolved = true;
|
|
64
|
+
this.#rejectFunc(reason);
|
|
65
|
+
};
|
|
66
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* @preserve
|
|
4
|
+
*
|
|
5
|
+
* MIT License
|
|
6
|
+
*
|
|
7
|
+
* Copyright (c) 2023 KeeeX SAS
|
|
8
|
+
*
|
|
9
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
10
|
+
*
|
|
11
|
+
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
12
|
+
*
|
|
13
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
14
|
+
*
|
|
15
|
+
*/
|
|
16
|
+
import { Awaitable } from "../types/types.js";
|
|
17
|
+
/**
|
|
18
|
+
* Function used to fill a cache entry on a cache miss.
|
|
19
|
+
*
|
|
20
|
+
* @param key - The requested key
|
|
21
|
+
*
|
|
22
|
+
* @returns
|
|
23
|
+
* The requested entry, or undefined if the value does not exist.
|
|
24
|
+
*/
|
|
25
|
+
export type CacheGetFunc<ValueType> = (key: string) => Awaitable<ValueType | undefined>;
|
|
26
|
+
/**
|
|
27
|
+
* Basic key-value cache mechanism.
|
|
28
|
+
*
|
|
29
|
+
* Discards old data based on last access.
|
|
30
|
+
* Cache entries can be fetched asynchronously; multiple fetch on the same value will share the same
|
|
31
|
+
* promise.
|
|
32
|
+
*
|
|
33
|
+
* @public
|
|
34
|
+
*/
|
|
35
|
+
export default class KeyCache<ValueType = string> {
|
|
36
|
+
#private;
|
|
37
|
+
/**
|
|
38
|
+
* Constructor.
|
|
39
|
+
*
|
|
40
|
+
* @param maxEntries - Maximum number of entries kept. Once more entries are added, oldest entries
|
|
41
|
+
* are discarded based on last access time.
|
|
42
|
+
*
|
|
43
|
+
* @param getFunc - A function to fetch missing cache entries.
|
|
44
|
+
* If the function returns undefined, the value is not cached. If the function throws, the error
|
|
45
|
+
* is kept (and requesting this entry again will return the rejected promise.
|
|
46
|
+
*/
|
|
47
|
+
constructor(maxEntries?: number, getFunc?: CacheGetFunc<ValueType>);
|
|
48
|
+
get cache(): Record<string, Promise<ValueType | undefined>>;
|
|
49
|
+
get keys(): Array<string>;
|
|
50
|
+
/** Return a cache entry if present. */
|
|
51
|
+
get: (key: string) => Promise<ValueType | undefined>;
|
|
52
|
+
/** Manually set a cache entry. */
|
|
53
|
+
set: (key: string, value: Awaitable<ValueType>) => this;
|
|
54
|
+
/** Remove a stale entry. */
|
|
55
|
+
remove: (key: string) => this;
|
|
56
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* @preserve
|
|
4
|
+
*
|
|
5
|
+
* MIT License
|
|
6
|
+
*
|
|
7
|
+
* Copyright (c) 2023 KeeeX SAS
|
|
8
|
+
*
|
|
9
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
10
|
+
*
|
|
11
|
+
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
12
|
+
*
|
|
13
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
14
|
+
*
|
|
15
|
+
*/
|
|
16
|
+
import { dropPromise } from "../promise.js";
|
|
17
|
+
/**
|
|
18
|
+
* Basic key-value cache mechanism.
|
|
19
|
+
*
|
|
20
|
+
* Discards old data based on last access.
|
|
21
|
+
* Cache entries can be fetched asynchronously; multiple fetch on the same value will share the same
|
|
22
|
+
* promise.
|
|
23
|
+
*
|
|
24
|
+
* @public
|
|
25
|
+
*/
|
|
26
|
+
export default class KeyCache {
|
|
27
|
+
#cache = {};
|
|
28
|
+
#keys = [];
|
|
29
|
+
#maxEntries;
|
|
30
|
+
#getFunc;
|
|
31
|
+
/**
|
|
32
|
+
* Constructor.
|
|
33
|
+
*
|
|
34
|
+
* @param maxEntries - Maximum number of entries kept. Once more entries are added, oldest entries
|
|
35
|
+
* are discarded based on last access time.
|
|
36
|
+
*
|
|
37
|
+
* @param getFunc - A function to fetch missing cache entries.
|
|
38
|
+
* If the function returns undefined, the value is not cached. If the function throws, the error
|
|
39
|
+
* is kept (and requesting this entry again will return the rejected promise.
|
|
40
|
+
*/
|
|
41
|
+
constructor(maxEntries = 1000, getFunc) {
|
|
42
|
+
this.#maxEntries = maxEntries;
|
|
43
|
+
this.#getFunc = getFunc;
|
|
44
|
+
}
|
|
45
|
+
get cache() {
|
|
46
|
+
return this.#cache;
|
|
47
|
+
}
|
|
48
|
+
get keys() {
|
|
49
|
+
return this.#keys;
|
|
50
|
+
}
|
|
51
|
+
/** Return a cache entry if present. */
|
|
52
|
+
get = async (key) => {
|
|
53
|
+
if (key in this.#cache)
|
|
54
|
+
return this.#cache[key];
|
|
55
|
+
if (this.#getFunc)
|
|
56
|
+
return this.#addKey(key, this.#getFunc(key));
|
|
57
|
+
};
|
|
58
|
+
/** Manually set a cache entry. */
|
|
59
|
+
set = (key, value) => {
|
|
60
|
+
dropPromise(this.#addKey(key, value));
|
|
61
|
+
return this;
|
|
62
|
+
};
|
|
63
|
+
/** Remove a stale entry. */
|
|
64
|
+
remove = (key) => {
|
|
65
|
+
this.#removeKey(key);
|
|
66
|
+
return this;
|
|
67
|
+
};
|
|
68
|
+
/** Add a cache entry, purging older ones if needed */
|
|
69
|
+
#addKey = (key, valuePromise) => {
|
|
70
|
+
const res = async () => {
|
|
71
|
+
const value = await valuePromise;
|
|
72
|
+
if (value === undefined) {
|
|
73
|
+
this.#removeKey(key);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
return value;
|
|
77
|
+
};
|
|
78
|
+
const promise = res();
|
|
79
|
+
if (!(key in this.#cache))
|
|
80
|
+
this.#keys.push(key);
|
|
81
|
+
this.#cache[key] = promise;
|
|
82
|
+
this.#trim();
|
|
83
|
+
return promise;
|
|
84
|
+
};
|
|
85
|
+
/** Remove a specific key from the cache */
|
|
86
|
+
#removeKey = (key) => {
|
|
87
|
+
if (!(key in this.#cache))
|
|
88
|
+
return;
|
|
89
|
+
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
|
|
90
|
+
delete this.#cache[key];
|
|
91
|
+
this.#keys.splice(this.#keys.indexOf(key), 1);
|
|
92
|
+
};
|
|
93
|
+
/** Remove excess entries */
|
|
94
|
+
#trim = () => {
|
|
95
|
+
const entriesToTrim = Math.max(0, this.#keys.length - this.#maxEntries);
|
|
96
|
+
if (entriesToTrim <= 0)
|
|
97
|
+
return;
|
|
98
|
+
const keysToTrim = this.#keys.splice(0, entriesToTrim);
|
|
99
|
+
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
|
|
100
|
+
for (const keyToTrim of keysToTrim)
|
|
101
|
+
delete this.#cache[keyToTrim];
|
|
102
|
+
};
|
|
103
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* @preserve
|
|
4
|
+
*
|
|
5
|
+
* MIT License
|
|
6
|
+
*
|
|
7
|
+
* Copyright (c) 2023 KeeeX SAS
|
|
8
|
+
*
|
|
9
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
10
|
+
*
|
|
11
|
+
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
12
|
+
*
|
|
13
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
14
|
+
*
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* Task function definition.
|
|
18
|
+
*
|
|
19
|
+
* @param params - is the argument passed to the `runTask()` method
|
|
20
|
+
* @param queueId - The queue identifier, starting at 0
|
|
21
|
+
*
|
|
22
|
+
* @public
|
|
23
|
+
*/
|
|
24
|
+
export type TaskFunc<TaskParams, TaskResult> = (params: TaskParams, queueId: number) => Promise<TaskResult>;
|
|
25
|
+
/**
|
|
26
|
+
* Customizing the handling of a task
|
|
27
|
+
*
|
|
28
|
+
* @public
|
|
29
|
+
*/
|
|
30
|
+
export interface TaskOptions {
|
|
31
|
+
/** Put the task in front of a queue instead of in the back */
|
|
32
|
+
priority?: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Force using the specified queue.
|
|
35
|
+
* This bypass the "max queued items" check.
|
|
36
|
+
*/
|
|
37
|
+
forceQueueId?: number;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Run asynchronous tasks in controlled queues.
|
|
41
|
+
*
|
|
42
|
+
* The task function is shared among all queues.
|
|
43
|
+
* Each queue runs one operation at a time.
|
|
44
|
+
* Queued tasks can be run in parallel, and each will be given it's queue ID to distinguish them.
|
|
45
|
+
*
|
|
46
|
+
* For example, if you setup 3 queues and schedule 10 tasks, they might run like this (each queue
|
|
47
|
+
* running only one task at a time)
|
|
48
|
+
*
|
|
49
|
+
* - Queue 1: T0, T2, T5, T3
|
|
50
|
+
* - Queue 2: T1, T3, T6, T7
|
|
51
|
+
* - Queue 3: T4, T8, T9
|
|
52
|
+
*
|
|
53
|
+
* @public
|
|
54
|
+
*/
|
|
55
|
+
export declare class Queues<TaskParams, TaskResult> {
|
|
56
|
+
#private;
|
|
57
|
+
/**
|
|
58
|
+
* @param maxQueuedItems - Maximum number of tasks pending. This is rounded up so that all queues
|
|
59
|
+
* have the same maximum.
|
|
60
|
+
*/
|
|
61
|
+
constructor(task: TaskFunc<TaskParams, TaskResult>, queuesCount: number, maxQueuedItems: number);
|
|
62
|
+
/**
|
|
63
|
+
* Run a task.
|
|
64
|
+
* As specified in the description, only one task per queue runs at a time.
|
|
65
|
+
*
|
|
66
|
+
* If the maximum queue length is reached, throws.
|
|
67
|
+
*/
|
|
68
|
+
runTask: (taskParams: TaskParams, options?: TaskOptions) => Promise<TaskResult>;
|
|
69
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* @preserve
|
|
4
|
+
*
|
|
5
|
+
* MIT License
|
|
6
|
+
*
|
|
7
|
+
* Copyright (c) 2023 KeeeX SAS
|
|
8
|
+
*
|
|
9
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
10
|
+
*
|
|
11
|
+
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
12
|
+
*
|
|
13
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
14
|
+
*
|
|
15
|
+
*/
|
|
16
|
+
import { dropPromise } from "../promise.js";
|
|
17
|
+
import { DeferredPromise } from "./deferredpromise.js";
|
|
18
|
+
/**
|
|
19
|
+
* Run asynchronous tasks in controlled queues.
|
|
20
|
+
*
|
|
21
|
+
* The task function is shared among all queues.
|
|
22
|
+
* Each queue runs one operation at a time.
|
|
23
|
+
* Queued tasks can be run in parallel, and each will be given it's queue ID to distinguish them.
|
|
24
|
+
*
|
|
25
|
+
* For example, if you setup 3 queues and schedule 10 tasks, they might run like this (each queue
|
|
26
|
+
* running only one task at a time)
|
|
27
|
+
*
|
|
28
|
+
* - Queue 1: T0, T2, T5, T3
|
|
29
|
+
* - Queue 2: T1, T3, T6, T7
|
|
30
|
+
* - Queue 3: T4, T8, T9
|
|
31
|
+
*
|
|
32
|
+
* @public
|
|
33
|
+
*/
|
|
34
|
+
export class Queues {
|
|
35
|
+
/** Function to run a single task */
|
|
36
|
+
#task;
|
|
37
|
+
/** Maximum length of each queue */
|
|
38
|
+
#maxQueueLength;
|
|
39
|
+
/** Pending tasks */
|
|
40
|
+
#queues;
|
|
41
|
+
/** Flag to control wether a queue needs to be started or not */
|
|
42
|
+
#queueRunning;
|
|
43
|
+
/**
|
|
44
|
+
* @param maxQueuedItems - Maximum number of tasks pending. This is rounded up so that all queues
|
|
45
|
+
* have the same maximum.
|
|
46
|
+
*/
|
|
47
|
+
constructor(task, queuesCount, maxQueuedItems) {
|
|
48
|
+
this.#task = task;
|
|
49
|
+
this.#maxQueueLength = Math.ceil(maxQueuedItems / queuesCount);
|
|
50
|
+
this.#queues = [];
|
|
51
|
+
this.#queueRunning = [];
|
|
52
|
+
for (let i = 0; i < queuesCount; ++i) {
|
|
53
|
+
this.#queues.push([]);
|
|
54
|
+
this.#queueRunning[i] = false;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Run a task.
|
|
59
|
+
* As specified in the description, only one task per queue runs at a time.
|
|
60
|
+
*
|
|
61
|
+
* If the maximum queue length is reached, throws.
|
|
62
|
+
*/
|
|
63
|
+
runTask = (taskParams, options = {}) => {
|
|
64
|
+
const taskDef = {
|
|
65
|
+
deferred: new DeferredPromise(),
|
|
66
|
+
taskOptions: options,
|
|
67
|
+
taskParams,
|
|
68
|
+
};
|
|
69
|
+
this.#addToQueue(taskDef);
|
|
70
|
+
return taskDef.deferred.promise;
|
|
71
|
+
};
|
|
72
|
+
/** Return the queue to use for this task */
|
|
73
|
+
#getTargetQueue = (taskDef) => {
|
|
74
|
+
if (taskDef.taskOptions.forceQueueId !== undefined) {
|
|
75
|
+
const target = taskDef.taskOptions.forceQueueId;
|
|
76
|
+
if (target < 0 || target >= this.#queues.length) {
|
|
77
|
+
throw new Error("Forced queue ID is invalid");
|
|
78
|
+
}
|
|
79
|
+
return target;
|
|
80
|
+
}
|
|
81
|
+
// Find shortest queue
|
|
82
|
+
let shortestId = null;
|
|
83
|
+
let shortestLength = this.#maxQueueLength;
|
|
84
|
+
for (let i = 0; i < this.#queues.length && shortestLength > 0; ++i) {
|
|
85
|
+
const queueLength = this.#queues[i].length + (this.#queueRunning[i] ? 1 : 0);
|
|
86
|
+
if (queueLength < shortestLength) {
|
|
87
|
+
shortestLength = queueLength;
|
|
88
|
+
shortestId = i;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
if (shortestId === null) {
|
|
92
|
+
throw new Error("Max queue length exceeded");
|
|
93
|
+
}
|
|
94
|
+
return shortestId;
|
|
95
|
+
};
|
|
96
|
+
/** Add a task definition to the currently shortest queue */
|
|
97
|
+
#addToQueue = (taskDef) => {
|
|
98
|
+
const targetQueue = this.#getTargetQueue(taskDef);
|
|
99
|
+
if (taskDef.taskOptions.priority) {
|
|
100
|
+
this.#queues[targetQueue].splice(0, 0, taskDef);
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
this.#queues[targetQueue].push(taskDef);
|
|
104
|
+
}
|
|
105
|
+
if (this.#queues[targetQueue].length === 1)
|
|
106
|
+
dropPromise(this.#runQueue(targetQueue));
|
|
107
|
+
};
|
|
108
|
+
/**
|
|
109
|
+
* Start running a single queue.
|
|
110
|
+
* The function will keep going until the queue is empty.
|
|
111
|
+
* It can safely be called multiple time with the same queueId.
|
|
112
|
+
*/
|
|
113
|
+
#runQueue = async (queueId) => {
|
|
114
|
+
if (this.#queueRunning[queueId]) {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
try {
|
|
118
|
+
this.#queueRunning[queueId] = true;
|
|
119
|
+
while (this.#queues[queueId].length > 0) {
|
|
120
|
+
const taskDef = this.#queues[queueId].splice(0, 1)[0];
|
|
121
|
+
try {
|
|
122
|
+
// eslint-disable-next-line no-await-in-loop
|
|
123
|
+
const res = await this.#task(taskDef.taskParams, queueId);
|
|
124
|
+
taskDef.deferred.resolve(res);
|
|
125
|
+
}
|
|
126
|
+
catch (e) {
|
|
127
|
+
taskDef.deferred.reject(e);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
finally {
|
|
132
|
+
this.#queueRunning[queueId] = false;
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* @preserve
|
|
4
|
+
*
|
|
5
|
+
* MIT License
|
|
6
|
+
*
|
|
7
|
+
* Copyright (c) 2023 KeeeX SAS
|
|
8
|
+
*
|
|
9
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
10
|
+
*
|
|
11
|
+
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
12
|
+
*
|
|
13
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
14
|
+
*
|
|
15
|
+
*/
|
|
16
|
+
import { Awaitable } from "../types/types.js";
|
|
17
|
+
/** Function used to refresh a timed cache */
|
|
18
|
+
export type ProbeFunc<T> = () => Awaitable<T>;
|
|
19
|
+
type HandlerFunc<T> = (error?: Error, value?: T) => void;
|
|
20
|
+
/** Constructor parameters for `TimeCache` */
|
|
21
|
+
interface TimeCacheCtor<T> {
|
|
22
|
+
/** Function used to refresh the cached value */
|
|
23
|
+
probeFunc: ProbeFunc<T>;
|
|
24
|
+
/** Duration of the cached result, in ms */
|
|
25
|
+
cacheDurationMs: number;
|
|
26
|
+
/**
|
|
27
|
+
* Set to true to refresh (call the probe function) automatically, even if the value isn't read.
|
|
28
|
+
*
|
|
29
|
+
* When false (the default), the probe function will only be called as a result of querying the
|
|
30
|
+
* cached value outside of its cache duration.
|
|
31
|
+
*/
|
|
32
|
+
autoProbe: boolean;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Remember a value for the specified amount of time, and reprobe it when needed.
|
|
36
|
+
*
|
|
37
|
+
* This support automatic probing over time and update callbacks.
|
|
38
|
+
*
|
|
39
|
+
* @public
|
|
40
|
+
*/
|
|
41
|
+
export default class TimeCache<T> {
|
|
42
|
+
#private;
|
|
43
|
+
constructor(params: TimeCacheCtor<T>);
|
|
44
|
+
get value(): Promise<T>;
|
|
45
|
+
get autoProbe(): boolean;
|
|
46
|
+
set autoProbe(value: boolean);
|
|
47
|
+
/**
|
|
48
|
+
* Setup a callback triggered when the value is updated.
|
|
49
|
+
*
|
|
50
|
+
* When auto-update is disabled, these handler still get called when the value is manually probed.
|
|
51
|
+
*/
|
|
52
|
+
onUpdate: (handler: HandlerFunc<T>) => void;
|
|
53
|
+
/**
|
|
54
|
+
* Remove a callback previously registered with `onUpdate()`.
|
|
55
|
+
*/
|
|
56
|
+
offUpdate: (handler: HandlerFunc<T>) => void;
|
|
57
|
+
}
|
|
58
|
+
export {};
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* @preserve
|
|
4
|
+
*
|
|
5
|
+
* MIT License
|
|
6
|
+
*
|
|
7
|
+
* Copyright (c) 2023 KeeeX SAS
|
|
8
|
+
*
|
|
9
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
10
|
+
*
|
|
11
|
+
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
12
|
+
*
|
|
13
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
14
|
+
*
|
|
15
|
+
*/
|
|
16
|
+
import { asError } from "../error.js";
|
|
17
|
+
/**
|
|
18
|
+
* Remember a value for the specified amount of time, and reprobe it when needed.
|
|
19
|
+
*
|
|
20
|
+
* This support automatic probing over time and update callbacks.
|
|
21
|
+
*
|
|
22
|
+
* @public
|
|
23
|
+
*/
|
|
24
|
+
export default class TimeCache {
|
|
25
|
+
#probeFunction;
|
|
26
|
+
#cacheDurationMs;
|
|
27
|
+
#autoProbe;
|
|
28
|
+
#loadedPromise;
|
|
29
|
+
#lastRefreshTime;
|
|
30
|
+
#nextRefreshTimeout;
|
|
31
|
+
#updateHandlers = [];
|
|
32
|
+
constructor(params) {
|
|
33
|
+
this.#probeFunction = params.probeFunc;
|
|
34
|
+
this.#cacheDurationMs = params.cacheDurationMs;
|
|
35
|
+
this.#autoProbe = params.autoProbe;
|
|
36
|
+
if (this.#autoProbe)
|
|
37
|
+
this.#probeTime();
|
|
38
|
+
}
|
|
39
|
+
get value() {
|
|
40
|
+
if (!this.#autoProbe)
|
|
41
|
+
this.#manualRefresh();
|
|
42
|
+
if (!this.#loadedPromise)
|
|
43
|
+
throw new Error("Unexpected state");
|
|
44
|
+
return this.#loadedPromise;
|
|
45
|
+
}
|
|
46
|
+
get autoProbe() {
|
|
47
|
+
return this.#autoProbe;
|
|
48
|
+
}
|
|
49
|
+
set autoProbe(value) {
|
|
50
|
+
if (this.#autoProbe === value)
|
|
51
|
+
return;
|
|
52
|
+
this.#autoProbe = value;
|
|
53
|
+
if (this.#autoProbe) {
|
|
54
|
+
this.#armAutoProbe();
|
|
55
|
+
}
|
|
56
|
+
else if (this.#nextRefreshTimeout) {
|
|
57
|
+
clearTimeout(this.#nextRefreshTimeout);
|
|
58
|
+
this.#nextRefreshTimeout = undefined;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Setup a callback triggered when the value is updated.
|
|
63
|
+
*
|
|
64
|
+
* When auto-update is disabled, these handler still get called when the value is manually probed.
|
|
65
|
+
*/
|
|
66
|
+
onUpdate = (handler) => {
|
|
67
|
+
this.#updateHandlers.push(handler);
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* Remove a callback previously registered with `onUpdate()`.
|
|
71
|
+
*/
|
|
72
|
+
offUpdate = (handler) => {
|
|
73
|
+
const id = this.#updateHandlers.lastIndexOf(handler);
|
|
74
|
+
if (id !== -1)
|
|
75
|
+
this.#updateHandlers.splice(id, 1);
|
|
76
|
+
};
|
|
77
|
+
/** Helper to setup #loadedPromise */
|
|
78
|
+
#callProbeFunction = async () => {
|
|
79
|
+
try {
|
|
80
|
+
const res = await this.#probeFunction();
|
|
81
|
+
this.#callHandler(undefined, res);
|
|
82
|
+
return res;
|
|
83
|
+
}
|
|
84
|
+
catch (e) {
|
|
85
|
+
this.#callHandler(asError(e));
|
|
86
|
+
throw e;
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
#callHandler = (error, value) => {
|
|
90
|
+
for (const handler of this.#updateHandlers)
|
|
91
|
+
handler(error, value);
|
|
92
|
+
};
|
|
93
|
+
/** Refresh the value */
|
|
94
|
+
#probeTime = () => {
|
|
95
|
+
this.#nextRefreshTimeout = undefined;
|
|
96
|
+
this.#loadedPromise = this.#callProbeFunction();
|
|
97
|
+
this.#lastRefreshTime = Date.now();
|
|
98
|
+
if (this.#autoProbe)
|
|
99
|
+
this.#armAutoProbe();
|
|
100
|
+
};
|
|
101
|
+
/** Setup the auto probe */
|
|
102
|
+
#armAutoProbe = () => {
|
|
103
|
+
if (this.#nextRefreshTimeout)
|
|
104
|
+
clearTimeout(this.#nextRefreshTimeout);
|
|
105
|
+
const remainingTime = this.#getRemainingTime();
|
|
106
|
+
this.#nextRefreshTimeout = setTimeout(this.#probeTime, remainingTime);
|
|
107
|
+
};
|
|
108
|
+
/** Return the remaining time before the next refresh (minimum 0) */
|
|
109
|
+
#getRemainingTime = () => {
|
|
110
|
+
const now = Date.now();
|
|
111
|
+
const nextRefresh = (this.#lastRefreshTime ?? Date.now()) + this.#cacheDurationMs;
|
|
112
|
+
return Math.max(0, nextRefresh - now);
|
|
113
|
+
};
|
|
114
|
+
#manualRefresh = () => {
|
|
115
|
+
if (this.#getRemainingTime() === 0 || !this.#loadedPromise)
|
|
116
|
+
this.#probeTime();
|
|
117
|
+
};
|
|
118
|
+
}
|
package/lib/base58.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* @preserve
|
|
4
|
+
*
|
|
5
|
+
* MIT License
|
|
6
|
+
*
|
|
7
|
+
* Copyright (c) 2023 KeeeX SAS
|
|
8
|
+
*
|
|
9
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
10
|
+
*
|
|
11
|
+
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
12
|
+
*
|
|
13
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
14
|
+
*
|
|
15
|
+
*/
|
|
16
|
+
/** @public */
|
|
17
|
+
export declare const encode: (data: Uint8Array) => string;
|
|
18
|
+
/** @public */
|
|
19
|
+
export declare const decode: (b58: string) => Uint8Array;
|
|
20
|
+
/**
|
|
21
|
+
* Encode a buf8 with base58.
|
|
22
|
+
*
|
|
23
|
+
* The output is padded accordingly to always accomodate a buffer of the full length of the input.
|
|
24
|
+
*
|
|
25
|
+
* @public
|
|
26
|
+
*/
|
|
27
|
+
export declare const encodePad: (data: Uint8Array) => string;
|