@hpcc-js/util 3.4.8 → 3.5.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/LICENSE +43 -43
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.umd.cjs +1 -1
- package/dist/index.umd.cjs.map +1 -1
- package/package.json +2 -2
- package/src/__package__.ts +3 -3
- package/src/array.ts +97 -97
- package/src/cache.ts +65 -65
- package/src/debounce.ts +88 -88
- package/src/dictionary.ts +69 -69
- package/src/dispatch.ts +125 -125
- package/src/esp.ts +32 -32
- package/src/graph.ts +353 -353
- package/src/graph2.ts +675 -675
- package/src/hashSum.ts +55 -55
- package/src/immutable.ts +156 -156
- package/src/index.ts +21 -21
- package/src/logging.ts +212 -212
- package/src/math.ts +92 -92
- package/src/object.ts +122 -122
- package/src/observer.ts +91 -91
- package/src/platform.ts +20 -20
- package/src/saxParser.ts +135 -135
- package/src/stack.ts +41 -41
- package/src/stateful.ts +178 -178
- package/src/string.ts +21 -21
- package/src/url.ts +27 -27
- package/src/utf8ToBase64.ts +47 -47
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hpcc-js/util",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.5.0",
|
|
4
4
|
"description": "hpcc-js - Utilities",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.umd.cjs",
|
|
@@ -55,5 +55,5 @@
|
|
|
55
55
|
"url": "https://github.com/hpcc-systems/Visualization/issues"
|
|
56
56
|
},
|
|
57
57
|
"homepage": "https://github.com/hpcc-systems/Visualization/tree/main/packages/util",
|
|
58
|
-
"gitHead": "
|
|
58
|
+
"gitHead": "ada394f582442d2b23a7ff55b9f87a50a723f45b"
|
|
59
59
|
}
|
package/src/__package__.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export const PKG_NAME = "__PACKAGE_NAME__";
|
|
2
|
-
export const PKG_VERSION = "__PACKAGE_VERSION__";
|
|
3
|
-
export const BUILD_VERSION = "__BUILD_VERSION__";
|
|
1
|
+
export const PKG_NAME = "__PACKAGE_NAME__";
|
|
2
|
+
export const PKG_VERSION = "__PACKAGE_VERSION__";
|
|
3
|
+
export const BUILD_VERSION = "__BUILD_VERSION__";
|
package/src/array.ts
CHANGED
|
@@ -1,97 +1,97 @@
|
|
|
1
|
-
// Based on: https://tc39.github.io/ecma262/#sec-array.prototype.find
|
|
2
|
-
export function find<T>(o: ReadonlyArray<T>, predicate: (value: T, index: number) => boolean) {
|
|
3
|
-
// 1. Let O be ? ToObject(this value).
|
|
4
|
-
if (o == null) {
|
|
5
|
-
throw new TypeError('"o" is null or not defined');
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
// 2. Let len be ? ToLength(? Get(O, "length")).
|
|
9
|
-
const len = o.length >>> 0;
|
|
10
|
-
|
|
11
|
-
// 3. If IsCallable(predicate) is false, throw a TypeError exception.
|
|
12
|
-
if (typeof predicate !== "function") {
|
|
13
|
-
throw new TypeError("predicate must be a function");
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
// 4. If thisArg was supplied, let T be thisArg; else let T be undefined.
|
|
17
|
-
const thisArg = arguments[1];
|
|
18
|
-
|
|
19
|
-
// 5. Let k be 0.
|
|
20
|
-
let k = 0;
|
|
21
|
-
|
|
22
|
-
// 6. Repeat, while k < len
|
|
23
|
-
while (k < len) {
|
|
24
|
-
// a. Let Pk be ! ToString(k).
|
|
25
|
-
// b. Let kValue be ? Get(O, Pk).
|
|
26
|
-
// c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)).
|
|
27
|
-
// d. If testResult is true, return kValue.
|
|
28
|
-
const kValue = o[k];
|
|
29
|
-
if (predicate.call(thisArg, kValue, k)) {
|
|
30
|
-
return kValue;
|
|
31
|
-
}
|
|
32
|
-
// e. Increase k by 1.
|
|
33
|
-
k++;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// 7. Return undefined.
|
|
37
|
-
return undefined;
|
|
38
|
-
}
|
|
39
|
-
export interface IDifferences2<T> {
|
|
40
|
-
update: T[];
|
|
41
|
-
exit: T[];
|
|
42
|
-
enter: T[];
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export function compare<T>(before: readonly T[], after: readonly T[]): IDifferences2<T> {
|
|
46
|
-
const retVal: IDifferences2<T> = {
|
|
47
|
-
update: [],
|
|
48
|
-
exit: [],
|
|
49
|
-
enter: [...after]
|
|
50
|
-
};
|
|
51
|
-
for (const row of before) {
|
|
52
|
-
const otherIdx = retVal.enter.indexOf(row);
|
|
53
|
-
if (otherIdx >= 0) {
|
|
54
|
-
retVal.update.push(row);
|
|
55
|
-
retVal.enter.splice(otherIdx, 1);
|
|
56
|
-
} else {
|
|
57
|
-
retVal.exit.push(row);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
return retVal;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export interface IDifferences2<T> {
|
|
64
|
-
enter: T[];
|
|
65
|
-
update: T[];
|
|
66
|
-
exit: T[];
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
export function compare2<T>(before: readonly T[], after: readonly T[], idFunc: (itme: T) => string | number, updateFunc: (before: T, after: T) => T = (before, after) => after): IDifferences2<T> {
|
|
70
|
-
const retVal: IDifferences2<T> = {
|
|
71
|
-
update: [],
|
|
72
|
-
exit: [],
|
|
73
|
-
enter: []
|
|
74
|
-
};
|
|
75
|
-
if (before === after) {
|
|
76
|
-
retVal.update = before as T[];
|
|
77
|
-
return retVal;
|
|
78
|
-
}
|
|
79
|
-
const unknownMap: { [key: string]: T } = {};
|
|
80
|
-
after.forEach(item => {
|
|
81
|
-
unknownMap[idFunc(item)] = item;
|
|
82
|
-
});
|
|
83
|
-
for (const row of before) {
|
|
84
|
-
const id = idFunc(row);
|
|
85
|
-
const item = unknownMap[id];
|
|
86
|
-
if (item !== undefined) {
|
|
87
|
-
delete unknownMap[id];
|
|
88
|
-
retVal.update.push(updateFunc(row, item));
|
|
89
|
-
} else {
|
|
90
|
-
retVal.exit.push(row);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
for (const key in unknownMap) {
|
|
94
|
-
retVal.enter.push(unknownMap[key]);
|
|
95
|
-
}
|
|
96
|
-
return retVal;
|
|
97
|
-
}
|
|
1
|
+
// Based on: https://tc39.github.io/ecma262/#sec-array.prototype.find
|
|
2
|
+
export function find<T>(o: ReadonlyArray<T>, predicate: (value: T, index: number) => boolean) {
|
|
3
|
+
// 1. Let O be ? ToObject(this value).
|
|
4
|
+
if (o == null) {
|
|
5
|
+
throw new TypeError('"o" is null or not defined');
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
// 2. Let len be ? ToLength(? Get(O, "length")).
|
|
9
|
+
const len = o.length >>> 0;
|
|
10
|
+
|
|
11
|
+
// 3. If IsCallable(predicate) is false, throw a TypeError exception.
|
|
12
|
+
if (typeof predicate !== "function") {
|
|
13
|
+
throw new TypeError("predicate must be a function");
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// 4. If thisArg was supplied, let T be thisArg; else let T be undefined.
|
|
17
|
+
const thisArg = arguments[1];
|
|
18
|
+
|
|
19
|
+
// 5. Let k be 0.
|
|
20
|
+
let k = 0;
|
|
21
|
+
|
|
22
|
+
// 6. Repeat, while k < len
|
|
23
|
+
while (k < len) {
|
|
24
|
+
// a. Let Pk be ! ToString(k).
|
|
25
|
+
// b. Let kValue be ? Get(O, Pk).
|
|
26
|
+
// c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)).
|
|
27
|
+
// d. If testResult is true, return kValue.
|
|
28
|
+
const kValue = o[k];
|
|
29
|
+
if (predicate.call(thisArg, kValue, k)) {
|
|
30
|
+
return kValue;
|
|
31
|
+
}
|
|
32
|
+
// e. Increase k by 1.
|
|
33
|
+
k++;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// 7. Return undefined.
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
export interface IDifferences2<T> {
|
|
40
|
+
update: T[];
|
|
41
|
+
exit: T[];
|
|
42
|
+
enter: T[];
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function compare<T>(before: readonly T[], after: readonly T[]): IDifferences2<T> {
|
|
46
|
+
const retVal: IDifferences2<T> = {
|
|
47
|
+
update: [],
|
|
48
|
+
exit: [],
|
|
49
|
+
enter: [...after]
|
|
50
|
+
};
|
|
51
|
+
for (const row of before) {
|
|
52
|
+
const otherIdx = retVal.enter.indexOf(row);
|
|
53
|
+
if (otherIdx >= 0) {
|
|
54
|
+
retVal.update.push(row);
|
|
55
|
+
retVal.enter.splice(otherIdx, 1);
|
|
56
|
+
} else {
|
|
57
|
+
retVal.exit.push(row);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return retVal;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export interface IDifferences2<T> {
|
|
64
|
+
enter: T[];
|
|
65
|
+
update: T[];
|
|
66
|
+
exit: T[];
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function compare2<T>(before: readonly T[], after: readonly T[], idFunc: (itme: T) => string | number, updateFunc: (before: T, after: T) => T = (before, after) => after): IDifferences2<T> {
|
|
70
|
+
const retVal: IDifferences2<T> = {
|
|
71
|
+
update: [],
|
|
72
|
+
exit: [],
|
|
73
|
+
enter: []
|
|
74
|
+
};
|
|
75
|
+
if (before === after) {
|
|
76
|
+
retVal.update = before as T[];
|
|
77
|
+
return retVal;
|
|
78
|
+
}
|
|
79
|
+
const unknownMap: { [key: string]: T } = {};
|
|
80
|
+
after.forEach(item => {
|
|
81
|
+
unknownMap[idFunc(item)] = item;
|
|
82
|
+
});
|
|
83
|
+
for (const row of before) {
|
|
84
|
+
const id = idFunc(row);
|
|
85
|
+
const item = unknownMap[id];
|
|
86
|
+
if (item !== undefined) {
|
|
87
|
+
delete unknownMap[id];
|
|
88
|
+
retVal.update.push(updateFunc(row, item));
|
|
89
|
+
} else {
|
|
90
|
+
retVal.exit.push(row);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
for (const key in unknownMap) {
|
|
94
|
+
retVal.enter.push(unknownMap[key]);
|
|
95
|
+
}
|
|
96
|
+
return retVal;
|
|
97
|
+
}
|
package/src/cache.ts
CHANGED
|
@@ -1,65 +1,65 @@
|
|
|
1
|
-
import { hashSum } from "./hashSum.ts";
|
|
2
|
-
|
|
3
|
-
export class Cache<I, C> {
|
|
4
|
-
private _cache: { [id: string]: C } = {};
|
|
5
|
-
private _calcID: (espObj: I | C) => string;
|
|
6
|
-
|
|
7
|
-
static hash(...args: any[]) {
|
|
8
|
-
return hashSum({ ...args });
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
constructor(calcID: (espObj: I | C) => string) {
|
|
12
|
-
this._calcID = calcID;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
has(espObj: I): boolean {
|
|
16
|
-
return this._calcID(espObj) in this._cache;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
set(obj: C): C {
|
|
20
|
-
this._cache[this._calcID(obj)] = obj;
|
|
21
|
-
return obj;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
get(espObj: I): C | null;
|
|
25
|
-
get(espObj: I, factory: () => C): C;
|
|
26
|
-
get(espObj: I, factory?: () => C): C | null {
|
|
27
|
-
const retVal = this._cache[this._calcID(espObj)];
|
|
28
|
-
if (!retVal) {
|
|
29
|
-
return factory ? this.set(factory()) : null;
|
|
30
|
-
}
|
|
31
|
-
return retVal;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export class AsyncCache<I, C> {
|
|
36
|
-
private _cache: { [id: string]: Promise<C> } = {};
|
|
37
|
-
private _calcID: (espObj: I | C) => string;
|
|
38
|
-
|
|
39
|
-
static hash(...args: any[]) {
|
|
40
|
-
return hashSum({ ...args });
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
constructor(calcID: (espObj: I | C) => string) {
|
|
44
|
-
this._calcID = calcID;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
has(espObj: I): boolean {
|
|
48
|
-
return this._calcID(espObj) in this._cache;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
set(espObj: I, obj: Promise<C>): Promise<C> {
|
|
52
|
-
this._cache[this._calcID(espObj)] = obj;
|
|
53
|
-
return obj;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
get(espObj: I): Promise<C | null>;
|
|
57
|
-
get(espObj: I, factory: () => Promise<C>): Promise<C>;
|
|
58
|
-
get(espObj: I, factory?: () => Promise<C>): Promise<C | null> {
|
|
59
|
-
const retVal = this._cache[this._calcID(espObj)];
|
|
60
|
-
if (!retVal) {
|
|
61
|
-
return factory ? this.set(espObj, factory()) : Promise.resolve(null);
|
|
62
|
-
}
|
|
63
|
-
return retVal;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
1
|
+
import { hashSum } from "./hashSum.ts";
|
|
2
|
+
|
|
3
|
+
export class Cache<I, C> {
|
|
4
|
+
private _cache: { [id: string]: C } = {};
|
|
5
|
+
private _calcID: (espObj: I | C) => string;
|
|
6
|
+
|
|
7
|
+
static hash(...args: any[]) {
|
|
8
|
+
return hashSum({ ...args });
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
constructor(calcID: (espObj: I | C) => string) {
|
|
12
|
+
this._calcID = calcID;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
has(espObj: I): boolean {
|
|
16
|
+
return this._calcID(espObj) in this._cache;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
set(obj: C): C {
|
|
20
|
+
this._cache[this._calcID(obj)] = obj;
|
|
21
|
+
return obj;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
get(espObj: I): C | null;
|
|
25
|
+
get(espObj: I, factory: () => C): C;
|
|
26
|
+
get(espObj: I, factory?: () => C): C | null {
|
|
27
|
+
const retVal = this._cache[this._calcID(espObj)];
|
|
28
|
+
if (!retVal) {
|
|
29
|
+
return factory ? this.set(factory()) : null;
|
|
30
|
+
}
|
|
31
|
+
return retVal;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export class AsyncCache<I, C> {
|
|
36
|
+
private _cache: { [id: string]: Promise<C> } = {};
|
|
37
|
+
private _calcID: (espObj: I | C) => string;
|
|
38
|
+
|
|
39
|
+
static hash(...args: any[]) {
|
|
40
|
+
return hashSum({ ...args });
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
constructor(calcID: (espObj: I | C) => string) {
|
|
44
|
+
this._calcID = calcID;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
has(espObj: I): boolean {
|
|
48
|
+
return this._calcID(espObj) in this._cache;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
set(espObj: I, obj: Promise<C>): Promise<C> {
|
|
52
|
+
this._cache[this._calcID(espObj)] = obj;
|
|
53
|
+
return obj;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
get(espObj: I): Promise<C | null>;
|
|
57
|
+
get(espObj: I, factory: () => Promise<C>): Promise<C>;
|
|
58
|
+
get(espObj: I, factory?: () => Promise<C>): Promise<C | null> {
|
|
59
|
+
const retVal = this._cache[this._calcID(espObj)];
|
|
60
|
+
if (!retVal) {
|
|
61
|
+
return factory ? this.set(espObj, factory()) : Promise.resolve(null);
|
|
62
|
+
}
|
|
63
|
+
return retVal;
|
|
64
|
+
}
|
|
65
|
+
}
|
package/src/debounce.ts
CHANGED
|
@@ -1,88 +1,88 @@
|
|
|
1
|
-
import { hashSum } from "./hashSum.ts";
|
|
2
|
-
|
|
3
|
-
export function debounce<R extends Promise<any>>(fn: () => R, timeout?: number): () => R;
|
|
4
|
-
export function debounce<P1, R extends Promise<any>>(fn: (param1: P1) => R, timeout?: number): (param1: P1) => R;
|
|
5
|
-
export function debounce<P1, P2, R extends Promise<any>>(fn: (param1: P1, param2: P2) => R, timeout?: number): (param1: P1, param2: P2) => R;
|
|
6
|
-
export function debounce<P1, P2, P3, R extends Promise<any>>(fn: (param1: P1, param2: P2, param3: P3) => R, timeout?: number): (param1: P1, param2: P2, param3: P3) => R;
|
|
7
|
-
export function debounce<P1, P2, P3, P4, R extends Promise<any>>(fn: (param1: P1, param2: P2, param3: P3, param4: P4) => R, timeout?: number): (param1: P1, param2: P2, param3: P3, param4: P4) => R;
|
|
8
|
-
export function debounce<TParam, R extends Promise<any>>(fn: (...params: TParam[]) => R, timeout?: number): (...params: TParam[]) => R {
|
|
9
|
-
const promises: { [key: string]: { promise: R, clockStart: number } | null } = {};
|
|
10
|
-
|
|
11
|
-
return (...params) => {
|
|
12
|
-
const hash = hashSum(params);
|
|
13
|
-
if (!promises[hash]) {
|
|
14
|
-
promises[hash] = {
|
|
15
|
-
clockStart: Date.now(),
|
|
16
|
-
promise: fn(...params).then(response => {
|
|
17
|
-
if (timeout === undefined) {
|
|
18
|
-
promises[hash] = null;
|
|
19
|
-
} else {
|
|
20
|
-
setTimeout(() => {
|
|
21
|
-
promises[hash] = null;
|
|
22
|
-
}, Math.max(timeout - (Date.now() - promises[hash]!.clockStart), 0));
|
|
23
|
-
}
|
|
24
|
-
return response;
|
|
25
|
-
}).catch(e => {
|
|
26
|
-
promises[hash] = null;
|
|
27
|
-
throw e;
|
|
28
|
-
}) as R
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
return promises[hash]!.promise;
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export function promiseTimeout<T>(ms: number, promise: Promise<T>): Promise<T> {
|
|
36
|
-
let id: any;
|
|
37
|
-
const timeout = new Promise((resolve, reject) => {
|
|
38
|
-
id = setTimeout(() => {
|
|
39
|
-
clearTimeout(id);
|
|
40
|
-
reject("Timed out in " + ms + "ms.");
|
|
41
|
-
}, ms);
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
return Promise.race([
|
|
45
|
-
promise,
|
|
46
|
-
timeout
|
|
47
|
-
]).then((response: unknown) => {
|
|
48
|
-
clearTimeout(id);
|
|
49
|
-
return response as T;
|
|
50
|
-
}).catch(e => {
|
|
51
|
-
clearTimeout(id);
|
|
52
|
-
throw e;
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export class AsyncOrderedQueue {
|
|
57
|
-
private _q: Array<Promise<any>> = [];
|
|
58
|
-
|
|
59
|
-
private isTop(p: Promise<any>): boolean {
|
|
60
|
-
return this._q[0] === p;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
push<T>(p: Promise<T>): Promise<T> {
|
|
64
|
-
const retVal = p.then(response => {
|
|
65
|
-
if (this.isTop(retVal)) {
|
|
66
|
-
this._q.shift();
|
|
67
|
-
return response;
|
|
68
|
-
}
|
|
69
|
-
return new Promise<T>((resolve, reject) => {
|
|
70
|
-
const intervalHandler = setInterval(() => {
|
|
71
|
-
if (this.isTop(retVal)) {
|
|
72
|
-
clearInterval(intervalHandler);
|
|
73
|
-
this._q.shift();
|
|
74
|
-
resolve(response);
|
|
75
|
-
}
|
|
76
|
-
}, 20);
|
|
77
|
-
});
|
|
78
|
-
});
|
|
79
|
-
this._q.push(retVal);
|
|
80
|
-
return retVal;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
export function sleep(ms: number): Promise<void> {
|
|
85
|
-
return new Promise(resolve => {
|
|
86
|
-
setTimeout(() => resolve(), ms);
|
|
87
|
-
});
|
|
88
|
-
}
|
|
1
|
+
import { hashSum } from "./hashSum.ts";
|
|
2
|
+
|
|
3
|
+
export function debounce<R extends Promise<any>>(fn: () => R, timeout?: number): () => R;
|
|
4
|
+
export function debounce<P1, R extends Promise<any>>(fn: (param1: P1) => R, timeout?: number): (param1: P1) => R;
|
|
5
|
+
export function debounce<P1, P2, R extends Promise<any>>(fn: (param1: P1, param2: P2) => R, timeout?: number): (param1: P1, param2: P2) => R;
|
|
6
|
+
export function debounce<P1, P2, P3, R extends Promise<any>>(fn: (param1: P1, param2: P2, param3: P3) => R, timeout?: number): (param1: P1, param2: P2, param3: P3) => R;
|
|
7
|
+
export function debounce<P1, P2, P3, P4, R extends Promise<any>>(fn: (param1: P1, param2: P2, param3: P3, param4: P4) => R, timeout?: number): (param1: P1, param2: P2, param3: P3, param4: P4) => R;
|
|
8
|
+
export function debounce<TParam, R extends Promise<any>>(fn: (...params: TParam[]) => R, timeout?: number): (...params: TParam[]) => R {
|
|
9
|
+
const promises: { [key: string]: { promise: R, clockStart: number } | null } = {};
|
|
10
|
+
|
|
11
|
+
return (...params) => {
|
|
12
|
+
const hash = hashSum(params);
|
|
13
|
+
if (!promises[hash]) {
|
|
14
|
+
promises[hash] = {
|
|
15
|
+
clockStart: Date.now(),
|
|
16
|
+
promise: fn(...params).then(response => {
|
|
17
|
+
if (timeout === undefined) {
|
|
18
|
+
promises[hash] = null;
|
|
19
|
+
} else {
|
|
20
|
+
setTimeout(() => {
|
|
21
|
+
promises[hash] = null;
|
|
22
|
+
}, Math.max(timeout - (Date.now() - promises[hash]!.clockStart), 0));
|
|
23
|
+
}
|
|
24
|
+
return response;
|
|
25
|
+
}).catch(e => {
|
|
26
|
+
promises[hash] = null;
|
|
27
|
+
throw e;
|
|
28
|
+
}) as R
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
return promises[hash]!.promise;
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function promiseTimeout<T>(ms: number, promise: Promise<T>): Promise<T> {
|
|
36
|
+
let id: any;
|
|
37
|
+
const timeout = new Promise((resolve, reject) => {
|
|
38
|
+
id = setTimeout(() => {
|
|
39
|
+
clearTimeout(id);
|
|
40
|
+
reject("Timed out in " + ms + "ms.");
|
|
41
|
+
}, ms);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
return Promise.race([
|
|
45
|
+
promise,
|
|
46
|
+
timeout
|
|
47
|
+
]).then((response: unknown) => {
|
|
48
|
+
clearTimeout(id);
|
|
49
|
+
return response as T;
|
|
50
|
+
}).catch(e => {
|
|
51
|
+
clearTimeout(id);
|
|
52
|
+
throw e;
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export class AsyncOrderedQueue {
|
|
57
|
+
private _q: Array<Promise<any>> = [];
|
|
58
|
+
|
|
59
|
+
private isTop(p: Promise<any>): boolean {
|
|
60
|
+
return this._q[0] === p;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
push<T>(p: Promise<T>): Promise<T> {
|
|
64
|
+
const retVal = p.then(response => {
|
|
65
|
+
if (this.isTop(retVal)) {
|
|
66
|
+
this._q.shift();
|
|
67
|
+
return response;
|
|
68
|
+
}
|
|
69
|
+
return new Promise<T>((resolve, reject) => {
|
|
70
|
+
const intervalHandler = setInterval(() => {
|
|
71
|
+
if (this.isTop(retVal)) {
|
|
72
|
+
clearInterval(intervalHandler);
|
|
73
|
+
this._q.shift();
|
|
74
|
+
resolve(response);
|
|
75
|
+
}
|
|
76
|
+
}, 20);
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
this._q.push(retVal);
|
|
80
|
+
return retVal;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export function sleep(ms: number): Promise<void> {
|
|
85
|
+
return new Promise(resolve => {
|
|
86
|
+
setTimeout(() => resolve(), ms);
|
|
87
|
+
});
|
|
88
|
+
}
|
package/src/dictionary.ts
CHANGED
|
@@ -1,69 +1,69 @@
|
|
|
1
|
-
export type StringAnyMap = { [key: string]: any };
|
|
2
|
-
|
|
3
|
-
export class Dictionary<T> {
|
|
4
|
-
private store: { [key: string]: T } = {};
|
|
5
|
-
|
|
6
|
-
constructor(attrs?: StringAnyMap) {
|
|
7
|
-
if (attrs) {
|
|
8
|
-
for (const key in attrs) {
|
|
9
|
-
this.set(key, attrs[key]);
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
set(key: string, value: T): T {
|
|
15
|
-
const retVal: T = this.store[key];
|
|
16
|
-
this.store[key] = value;
|
|
17
|
-
return retVal;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
get(key: string): T {
|
|
21
|
-
return this.store[key];
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
has(key: string) {
|
|
25
|
-
return this.store[key] !== undefined;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
remove(key: string) {
|
|
29
|
-
delete this.store[key];
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
keys(): string[] {
|
|
33
|
-
const retVal: string[] = [];
|
|
34
|
-
for (const key in this.store) {
|
|
35
|
-
retVal.push(key);
|
|
36
|
-
}
|
|
37
|
-
return retVal;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
values(): T[] {
|
|
41
|
-
const retVal: T[] = [];
|
|
42
|
-
for (const key in this.store) {
|
|
43
|
-
retVal.push(this.store[key]);
|
|
44
|
-
}
|
|
45
|
-
return retVal;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export class DictionaryNoCase<T> extends Dictionary<T> {
|
|
50
|
-
constructor(attrs?: StringAnyMap) {
|
|
51
|
-
super(attrs);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
set(key: string, value: T): T {
|
|
55
|
-
return super.set(key.toLowerCase(), value);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
get(key: string): T {
|
|
59
|
-
return super.get(key.toLowerCase());
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
has(key: string) {
|
|
63
|
-
return super.has(key.toLowerCase());
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
remove(key: string) {
|
|
67
|
-
return super.remove(key.toLowerCase());
|
|
68
|
-
}
|
|
69
|
-
}
|
|
1
|
+
export type StringAnyMap = { [key: string]: any };
|
|
2
|
+
|
|
3
|
+
export class Dictionary<T> {
|
|
4
|
+
private store: { [key: string]: T } = {};
|
|
5
|
+
|
|
6
|
+
constructor(attrs?: StringAnyMap) {
|
|
7
|
+
if (attrs) {
|
|
8
|
+
for (const key in attrs) {
|
|
9
|
+
this.set(key, attrs[key]);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
set(key: string, value: T): T {
|
|
15
|
+
const retVal: T = this.store[key];
|
|
16
|
+
this.store[key] = value;
|
|
17
|
+
return retVal;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
get(key: string): T {
|
|
21
|
+
return this.store[key];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
has(key: string) {
|
|
25
|
+
return this.store[key] !== undefined;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
remove(key: string) {
|
|
29
|
+
delete this.store[key];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
keys(): string[] {
|
|
33
|
+
const retVal: string[] = [];
|
|
34
|
+
for (const key in this.store) {
|
|
35
|
+
retVal.push(key);
|
|
36
|
+
}
|
|
37
|
+
return retVal;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
values(): T[] {
|
|
41
|
+
const retVal: T[] = [];
|
|
42
|
+
for (const key in this.store) {
|
|
43
|
+
retVal.push(this.store[key]);
|
|
44
|
+
}
|
|
45
|
+
return retVal;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export class DictionaryNoCase<T> extends Dictionary<T> {
|
|
50
|
+
constructor(attrs?: StringAnyMap) {
|
|
51
|
+
super(attrs);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
set(key: string, value: T): T {
|
|
55
|
+
return super.set(key.toLowerCase(), value);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
get(key: string): T {
|
|
59
|
+
return super.get(key.toLowerCase());
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
has(key: string) {
|
|
63
|
+
return super.has(key.toLowerCase());
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
remove(key: string) {
|
|
67
|
+
return super.remove(key.toLowerCase());
|
|
68
|
+
}
|
|
69
|
+
}
|