@xylabs/forget 4.10.1 → 4.11.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/dist/neutral/index.mjs +60 -32
- package/dist/neutral/index.mjs.map +1 -1
- package/dist/node/index-node.mjs +134 -0
- package/dist/node/index-node.mjs.map +1 -0
- package/dist/types/ForgetConfig.d.ts +8 -0
- package/dist/types/ForgetConfig.d.ts.map +1 -0
- package/dist/types/ForgetNodeConfig.d.ts +7 -0
- package/dist/types/ForgetNodeConfig.d.ts.map +1 -0
- package/dist/types/ForgetPromise.d.ts +17 -0
- package/dist/types/ForgetPromise.d.ts.map +1 -0
- package/dist/types/ForgetPromiseNode.d.ts +17 -0
- package/dist/types/ForgetPromiseNode.d.ts.map +1 -0
- package/dist/types/forget.d.ts +2 -16
- package/dist/types/forget.d.ts.map +1 -1
- package/dist/types/forgetNode.d.ts +4 -0
- package/dist/types/forgetNode.d.ts.map +1 -0
- package/dist/types/index-node.d.ts +4 -0
- package/dist/types/index-node.d.ts.map +1 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +8 -3
- package/src/ForgetConfig.ts +9 -0
- package/src/ForgetNodeConfig.ts +13 -0
- package/src/ForgetPromise.ts +99 -0
- package/src/ForgetPromiseNode.ts +38 -0
- package/src/forget.ts +5 -82
- package/src/forgetNode.ts +9 -0
- package/src/global-config-node.d.ts +9 -0
- package/src/global-config.d.ts +9 -0
- package/src/index-node.ts +3 -0
- package/src/index.ts +2 -0
- package/xy.config.ts +2 -2
package/dist/neutral/index.mjs
CHANGED
|
@@ -1,11 +1,24 @@
|
|
|
1
|
-
// src/
|
|
1
|
+
// src/ForgetPromise.ts
|
|
2
2
|
import { delay } from "@xylabs/delay";
|
|
3
3
|
import { isPromise } from "@xylabs/promise";
|
|
4
|
+
import { isNumber } from "@xylabs/typeof";
|
|
5
|
+
|
|
6
|
+
// src/ForgetConfig.ts
|
|
7
|
+
var defaultForgetConfig = { timeout: 3e4 };
|
|
8
|
+
|
|
9
|
+
// src/ForgetPromise.ts
|
|
4
10
|
var ForgetPromise = {
|
|
5
11
|
get active() {
|
|
6
12
|
return this.activeForgets > 0;
|
|
7
13
|
},
|
|
8
14
|
activeForgets: 0,
|
|
15
|
+
exceptedForgets: 0,
|
|
16
|
+
exceptionHandler: (error, _config) => {
|
|
17
|
+
console.error(`forget promise handler excepted: ${error.message}`, error);
|
|
18
|
+
},
|
|
19
|
+
timeoutHandler: (time, _config) => {
|
|
20
|
+
console.error(`forget promise timeout out after ${time}ms [Cancelling]`);
|
|
21
|
+
},
|
|
9
22
|
async awaitInactive(interval = 100, timeout) {
|
|
10
23
|
let timeoutRemaining = timeout;
|
|
11
24
|
while (this.active) {
|
|
@@ -24,48 +37,63 @@ var ForgetPromise = {
|
|
|
24
37
|
* @param promise The promise to forget
|
|
25
38
|
* @param config Configuration of forget settings
|
|
26
39
|
*/
|
|
27
|
-
forget(promise,
|
|
40
|
+
forget(promise, config) {
|
|
41
|
+
const resolvedConfig = {
|
|
42
|
+
...defaultForgetConfig,
|
|
43
|
+
...globalThis.xy?.forget?.config,
|
|
44
|
+
...config
|
|
45
|
+
};
|
|
28
46
|
if (isPromise(promise)) {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
const promises = [promiseWrapper()];
|
|
43
|
-
if (config) {
|
|
44
|
-
const timeoutFunc = async () => {
|
|
45
|
-
await delay(config.delay);
|
|
46
|
-
if (!completed) {
|
|
47
|
-
console.log(`forget promise timeout out after ${config.delay}ms [Cancelling]`);
|
|
48
|
-
config.cancel?.();
|
|
49
|
-
}
|
|
47
|
+
try {
|
|
48
|
+
let completed = false;
|
|
49
|
+
this.activeForgets++;
|
|
50
|
+
const promiseWrapper = async () => {
|
|
51
|
+
await promise.then((result) => {
|
|
52
|
+
this.activeForgets--;
|
|
53
|
+
completed = true;
|
|
54
|
+
resolvedConfig?.onComplete?.([result, void 0]);
|
|
55
|
+
}).catch((error) => {
|
|
56
|
+
this.activeForgets--;
|
|
57
|
+
completed = true;
|
|
58
|
+
resolvedConfig?.onComplete?.([void 0, error]);
|
|
59
|
+
});
|
|
50
60
|
};
|
|
51
|
-
promises
|
|
61
|
+
const promises = [promiseWrapper()];
|
|
62
|
+
const timeout = resolvedConfig.timeout ?? defaultForgetConfig.timeout;
|
|
63
|
+
if (isNumber(timeout)) {
|
|
64
|
+
const timeoutFunc = async () => {
|
|
65
|
+
await delay(timeout);
|
|
66
|
+
if (!completed) {
|
|
67
|
+
resolvedConfig.onCancel?.();
|
|
68
|
+
this.timeoutHandler(timeout, resolvedConfig);
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
promises.push(timeoutFunc());
|
|
72
|
+
}
|
|
73
|
+
const all = Promise.race(promises);
|
|
74
|
+
all.then(() => {
|
|
75
|
+
return;
|
|
76
|
+
}).catch(() => {
|
|
77
|
+
return;
|
|
78
|
+
});
|
|
79
|
+
} catch (ex) {
|
|
80
|
+
this.exceptedForgets += 1;
|
|
81
|
+
resolvedConfig?.onException?.(ex);
|
|
82
|
+
this.exceptionHandler(ex, resolvedConfig);
|
|
52
83
|
}
|
|
53
|
-
const all = Promise.race(promises);
|
|
54
|
-
all.then(() => {
|
|
55
|
-
return;
|
|
56
|
-
}).catch(() => {
|
|
57
|
-
return;
|
|
58
|
-
});
|
|
59
84
|
} else {
|
|
60
85
|
return promise();
|
|
61
86
|
}
|
|
62
87
|
}
|
|
63
88
|
};
|
|
64
|
-
|
|
65
|
-
|
|
89
|
+
|
|
90
|
+
// src/forget.ts
|
|
91
|
+
var forget = (promise, config) => {
|
|
92
|
+
ForgetPromise.forget(promise, config);
|
|
66
93
|
};
|
|
67
94
|
export {
|
|
68
95
|
ForgetPromise,
|
|
96
|
+
defaultForgetConfig,
|
|
69
97
|
forget
|
|
70
98
|
};
|
|
71
99
|
//# sourceMappingURL=index.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/forget.ts"],"sourcesContent":["import { delay } from '@xylabs/delay'\nimport { isPromise, type Promisable } from '@xylabs/promise'\
|
|
1
|
+
{"version":3,"sources":["../../src/ForgetPromise.ts","../../src/ForgetConfig.ts","../../src/forget.ts"],"sourcesContent":["import { delay } from '@xylabs/delay'\nimport { isPromise, type Promisable } from '@xylabs/promise'\nimport { isNumber } from '@xylabs/typeof'\n\nimport { defaultForgetConfig, type ForgetConfig } from './ForgetConfig.ts'\n\nexport const ForgetPromise = {\n get active() {\n return this.activeForgets > 0\n },\n\n activeForgets: 0,\n exceptedForgets: 0,\n\n exceptionHandler: (error: Error, _config: ForgetConfig) => {\n console.error(`forget promise handler excepted: ${error.message}`, error)\n },\n\n timeoutHandler: (time: number, _config: ForgetConfig) => {\n console.error(`forget promise timeout out after ${time}ms [Cancelling]`)\n },\n\n async awaitInactive(interval = 100, timeout?: number) {\n let timeoutRemaining = timeout\n while (this.active) {\n await delay(interval)\n if (timeoutRemaining !== undefined) {\n timeoutRemaining -= interval\n if (timeoutRemaining <= 0) {\n return this.activeForgets\n }\n }\n }\n return 0\n },\n\n /**\n * Used to explicitly launch an async function (or Promise) with awaiting it\n * @param promise The promise to forget\n * @param config Configuration of forget settings\n */\n forget<T>(promise: Promisable<T>, config?: ForgetConfig<T>) {\n // default | global | provided priorities for config (not deep merge)\n const resolvedConfig = {\n ...defaultForgetConfig, ...globalThis.xy?.forget?.config, ...config,\n }\n if (isPromise(promise)) {\n try {\n let completed = false\n this.activeForgets++\n\n const promiseWrapper = async () => {\n await promise\n .then((result: T) => {\n this.activeForgets--\n completed = true\n resolvedConfig?.onComplete?.([result, undefined])\n })\n .catch((error) => {\n this.activeForgets--\n completed = true\n resolvedConfig?.onComplete?.([undefined, error])\n })\n }\n\n const promises = [promiseWrapper()]\n\n // if there is a timeout, add it to the race\n const timeout = resolvedConfig.timeout ?? defaultForgetConfig.timeout\n if (isNumber(timeout)) {\n const timeoutFunc = async () => {\n await delay(timeout)\n if (!completed) {\n resolvedConfig.onCancel?.()\n this.timeoutHandler(timeout, resolvedConfig)\n }\n }\n promises.push(timeoutFunc())\n }\n\n const all = Promise.race(promises)\n\n all\n .then(() => {\n return\n })\n .catch(() => {\n return\n })\n } catch (ex) {\n this.exceptedForgets += 1\n resolvedConfig?.onException?.(ex as Error)\n this.exceptionHandler(ex as Error, resolvedConfig)\n }\n } else {\n return (promise as () => void)()\n }\n },\n}\n","// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport interface ForgetConfig<T = any> {\n onCancel?: () => void\n onComplete?: (result: [T | undefined, Error | undefined]) => void\n onException?: (error: Error) => void\n timeout?: number\n}\n\nexport const defaultForgetConfig: ForgetConfig<unknown> = { timeout: 30_000 }\n","import { type Promisable } from '@xylabs/promise'\n\nimport type { ForgetConfig } from './ForgetConfig.ts'\nimport { ForgetPromise } from './ForgetPromise.ts'\n\n// used to explicitly launch an async function (or Promise) with awaiting it\nexport const forget = <T>(promise: Promisable<T>, config?: ForgetConfig<T>) => {\n ForgetPromise.forget<T>(promise, config)\n}\n"],"mappings":";AAAA,SAAS,aAAa;AACtB,SAAS,iBAAkC;AAC3C,SAAS,gBAAgB;;;ACMlB,IAAM,sBAA6C,EAAE,SAAS,IAAO;;;ADFrE,IAAM,gBAAgB;AAAA,EAC3B,IAAI,SAAS;AACX,WAAO,KAAK,gBAAgB;AAAA,EAC9B;AAAA,EAEA,eAAe;AAAA,EACf,iBAAiB;AAAA,EAEjB,kBAAkB,CAAC,OAAc,YAA0B;AACzD,YAAQ,MAAM,oCAAoC,MAAM,OAAO,IAAI,KAAK;AAAA,EAC1E;AAAA,EAEA,gBAAgB,CAAC,MAAc,YAA0B;AACvD,YAAQ,MAAM,oCAAoC,IAAI,iBAAiB;AAAA,EACzE;AAAA,EAEA,MAAM,cAAc,WAAW,KAAK,SAAkB;AACpD,QAAI,mBAAmB;AACvB,WAAO,KAAK,QAAQ;AAClB,YAAM,MAAM,QAAQ;AACpB,UAAI,qBAAqB,QAAW;AAClC,4BAAoB;AACpB,YAAI,oBAAoB,GAAG;AACzB,iBAAO,KAAK;AAAA,QACd;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAU,SAAwB,QAA0B;AAE1D,UAAM,iBAAiB;AAAA,MACrB,GAAG;AAAA,MAAqB,GAAG,WAAW,IAAI,QAAQ;AAAA,MAAQ,GAAG;AAAA,IAC/D;AACA,QAAI,UAAU,OAAO,GAAG;AACtB,UAAI;AACF,YAAI,YAAY;AAChB,aAAK;AAEL,cAAM,iBAAiB,YAAY;AACjC,gBAAM,QACH,KAAK,CAAC,WAAc;AACnB,iBAAK;AACL,wBAAY;AACZ,4BAAgB,aAAa,CAAC,QAAQ,MAAS,CAAC;AAAA,UAClD,CAAC,EACA,MAAM,CAAC,UAAU;AAChB,iBAAK;AACL,wBAAY;AACZ,4BAAgB,aAAa,CAAC,QAAW,KAAK,CAAC;AAAA,UACjD,CAAC;AAAA,QACL;AAEA,cAAM,WAAW,CAAC,eAAe,CAAC;AAGlC,cAAM,UAAU,eAAe,WAAW,oBAAoB;AAC9D,YAAI,SAAS,OAAO,GAAG;AACrB,gBAAM,cAAc,YAAY;AAC9B,kBAAM,MAAM,OAAO;AACnB,gBAAI,CAAC,WAAW;AACd,6BAAe,WAAW;AAC1B,mBAAK,eAAe,SAAS,cAAc;AAAA,YAC7C;AAAA,UACF;AACA,mBAAS,KAAK,YAAY,CAAC;AAAA,QAC7B;AAEA,cAAM,MAAM,QAAQ,KAAK,QAAQ;AAEjC,YACG,KAAK,MAAM;AACV;AAAA,QACF,CAAC,EACA,MAAM,MAAM;AACX;AAAA,QACF,CAAC;AAAA,MACL,SAAS,IAAI;AACX,aAAK,mBAAmB;AACxB,wBAAgB,cAAc,EAAW;AACzC,aAAK,iBAAiB,IAAa,cAAc;AAAA,MACnD;AAAA,IACF,OAAO;AACL,aAAQ,QAAuB;AAAA,IACjC;AAAA,EACF;AACF;;;AE5FO,IAAM,SAAS,CAAI,SAAwB,WAA6B;AAC7E,gBAAc,OAAU,SAAS,MAAM;AACzC;","names":[]}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
// src/ForgetConfig.ts
|
|
2
|
+
var defaultForgetConfig = { timeout: 3e4 };
|
|
3
|
+
|
|
4
|
+
// src/ForgetNodeConfig.ts
|
|
5
|
+
var defaultForgetNodeConfig = {
|
|
6
|
+
...defaultForgetConfig,
|
|
7
|
+
terminateOnTimeout: true,
|
|
8
|
+
terminateOnException: true
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
// src/ForgetPromise.ts
|
|
12
|
+
import { delay } from "@xylabs/delay";
|
|
13
|
+
import { isPromise } from "@xylabs/promise";
|
|
14
|
+
import { isNumber } from "@xylabs/typeof";
|
|
15
|
+
var ForgetPromise = {
|
|
16
|
+
get active() {
|
|
17
|
+
return this.activeForgets > 0;
|
|
18
|
+
},
|
|
19
|
+
activeForgets: 0,
|
|
20
|
+
exceptedForgets: 0,
|
|
21
|
+
exceptionHandler: (error, _config) => {
|
|
22
|
+
console.error(`forget promise handler excepted: ${error.message}`, error);
|
|
23
|
+
},
|
|
24
|
+
timeoutHandler: (time, _config) => {
|
|
25
|
+
console.error(`forget promise timeout out after ${time}ms [Cancelling]`);
|
|
26
|
+
},
|
|
27
|
+
async awaitInactive(interval = 100, timeout) {
|
|
28
|
+
let timeoutRemaining = timeout;
|
|
29
|
+
while (this.active) {
|
|
30
|
+
await delay(interval);
|
|
31
|
+
if (timeoutRemaining !== void 0) {
|
|
32
|
+
timeoutRemaining -= interval;
|
|
33
|
+
if (timeoutRemaining <= 0) {
|
|
34
|
+
return this.activeForgets;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return 0;
|
|
39
|
+
},
|
|
40
|
+
/**
|
|
41
|
+
* Used to explicitly launch an async function (or Promise) with awaiting it
|
|
42
|
+
* @param promise The promise to forget
|
|
43
|
+
* @param config Configuration of forget settings
|
|
44
|
+
*/
|
|
45
|
+
forget(promise, config) {
|
|
46
|
+
const resolvedConfig = {
|
|
47
|
+
...defaultForgetConfig,
|
|
48
|
+
...globalThis.xy?.forget?.config,
|
|
49
|
+
...config
|
|
50
|
+
};
|
|
51
|
+
if (isPromise(promise)) {
|
|
52
|
+
try {
|
|
53
|
+
let completed = false;
|
|
54
|
+
this.activeForgets++;
|
|
55
|
+
const promiseWrapper = async () => {
|
|
56
|
+
await promise.then((result) => {
|
|
57
|
+
this.activeForgets--;
|
|
58
|
+
completed = true;
|
|
59
|
+
resolvedConfig?.onComplete?.([result, void 0]);
|
|
60
|
+
}).catch((error) => {
|
|
61
|
+
this.activeForgets--;
|
|
62
|
+
completed = true;
|
|
63
|
+
resolvedConfig?.onComplete?.([void 0, error]);
|
|
64
|
+
});
|
|
65
|
+
};
|
|
66
|
+
const promises = [promiseWrapper()];
|
|
67
|
+
const timeout = resolvedConfig.timeout ?? defaultForgetConfig.timeout;
|
|
68
|
+
if (isNumber(timeout)) {
|
|
69
|
+
const timeoutFunc = async () => {
|
|
70
|
+
await delay(timeout);
|
|
71
|
+
if (!completed) {
|
|
72
|
+
resolvedConfig.onCancel?.();
|
|
73
|
+
this.timeoutHandler(timeout, resolvedConfig);
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
promises.push(timeoutFunc());
|
|
77
|
+
}
|
|
78
|
+
const all = Promise.race(promises);
|
|
79
|
+
all.then(() => {
|
|
80
|
+
return;
|
|
81
|
+
}).catch(() => {
|
|
82
|
+
return;
|
|
83
|
+
});
|
|
84
|
+
} catch (ex) {
|
|
85
|
+
this.exceptedForgets += 1;
|
|
86
|
+
resolvedConfig?.onException?.(ex);
|
|
87
|
+
this.exceptionHandler(ex, resolvedConfig);
|
|
88
|
+
}
|
|
89
|
+
} else {
|
|
90
|
+
return promise();
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
// src/ForgetPromiseNode.ts
|
|
96
|
+
var ForgetPromiseNode = {
|
|
97
|
+
...ForgetPromise,
|
|
98
|
+
exceptionHandler: (error, config) => {
|
|
99
|
+
ForgetPromise.exceptionHandler(error, config);
|
|
100
|
+
if (config?.terminateOnException === true) {
|
|
101
|
+
process.exit(1);
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
timeoutHandler: (time, config) => {
|
|
105
|
+
ForgetPromise.timeoutHandler(time, config);
|
|
106
|
+
if (config?.terminateOnTimeout === true) {
|
|
107
|
+
process.exit(2);
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
/**
|
|
111
|
+
* Used to explicitly launch an async function (or Promise) with awaiting it
|
|
112
|
+
* @param promise The promise to forget
|
|
113
|
+
* @param config Configuration of forget settings
|
|
114
|
+
*/
|
|
115
|
+
forget(promise, config) {
|
|
116
|
+
const resolvedConfig = {
|
|
117
|
+
...defaultForgetNodeConfig,
|
|
118
|
+
...globalThis.xy?.forget?.config,
|
|
119
|
+
...config
|
|
120
|
+
};
|
|
121
|
+
ForgetPromise.forget(promise, resolvedConfig);
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
// src/forgetNode.ts
|
|
126
|
+
var forgetNode = (promise, config) => {
|
|
127
|
+
ForgetPromiseNode.forget(promise, config);
|
|
128
|
+
};
|
|
129
|
+
export {
|
|
130
|
+
ForgetPromiseNode as ForgetPromise,
|
|
131
|
+
defaultForgetConfig,
|
|
132
|
+
forgetNode as forget
|
|
133
|
+
};
|
|
134
|
+
//# sourceMappingURL=index-node.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/ForgetConfig.ts","../../src/ForgetNodeConfig.ts","../../src/ForgetPromise.ts","../../src/ForgetPromiseNode.ts","../../src/forgetNode.ts"],"sourcesContent":["// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport interface ForgetConfig<T = any> {\n onCancel?: () => void\n onComplete?: (result: [T | undefined, Error | undefined]) => void\n onException?: (error: Error) => void\n timeout?: number\n}\n\nexport const defaultForgetConfig: ForgetConfig<unknown> = { timeout: 30_000 }\n","import { defaultForgetConfig, type ForgetConfig } from './ForgetConfig.ts'\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport interface ForgetNodeConfig<T = any> extends ForgetConfig<T> {\n terminateOnException?: boolean // terminate the process on an exception that happens outside of the promise being forgotten\n terminateOnTimeout?: boolean // terminate the process if the promise times out\n}\n\nexport const defaultForgetNodeConfig: ForgetNodeConfig<unknown> = {\n ...defaultForgetConfig,\n terminateOnTimeout: true,\n terminateOnException: true,\n}\n","import { delay } from '@xylabs/delay'\nimport { isPromise, type Promisable } from '@xylabs/promise'\nimport { isNumber } from '@xylabs/typeof'\n\nimport { defaultForgetConfig, type ForgetConfig } from './ForgetConfig.ts'\n\nexport const ForgetPromise = {\n get active() {\n return this.activeForgets > 0\n },\n\n activeForgets: 0,\n exceptedForgets: 0,\n\n exceptionHandler: (error: Error, _config: ForgetConfig) => {\n console.error(`forget promise handler excepted: ${error.message}`, error)\n },\n\n timeoutHandler: (time: number, _config: ForgetConfig) => {\n console.error(`forget promise timeout out after ${time}ms [Cancelling]`)\n },\n\n async awaitInactive(interval = 100, timeout?: number) {\n let timeoutRemaining = timeout\n while (this.active) {\n await delay(interval)\n if (timeoutRemaining !== undefined) {\n timeoutRemaining -= interval\n if (timeoutRemaining <= 0) {\n return this.activeForgets\n }\n }\n }\n return 0\n },\n\n /**\n * Used to explicitly launch an async function (or Promise) with awaiting it\n * @param promise The promise to forget\n * @param config Configuration of forget settings\n */\n forget<T>(promise: Promisable<T>, config?: ForgetConfig<T>) {\n // default | global | provided priorities for config (not deep merge)\n const resolvedConfig = {\n ...defaultForgetConfig, ...globalThis.xy?.forget?.config, ...config,\n }\n if (isPromise(promise)) {\n try {\n let completed = false\n this.activeForgets++\n\n const promiseWrapper = async () => {\n await promise\n .then((result: T) => {\n this.activeForgets--\n completed = true\n resolvedConfig?.onComplete?.([result, undefined])\n })\n .catch((error) => {\n this.activeForgets--\n completed = true\n resolvedConfig?.onComplete?.([undefined, error])\n })\n }\n\n const promises = [promiseWrapper()]\n\n // if there is a timeout, add it to the race\n const timeout = resolvedConfig.timeout ?? defaultForgetConfig.timeout\n if (isNumber(timeout)) {\n const timeoutFunc = async () => {\n await delay(timeout)\n if (!completed) {\n resolvedConfig.onCancel?.()\n this.timeoutHandler(timeout, resolvedConfig)\n }\n }\n promises.push(timeoutFunc())\n }\n\n const all = Promise.race(promises)\n\n all\n .then(() => {\n return\n })\n .catch(() => {\n return\n })\n } catch (ex) {\n this.exceptedForgets += 1\n resolvedConfig?.onException?.(ex as Error)\n this.exceptionHandler(ex as Error, resolvedConfig)\n }\n } else {\n return (promise as () => void)()\n }\n },\n}\n","/// <reference types=\"node\" />\n\nimport type { Promisable } from '@xylabs/promise'\n\nimport { defaultForgetNodeConfig, type ForgetNodeConfig } from './ForgetNodeConfig.ts'\nimport { ForgetPromise } from './ForgetPromise.ts'\n\nexport const ForgetPromiseNode = {\n ...ForgetPromise,\n exceptionHandler: (error: Error, config: ForgetNodeConfig) => {\n // default | global | provided priorities for config (not deep merge)\n ForgetPromise.exceptionHandler(error, config)\n\n if (config?.terminateOnException === true) {\n // eslint-disable-next-line unicorn/no-process-exit\n process.exit(1)\n }\n },\n timeoutHandler: (time: number, config: ForgetNodeConfig) => {\n ForgetPromise.timeoutHandler(time, config)\n if (config?.terminateOnTimeout === true) {\n // eslint-disable-next-line unicorn/no-process-exit\n process.exit(2)\n }\n },\n\n /**\n * Used to explicitly launch an async function (or Promise) with awaiting it\n * @param promise The promise to forget\n * @param config Configuration of forget settings\n */\n forget<T>(promise: Promisable<T>, config?: ForgetNodeConfig<T>) {\n const resolvedConfig = {\n ...defaultForgetNodeConfig, ...globalThis.xy?.forget?.config, ...config,\n }\n ForgetPromise.forget<T>(promise, resolvedConfig)\n },\n}\n","import { type Promisable } from '@xylabs/promise'\n\nimport type { ForgetConfig } from './ForgetConfig.ts'\nimport { ForgetPromiseNode } from './ForgetPromiseNode.ts'\n\n// used to explicitly launch an async function (or Promise) with awaiting it\nexport const forgetNode = <T>(promise: Promisable<T>, config?: ForgetConfig<T>) => {\n ForgetPromiseNode.forget<T>(promise, config)\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface ForgetConfig<T = any> {
|
|
2
|
+
onCancel?: () => void;
|
|
3
|
+
onComplete?: (result: [T | undefined, Error | undefined]) => void;
|
|
4
|
+
onException?: (error: Error) => void;
|
|
5
|
+
timeout?: number;
|
|
6
|
+
}
|
|
7
|
+
export declare const defaultForgetConfig: ForgetConfig<unknown>;
|
|
8
|
+
//# sourceMappingURL=ForgetConfig.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ForgetConfig.d.ts","sourceRoot":"","sources":["../../src/ForgetConfig.ts"],"names":[],"mappings":"AACA,MAAM,WAAW,YAAY,CAAC,CAAC,GAAG,GAAG;IACnC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;IACrB,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,SAAS,EAAE,KAAK,GAAG,SAAS,CAAC,KAAK,IAAI,CAAA;IACjE,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;IACpC,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,eAAO,MAAM,mBAAmB,EAAE,YAAY,CAAC,OAAO,CAAuB,CAAA"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type ForgetConfig } from './ForgetConfig.ts';
|
|
2
|
+
export interface ForgetNodeConfig<T = any> extends ForgetConfig<T> {
|
|
3
|
+
terminateOnException?: boolean;
|
|
4
|
+
terminateOnTimeout?: boolean;
|
|
5
|
+
}
|
|
6
|
+
export declare const defaultForgetNodeConfig: ForgetNodeConfig<unknown>;
|
|
7
|
+
//# sourceMappingURL=ForgetNodeConfig.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ForgetNodeConfig.d.ts","sourceRoot":"","sources":["../../src/ForgetNodeConfig.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAG1E,MAAM,WAAW,gBAAgB,CAAC,CAAC,GAAG,GAAG,CAAE,SAAQ,YAAY,CAAC,CAAC,CAAC;IAChE,oBAAoB,CAAC,EAAE,OAAO,CAAA;IAC9B,kBAAkB,CAAC,EAAE,OAAO,CAAA;CAC7B;AAED,eAAO,MAAM,uBAAuB,EAAE,gBAAgB,CAAC,OAAO,CAI7D,CAAA"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type Promisable } from '@xylabs/promise';
|
|
2
|
+
import { type ForgetConfig } from './ForgetConfig.ts';
|
|
3
|
+
export declare const ForgetPromise: {
|
|
4
|
+
readonly active: boolean;
|
|
5
|
+
activeForgets: number;
|
|
6
|
+
exceptedForgets: number;
|
|
7
|
+
exceptionHandler: (error: Error, _config: ForgetConfig) => void;
|
|
8
|
+
timeoutHandler: (time: number, _config: ForgetConfig) => void;
|
|
9
|
+
awaitInactive(interval?: number, timeout?: number): Promise<number>;
|
|
10
|
+
/**
|
|
11
|
+
* Used to explicitly launch an async function (or Promise) with awaiting it
|
|
12
|
+
* @param promise The promise to forget
|
|
13
|
+
* @param config Configuration of forget settings
|
|
14
|
+
*/
|
|
15
|
+
forget<T>(promise: Promisable<T>, config?: ForgetConfig<T>): void;
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=ForgetPromise.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ForgetPromise.d.ts","sourceRoot":"","sources":["../../src/ForgetPromise.ts"],"names":[],"mappings":"AACA,OAAO,EAAa,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAG5D,OAAO,EAAuB,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAE1E,eAAO,MAAM,aAAa;;;;8BAQE,KAAK,WAAW,YAAY;2BAI/B,MAAM,WAAW,YAAY;+CAIN,MAAM;IAcpD;;;;OAIG;WACI,CAAC,WAAW,UAAU,CAAC,CAAC,CAAC,WAAW,YAAY,CAAC,CAAC,CAAC;CAyD3D,CAAA"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Promisable } from '@xylabs/promise';
|
|
2
|
+
import { type ForgetNodeConfig } from './ForgetNodeConfig.ts';
|
|
3
|
+
export declare const ForgetPromiseNode: {
|
|
4
|
+
exceptionHandler: (error: Error, config: ForgetNodeConfig) => void;
|
|
5
|
+
timeoutHandler: (time: number, config: ForgetNodeConfig) => void;
|
|
6
|
+
/**
|
|
7
|
+
* Used to explicitly launch an async function (or Promise) with awaiting it
|
|
8
|
+
* @param promise The promise to forget
|
|
9
|
+
* @param config Configuration of forget settings
|
|
10
|
+
*/
|
|
11
|
+
forget<T>(promise: Promisable<T>, config?: ForgetNodeConfig<T>): void;
|
|
12
|
+
active: boolean;
|
|
13
|
+
activeForgets: number;
|
|
14
|
+
exceptedForgets: number;
|
|
15
|
+
awaitInactive(interval?: number, timeout?: number): Promise<number>;
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=ForgetPromiseNode.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ForgetPromiseNode.d.ts","sourceRoot":"","sources":["../../src/ForgetPromiseNode.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAEjD,OAAO,EAA2B,KAAK,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AAGtF,eAAO,MAAM,iBAAiB;8BAEF,KAAK,UAAU,gBAAgB;2BASlC,MAAM,UAAU,gBAAgB;IAQvD;;;;SAIK;WACE,CAAC,WAAW,UAAU,CAAC,CAAC,CAAC,WAAW,gBAAgB,CAAC,CAAC,CAAC;;;;;CAM/D,CAAA"}
|
package/dist/types/forget.d.ts
CHANGED
|
@@ -1,18 +1,4 @@
|
|
|
1
1
|
import { type Promisable } from '@xylabs/promise';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
delay: number;
|
|
5
|
-
}
|
|
6
|
-
export declare const ForgetPromise: {
|
|
7
|
-
readonly active: boolean;
|
|
8
|
-
activeForgets: number;
|
|
9
|
-
awaitInactive(interval?: number, timeout?: number): Promise<number>;
|
|
10
|
-
/**
|
|
11
|
-
* Used to explicitly launch an async function (or Promise) with awaiting it
|
|
12
|
-
* @param promise The promise to forget
|
|
13
|
-
* @param config Configuration of forget settings
|
|
14
|
-
*/
|
|
15
|
-
forget<T>(promise: Promisable<T>, onComplete?: (result: [T | undefined, Error | undefined]) => void, config?: ForgetTimeoutConfig): void;
|
|
16
|
-
};
|
|
17
|
-
export declare const forget: <T>(promise: Promisable<T>, onComplete?: (result: [T | undefined, Error | undefined]) => void, timeout?: ForgetTimeoutConfig) => void;
|
|
2
|
+
import type { ForgetConfig } from './ForgetConfig.ts';
|
|
3
|
+
export declare const forget: <T>(promise: Promisable<T>, config?: ForgetConfig<T>) => void;
|
|
18
4
|
//# sourceMappingURL=forget.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"forget.d.ts","sourceRoot":"","sources":["../../src/forget.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"forget.d.ts","sourceRoot":"","sources":["../../src/forget.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAEjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAIrD,eAAO,MAAM,MAAM,GAAI,CAAC,EAAE,SAAS,UAAU,CAAC,CAAC,CAAC,EAAE,SAAS,YAAY,CAAC,CAAC,CAAC,SAEzE,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"forgetNode.d.ts","sourceRoot":"","sources":["../../src/forgetNode.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAEjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAIrD,eAAO,MAAM,UAAU,GAAI,CAAC,EAAE,SAAS,UAAU,CAAC,CAAC,CAAC,EAAE,SAAS,YAAY,CAAC,CAAC,CAAC,SAE7E,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-node.d.ts","sourceRoot":"","sources":["../../src/index-node.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAA;AACjC,OAAO,EAAE,UAAU,IAAI,MAAM,EAAE,MAAM,iBAAiB,CAAA;AACtD,OAAO,EAAE,iBAAiB,IAAI,aAAa,EAAE,MAAM,wBAAwB,CAAA"}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAA;AAC3B,cAAc,mBAAmB,CAAA;AACjC,cAAc,oBAAoB,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xylabs/forget",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.11.1",
|
|
4
4
|
"description": "Base functionality used throughout XY Labs TypeScript/JavaScript libraries",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"forget",
|
|
@@ -28,6 +28,10 @@
|
|
|
28
28
|
"type": "module",
|
|
29
29
|
"exports": {
|
|
30
30
|
".": {
|
|
31
|
+
"node": {
|
|
32
|
+
"types": "./dist/types/index-node.d.ts",
|
|
33
|
+
"default": "./dist/node/index-node.mjs"
|
|
34
|
+
},
|
|
31
35
|
"types": "./dist/types/index.d.ts",
|
|
32
36
|
"default": "./dist/neutral/index.mjs"
|
|
33
37
|
},
|
|
@@ -36,8 +40,9 @@
|
|
|
36
40
|
"module": "./dist/neutral/index.mjs",
|
|
37
41
|
"types": "./dist/types/index.d.ts",
|
|
38
42
|
"dependencies": {
|
|
39
|
-
"@xylabs/delay": "^4.
|
|
40
|
-
"@xylabs/promise": "^4.
|
|
43
|
+
"@xylabs/delay": "^4.11.1",
|
|
44
|
+
"@xylabs/promise": "^4.11.1",
|
|
45
|
+
"@xylabs/typeof": "^4.11.1"
|
|
41
46
|
},
|
|
42
47
|
"devDependencies": {
|
|
43
48
|
"@xylabs/ts-scripts-yarn3": "^6.5.7",
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
2
|
+
export interface ForgetConfig<T = any> {
|
|
3
|
+
onCancel?: () => void
|
|
4
|
+
onComplete?: (result: [T | undefined, Error | undefined]) => void
|
|
5
|
+
onException?: (error: Error) => void
|
|
6
|
+
timeout?: number
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const defaultForgetConfig: ForgetConfig<unknown> = { timeout: 30_000 }
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { defaultForgetConfig, type ForgetConfig } from './ForgetConfig.ts'
|
|
2
|
+
|
|
3
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
4
|
+
export interface ForgetNodeConfig<T = any> extends ForgetConfig<T> {
|
|
5
|
+
terminateOnException?: boolean // terminate the process on an exception that happens outside of the promise being forgotten
|
|
6
|
+
terminateOnTimeout?: boolean // terminate the process if the promise times out
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const defaultForgetNodeConfig: ForgetNodeConfig<unknown> = {
|
|
10
|
+
...defaultForgetConfig,
|
|
11
|
+
terminateOnTimeout: true,
|
|
12
|
+
terminateOnException: true,
|
|
13
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { delay } from '@xylabs/delay'
|
|
2
|
+
import { isPromise, type Promisable } from '@xylabs/promise'
|
|
3
|
+
import { isNumber } from '@xylabs/typeof'
|
|
4
|
+
|
|
5
|
+
import { defaultForgetConfig, type ForgetConfig } from './ForgetConfig.ts'
|
|
6
|
+
|
|
7
|
+
export const ForgetPromise = {
|
|
8
|
+
get active() {
|
|
9
|
+
return this.activeForgets > 0
|
|
10
|
+
},
|
|
11
|
+
|
|
12
|
+
activeForgets: 0,
|
|
13
|
+
exceptedForgets: 0,
|
|
14
|
+
|
|
15
|
+
exceptionHandler: (error: Error, _config: ForgetConfig) => {
|
|
16
|
+
console.error(`forget promise handler excepted: ${error.message}`, error)
|
|
17
|
+
},
|
|
18
|
+
|
|
19
|
+
timeoutHandler: (time: number, _config: ForgetConfig) => {
|
|
20
|
+
console.error(`forget promise timeout out after ${time}ms [Cancelling]`)
|
|
21
|
+
},
|
|
22
|
+
|
|
23
|
+
async awaitInactive(interval = 100, timeout?: number) {
|
|
24
|
+
let timeoutRemaining = timeout
|
|
25
|
+
while (this.active) {
|
|
26
|
+
await delay(interval)
|
|
27
|
+
if (timeoutRemaining !== undefined) {
|
|
28
|
+
timeoutRemaining -= interval
|
|
29
|
+
if (timeoutRemaining <= 0) {
|
|
30
|
+
return this.activeForgets
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return 0
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Used to explicitly launch an async function (or Promise) with awaiting it
|
|
39
|
+
* @param promise The promise to forget
|
|
40
|
+
* @param config Configuration of forget settings
|
|
41
|
+
*/
|
|
42
|
+
forget<T>(promise: Promisable<T>, config?: ForgetConfig<T>) {
|
|
43
|
+
// default | global | provided priorities for config (not deep merge)
|
|
44
|
+
const resolvedConfig = {
|
|
45
|
+
...defaultForgetConfig, ...globalThis.xy?.forget?.config, ...config,
|
|
46
|
+
}
|
|
47
|
+
if (isPromise(promise)) {
|
|
48
|
+
try {
|
|
49
|
+
let completed = false
|
|
50
|
+
this.activeForgets++
|
|
51
|
+
|
|
52
|
+
const promiseWrapper = async () => {
|
|
53
|
+
await promise
|
|
54
|
+
.then((result: T) => {
|
|
55
|
+
this.activeForgets--
|
|
56
|
+
completed = true
|
|
57
|
+
resolvedConfig?.onComplete?.([result, undefined])
|
|
58
|
+
})
|
|
59
|
+
.catch((error) => {
|
|
60
|
+
this.activeForgets--
|
|
61
|
+
completed = true
|
|
62
|
+
resolvedConfig?.onComplete?.([undefined, error])
|
|
63
|
+
})
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const promises = [promiseWrapper()]
|
|
67
|
+
|
|
68
|
+
// if there is a timeout, add it to the race
|
|
69
|
+
const timeout = resolvedConfig.timeout ?? defaultForgetConfig.timeout
|
|
70
|
+
if (isNumber(timeout)) {
|
|
71
|
+
const timeoutFunc = async () => {
|
|
72
|
+
await delay(timeout)
|
|
73
|
+
if (!completed) {
|
|
74
|
+
resolvedConfig.onCancel?.()
|
|
75
|
+
this.timeoutHandler(timeout, resolvedConfig)
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
promises.push(timeoutFunc())
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const all = Promise.race(promises)
|
|
82
|
+
|
|
83
|
+
all
|
|
84
|
+
.then(() => {
|
|
85
|
+
return
|
|
86
|
+
})
|
|
87
|
+
.catch(() => {
|
|
88
|
+
return
|
|
89
|
+
})
|
|
90
|
+
} catch (ex) {
|
|
91
|
+
this.exceptedForgets += 1
|
|
92
|
+
resolvedConfig?.onException?.(ex as Error)
|
|
93
|
+
this.exceptionHandler(ex as Error, resolvedConfig)
|
|
94
|
+
}
|
|
95
|
+
} else {
|
|
96
|
+
return (promise as () => void)()
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
|
|
3
|
+
import type { Promisable } from '@xylabs/promise'
|
|
4
|
+
|
|
5
|
+
import { defaultForgetNodeConfig, type ForgetNodeConfig } from './ForgetNodeConfig.ts'
|
|
6
|
+
import { ForgetPromise } from './ForgetPromise.ts'
|
|
7
|
+
|
|
8
|
+
export const ForgetPromiseNode = {
|
|
9
|
+
...ForgetPromise,
|
|
10
|
+
exceptionHandler: (error: Error, config: ForgetNodeConfig) => {
|
|
11
|
+
// default | global | provided priorities for config (not deep merge)
|
|
12
|
+
ForgetPromise.exceptionHandler(error, config)
|
|
13
|
+
|
|
14
|
+
if (config?.terminateOnException === true) {
|
|
15
|
+
// eslint-disable-next-line unicorn/no-process-exit
|
|
16
|
+
process.exit(1)
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
timeoutHandler: (time: number, config: ForgetNodeConfig) => {
|
|
20
|
+
ForgetPromise.timeoutHandler(time, config)
|
|
21
|
+
if (config?.terminateOnTimeout === true) {
|
|
22
|
+
// eslint-disable-next-line unicorn/no-process-exit
|
|
23
|
+
process.exit(2)
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Used to explicitly launch an async function (or Promise) with awaiting it
|
|
29
|
+
* @param promise The promise to forget
|
|
30
|
+
* @param config Configuration of forget settings
|
|
31
|
+
*/
|
|
32
|
+
forget<T>(promise: Promisable<T>, config?: ForgetNodeConfig<T>) {
|
|
33
|
+
const resolvedConfig = {
|
|
34
|
+
...defaultForgetNodeConfig, ...globalThis.xy?.forget?.config, ...config,
|
|
35
|
+
}
|
|
36
|
+
ForgetPromise.forget<T>(promise, resolvedConfig)
|
|
37
|
+
},
|
|
38
|
+
}
|
package/src/forget.ts
CHANGED
|
@@ -1,86 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { isPromise, type Promisable } from '@xylabs/promise'
|
|
1
|
+
import { type Promisable } from '@xylabs/promise'
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
delay: number
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export const ForgetPromise = {
|
|
10
|
-
get active() {
|
|
11
|
-
return this.activeForgets > 0
|
|
12
|
-
},
|
|
13
|
-
|
|
14
|
-
activeForgets: 0,
|
|
15
|
-
|
|
16
|
-
async awaitInactive(interval = 100, timeout?: number) {
|
|
17
|
-
let timeoutRemaining = timeout
|
|
18
|
-
while (this.active) {
|
|
19
|
-
await delay(interval)
|
|
20
|
-
if (timeoutRemaining !== undefined) {
|
|
21
|
-
timeoutRemaining -= interval
|
|
22
|
-
if (timeoutRemaining <= 0) {
|
|
23
|
-
return this.activeForgets
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
return 0
|
|
28
|
-
},
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Used to explicitly launch an async function (or Promise) with awaiting it
|
|
32
|
-
* @param promise The promise to forget
|
|
33
|
-
* @param config Configuration of forget settings
|
|
34
|
-
*/
|
|
35
|
-
forget<T>(promise: Promisable<T>, onComplete?: (result: [T | undefined, Error | undefined]) => void, config?: ForgetTimeoutConfig) {
|
|
36
|
-
if (isPromise(promise)) {
|
|
37
|
-
let completed = false
|
|
38
|
-
this.activeForgets++
|
|
39
|
-
|
|
40
|
-
const promiseWrapper = async () => {
|
|
41
|
-
await promise
|
|
42
|
-
.then((result: T) => {
|
|
43
|
-
this.activeForgets--
|
|
44
|
-
completed = true
|
|
45
|
-
onComplete?.([result, undefined])
|
|
46
|
-
})
|
|
47
|
-
.catch((error) => {
|
|
48
|
-
this.activeForgets--
|
|
49
|
-
completed = true
|
|
50
|
-
onComplete?.([undefined, error])
|
|
51
|
-
})
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const promises = [promiseWrapper()]
|
|
55
|
-
|
|
56
|
-
// if there is a timeout, add it to the race
|
|
57
|
-
if (config) {
|
|
58
|
-
const timeoutFunc = async () => {
|
|
59
|
-
await delay(config.delay)
|
|
60
|
-
if (!completed) {
|
|
61
|
-
console.log(`forget promise timeout out after ${config.delay}ms [Cancelling]`)
|
|
62
|
-
config.cancel?.()
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
promises.push(timeoutFunc())
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const all = Promise.race(promises)
|
|
69
|
-
|
|
70
|
-
all
|
|
71
|
-
.then(() => {
|
|
72
|
-
return
|
|
73
|
-
})
|
|
74
|
-
.catch(() => {
|
|
75
|
-
return
|
|
76
|
-
})
|
|
77
|
-
} else {
|
|
78
|
-
return (promise as () => void)()
|
|
79
|
-
}
|
|
80
|
-
},
|
|
81
|
-
}
|
|
3
|
+
import type { ForgetConfig } from './ForgetConfig.ts'
|
|
4
|
+
import { ForgetPromise } from './ForgetPromise.ts'
|
|
82
5
|
|
|
83
6
|
// used to explicitly launch an async function (or Promise) with awaiting it
|
|
84
|
-
export const forget = <T>(promise: Promisable<T>,
|
|
85
|
-
ForgetPromise.forget<T>(promise,
|
|
7
|
+
export const forget = <T>(promise: Promisable<T>, config?: ForgetConfig<T>) => {
|
|
8
|
+
ForgetPromise.forget<T>(promise, config)
|
|
86
9
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type Promisable } from '@xylabs/promise'
|
|
2
|
+
|
|
3
|
+
import type { ForgetConfig } from './ForgetConfig.ts'
|
|
4
|
+
import { ForgetPromiseNode } from './ForgetPromiseNode.ts'
|
|
5
|
+
|
|
6
|
+
// used to explicitly launch an async function (or Promise) with awaiting it
|
|
7
|
+
export const forgetNode = <T>(promise: Promisable<T>, config?: ForgetConfig<T>) => {
|
|
8
|
+
ForgetPromiseNode.forget<T>(promise, config)
|
|
9
|
+
}
|
package/src/index.ts
CHANGED
package/xy.config.ts
CHANGED
|
@@ -2,8 +2,8 @@ import type { XyTsupConfig } from '@xylabs/ts-scripts-yarn3'
|
|
|
2
2
|
const config: XyTsupConfig = {
|
|
3
3
|
compile: {
|
|
4
4
|
browser: {},
|
|
5
|
-
neutral: { src:
|
|
6
|
-
node: {},
|
|
5
|
+
neutral: { src: { entry: ['src/index.ts'] } },
|
|
6
|
+
node: { src: { entry: ['src/index-node.ts'] } },
|
|
7
7
|
},
|
|
8
8
|
}
|
|
9
9
|
|