@dr.pogodin/js-utils 0.0.15 → 0.0.16

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.
Files changed (41) hide show
  1. package/babel.config.js +4 -2
  2. package/babel.module.config.js +10 -0
  3. package/build/common/Barrier.js +104 -0
  4. package/build/common/Barrier.js.map +1 -0
  5. package/build/common/Emitter.js +62 -0
  6. package/build/common/Emitter.js.map +1 -0
  7. package/build/common/Semaphore.js +85 -0
  8. package/build/common/Semaphore.js.map +1 -0
  9. package/build/common/index.js +57 -0
  10. package/build/common/index.js.map +1 -0
  11. package/build/common/time.js +80 -0
  12. package/build/common/time.js.map +1 -0
  13. package/build/common/withRetries.js +33 -0
  14. package/build/common/withRetries.js.map +1 -0
  15. package/build/module/Barrier.js +97 -0
  16. package/build/module/Barrier.js.map +1 -0
  17. package/build/module/Emitter.js +55 -0
  18. package/build/module/Emitter.js.map +1 -0
  19. package/build/module/Semaphore.js +78 -0
  20. package/build/module/Semaphore.js.map +1 -0
  21. package/build/{index.js → module/index.js} +1 -0
  22. package/build/module/index.js.map +1 -0
  23. package/build/module/time.js +72 -0
  24. package/build/module/time.js.map +1 -0
  25. package/build/module/withRetries.js +28 -0
  26. package/build/module/withRetries.js.map +1 -0
  27. package/config/babel/preset.js +10 -0
  28. package/package.json +16 -5
  29. package/tsconfig.json +4 -3
  30. package/tsconfig.types.json +11 -0
  31. package/build/Barrier.js +0 -88
  32. package/build/Emitter.js +0 -52
  33. package/build/Semaphore.js +0 -84
  34. package/build/time.js +0 -65
  35. package/build/withRetries.js +0 -39
  36. /package/build/{Barrier.d.ts → types/Barrier.d.ts} +0 -0
  37. /package/build/{Emitter.d.ts → types/Emitter.d.ts} +0 -0
  38. /package/build/{Semaphore.d.ts → types/Semaphore.d.ts} +0 -0
  39. /package/build/{index.d.ts → types/index.d.ts} +0 -0
  40. /package/build/{time.d.ts → types/time.d.ts} +0 -0
  41. /package/build/{withRetries.d.ts → types/withRetries.d.ts} +0 -0
package/babel.config.js CHANGED
@@ -2,7 +2,9 @@
2
2
 
3
3
  export default {
4
4
  presets: [
5
- ['@babel/preset-env', { targets: { node: 'current' } }],
6
- '@babel/preset-typescript',
5
+ ['./config/babel/preset', {
6
+ modules: 'cjs',
7
+ targets: 'defaults',
8
+ }],
7
9
  ],
8
10
  };
@@ -0,0 +1,10 @@
1
+ // Babel is used for Jest testing.
2
+
3
+ export default {
4
+ presets: [
5
+ ['./config/babel/preset', {
6
+ modules: false,
7
+ targets: 'defaults',
8
+ }],
9
+ ],
10
+ };
@@ -0,0 +1,104 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var STATE = /*#__PURE__*/function (STATE) {
8
+ STATE["PENDING"] = "PENDING";
9
+ STATE["REJECTED"] = "REJECTED";
10
+ STATE["RESOLVED"] = "RESOLVED";
11
+ return STATE;
12
+ }(STATE || {});
13
+ /**
14
+ * Barrier is just a Promise which has resolve and reject exposed as instance
15
+ * methods.
16
+ *
17
+ * It has two generic arguments T and TR which correspond to the argument of
18
+ * the .resolve() method, and to the value resolved by the promise (barrier).
19
+ * For a simple barrier TR equals to T, however for barriers created via .then()
20
+ * chain, T corresponds to the argument of the original barrier, and TR to
21
+ * the value resolved by the latest promise in the chain. Consider this:
22
+ *
23
+ * const b = new Barrier<string>();
24
+ * b.resolve('result');
25
+ * const s = await b; // `s` has `string` type, and equals "result".
26
+ *
27
+ * const b = (new Barrier<string>()).then((s) => s.length);
28
+ * b.resolve('result'); // Chained barrier exposes .resolve() method of
29
+ * // the first barrier in the chain, which expects
30
+ * // `string` arugment (T), but the chained barrier
31
+ * // resolves to `number` (TR).
32
+ * const n = await b; // `n` has `number` type, and equals 6.
33
+ *
34
+ * Docs: https://dr.pogodin.studio/docs/react-utils/docs/api/classes/Barrier
35
+ */
36
+ class Barrier extends Promise {
37
+ p_state = (() => STATE.PENDING)();
38
+ constructor(executor) {
39
+ let resolveRef;
40
+ let rejectRef;
41
+ super((resolve, reject) => {
42
+ // Note: Enforcing `void` return type because of the BEWARE note below.
43
+ resolveRef = value => {
44
+ resolve(value);
45
+ this.p_state = STATE.RESOLVED;
46
+
47
+ // BEWARE: Don't try to return `this` here, it will easily cause
48
+ // infinite loops in React Native, which are extremely difficult
49
+ // to troubleshoot (I wasn't able to figure out, are they due to
50
+ // internal Promise implementation in RN, or because of some bad
51
+ // patterns in the host code).
52
+ };
53
+
54
+ // Note: Enforcing `void` return type because of the BEWARE note below.
55
+ rejectRef = reason => {
56
+ reject(reason);
57
+ this.p_state = STATE.REJECTED;
58
+ };
59
+ if (executor) executor(resolveRef, rejectRef);
60
+ });
61
+
62
+ // NOTE: We assume, the only scenario where TR is not equal T is when
63
+ // the Barrier is constructed by a .then() call on a "parent" barrier,
64
+ // and in that scenario .then() itself will replace .p_resolve by another
65
+ // resolver immediately after this constructor returns.
66
+ this.p_resolve = resolveRef;
67
+ this.p_reject = rejectRef;
68
+ }
69
+ get resolve() {
70
+ return arg => {
71
+ this.p_resolve(arg);
72
+ return this;
73
+ };
74
+ }
75
+ get reject() {
76
+ return arg => {
77
+ this.p_reject(arg);
78
+ return this;
79
+ };
80
+ }
81
+ get resolved() {
82
+ return this.p_state === STATE.RESOLVED;
83
+ }
84
+ get rejected() {
85
+ return this.p_state === STATE.REJECTED;
86
+ }
87
+ get settled() {
88
+ return this.p_state !== STATE.PENDING;
89
+ }
90
+ catch(onRejected) {
91
+ return super.catch(onRejected);
92
+ }
93
+ finally(onFinally) {
94
+ return super.finally(onFinally);
95
+ }
96
+ then(onFulfilled, onRejected) {
97
+ const res = super.then(onFulfilled, onRejected);
98
+ res.p_resolve = this.resolve;
99
+ res.p_reject = this.reject;
100
+ return res;
101
+ }
102
+ }
103
+ exports.default = Barrier;
104
+ //# sourceMappingURL=Barrier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Barrier.js","names":["STATE","Barrier","Promise","p_state","PENDING","constructor","executor","resolveRef","rejectRef","resolve","reject","value","RESOLVED","reason","REJECTED","p_resolve","p_reject","arg","resolved","rejected","settled","catch","onRejected","finally","onFinally","then","onFulfilled","res","exports","default"],"sources":["../../src/Barrier.ts"],"sourcesContent":["export type Executor<T> = ConstructorParameters<typeof Promise<T>>[0];\n\ntype Resolver<T> = Parameters<Executor<T>>[0];\ntype Rejecter = Parameters<Executor<unknown>>[1];\n\nenum STATE {\n PENDING = 'PENDING',\n REJECTED = 'REJECTED',\n RESOLVED = 'RESOLVED',\n}\n\n/**\n * Barrier is just a Promise which has resolve and reject exposed as instance\n * methods.\n *\n * It has two generic arguments T and TR which correspond to the argument of\n * the .resolve() method, and to the value resolved by the promise (barrier).\n * For a simple barrier TR equals to T, however for barriers created via .then()\n * chain, T corresponds to the argument of the original barrier, and TR to\n * the value resolved by the latest promise in the chain. Consider this:\n *\n * const b = new Barrier<string>();\n * b.resolve('result');\n * const s = await b; // `s` has `string` type, and equals \"result\".\n *\n * const b = (new Barrier<string>()).then((s) => s.length);\n * b.resolve('result'); // Chained barrier exposes .resolve() method of\n * // the first barrier in the chain, which expects\n * // `string` arugment (T), but the chained barrier\n * // resolves to `number` (TR).\n * const n = await b; // `n` has `number` type, and equals 6.\n *\n * Docs: https://dr.pogodin.studio/docs/react-utils/docs/api/classes/Barrier\n */\nexport default class Barrier<T = unknown, TR = T> extends Promise<TR> {\n private p_resolve: Resolver<T>;\n\n private p_reject: Rejecter;\n\n private p_state = STATE.PENDING;\n\n constructor(executor?: Executor<TR>) {\n let resolveRef: Resolver<TR>;\n let rejectRef: Rejecter;\n\n super((resolve, reject) => {\n // Note: Enforcing `void` return type because of the BEWARE note below.\n resolveRef = (value: TR | PromiseLike<TR>): void => {\n resolve(value);\n this.p_state = STATE.RESOLVED;\n\n // BEWARE: Don't try to return `this` here, it will easily cause\n // infinite loops in React Native, which are extremely difficult\n // to troubleshoot (I wasn't able to figure out, are they due to\n // internal Promise implementation in RN, or because of some bad\n // patterns in the host code).\n };\n\n // Note: Enforcing `void` return type because of the BEWARE note below.\n rejectRef = (reason?: any): void => {\n reject(reason);\n this.p_state = STATE.REJECTED;\n };\n\n if (executor) executor(resolveRef, rejectRef);\n });\n\n // NOTE: We assume, the only scenario where TR is not equal T is when\n // the Barrier is constructed by a .then() call on a \"parent\" barrier,\n // and in that scenario .then() itself will replace .p_resolve by another\n // resolver immediately after this constructor returns.\n this.p_resolve = resolveRef! as Resolver<T>;\n\n this.p_reject = rejectRef!;\n }\n\n get resolve() {\n return (arg: Parameters<Resolver<T>>[0]) => {\n this.p_resolve(arg);\n return this;\n };\n }\n\n get reject() {\n return (arg: Parameters<Rejecter>[0]) => {\n this.p_reject(arg);\n return this;\n };\n }\n\n get resolved() { return this.p_state === STATE.RESOLVED; }\n\n get rejected() { return this.p_state === STATE.REJECTED; }\n\n get settled() { return this.p_state !== STATE.PENDING; }\n\n catch<TR1>(\n onRejected?: ((reason: any) => TR1 | PromiseLike<TR1>) | null,\n ): Barrier<T, TR1> {\n return <Barrier<T, TR1>> super.catch(onRejected);\n }\n\n finally(onFinally?: (() => void) | null): Barrier<TR> {\n return <Barrier<TR>> super.finally(onFinally);\n }\n\n then<TR1, TR2>(\n onFulfilled?: ((value: TR) => TR1 | PromiseLike<TR1>) | null,\n onRejected?: ((reason: any) => TR2 | PromiseLike<TR2>) | null,\n ): Barrier<T, TR1 | TR2> {\n const res = <Barrier<T, TR1 | TR2>> super.then(onFulfilled, onRejected);\n res.p_resolve = this.resolve;\n res.p_reject = this.reject;\n return res;\n }\n}\n"],"mappings":";;;;;;IAKKA,KAAK,0BAALA,KAAK;EAALA,KAAK;EAALA,KAAK;EAALA,KAAK;EAAA,OAALA,KAAK;AAAA,EAALA,KAAK;AAMV;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACe,MAAMC,OAAO,SAA8BC,OAAO,CAAK;EAK5DC,OAAO,UAAGH,KAAK,CAACI,OAAO;EAE/BC,WAAWA,CAACC,QAAuB,EAAE;IACnC,IAAIC,UAAwB;IAC5B,IAAIC,SAAmB;IAEvB,KAAK,CAAC,CAACC,OAAO,EAAEC,MAAM,KAAK;MACzB;MACAH,UAAU,GAAII,KAA2B,IAAW;QAClDF,OAAO,CAACE,KAAK,CAAC;QACd,IAAI,CAACR,OAAO,GAAGH,KAAK,CAACY,QAAQ;;QAE7B;QACA;QACA;QACA;QACA;MACF,CAAC;;MAED;MACAJ,SAAS,GAAIK,MAAY,IAAW;QAClCH,MAAM,CAACG,MAAM,CAAC;QACd,IAAI,CAACV,OAAO,GAAGH,KAAK,CAACc,QAAQ;MAC/B,CAAC;MAED,IAAIR,QAAQ,EAAEA,QAAQ,CAACC,UAAU,EAAEC,SAAS,CAAC;IAC/C,CAAC,CAAC;;IAEF;IACA;IACA;IACA;IACA,IAAI,CAACO,SAAS,GAAGR,UAA0B;IAE3C,IAAI,CAACS,QAAQ,GAAGR,SAAU;EAC5B;EAEA,IAAIC,OAAOA,CAAA,EAAG;IACZ,OAAQQ,GAA+B,IAAK;MAC1C,IAAI,CAACF,SAAS,CAACE,GAAG,CAAC;MACnB,OAAO,IAAI;IACb,CAAC;EACH;EAEA,IAAIP,MAAMA,CAAA,EAAG;IACX,OAAQO,GAA4B,IAAK;MACvC,IAAI,CAACD,QAAQ,CAACC,GAAG,CAAC;MAClB,OAAO,IAAI;IACb,CAAC;EACH;EAEA,IAAIC,QAAQA,CAAA,EAAG;IAAE,OAAO,IAAI,CAACf,OAAO,KAAKH,KAAK,CAACY,QAAQ;EAAE;EAEzD,IAAIO,QAAQA,CAAA,EAAG;IAAE,OAAO,IAAI,CAAChB,OAAO,KAAKH,KAAK,CAACc,QAAQ;EAAE;EAEzD,IAAIM,OAAOA,CAAA,EAAG;IAAE,OAAO,IAAI,CAACjB,OAAO,KAAKH,KAAK,CAACI,OAAO;EAAE;EAEvDiB,KAAKA,CACHC,UAA6D,EAC5C;IACjB,OAAyB,KAAK,CAACD,KAAK,CAACC,UAAU,CAAC;EAClD;EAEAC,OAAOA,CAACC,SAA+B,EAAe;IACpD,OAAqB,KAAK,CAACD,OAAO,CAACC,SAAS,CAAC;EAC/C;EAEAC,IAAIA,CACFC,WAA4D,EAC5DJ,UAA6D,EACtC;IACvB,MAAMK,GAAG,GAA2B,KAAK,CAACF,IAAI,CAACC,WAAW,EAAEJ,UAAU,CAAC;IACvEK,GAAG,CAACZ,SAAS,GAAG,IAAI,CAACN,OAAO;IAC5BkB,GAAG,CAACX,QAAQ,GAAG,IAAI,CAACN,MAAM;IAC1B,OAAOiB,GAAG;EACZ;AACF;AAACC,OAAA,CAAAC,OAAA,GAAA5B,OAAA","ignoreList":[]}
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.Emitter = void 0;
7
+ /**
8
+ * Simple listeneable data Emitter.
9
+ */
10
+ class Emitter {
11
+ p_listeners = [];
12
+
13
+ /**
14
+ * Returns "true" if any listener is connected; "false" otherwise.
15
+ * @return {boolean}
16
+ */
17
+ get hasListeners() {
18
+ return !!this.p_listeners.length;
19
+ }
20
+ get listeners() {
21
+ return this.p_listeners;
22
+ }
23
+
24
+ /**
25
+ * Adds `listener` if it is not already connected.
26
+ * @param {function} listener
27
+ * @return {function} Unsubscribe function.
28
+ */
29
+ addListener(listener) {
30
+ if (!this.p_listeners.includes(listener)) {
31
+ this.p_listeners.push(listener);
32
+ }
33
+ return () => this.removeListener(listener);
34
+ }
35
+
36
+ /**
37
+ * Calls every connected listener with the given arguments.
38
+ * @param args
39
+ */
40
+ emit() {
41
+ const listeners = this.p_listeners.slice();
42
+ for (const listener of listeners) listener(...arguments);
43
+ }
44
+
45
+ /**
46
+ * Removes all connected listeners.
47
+ */
48
+ removeAllListeners() {
49
+ this.p_listeners = [];
50
+ }
51
+
52
+ /**
53
+ * Removes specified `listener`, if connected.
54
+ * @param listener
55
+ */
56
+ removeListener(listener) {
57
+ const idx = this.p_listeners.indexOf(listener);
58
+ if (idx >= 0) this.p_listeners.splice(idx, 1);
59
+ }
60
+ }
61
+ exports.Emitter = Emitter;
62
+ //# sourceMappingURL=Emitter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Emitter.js","names":["Emitter","p_listeners","hasListeners","length","listeners","addListener","listener","includes","push","removeListener","emit","slice","arguments","removeAllListeners","idx","indexOf","splice","exports"],"sources":["../../src/Emitter.ts"],"sourcesContent":["export type Listener<T extends unknown[] = unknown[]> = (...args: T) => void;\n\n/**\n * Simple listeneable data Emitter.\n */\nexport class Emitter<T extends unknown[] = unknown[]> {\n private p_listeners: Listener<T>[] = [];\n\n /**\n * Returns \"true\" if any listener is connected; \"false\" otherwise.\n * @return {boolean}\n */\n get hasListeners(): boolean {\n return !!this.p_listeners.length;\n }\n\n get listeners(): ReadonlyArray<Listener<T>> { return this.p_listeners; }\n\n /**\n * Adds `listener` if it is not already connected.\n * @param {function} listener\n * @return {function} Unsubscribe function.\n */\n addListener(listener: Listener<T>): () => void {\n if (!this.p_listeners.includes(listener)) {\n this.p_listeners.push(listener);\n }\n return () => this.removeListener(listener);\n }\n\n /**\n * Calls every connected listener with the given arguments.\n * @param args\n */\n emit(...args: T) {\n const listeners = this.p_listeners.slice();\n for (const listener of listeners) listener(...args);\n }\n\n /**\n * Removes all connected listeners.\n */\n removeAllListeners() {\n this.p_listeners = [];\n }\n\n /**\n * Removes specified `listener`, if connected.\n * @param listener\n */\n removeListener(listener: Listener<T>) {\n const idx = this.p_listeners.indexOf(listener);\n if (idx >= 0) this.p_listeners.splice(idx, 1);\n }\n}\n"],"mappings":";;;;;;AAEA;AACA;AACA;AACO,MAAMA,OAAO,CAAkC;EAC5CC,WAAW,GAAkB,EAAE;;EAEvC;AACF;AACA;AACA;EACE,IAAIC,YAAYA,CAAA,EAAY;IAC1B,OAAO,CAAC,CAAC,IAAI,CAACD,WAAW,CAACE,MAAM;EAClC;EAEA,IAAIC,SAASA,CAAA,EAA+B;IAAE,OAAO,IAAI,CAACH,WAAW;EAAE;;EAEvE;AACF;AACA;AACA;AACA;EACEI,WAAWA,CAACC,QAAqB,EAAc;IAC7C,IAAI,CAAC,IAAI,CAACL,WAAW,CAACM,QAAQ,CAACD,QAAQ,CAAC,EAAE;MACxC,IAAI,CAACL,WAAW,CAACO,IAAI,CAACF,QAAQ,CAAC;IACjC;IACA,OAAO,MAAM,IAAI,CAACG,cAAc,CAACH,QAAQ,CAAC;EAC5C;;EAEA;AACF;AACA;AACA;EACEI,IAAIA,CAAA,EAAa;IACf,MAAMN,SAAS,GAAG,IAAI,CAACH,WAAW,CAACU,KAAK,CAAC,CAAC;IAC1C,KAAK,MAAML,QAAQ,IAAIF,SAAS,EAAEE,QAAQ,CAAC,GAAAM,SAAO,CAAC;EACrD;;EAEA;AACF;AACA;EACEC,kBAAkBA,CAAA,EAAG;IACnB,IAAI,CAACZ,WAAW,GAAG,EAAE;EACvB;;EAEA;AACF;AACA;AACA;EACEQ,cAAcA,CAACH,QAAqB,EAAE;IACpC,MAAMQ,GAAG,GAAG,IAAI,CAACb,WAAW,CAACc,OAAO,CAACT,QAAQ,CAAC;IAC9C,IAAIQ,GAAG,IAAI,CAAC,EAAE,IAAI,CAACb,WAAW,CAACe,MAAM,CAACF,GAAG,EAAE,CAAC,CAAC;EAC/C;AACF;AAACG,OAAA,CAAAjB,OAAA,GAAAA,OAAA","ignoreList":[]}
@@ -0,0 +1,85 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.default = void 0;
8
+ var _Barrier = _interopRequireDefault(require("./Barrier"));
9
+ /**
10
+ * Implements a simple semaphore for async code logic.
11
+ */
12
+ class Semaphore {
13
+ constructor() {
14
+ let ready = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
15
+ this.p_ready = !!ready;
16
+ }
17
+ get ready() {
18
+ return this.p_ready;
19
+ }
20
+ setReady(ready) {
21
+ const bool = !!ready;
22
+ if (this.p_ready !== bool) {
23
+ this.p_ready = bool;
24
+ if (bool && !this.p_draining && this.p_queue.length) {
25
+ this.p_drainQueue();
26
+ }
27
+ }
28
+ }
29
+
30
+ /**
31
+ * Waits until the semaphore is ready, and marks it as non-ready (seizes it).
32
+ * @return {Promise}
33
+ */
34
+ async seize() {
35
+ return this.waitReady(true);
36
+ }
37
+ async waitReady() {
38
+ let seize = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
39
+ if (!this.p_ready || this.p_queue.length) {
40
+ const barrier = new _Barrier.default();
41
+ this.p_queue.push(barrier);
42
+ await barrier;
43
+ if (seize) this.p_ready = false;
44
+ this.p_drainLock.resolve();
45
+ } else if (seize) this.p_ready = false;
46
+ }
47
+
48
+ // Private members below this point.
49
+
50
+ /**
51
+ * If semaphore is ready, it releases the next barrier in the queue, if any,
52
+ * and reschedules itself for a call in the next event loop iteration.
53
+ * Otherwise, it breaks the queue draining loop, which will be restarted
54
+ * the next time the semaphore is set ready.
55
+ */
56
+ async p_drainQueue() {
57
+ this.p_draining = true;
58
+ while (this.p_ready && this.p_queue.length) {
59
+ this.p_drainLock = new _Barrier.default();
60
+ this.p_queue[0].resolve();
61
+ await this.p_drainLock; // eslint-disable-line no-await-in-loop
62
+ this.p_queue.shift();
63
+ }
64
+ this.p_draining = false;
65
+ this.p_drainLock = null;
66
+ }
67
+
68
+ // "true" when the drain queue process is running (and thus no need to start
69
+ // a new one).
70
+ p_draining = false;
71
+
72
+ // Each time a Promise from drain queue is resolved this drainLock is set
73
+ // to block further queue draining until the promise resolution handler
74
+ // (.seize() or .waitReady()) unlocks it, thus confirming it is fine
75
+ // to continue the draining. This is specifically important for .seize(),
76
+ // which should have a chance to switch semaphore state to non-ready prior
77
+ // to next Promise in the queue being unlocked.
78
+ p_drainLock = null;
79
+
80
+ // The array of barriers set for each async code flow awaiting for
81
+ // the Semaphore to become ready.
82
+ p_queue = [];
83
+ }
84
+ exports.default = Semaphore;
85
+ //# sourceMappingURL=Semaphore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Semaphore.js","names":["_Barrier","_interopRequireDefault","require","Semaphore","constructor","ready","arguments","length","undefined","p_ready","setReady","bool","p_draining","p_queue","p_drainQueue","seize","waitReady","barrier","Barrier","push","p_drainLock","resolve","shift","exports","default"],"sources":["../../src/Semaphore.ts"],"sourcesContent":["import Barrier from './Barrier';\n\n/**\n * Implements a simple semaphore for async code logic.\n */\nexport default class Semaphore {\n constructor(ready = false) {\n this.p_ready = !!ready;\n }\n\n get ready() { return this.p_ready; }\n\n setReady(ready: boolean) {\n const bool = !!ready;\n if (this.p_ready !== bool) {\n this.p_ready = bool;\n if (bool && !this.p_draining && this.p_queue.length) {\n this.p_drainQueue();\n }\n }\n }\n\n /**\n * Waits until the semaphore is ready, and marks it as non-ready (seizes it).\n * @return {Promise}\n */\n async seize() {\n return this.waitReady(true);\n }\n\n async waitReady(seize = false) {\n if (!this.p_ready || this.p_queue.length) {\n const barrier = new Barrier<void>();\n this.p_queue.push(barrier);\n await barrier;\n if (seize) this.p_ready = false;\n this.p_drainLock!.resolve();\n } else if (seize) this.p_ready = false;\n }\n\n // Private members below this point.\n\n /**\n * If semaphore is ready, it releases the next barrier in the queue, if any,\n * and reschedules itself for a call in the next event loop iteration.\n * Otherwise, it breaks the queue draining loop, which will be restarted\n * the next time the semaphore is set ready.\n */\n async p_drainQueue() {\n this.p_draining = true;\n while (this.p_ready && this.p_queue.length) {\n this.p_drainLock = new Barrier();\n this.p_queue[0]!.resolve();\n await this.p_drainLock; // eslint-disable-line no-await-in-loop\n this.p_queue.shift();\n }\n this.p_draining = false;\n this.p_drainLock = null;\n }\n\n // \"true\" when the drain queue process is running (and thus no need to start\n // a new one).\n private p_draining = false;\n\n // Each time a Promise from drain queue is resolved this drainLock is set\n // to block further queue draining until the promise resolution handler\n // (.seize() or .waitReady()) unlocks it, thus confirming it is fine\n // to continue the draining. This is specifically important for .seize(),\n // which should have a chance to switch semaphore state to non-ready prior\n // to next Promise in the queue being unlocked.\n private p_drainLock: Barrier<void> | null = null;\n\n // The array of barriers set for each async code flow awaiting for\n // the Semaphore to become ready.\n private p_queue: Barrier<void>[] = [];\n\n private p_ready: boolean;\n}\n"],"mappings":";;;;;;;AAAA,IAAAA,QAAA,GAAAC,sBAAA,CAAAC,OAAA;AAEA;AACA;AACA;AACe,MAAMC,SAAS,CAAC;EAC7BC,WAAWA,CAAA,EAAgB;IAAA,IAAfC,KAAK,GAAAC,SAAA,CAAAC,MAAA,QAAAD,SAAA,QAAAE,SAAA,GAAAF,SAAA,MAAG,KAAK;IACvB,IAAI,CAACG,OAAO,GAAG,CAAC,CAACJ,KAAK;EACxB;EAEA,IAAIA,KAAKA,CAAA,EAAG;IAAE,OAAO,IAAI,CAACI,OAAO;EAAE;EAEnCC,QAAQA,CAACL,KAAc,EAAE;IACvB,MAAMM,IAAI,GAAG,CAAC,CAACN,KAAK;IACpB,IAAI,IAAI,CAACI,OAAO,KAAKE,IAAI,EAAE;MACzB,IAAI,CAACF,OAAO,GAAGE,IAAI;MACnB,IAAIA,IAAI,IAAI,CAAC,IAAI,CAACC,UAAU,IAAI,IAAI,CAACC,OAAO,CAACN,MAAM,EAAE;QACnD,IAAI,CAACO,YAAY,CAAC,CAAC;MACrB;IACF;EACF;;EAEA;AACF;AACA;AACA;EACE,MAAMC,KAAKA,CAAA,EAAG;IACZ,OAAO,IAAI,CAACC,SAAS,CAAC,IAAI,CAAC;EAC7B;EAEA,MAAMA,SAASA,CAAA,EAAgB;IAAA,IAAfD,KAAK,GAAAT,SAAA,CAAAC,MAAA,QAAAD,SAAA,QAAAE,SAAA,GAAAF,SAAA,MAAG,KAAK;IAC3B,IAAI,CAAC,IAAI,CAACG,OAAO,IAAI,IAAI,CAACI,OAAO,CAACN,MAAM,EAAE;MACxC,MAAMU,OAAO,GAAG,IAAIC,gBAAO,CAAO,CAAC;MACnC,IAAI,CAACL,OAAO,CAACM,IAAI,CAACF,OAAO,CAAC;MAC1B,MAAMA,OAAO;MACb,IAAIF,KAAK,EAAE,IAAI,CAACN,OAAO,GAAG,KAAK;MAC/B,IAAI,CAACW,WAAW,CAAEC,OAAO,CAAC,CAAC;IAC7B,CAAC,MAAM,IAAIN,KAAK,EAAE,IAAI,CAACN,OAAO,GAAG,KAAK;EACxC;;EAEA;;EAEA;AACF;AACA;AACA;AACA;AACA;EACE,MAAMK,YAAYA,CAAA,EAAG;IACnB,IAAI,CAACF,UAAU,GAAG,IAAI;IACtB,OAAO,IAAI,CAACH,OAAO,IAAI,IAAI,CAACI,OAAO,CAACN,MAAM,EAAE;MAC1C,IAAI,CAACa,WAAW,GAAG,IAAIF,gBAAO,CAAC,CAAC;MAChC,IAAI,CAACL,OAAO,CAAC,CAAC,CAAC,CAAEQ,OAAO,CAAC,CAAC;MAC1B,MAAM,IAAI,CAACD,WAAW,CAAC,CAAC;MACxB,IAAI,CAACP,OAAO,CAACS,KAAK,CAAC,CAAC;IACtB;IACA,IAAI,CAACV,UAAU,GAAG,KAAK;IACvB,IAAI,CAACQ,WAAW,GAAG,IAAI;EACzB;;EAEA;EACA;EACQR,UAAU,GAAG,KAAK;;EAE1B;EACA;EACA;EACA;EACA;EACA;EACQQ,WAAW,GAAyB,IAAI;;EAEhD;EACA;EACQP,OAAO,GAAoB,EAAE;AAGvC;AAACU,OAAA,CAAAC,OAAA,GAAArB,SAAA","ignoreList":[]}
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ var _exportNames = {
8
+ Barrier: true,
9
+ Semaphore: true,
10
+ withRetries: true
11
+ };
12
+ Object.defineProperty(exports, "Barrier", {
13
+ enumerable: true,
14
+ get: function () {
15
+ return _Barrier.default;
16
+ }
17
+ });
18
+ Object.defineProperty(exports, "Semaphore", {
19
+ enumerable: true,
20
+ get: function () {
21
+ return _Semaphore.default;
22
+ }
23
+ });
24
+ Object.defineProperty(exports, "withRetries", {
25
+ enumerable: true,
26
+ get: function () {
27
+ return _withRetries.default;
28
+ }
29
+ });
30
+ var _Barrier = _interopRequireDefault(require("./Barrier"));
31
+ var _Emitter = require("./Emitter");
32
+ Object.keys(_Emitter).forEach(function (key) {
33
+ if (key === "default" || key === "__esModule") return;
34
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
35
+ if (key in exports && exports[key] === _Emitter[key]) return;
36
+ Object.defineProperty(exports, key, {
37
+ enumerable: true,
38
+ get: function () {
39
+ return _Emitter[key];
40
+ }
41
+ });
42
+ });
43
+ var _Semaphore = _interopRequireDefault(require("./Semaphore"));
44
+ var _time = require("./time");
45
+ Object.keys(_time).forEach(function (key) {
46
+ if (key === "default" || key === "__esModule") return;
47
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
48
+ if (key in exports && exports[key] === _time[key]) return;
49
+ Object.defineProperty(exports, key, {
50
+ enumerable: true,
51
+ get: function () {
52
+ return _time[key];
53
+ }
54
+ });
55
+ });
56
+ var _withRetries = _interopRequireDefault(require("./withRetries"));
57
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["_Barrier","_interopRequireDefault","require","_Emitter","Object","keys","forEach","key","prototype","hasOwnProperty","call","_exportNames","exports","defineProperty","enumerable","get","_Semaphore","_time","_withRetries"],"sources":["../../src/index.ts"],"sourcesContent":["export { default as Barrier } from './Barrier';\nexport * from './Emitter';\nexport { default as Semaphore } from './Semaphore';\nexport * from './time';\nexport { default as withRetries } from './withRetries';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,IAAAA,QAAA,GAAAC,sBAAA,CAAAC,OAAA;AACA,IAAAC,QAAA,GAAAD,OAAA;AAAAE,MAAA,CAAAC,IAAA,CAAAF,QAAA,EAAAG,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAH,MAAA,CAAAI,SAAA,CAAAC,cAAA,CAAAC,IAAA,CAAAC,YAAA,EAAAJ,GAAA;EAAA,IAAAA,GAAA,IAAAK,OAAA,IAAAA,OAAA,CAAAL,GAAA,MAAAJ,QAAA,CAAAI,GAAA;EAAAH,MAAA,CAAAS,cAAA,CAAAD,OAAA,EAAAL,GAAA;IAAAO,UAAA;IAAAC,GAAA,WAAAA,CAAA;MAAA,OAAAZ,QAAA,CAAAI,GAAA;IAAA;EAAA;AAAA;AACA,IAAAS,UAAA,GAAAf,sBAAA,CAAAC,OAAA;AACA,IAAAe,KAAA,GAAAf,OAAA;AAAAE,MAAA,CAAAC,IAAA,CAAAY,KAAA,EAAAX,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAH,MAAA,CAAAI,SAAA,CAAAC,cAAA,CAAAC,IAAA,CAAAC,YAAA,EAAAJ,GAAA;EAAA,IAAAA,GAAA,IAAAK,OAAA,IAAAA,OAAA,CAAAL,GAAA,MAAAU,KAAA,CAAAV,GAAA;EAAAH,MAAA,CAAAS,cAAA,CAAAD,OAAA,EAAAL,GAAA;IAAAO,UAAA;IAAAC,GAAA,WAAAA,CAAA;MAAA,OAAAE,KAAA,CAAAV,GAAA;IAAA;EAAA;AAAA;AACA,IAAAW,YAAA,GAAAjB,sBAAA,CAAAC,OAAA","ignoreList":[]}
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.YEAR_MS = exports.Timer = exports.SEC_MS = exports.MIN_MS = exports.HOUR_MS = exports.DAY_MS = void 0;
8
+ exports.timer = timer;
9
+ var _Barrier = _interopRequireDefault(require("./Barrier"));
10
+ // This is not very elegant, but as of now TypeScript does not support type
11
+ // arithmetic, thus we can't have constants assigned like `MIN_MS = 60 * SEC_MS`
12
+ // and have the result type to be 60000 (number literal), it would be just
13
+ // the generic number type.
14
+ const SEC_MS = exports.SEC_MS = 1000;
15
+ const MIN_MS = exports.MIN_MS = 60000; // 60 * SEC_MS
16
+ const HOUR_MS = exports.HOUR_MS = 3600000; // 60 * MIN_MS
17
+ const DAY_MS = exports.DAY_MS = 86400000; // 24 * HOUR_MS
18
+ const YEAR_MS = exports.YEAR_MS = 31536000000; // 365 * DAY_MS
19
+
20
+ // TODO: Ok, as we have ended up with a Timer class, mostly to achieve a good
21
+ // TypeScript typing for timer() function, it makes sense to expose the class
22
+ // from the library as well, and it should be documented later.
23
+ class Timer extends _Barrier.default {
24
+ get abort() {
25
+ return this.p_abort;
26
+ }
27
+ get timeout() {
28
+ return this.p_timeout;
29
+ }
30
+
31
+ /**
32
+ * Creates a new, non-initialized instance of Timer. Call .init() method
33
+ * to actually initialize and launch the timer.
34
+ *
35
+ * NOTE: Although it might be tempting to accept `timeout` value as
36
+ * a constructor's argument, it won't work well, because Timer is an
37
+ * extension of Promise (via Barrier), and the way Promises works (in
38
+ * particular their .then() method, which internally calls constructor()
39
+ * with special executor) does not play along with initalization depending
40
+ * on custom parameters done in constructor().
41
+ *
42
+ * @param executor
43
+ */
44
+ constructor(executor) {
45
+ super(executor);
46
+ this.p_abort = () => {};
47
+ }
48
+ init(timeout) {
49
+ if (this.p_timeout !== undefined) {
50
+ throw Error('This Timer is initialized already');
51
+ }
52
+ this.p_timeout = timeout;
53
+ if (timeout > 0) {
54
+ const id = setTimeout(super.resolve.bind(this), timeout);
55
+ this.p_abort = () => clearTimeout(id);
56
+ } else {
57
+ super.resolve();
58
+ }
59
+ return this;
60
+ }
61
+ then(onFulfilled, onRejected) {
62
+ const res = super.then(onFulfilled, onRejected);
63
+ if (this.timeout !== undefined) res.init(this.timeout);
64
+ return res;
65
+ }
66
+ }
67
+
68
+ /**
69
+ * Creates a Promise, which resolves after the given timeout.
70
+ * @param {number} timeout Timeout [ms].
71
+ * @return {Barrier} Resolves after the timeout. It has additional
72
+ * .abort() method attached, which cancels the pending timer resolution
73
+ * (without resolving or rejecting the barrier).
74
+ */
75
+ exports.Timer = Timer;
76
+ function timer(timeout) {
77
+ const t = new Timer();
78
+ return t.init(timeout);
79
+ }
80
+ //# sourceMappingURL=time.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"time.js","names":["_Barrier","_interopRequireDefault","require","SEC_MS","exports","MIN_MS","HOUR_MS","DAY_MS","YEAR_MS","Timer","Barrier","abort","p_abort","timeout","p_timeout","constructor","executor","init","undefined","Error","id","setTimeout","resolve","bind","clearTimeout","then","onFulfilled","onRejected","res","timer","t"],"sources":["../../src/time.ts"],"sourcesContent":["import Barrier, { type Executor } from './Barrier';\n\n// This is not very elegant, but as of now TypeScript does not support type\n// arithmetic, thus we can't have constants assigned like `MIN_MS = 60 * SEC_MS`\n// and have the result type to be 60000 (number literal), it would be just\n// the generic number type.\nexport const SEC_MS = 1000;\nexport const MIN_MS = 60000; // 60 * SEC_MS\nexport const HOUR_MS = 3600000; // 60 * MIN_MS\nexport const DAY_MS = 86400000; // 24 * HOUR_MS\nexport const YEAR_MS = 31536000000; // 365 * DAY_MS\n\n// TODO: Ok, as we have ended up with a Timer class, mostly to achieve a good\n// TypeScript typing for timer() function, it makes sense to expose the class\n// from the library as well, and it should be documented later.\nexport class Timer<T> extends Barrier<void, T> {\n private p_abort: () => void;\n\n private p_timeout?: number;\n\n get abort(): () => void { return this.p_abort; }\n\n get timeout(): number | undefined { return this.p_timeout; }\n\n /**\n * Creates a new, non-initialized instance of Timer. Call .init() method\n * to actually initialize and launch the timer.\n *\n * NOTE: Although it might be tempting to accept `timeout` value as\n * a constructor's argument, it won't work well, because Timer is an\n * extension of Promise (via Barrier), and the way Promises works (in\n * particular their .then() method, which internally calls constructor()\n * with special executor) does not play along with initalization depending\n * on custom parameters done in constructor().\n *\n * @param executor\n */\n constructor(executor?: Executor<T>) {\n super(executor);\n this.p_abort = () => {};\n }\n\n init(timeout: number): Timer<T> {\n if (this.p_timeout !== undefined) {\n throw Error('This Timer is initialized already');\n }\n this.p_timeout = timeout;\n if (timeout > 0) {\n const id = setTimeout(super.resolve.bind(this), timeout);\n this.p_abort = () => clearTimeout(id);\n } else {\n super.resolve();\n }\n return this;\n }\n\n then<TR1, TR2>(\n onFulfilled?: ((value: T) => TR1 | PromiseLike<TR1>) | null,\n onRejected?: ((reason: any) => TR2 | PromiseLike<TR2>) | null,\n ): Timer<TR1 | TR2> {\n const res = <Timer<TR1 | TR2>> super.then(onFulfilled, onRejected);\n if (this.timeout !== undefined) res.init(this.timeout);\n return res;\n }\n}\n\n/**\n * Creates a Promise, which resolves after the given timeout.\n * @param {number} timeout Timeout [ms].\n * @return {Barrier} Resolves after the timeout. It has additional\n * .abort() method attached, which cancels the pending timer resolution\n * (without resolving or rejecting the barrier).\n */\nexport function timer(timeout: number): Timer<void> {\n const t = new Timer<void>();\n return t.init(timeout);\n}\n"],"mappings":";;;;;;;;AAAA,IAAAA,QAAA,GAAAC,sBAAA,CAAAC,OAAA;AAEA;AACA;AACA;AACA;AACO,MAAMC,MAAM,GAAAC,OAAA,CAAAD,MAAA,GAAG,IAAI;AACnB,MAAME,MAAM,GAAAD,OAAA,CAAAC,MAAA,GAAG,KAAK,CAAC,CAAC;AACtB,MAAMC,OAAO,GAAAF,OAAA,CAAAE,OAAA,GAAG,OAAO,CAAC,CAAC;AACzB,MAAMC,MAAM,GAAAH,OAAA,CAAAG,MAAA,GAAG,QAAQ,CAAC,CAAC;AACzB,MAAMC,OAAO,GAAAJ,OAAA,CAAAI,OAAA,GAAG,WAAW,CAAC,CAAC;;AAEpC;AACA;AACA;AACO,MAAMC,KAAK,SAAYC,gBAAO,CAAU;EAK7C,IAAIC,KAAKA,CAAA,EAAe;IAAE,OAAO,IAAI,CAACC,OAAO;EAAE;EAE/C,IAAIC,OAAOA,CAAA,EAAuB;IAAE,OAAO,IAAI,CAACC,SAAS;EAAE;;EAE3D;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACEC,WAAWA,CAACC,QAAsB,EAAE;IAClC,KAAK,CAACA,QAAQ,CAAC;IACf,IAAI,CAACJ,OAAO,GAAG,MAAM,CAAC,CAAC;EACzB;EAEAK,IAAIA,CAACJ,OAAe,EAAY;IAC9B,IAAI,IAAI,CAACC,SAAS,KAAKI,SAAS,EAAE;MAChC,MAAMC,KAAK,CAAC,mCAAmC,CAAC;IAClD;IACA,IAAI,CAACL,SAAS,GAAGD,OAAO;IACxB,IAAIA,OAAO,GAAG,CAAC,EAAE;MACf,MAAMO,EAAE,GAAGC,UAAU,CAAC,KAAK,CAACC,OAAO,CAACC,IAAI,CAAC,IAAI,CAAC,EAAEV,OAAO,CAAC;MACxD,IAAI,CAACD,OAAO,GAAG,MAAMY,YAAY,CAACJ,EAAE,CAAC;IACvC,CAAC,MAAM;MACL,KAAK,CAACE,OAAO,CAAC,CAAC;IACjB;IACA,OAAO,IAAI;EACb;EAEAG,IAAIA,CACFC,WAA2D,EAC3DC,UAA6D,EAC3C;IAClB,MAAMC,GAAG,GAAsB,KAAK,CAACH,IAAI,CAACC,WAAW,EAAEC,UAAU,CAAC;IAClE,IAAI,IAAI,CAACd,OAAO,KAAKK,SAAS,EAAEU,GAAG,CAACX,IAAI,CAAC,IAAI,CAACJ,OAAO,CAAC;IACtD,OAAOe,GAAG;EACZ;AACF;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AANAxB,OAAA,CAAAK,KAAA,GAAAA,KAAA;AAOO,SAASoB,KAAKA,CAAChB,OAAe,EAAe;EAClD,MAAMiB,CAAC,GAAG,IAAIrB,KAAK,CAAO,CAAC;EAC3B,OAAOqB,CAAC,CAACb,IAAI,CAACJ,OAAO,CAAC;AACxB","ignoreList":[]}
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = withRetries;
7
+ var _time = require("./time");
8
+ /**
9
+ * Attempts to perform the given async `action` up to `maxRetries` times with
10
+ * the specified `interval`, stopping at the first successful (non-throwing)
11
+ * execution.
12
+ * @param action
13
+ * @param maxRetries Optional. The maximum number of re-tries. Defaults 3.
14
+ * @param interval Optional. The interval between re-tries (in milliseconds).
15
+ * Defaults to 300ms.
16
+ * @returns Resolves to the result of the successful `action` execution;
17
+ * or rejects with the error from the last faileda attempt.
18
+ */
19
+ async function withRetries(action) {
20
+ let maxRetries = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 3;
21
+ let interval = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 300;
22
+ /* eslint-disable no-await-in-loop */
23
+ for (let n = 1;; ++n) {
24
+ try {
25
+ const res = action();
26
+ return res instanceof Promise ? await res : res;
27
+ } catch (error) {
28
+ if (n < maxRetries) await (0, _time.timer)(interval);else throw error;
29
+ }
30
+ }
31
+ /* eslint-enable no-await-in-loop */
32
+ }
33
+ //# sourceMappingURL=withRetries.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"withRetries.js","names":["_time","require","withRetries","action","maxRetries","arguments","length","undefined","interval","n","res","Promise","error","timer"],"sources":["../../src/withRetries.ts"],"sourcesContent":["import { timer } from './time';\n\n/**\n * Attempts to perform the given async `action` up to `maxRetries` times with\n * the specified `interval`, stopping at the first successful (non-throwing)\n * execution.\n * @param action\n * @param maxRetries Optional. The maximum number of re-tries. Defaults 3.\n * @param interval Optional. The interval between re-tries (in milliseconds).\n * Defaults to 300ms.\n * @returns Resolves to the result of the successful `action` execution;\n * or rejects with the error from the last faileda attempt.\n */\nexport default async function withRetries<T>(\n action: () => T,\n maxRetries = 3,\n interval = 300,\n): Promise<Awaited<T>> {\n /* eslint-disable no-await-in-loop */\n for (let n = 1; ; ++n) {\n try {\n const res = action();\n return res instanceof Promise ? await res : (res as Awaited<T>);\n } catch (error) {\n if (n < maxRetries) await timer(interval);\n else throw error;\n }\n }\n /* eslint-enable no-await-in-loop */\n}\n"],"mappings":";;;;;;AAAA,IAAAA,KAAA,GAAAC,OAAA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACe,eAAeC,WAAWA,CACvCC,MAAe,EAGM;EAAA,IAFrBC,UAAU,GAAAC,SAAA,CAAAC,MAAA,QAAAD,SAAA,QAAAE,SAAA,GAAAF,SAAA,MAAG,CAAC;EAAA,IACdG,QAAQ,GAAAH,SAAA,CAAAC,MAAA,QAAAD,SAAA,QAAAE,SAAA,GAAAF,SAAA,MAAG,GAAG;EAEd;EACA,KAAK,IAAII,CAAC,GAAG,CAAC,GAAI,EAAEA,CAAC,EAAE;IACrB,IAAI;MACF,MAAMC,GAAG,GAAGP,MAAM,CAAC,CAAC;MACpB,OAAOO,GAAG,YAAYC,OAAO,GAAG,MAAMD,GAAG,GAAIA,GAAkB;IACjE,CAAC,CAAC,OAAOE,KAAK,EAAE;MACd,IAAIH,CAAC,GAAGL,UAAU,EAAE,MAAM,IAAAS,WAAK,EAACL,QAAQ,CAAC,CAAC,KACrC,MAAMI,KAAK;IAClB;EACF;EACA;AACF","ignoreList":[]}
@@ -0,0 +1,97 @@
1
+ var STATE = /*#__PURE__*/function (STATE) {
2
+ STATE["PENDING"] = "PENDING";
3
+ STATE["REJECTED"] = "REJECTED";
4
+ STATE["RESOLVED"] = "RESOLVED";
5
+ return STATE;
6
+ }(STATE || {});
7
+ /**
8
+ * Barrier is just a Promise which has resolve and reject exposed as instance
9
+ * methods.
10
+ *
11
+ * It has two generic arguments T and TR which correspond to the argument of
12
+ * the .resolve() method, and to the value resolved by the promise (barrier).
13
+ * For a simple barrier TR equals to T, however for barriers created via .then()
14
+ * chain, T corresponds to the argument of the original barrier, and TR to
15
+ * the value resolved by the latest promise in the chain. Consider this:
16
+ *
17
+ * const b = new Barrier<string>();
18
+ * b.resolve('result');
19
+ * const s = await b; // `s` has `string` type, and equals "result".
20
+ *
21
+ * const b = (new Barrier<string>()).then((s) => s.length);
22
+ * b.resolve('result'); // Chained barrier exposes .resolve() method of
23
+ * // the first barrier in the chain, which expects
24
+ * // `string` arugment (T), but the chained barrier
25
+ * // resolves to `number` (TR).
26
+ * const n = await b; // `n` has `number` type, and equals 6.
27
+ *
28
+ * Docs: https://dr.pogodin.studio/docs/react-utils/docs/api/classes/Barrier
29
+ */
30
+ export default class Barrier extends Promise {
31
+ p_state = (() => STATE.PENDING)();
32
+ constructor(executor) {
33
+ let resolveRef;
34
+ let rejectRef;
35
+ super((resolve, reject) => {
36
+ // Note: Enforcing `void` return type because of the BEWARE note below.
37
+ resolveRef = value => {
38
+ resolve(value);
39
+ this.p_state = STATE.RESOLVED;
40
+
41
+ // BEWARE: Don't try to return `this` here, it will easily cause
42
+ // infinite loops in React Native, which are extremely difficult
43
+ // to troubleshoot (I wasn't able to figure out, are they due to
44
+ // internal Promise implementation in RN, or because of some bad
45
+ // patterns in the host code).
46
+ };
47
+
48
+ // Note: Enforcing `void` return type because of the BEWARE note below.
49
+ rejectRef = reason => {
50
+ reject(reason);
51
+ this.p_state = STATE.REJECTED;
52
+ };
53
+ if (executor) executor(resolveRef, rejectRef);
54
+ });
55
+
56
+ // NOTE: We assume, the only scenario where TR is not equal T is when
57
+ // the Barrier is constructed by a .then() call on a "parent" barrier,
58
+ // and in that scenario .then() itself will replace .p_resolve by another
59
+ // resolver immediately after this constructor returns.
60
+ this.p_resolve = resolveRef;
61
+ this.p_reject = rejectRef;
62
+ }
63
+ get resolve() {
64
+ return arg => {
65
+ this.p_resolve(arg);
66
+ return this;
67
+ };
68
+ }
69
+ get reject() {
70
+ return arg => {
71
+ this.p_reject(arg);
72
+ return this;
73
+ };
74
+ }
75
+ get resolved() {
76
+ return this.p_state === STATE.RESOLVED;
77
+ }
78
+ get rejected() {
79
+ return this.p_state === STATE.REJECTED;
80
+ }
81
+ get settled() {
82
+ return this.p_state !== STATE.PENDING;
83
+ }
84
+ catch(onRejected) {
85
+ return super.catch(onRejected);
86
+ }
87
+ finally(onFinally) {
88
+ return super.finally(onFinally);
89
+ }
90
+ then(onFulfilled, onRejected) {
91
+ const res = super.then(onFulfilled, onRejected);
92
+ res.p_resolve = this.resolve;
93
+ res.p_reject = this.reject;
94
+ return res;
95
+ }
96
+ }
97
+ //# sourceMappingURL=Barrier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Barrier.js","names":["STATE","Barrier","Promise","p_state","PENDING","constructor","executor","resolveRef","rejectRef","resolve","reject","value","RESOLVED","reason","REJECTED","p_resolve","p_reject","arg","resolved","rejected","settled","catch","onRejected","finally","onFinally","then","onFulfilled","res"],"sources":["../../src/Barrier.ts"],"sourcesContent":["export type Executor<T> = ConstructorParameters<typeof Promise<T>>[0];\n\ntype Resolver<T> = Parameters<Executor<T>>[0];\ntype Rejecter = Parameters<Executor<unknown>>[1];\n\nenum STATE {\n PENDING = 'PENDING',\n REJECTED = 'REJECTED',\n RESOLVED = 'RESOLVED',\n}\n\n/**\n * Barrier is just a Promise which has resolve and reject exposed as instance\n * methods.\n *\n * It has two generic arguments T and TR which correspond to the argument of\n * the .resolve() method, and to the value resolved by the promise (barrier).\n * For a simple barrier TR equals to T, however for barriers created via .then()\n * chain, T corresponds to the argument of the original barrier, and TR to\n * the value resolved by the latest promise in the chain. Consider this:\n *\n * const b = new Barrier<string>();\n * b.resolve('result');\n * const s = await b; // `s` has `string` type, and equals \"result\".\n *\n * const b = (new Barrier<string>()).then((s) => s.length);\n * b.resolve('result'); // Chained barrier exposes .resolve() method of\n * // the first barrier in the chain, which expects\n * // `string` arugment (T), but the chained barrier\n * // resolves to `number` (TR).\n * const n = await b; // `n` has `number` type, and equals 6.\n *\n * Docs: https://dr.pogodin.studio/docs/react-utils/docs/api/classes/Barrier\n */\nexport default class Barrier<T = unknown, TR = T> extends Promise<TR> {\n private p_resolve: Resolver<T>;\n\n private p_reject: Rejecter;\n\n private p_state = STATE.PENDING;\n\n constructor(executor?: Executor<TR>) {\n let resolveRef: Resolver<TR>;\n let rejectRef: Rejecter;\n\n super((resolve, reject) => {\n // Note: Enforcing `void` return type because of the BEWARE note below.\n resolveRef = (value: TR | PromiseLike<TR>): void => {\n resolve(value);\n this.p_state = STATE.RESOLVED;\n\n // BEWARE: Don't try to return `this` here, it will easily cause\n // infinite loops in React Native, which are extremely difficult\n // to troubleshoot (I wasn't able to figure out, are they due to\n // internal Promise implementation in RN, or because of some bad\n // patterns in the host code).\n };\n\n // Note: Enforcing `void` return type because of the BEWARE note below.\n rejectRef = (reason?: any): void => {\n reject(reason);\n this.p_state = STATE.REJECTED;\n };\n\n if (executor) executor(resolveRef, rejectRef);\n });\n\n // NOTE: We assume, the only scenario where TR is not equal T is when\n // the Barrier is constructed by a .then() call on a \"parent\" barrier,\n // and in that scenario .then() itself will replace .p_resolve by another\n // resolver immediately after this constructor returns.\n this.p_resolve = resolveRef! as Resolver<T>;\n\n this.p_reject = rejectRef!;\n }\n\n get resolve() {\n return (arg: Parameters<Resolver<T>>[0]) => {\n this.p_resolve(arg);\n return this;\n };\n }\n\n get reject() {\n return (arg: Parameters<Rejecter>[0]) => {\n this.p_reject(arg);\n return this;\n };\n }\n\n get resolved() { return this.p_state === STATE.RESOLVED; }\n\n get rejected() { return this.p_state === STATE.REJECTED; }\n\n get settled() { return this.p_state !== STATE.PENDING; }\n\n catch<TR1>(\n onRejected?: ((reason: any) => TR1 | PromiseLike<TR1>) | null,\n ): Barrier<T, TR1> {\n return <Barrier<T, TR1>> super.catch(onRejected);\n }\n\n finally(onFinally?: (() => void) | null): Barrier<TR> {\n return <Barrier<TR>> super.finally(onFinally);\n }\n\n then<TR1, TR2>(\n onFulfilled?: ((value: TR) => TR1 | PromiseLike<TR1>) | null,\n onRejected?: ((reason: any) => TR2 | PromiseLike<TR2>) | null,\n ): Barrier<T, TR1 | TR2> {\n const res = <Barrier<T, TR1 | TR2>> super.then(onFulfilled, onRejected);\n res.p_resolve = this.resolve;\n res.p_reject = this.reject;\n return res;\n }\n}\n"],"mappings":"IAKKA,KAAK,0BAALA,KAAK;EAALA,KAAK;EAALA,KAAK;EAALA,KAAK;EAAA,OAALA,KAAK;AAAA,EAALA,KAAK;AAMV;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,eAAe,MAAMC,OAAO,SAA8BC,OAAO,CAAK;EAK5DC,OAAO,UAAGH,KAAK,CAACI,OAAO;EAE/BC,WAAWA,CAACC,QAAuB,EAAE;IACnC,IAAIC,UAAwB;IAC5B,IAAIC,SAAmB;IAEvB,KAAK,CAAC,CAACC,OAAO,EAAEC,MAAM,KAAK;MACzB;MACAH,UAAU,GAAII,KAA2B,IAAW;QAClDF,OAAO,CAACE,KAAK,CAAC;QACd,IAAI,CAACR,OAAO,GAAGH,KAAK,CAACY,QAAQ;;QAE7B;QACA;QACA;QACA;QACA;MACF,CAAC;;MAED;MACAJ,SAAS,GAAIK,MAAY,IAAW;QAClCH,MAAM,CAACG,MAAM,CAAC;QACd,IAAI,CAACV,OAAO,GAAGH,KAAK,CAACc,QAAQ;MAC/B,CAAC;MAED,IAAIR,QAAQ,EAAEA,QAAQ,CAACC,UAAU,EAAEC,SAAS,CAAC;IAC/C,CAAC,CAAC;;IAEF;IACA;IACA;IACA;IACA,IAAI,CAACO,SAAS,GAAGR,UAA0B;IAE3C,IAAI,CAACS,QAAQ,GAAGR,SAAU;EAC5B;EAEA,IAAIC,OAAOA,CAAA,EAAG;IACZ,OAAQQ,GAA+B,IAAK;MAC1C,IAAI,CAACF,SAAS,CAACE,GAAG,CAAC;MACnB,OAAO,IAAI;IACb,CAAC;EACH;EAEA,IAAIP,MAAMA,CAAA,EAAG;IACX,OAAQO,GAA4B,IAAK;MACvC,IAAI,CAACD,QAAQ,CAACC,GAAG,CAAC;MAClB,OAAO,IAAI;IACb,CAAC;EACH;EAEA,IAAIC,QAAQA,CAAA,EAAG;IAAE,OAAO,IAAI,CAACf,OAAO,KAAKH,KAAK,CAACY,QAAQ;EAAE;EAEzD,IAAIO,QAAQA,CAAA,EAAG;IAAE,OAAO,IAAI,CAAChB,OAAO,KAAKH,KAAK,CAACc,QAAQ;EAAE;EAEzD,IAAIM,OAAOA,CAAA,EAAG;IAAE,OAAO,IAAI,CAACjB,OAAO,KAAKH,KAAK,CAACI,OAAO;EAAE;EAEvDiB,KAAKA,CACHC,UAA6D,EAC5C;IACjB,OAAyB,KAAK,CAACD,KAAK,CAACC,UAAU,CAAC;EAClD;EAEAC,OAAOA,CAACC,SAA+B,EAAe;IACpD,OAAqB,KAAK,CAACD,OAAO,CAACC,SAAS,CAAC;EAC/C;EAEAC,IAAIA,CACFC,WAA4D,EAC5DJ,UAA6D,EACtC;IACvB,MAAMK,GAAG,GAA2B,KAAK,CAACF,IAAI,CAACC,WAAW,EAAEJ,UAAU,CAAC;IACvEK,GAAG,CAACZ,SAAS,GAAG,IAAI,CAACN,OAAO;IAC5BkB,GAAG,CAACX,QAAQ,GAAG,IAAI,CAACN,MAAM;IAC1B,OAAOiB,GAAG;EACZ;AACF","ignoreList":[]}