@xylabs/forget 4.10.0 → 4.11.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.
@@ -1,11 +1,24 @@
1
- // src/forget.ts
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, onComplete, config) {
40
+ forget(promise, config) {
41
+ const resolvedConfig = {
42
+ ...defaultForgetConfig,
43
+ ...globalThis.xy?.forget?.config,
44
+ ...config
45
+ };
28
46
  if (isPromise(promise)) {
29
- let completed = false;
30
- this.activeForgets++;
31
- const promiseWrapper = async () => {
32
- await promise.then((result) => {
33
- this.activeForgets--;
34
- completed = true;
35
- onComplete?.([result, void 0]);
36
- }).catch((error) => {
37
- this.activeForgets--;
38
- completed = true;
39
- onComplete?.([void 0, error]);
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.push(timeoutFunc());
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
- var forget = (promise, onComplete, timeout) => {
65
- ForgetPromise.forget(promise, onComplete, timeout);
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'\n\nexport interface ForgetTimeoutConfig {\n cancel: () => void\n delay: number\n}\n\nexport const ForgetPromise = {\n get active() {\n return this.activeForgets > 0\n },\n\n activeForgets: 0,\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>, onComplete?: (result: [T | undefined, Error | undefined]) => void, config?: ForgetTimeoutConfig) {\n if (isPromise(promise)) {\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 onComplete?.([result, undefined])\n })\n .catch((error) => {\n this.activeForgets--\n completed = true\n onComplete?.([undefined, error])\n })\n }\n\n const promises = [promiseWrapper()]\n\n // if there is a timeout, add it to the race\n if (config) {\n const timeoutFunc = async () => {\n await delay(config.delay)\n if (!completed) {\n console.log(`forget promise timeout out after ${config.delay}ms [Cancelling]`)\n config.cancel?.()\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 } else {\n return (promise as () => void)()\n }\n },\n}\n\n// used to explicitly launch an async function (or Promise) with awaiting it\nexport const forget = <T>(promise: Promisable<T>, onComplete?: (result: [T | undefined, Error | undefined]) => void, timeout?: ForgetTimeoutConfig) => {\n ForgetPromise.forget<T>(promise, onComplete, timeout)\n}\n"],"mappings":";AAAA,SAAS,aAAa;AACtB,SAAS,iBAAkC;AAOpC,IAAM,gBAAgB;AAAA,EAC3B,IAAI,SAAS;AACX,WAAO,KAAK,gBAAgB;AAAA,EAC9B;AAAA,EAEA,eAAe;AAAA,EAEf,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,YAAmE,QAA8B;AACjI,QAAI,UAAU,OAAO,GAAG;AACtB,UAAI,YAAY;AAChB,WAAK;AAEL,YAAM,iBAAiB,YAAY;AACjC,cAAM,QACH,KAAK,CAAC,WAAc;AACnB,eAAK;AACL,sBAAY;AACZ,uBAAa,CAAC,QAAQ,MAAS,CAAC;AAAA,QAClC,CAAC,EACA,MAAM,CAAC,UAAU;AAChB,eAAK;AACL,sBAAY;AACZ,uBAAa,CAAC,QAAW,KAAK,CAAC;AAAA,QACjC,CAAC;AAAA,MACL;AAEA,YAAM,WAAW,CAAC,eAAe,CAAC;AAGlC,UAAI,QAAQ;AACV,cAAM,cAAc,YAAY;AAC9B,gBAAM,MAAM,OAAO,KAAK;AACxB,cAAI,CAAC,WAAW;AACd,oBAAQ,IAAI,oCAAoC,OAAO,KAAK,iBAAiB;AAC7E,mBAAO,SAAS;AAAA,UAClB;AAAA,QACF;AACA,iBAAS,KAAK,YAAY,CAAC;AAAA,MAC7B;AAEA,YAAM,MAAM,QAAQ,KAAK,QAAQ;AAEjC,UACG,KAAK,MAAM;AACV;AAAA,MACF,CAAC,EACA,MAAM,MAAM;AACX;AAAA,MACF,CAAC;AAAA,IACL,OAAO;AACL,aAAQ,QAAuB;AAAA,IACjC;AAAA,EACF;AACF;AAGO,IAAM,SAAS,CAAI,SAAwB,YAAmE,YAAkC;AACrJ,gBAAc,OAAU,SAAS,YAAY,OAAO;AACtD;","names":[]}
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"}
@@ -1,18 +1,4 @@
1
1
  import { type Promisable } from '@xylabs/promise';
2
- export interface ForgetTimeoutConfig {
3
- cancel: () => void;
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":"AACA,OAAO,EAAa,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAE5D,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,IAAI,CAAA;IAClB,KAAK,EAAE,MAAM,CAAA;CACd;AAED,eAAO,MAAM,aAAa;;;+CAOsB,MAAM;IAcpD;;;;OAIG;WACI,CAAC,WAAW,UAAU,CAAC,CAAC,CAAC,eAAe,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,SAAS,EAAE,KAAK,GAAG,SAAS,CAAC,KAAK,IAAI,WAAW,mBAAmB;CA8ClI,CAAA;AAGD,eAAO,MAAM,MAAM,GAAI,CAAC,EAAE,SAAS,UAAU,CAAC,CAAC,CAAC,EAAE,aAAa,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,SAAS,EAAE,KAAK,GAAG,SAAS,CAAC,KAAK,IAAI,EAAE,UAAU,mBAAmB,SAEjJ,CAAA"}
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,4 @@
1
+ import { type Promisable } from '@xylabs/promise';
2
+ import type { ForgetConfig } from './ForgetConfig.ts';
3
+ export declare const forgetNode: <T>(promise: Promisable<T>, config?: ForgetConfig<T>) => void;
4
+ //# sourceMappingURL=forgetNode.d.ts.map
@@ -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,4 @@
1
+ export * from './ForgetConfig.ts';
2
+ export { forgetNode as forget } from './forgetNode.ts';
3
+ export { ForgetPromiseNode as ForgetPromise } from './ForgetPromiseNode.ts';
4
+ //# sourceMappingURL=index-node.d.ts.map
@@ -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"}
@@ -1,2 +1,4 @@
1
1
  export * from './forget.ts';
2
+ export * from './ForgetConfig.ts';
3
+ export * from './ForgetPromise.ts';
2
4
  //# sourceMappingURL=index.d.ts.map
@@ -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.10.0",
3
+ "version": "4.11.0",
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.10.0",
40
- "@xylabs/promise": "^4.10.0"
43
+ "@xylabs/delay": "^4.11.0",
44
+ "@xylabs/promise": "^4.11.0",
45
+ "@xylabs/typeof": "^4.11.0"
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 { delay } from '@xylabs/delay'
2
- import { isPromise, type Promisable } from '@xylabs/promise'
1
+ import { type Promisable } from '@xylabs/promise'
3
2
 
4
- export interface ForgetTimeoutConfig {
5
- cancel: () => void
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>, onComplete?: (result: [T | undefined, Error | undefined]) => void, timeout?: ForgetTimeoutConfig) => {
85
- ForgetPromise.forget<T>(promise, onComplete, timeout)
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
+ }
@@ -0,0 +1,9 @@
1
+ import type { ForgetNodeConfig } from './ForgetNodeConfig.ts'
2
+
3
+ declare global {
4
+ var xy: {
5
+ forget: {
6
+ config: ForgetNodeConfig | undefined
7
+ } | undefined
8
+ } | undefined
9
+ }
@@ -0,0 +1,9 @@
1
+ import type { ForgetConfig } from './ForgetConfig.ts'
2
+
3
+ declare global {
4
+ var xy: {
5
+ forget: {
6
+ config: ForgetConfig | undefined
7
+ } | undefined
8
+ } | undefined
9
+ }
@@ -0,0 +1,3 @@
1
+ export * from './ForgetConfig.ts'
2
+ export { forgetNode as forget } from './forgetNode.ts'
3
+ export { ForgetPromiseNode as ForgetPromise } from './ForgetPromiseNode.ts'
package/src/index.ts CHANGED
@@ -1 +1,3 @@
1
1
  export * from './forget.ts'
2
+ export * from './ForgetConfig.ts'
3
+ export * from './ForgetPromise.ts'
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: true },
6
- node: {},
5
+ neutral: { src: { entry: ['src/index.ts'] } },
6
+ node: { src: { entry: ['src/index-node.ts'] } },
7
7
  },
8
8
  }
9
9