@dr.pogodin/js-utils 0.1.2 → 0.1.4

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,6 +1,9 @@
1
1
  // Babel is used for Jest testing.
2
2
 
3
3
  export default {
4
+ plugins: [
5
+ 'babel-plugin-add-import-extension',
6
+ ],
4
7
  presets: [
5
8
  ['./config/babel/preset', {
6
9
  modules: false,
@@ -1,5 +1,4 @@
1
- import Barrier from './Barrier';
2
-
1
+ import Barrier from "./Barrier.js";
3
2
  /**
4
3
  * Implements a simple semaphore for async code logic.
5
4
  */
@@ -1 +1 @@
1
- {"version":3,"file":"Semaphore.js","names":["Barrier","Semaphore","constructor","ready","pReady","setReady","bool","pDraining","pQueue","length","pDrainQueue","seize","waitReady","barrier","push","pDrainLock","resolve","shift"],"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 // TODO: Boolean conversion is performed for backward compatibility with\n // plain JS projects. Drop it in future.\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-conversion\n this.pReady = !!ready;\n }\n\n get ready(): boolean {\n return this.pReady;\n }\n\n setReady(ready: boolean): void {\n // TODO: Boolean conversion is performed for backward compatibility with\n // plain JS projects. Drop it in future.\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-conversion\n const bool = !!ready;\n if (this.pReady !== bool) {\n this.pReady = bool;\n if (bool && !this.pDraining && this.pQueue.length) {\n void this.pDrainQueue();\n }\n }\n }\n\n /**\n * Waits until the semaphore is ready, and marks it as non-ready (seizes it).\n */\n async seize(): Promise<void> {\n return this.waitReady(true);\n }\n\n async waitReady(seize = false): Promise<void> {\n if (!this.pReady || this.pQueue.length) {\n const barrier = new Barrier<void>();\n this.pQueue.push(barrier);\n await barrier;\n if (seize) this.pReady = false;\n void this.pDrainLock!.resolve();\n } else if (seize) this.pReady = 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 pDrainQueue(): Promise<void> {\n this.pDraining = true;\n while (this.pReady && this.pQueue.length) {\n this.pDrainLock = new Barrier();\n void this.pQueue[0]!.resolve();\n await this.pDrainLock;\n void this.pQueue.shift();\n }\n this.pDraining = false;\n this.pDrainLock = null;\n }\n\n // \"true\" when the drain queue process is running (and thus no need to start\n // a new one).\n private pDraining = 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 pDrainLock: 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 pQueue: Array<Barrier<void>> = [];\n\n private pReady: boolean;\n}\n"],"mappings":"AAAA,OAAOA,OAAO,MAAM,WAAW;;AAE/B;AACA;AACA;AACA,eAAe,MAAMC,SAAS,CAAC;EAC7BC,WAAWA,CAACC,KAAK,GAAG,KAAK,EAAE;IACzB;IACA;IACA;IACA,IAAI,CAACC,MAAM,GAAG,CAAC,CAACD,KAAK;EACvB;EAEA,IAAIA,KAAKA,CAAA,EAAY;IACnB,OAAO,IAAI,CAACC,MAAM;EACpB;EAEAC,QAAQA,CAACF,KAAc,EAAQ;IAC7B;IACA;IACA;IACA,MAAMG,IAAI,GAAG,CAAC,CAACH,KAAK;IACpB,IAAI,IAAI,CAACC,MAAM,KAAKE,IAAI,EAAE;MACxB,IAAI,CAACF,MAAM,GAAGE,IAAI;MAClB,IAAIA,IAAI,IAAI,CAAC,IAAI,CAACC,SAAS,IAAI,IAAI,CAACC,MAAM,CAACC,MAAM,EAAE;QACjD,KAAK,IAAI,CAACC,WAAW,CAAC,CAAC;MACzB;IACF;EACF;;EAEA;AACF;AACA;EACE,MAAMC,KAAKA,CAAA,EAAkB;IAC3B,OAAO,IAAI,CAACC,SAAS,CAAC,IAAI,CAAC;EAC7B;EAEA,MAAMA,SAASA,CAACD,KAAK,GAAG,KAAK,EAAiB;IAC5C,IAAI,CAAC,IAAI,CAACP,MAAM,IAAI,IAAI,CAACI,MAAM,CAACC,MAAM,EAAE;MACtC,MAAMI,OAAO,GAAG,IAAIb,OAAO,CAAO,CAAC;MACnC,IAAI,CAACQ,MAAM,CAACM,IAAI,CAACD,OAAO,CAAC;MACzB,MAAMA,OAAO;MACb,IAAIF,KAAK,EAAE,IAAI,CAACP,MAAM,GAAG,KAAK;MAC9B,KAAK,IAAI,CAACW,UAAU,CAAEC,OAAO,CAAC,CAAC;IACjC,CAAC,MAAM,IAAIL,KAAK,EAAE,IAAI,CAACP,MAAM,GAAG,KAAK;EACvC;;EAEA;;EAEA;AACF;AACA;AACA;AACA;AACA;EACE,MAAMM,WAAWA,CAAA,EAAkB;IACjC,IAAI,CAACH,SAAS,GAAG,IAAI;IACrB,OAAO,IAAI,CAACH,MAAM,IAAI,IAAI,CAACI,MAAM,CAACC,MAAM,EAAE;MACxC,IAAI,CAACM,UAAU,GAAG,IAAIf,OAAO,CAAC,CAAC;MAC/B,KAAK,IAAI,CAACQ,MAAM,CAAC,CAAC,CAAC,CAAEQ,OAAO,CAAC,CAAC;MAC9B,MAAM,IAAI,CAACD,UAAU;MACrB,KAAK,IAAI,CAACP,MAAM,CAACS,KAAK,CAAC,CAAC;IAC1B;IACA,IAAI,CAACV,SAAS,GAAG,KAAK;IACtB,IAAI,CAACQ,UAAU,GAAG,IAAI;EACxB;;EAEA;EACA;EACQR,SAAS,GAAG,KAAK;;EAEzB;EACA;EACA;EACA;EACA;EACA;EACQQ,UAAU,GAAyB,IAAI;;EAE/C;EACA;EACQP,MAAM,GAAyB,EAAE;AAG3C","ignoreList":[]}
1
+ {"version":3,"file":"Semaphore.js","names":["Barrier","Semaphore","constructor","ready","pReady","setReady","bool","pDraining","pQueue","length","pDrainQueue","seize","waitReady","barrier","push","pDrainLock","resolve","shift"],"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 // TODO: Boolean conversion is performed for backward compatibility with\n // plain JS projects. Drop it in future.\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-conversion\n this.pReady = !!ready;\n }\n\n get ready(): boolean {\n return this.pReady;\n }\n\n setReady(ready: boolean): void {\n // TODO: Boolean conversion is performed for backward compatibility with\n // plain JS projects. Drop it in future.\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-conversion\n const bool = !!ready;\n if (this.pReady !== bool) {\n this.pReady = bool;\n if (bool && !this.pDraining && this.pQueue.length) {\n void this.pDrainQueue();\n }\n }\n }\n\n /**\n * Waits until the semaphore is ready, and marks it as non-ready (seizes it).\n */\n async seize(): Promise<void> {\n return this.waitReady(true);\n }\n\n async waitReady(seize = false): Promise<void> {\n if (!this.pReady || this.pQueue.length) {\n const barrier = new Barrier<void>();\n this.pQueue.push(barrier);\n await barrier;\n if (seize) this.pReady = false;\n void this.pDrainLock!.resolve();\n } else if (seize) this.pReady = 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 pDrainQueue(): Promise<void> {\n this.pDraining = true;\n while (this.pReady && this.pQueue.length) {\n this.pDrainLock = new Barrier();\n void this.pQueue[0]!.resolve();\n await this.pDrainLock;\n void this.pQueue.shift();\n }\n this.pDraining = false;\n this.pDrainLock = null;\n }\n\n // \"true\" when the drain queue process is running (and thus no need to start\n // a new one).\n private pDraining = 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 pDrainLock: 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 pQueue: Array<Barrier<void>> = [];\n\n private pReady: boolean;\n}\n"],"mappings":"OAAOA,OAAO;AAEd;AACA;AACA;AACA,eAAe,MAAMC,SAAS,CAAC;EAC7BC,WAAWA,CAACC,KAAK,GAAG,KAAK,EAAE;IACzB;IACA;IACA;IACA,IAAI,CAACC,MAAM,GAAG,CAAC,CAACD,KAAK;EACvB;EAEA,IAAIA,KAAKA,CAAA,EAAY;IACnB,OAAO,IAAI,CAACC,MAAM;EACpB;EAEAC,QAAQA,CAACF,KAAc,EAAQ;IAC7B;IACA;IACA;IACA,MAAMG,IAAI,GAAG,CAAC,CAACH,KAAK;IACpB,IAAI,IAAI,CAACC,MAAM,KAAKE,IAAI,EAAE;MACxB,IAAI,CAACF,MAAM,GAAGE,IAAI;MAClB,IAAIA,IAAI,IAAI,CAAC,IAAI,CAACC,SAAS,IAAI,IAAI,CAACC,MAAM,CAACC,MAAM,EAAE;QACjD,KAAK,IAAI,CAACC,WAAW,CAAC,CAAC;MACzB;IACF;EACF;;EAEA;AACF;AACA;EACE,MAAMC,KAAKA,CAAA,EAAkB;IAC3B,OAAO,IAAI,CAACC,SAAS,CAAC,IAAI,CAAC;EAC7B;EAEA,MAAMA,SAASA,CAACD,KAAK,GAAG,KAAK,EAAiB;IAC5C,IAAI,CAAC,IAAI,CAACP,MAAM,IAAI,IAAI,CAACI,MAAM,CAACC,MAAM,EAAE;MACtC,MAAMI,OAAO,GAAG,IAAIb,OAAO,CAAO,CAAC;MACnC,IAAI,CAACQ,MAAM,CAACM,IAAI,CAACD,OAAO,CAAC;MACzB,MAAMA,OAAO;MACb,IAAIF,KAAK,EAAE,IAAI,CAACP,MAAM,GAAG,KAAK;MAC9B,KAAK,IAAI,CAACW,UAAU,CAAEC,OAAO,CAAC,CAAC;IACjC,CAAC,MAAM,IAAIL,KAAK,EAAE,IAAI,CAACP,MAAM,GAAG,KAAK;EACvC;;EAEA;;EAEA;AACF;AACA;AACA;AACA;AACA;EACE,MAAMM,WAAWA,CAAA,EAAkB;IACjC,IAAI,CAACH,SAAS,GAAG,IAAI;IACrB,OAAO,IAAI,CAACH,MAAM,IAAI,IAAI,CAACI,MAAM,CAACC,MAAM,EAAE;MACxC,IAAI,CAACM,UAAU,GAAG,IAAIf,OAAO,CAAC,CAAC;MAC/B,KAAK,IAAI,CAACQ,MAAM,CAAC,CAAC,CAAC,CAAEQ,OAAO,CAAC,CAAC;MAC9B,MAAM,IAAI,CAACD,UAAU;MACrB,KAAK,IAAI,CAACP,MAAM,CAACS,KAAK,CAAC,CAAC;IAC1B;IACA,IAAI,CAACV,SAAS,GAAG,KAAK;IACtB,IAAI,CAACQ,UAAU,GAAG,IAAI;EACxB;;EAEA;EACA;EACQR,SAAS,GAAG,KAAK;;EAEzB;EACA;EACA;EACA;EACA;EACA;EACQQ,UAAU,GAAyB,IAAI;;EAE/C;EACA;EACQP,MAAM,GAAyB,EAAE;AAG3C","ignoreList":[]}
@@ -1,8 +1,8 @@
1
- export { default as Barrier } from './Barrier';
2
- export * from './Cached';
3
- export * from './Emitter';
4
- export { default as Semaphore } from './Semaphore';
5
- export * from './time';
6
- export * from './types';
7
- export { default as withRetries } from './withRetries';
1
+ export { default as Barrier } from "./Barrier.js";
2
+ export * from "./Cached.js";
3
+ export * from "./Emitter.js";
4
+ export { default as Semaphore } from "./Semaphore.js";
5
+ export * from "./time.js";
6
+ export * from "./types.js";
7
+ export { default as withRetries } from "./withRetries.js";
8
8
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["default","Barrier","Semaphore","withRetries"],"sources":["../../src/index.ts"],"sourcesContent":["export { default as Barrier } from './Barrier';\nexport * from './Cached';\nexport * from './Emitter';\nexport { default as Semaphore } from './Semaphore';\nexport * from './time';\nexport * from './types';\nexport { default as withRetries } from './withRetries';\n"],"mappings":"AAAA,SAASA,OAAO,IAAIC,OAAO,QAAQ,WAAW;AAC9C,cAAc,UAAU;AACxB,cAAc,WAAW;AACzB,SAASD,OAAO,IAAIE,SAAS,QAAQ,aAAa;AAClD,cAAc,QAAQ;AACtB,cAAc,SAAS;AACvB,SAASF,OAAO,IAAIG,WAAW,QAAQ,eAAe","ignoreList":[]}
1
+ {"version":3,"file":"index.js","names":["default","Barrier","Semaphore","withRetries"],"sources":["../../src/index.ts"],"sourcesContent":["export { default as Barrier } from './Barrier';\nexport * from './Cached';\nexport * from './Emitter';\nexport { default as Semaphore } from './Semaphore';\nexport * from './time';\nexport * from './types';\nexport { default as withRetries } from './withRetries';\n"],"mappings":"SAASA,OAAO,IAAIC,OAAO;AAAA;AAAA;AAAA,SAGlBD,OAAO,IAAIE,SAAS;AAAA;AAAA;AAAA,SAGpBF,OAAO,IAAIG,WAAW","ignoreList":[]}
@@ -1,6 +1,4 @@
1
- import Barrier from './Barrier';
2
-
3
- // This is not very elegant, but as of now TypeScript does not support type
1
+ import Barrier from "./Barrier.js"; // This is not very elegant, but as of now TypeScript does not support type
4
2
  // arithmetic, thus we can't have constants assigned like `MIN_MS = 60 * SEC_MS`
5
3
  // and have the result type to be 60000 (number literal), it would be just
6
4
  // the generic number type.
@@ -1 +1 @@
1
- {"version":3,"file":"time.js","names":["Barrier","SEC_MS","MIN_MS","HOUR_MS","DAY_MS","YEAR_MS","Timer","abort","pAbort","timeout","pTimeout","constructor","executor","undefined","init","Error","id","setTimeout","resolve","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 pAbort: () => void;\n\n private pTimeout?: number;\n\n get abort(): () => void {\n return this.pAbort;\n }\n\n get timeout(): number | undefined {\n return this.pTimeout;\n }\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.pAbort = () => undefined;\n }\n\n init(timeout: number): this {\n if (this.pTimeout !== undefined) {\n throw Error('This Timer is initialized already');\n }\n this.pTimeout = timeout;\n if (timeout > 0) {\n const id = setTimeout(() => {\n void super.resolve();\n }, timeout);\n this.pAbort = () => {\n clearTimeout(id);\n };\n } else {\n void super.resolve();\n }\n return this;\n }\n\n // TODO: For async functions TS requires the return type to be the global\n // Promise, thus not allowing to return our Timer type extending that via\n // Barrier. Thus, we don't mark this method async for now, disabling the rule,\n // and we should think more about it in future.\n // eslint-disable-next-line @typescript-eslint/promise-function-async\n then<TR1, TR2>(\n onFulfilled?: ((value: T) => TR1 | PromiseLike<TR1>) | null,\n onRejected?: ((reason: unknown) => TR2 | PromiseLike<TR2>) | null,\n ): Timer<TR1 | TR2> {\n const res = super.then(onFulfilled, onRejected) as Timer<TR1 | TR2>;\n if (this.timeout !== undefined) void 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 */\n// TODO: For async functions TS requires the return type to be the global\n// Promise, thus not allowing to return our Timer type extending that via\n// Barrier. Thus, we don't mark this method async for now, disabling the rule,\n// and we should think more about it in future.\n// eslint-disable-next-line @typescript-eslint/promise-function-async\nexport function timer(timeout: number): Timer<void> {\n const t = new Timer<void>();\n return t.init(timeout);\n}\n"],"mappings":"AAAA,OAAOA,OAAO,MAAyB,WAAW;;AAElD;AACA;AACA;AACA;AACA,OAAO,MAAMC,MAAM,GAAG,IAAI;AAC1B,OAAO,MAAMC,MAAM,GAAG,KAAK,CAAC,CAAC;AAC7B,OAAO,MAAMC,OAAO,GAAG,OAAO,CAAC,CAAC;AAChC,OAAO,MAAMC,MAAM,GAAG,QAAQ,CAAC,CAAC;AAChC,OAAO,MAAMC,OAAO,GAAG,WAAW,CAAC,CAAC;;AAEpC;AACA;AACA;AACA,OAAO,MAAMC,KAAK,SAAYN,OAAO,CAAU;EAK7C,IAAIO,KAAKA,CAAA,EAAe;IACtB,OAAO,IAAI,CAACC,MAAM;EACpB;EAEA,IAAIC,OAAOA,CAAA,EAAuB;IAChC,OAAO,IAAI,CAACC,QAAQ;EACtB;;EAEA;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,MAAM,GAAG,MAAMK,SAAS;EAC/B;EAEAC,IAAIA,CAACL,OAAe,EAAQ;IAC1B,IAAI,IAAI,CAACC,QAAQ,KAAKG,SAAS,EAAE;MAC/B,MAAME,KAAK,CAAC,mCAAmC,CAAC;IAClD;IACA,IAAI,CAACL,QAAQ,GAAGD,OAAO;IACvB,IAAIA,OAAO,GAAG,CAAC,EAAE;MACf,MAAMO,EAAE,GAAGC,UAAU,CAAC,MAAM;QAC1B,KAAK,KAAK,CAACC,OAAO,CAAC,CAAC;MACtB,CAAC,EAAET,OAAO,CAAC;MACX,IAAI,CAACD,MAAM,GAAG,MAAM;QAClBW,YAAY,CAACH,EAAE,CAAC;MAClB,CAAC;IACH,CAAC,MAAM;MACL,KAAK,KAAK,CAACE,OAAO,CAAC,CAAC;IACtB;IACA,OAAO,IAAI;EACb;;EAEA;EACA;EACA;EACA;EACA;EACAE,IAAIA,CACFC,WAA2D,EAC3DC,UAAiE,EAC/C;IAClB,MAAMC,GAAG,GAAG,KAAK,CAACH,IAAI,CAACC,WAAW,EAAEC,UAAU,CAAqB;IACnE,IAAI,IAAI,CAACb,OAAO,KAAKI,SAAS,EAAE,KAAKU,GAAG,CAACT,IAAI,CAAC,IAAI,CAACL,OAAO,CAAC;IAC3D,OAAOc,GAAG;EACZ;AACF;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,KAAKA,CAACf,OAAe,EAAe;EAClD,MAAMgB,CAAC,GAAG,IAAInB,KAAK,CAAO,CAAC;EAC3B,OAAOmB,CAAC,CAACX,IAAI,CAACL,OAAO,CAAC;AACxB","ignoreList":[]}
1
+ {"version":3,"file":"time.js","names":["Barrier","SEC_MS","MIN_MS","HOUR_MS","DAY_MS","YEAR_MS","Timer","abort","pAbort","timeout","pTimeout","constructor","executor","undefined","init","Error","id","setTimeout","resolve","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 pAbort: () => void;\n\n private pTimeout?: number;\n\n get abort(): () => void {\n return this.pAbort;\n }\n\n get timeout(): number | undefined {\n return this.pTimeout;\n }\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.pAbort = () => undefined;\n }\n\n init(timeout: number): this {\n if (this.pTimeout !== undefined) {\n throw Error('This Timer is initialized already');\n }\n this.pTimeout = timeout;\n if (timeout > 0) {\n const id = setTimeout(() => {\n void super.resolve();\n }, timeout);\n this.pAbort = () => {\n clearTimeout(id);\n };\n } else {\n void super.resolve();\n }\n return this;\n }\n\n // TODO: For async functions TS requires the return type to be the global\n // Promise, thus not allowing to return our Timer type extending that via\n // Barrier. Thus, we don't mark this method async for now, disabling the rule,\n // and we should think more about it in future.\n // eslint-disable-next-line @typescript-eslint/promise-function-async\n then<TR1, TR2>(\n onFulfilled?: ((value: T) => TR1 | PromiseLike<TR1>) | null,\n onRejected?: ((reason: unknown) => TR2 | PromiseLike<TR2>) | null,\n ): Timer<TR1 | TR2> {\n const res = super.then(onFulfilled, onRejected) as Timer<TR1 | TR2>;\n if (this.timeout !== undefined) void 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 */\n// TODO: For async functions TS requires the return type to be the global\n// Promise, thus not allowing to return our Timer type extending that via\n// Barrier. Thus, we don't mark this method async for now, disabling the rule,\n// and we should think more about it in future.\n// eslint-disable-next-line @typescript-eslint/promise-function-async\nexport function timer(timeout: number): Timer<void> {\n const t = new Timer<void>();\n return t.init(timeout);\n}\n"],"mappings":"OAAOA,OAAO,sBAEd;AACA;AACA;AACA;AACA,OAAO,MAAMC,MAAM,GAAG,IAAI;AAC1B,OAAO,MAAMC,MAAM,GAAG,KAAK,CAAC,CAAC;AAC7B,OAAO,MAAMC,OAAO,GAAG,OAAO,CAAC,CAAC;AAChC,OAAO,MAAMC,MAAM,GAAG,QAAQ,CAAC,CAAC;AAChC,OAAO,MAAMC,OAAO,GAAG,WAAW,CAAC,CAAC;;AAEpC;AACA;AACA;AACA,OAAO,MAAMC,KAAK,SAAYN,OAAO,CAAU;EAK7C,IAAIO,KAAKA,CAAA,EAAe;IACtB,OAAO,IAAI,CAACC,MAAM;EACpB;EAEA,IAAIC,OAAOA,CAAA,EAAuB;IAChC,OAAO,IAAI,CAACC,QAAQ;EACtB;;EAEA;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,MAAM,GAAG,MAAMK,SAAS;EAC/B;EAEAC,IAAIA,CAACL,OAAe,EAAQ;IAC1B,IAAI,IAAI,CAACC,QAAQ,KAAKG,SAAS,EAAE;MAC/B,MAAME,KAAK,CAAC,mCAAmC,CAAC;IAClD;IACA,IAAI,CAACL,QAAQ,GAAGD,OAAO;IACvB,IAAIA,OAAO,GAAG,CAAC,EAAE;MACf,MAAMO,EAAE,GAAGC,UAAU,CAAC,MAAM;QAC1B,KAAK,KAAK,CAACC,OAAO,CAAC,CAAC;MACtB,CAAC,EAAET,OAAO,CAAC;MACX,IAAI,CAACD,MAAM,GAAG,MAAM;QAClBW,YAAY,CAACH,EAAE,CAAC;MAClB,CAAC;IACH,CAAC,MAAM;MACL,KAAK,KAAK,CAACE,OAAO,CAAC,CAAC;IACtB;IACA,OAAO,IAAI;EACb;;EAEA;EACA;EACA;EACA;EACA;EACAE,IAAIA,CACFC,WAA2D,EAC3DC,UAAiE,EAC/C;IAClB,MAAMC,GAAG,GAAG,KAAK,CAACH,IAAI,CAACC,WAAW,EAAEC,UAAU,CAAqB;IACnE,IAAI,IAAI,CAACb,OAAO,KAAKI,SAAS,EAAE,KAAKU,GAAG,CAACT,IAAI,CAAC,IAAI,CAACL,OAAO,CAAC;IAC3D,OAAOc,GAAG;EACZ;AACF;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,KAAKA,CAACf,OAAe,EAAe;EAClD,MAAMgB,CAAC,GAAG,IAAInB,KAAK,CAAO,CAAC;EAC3B,OAAOmB,CAAC,CAACX,IAAI,CAACL,OAAO,CAAC;AACxB","ignoreList":[]}
@@ -1,5 +1,4 @@
1
- import { timer } from './time';
2
-
1
+ import { timer } from "./time.js";
3
2
  /**
4
3
  * Attempts to perform the given async `action` up to `maxRetries` times with
5
4
  * the specified `interval`, stopping at the first successful (non-throwing)
@@ -1 +1 @@
1
- {"version":3,"file":"withRetries.js","names":["timer","withRetries","action","maxRetries","interval","n","res","Promise","error"],"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 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}\n"],"mappings":"AAAA,SAASA,KAAK,QAAQ,QAAQ;;AAE9B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,eAAe,eAAeC,WAAWA,CACvCC,MAAe,EACfC,UAAU,GAAG,CAAC,EACdC,QAAQ,GAAG,GAAG,EACO;EACrB,KAAK,IAAIC,CAAC,GAAG,CAAC,GAAI,EAAEA,CAAC,EAAE;IACrB,IAAI;MACF,MAAMC,GAAG,GAAGJ,MAAM,CAAC,CAAC;MACpB,OAAOI,GAAG,YAAYC,OAAO,GAAG,MAAMD,GAAG,GAAIA,GAAkB;IACjE,CAAC,CAAC,OAAOE,KAAK,EAAE;MACd,IAAIH,CAAC,GAAGF,UAAU,EAAE,MAAMH,KAAK,CAACI,QAAQ,CAAC,CAAC,KACrC,MAAMI,KAAK;IAClB;EACF;AACF","ignoreList":[]}
1
+ {"version":3,"file":"withRetries.js","names":["timer","withRetries","action","maxRetries","interval","n","res","Promise","error"],"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 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}\n"],"mappings":"SAASA,KAAK;AAEd;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,eAAe,eAAeC,WAAWA,CACvCC,MAAe,EACfC,UAAU,GAAG,CAAC,EACdC,QAAQ,GAAG,GAAG,EACO;EACrB,KAAK,IAAIC,CAAC,GAAG,CAAC,GAAI,EAAEA,CAAC,EAAE;IACrB,IAAI;MACF,MAAMC,GAAG,GAAGJ,MAAM,CAAC,CAAC;MACpB,OAAOI,GAAG,YAAYC,OAAO,GAAG,MAAMD,GAAG,GAAIA,GAAkB;IACjE,CAAC,CAAC,OAAOE,KAAK,EAAE;MACd,IAAIH,CAAC,GAAGF,UAAU,EAAE,MAAMH,KAAK,CAACI,QAAQ,CAAC,CAAC,KACrC,MAAMI,KAAK;IAClB;EACF;AACF","ignoreList":[]}
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@dr.pogodin/js-utils",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "Collection of JavaScript (TypeScript) utilities.",
5
5
  "main": "./build/module/index.js",
6
6
  "module": "./build/module/index.js",
7
7
  "types": "./build/types/index.d.ts",
8
8
  "exports": {
9
- "require": "./cjs.js",
9
+ "require": "./build/common/index.js",
10
10
  "types": "./build/types/index.d.ts",
11
11
  "default": "./build/module/index.js"
12
12
  },
@@ -16,7 +16,7 @@
16
16
  "build:module": "rimraf build/module && babel src -x .ts --out-dir build/module --source-maps --config-file ./babel.module.config.js",
17
17
  "build:types": "rimraf build/types && tsc --project tsconfig.types.json",
18
18
  "jest": "npm run jest:types && npm run jest:logic",
19
- "jest:logic": "jest --config jest.config.js",
19
+ "jest:logic": "jest --config jest.config.js --no-cache",
20
20
  "jest:types": "tstyche",
21
21
  "lint": "eslint",
22
22
  "test": "npm run lint && npm run typecheck && npm run jest",
@@ -38,22 +38,23 @@
38
38
  },
39
39
  "homepage": "https://github.com/birdofpreyru/js-utils#readme",
40
40
  "devDependencies": {
41
- "@babel/cli": "^7.28.0",
42
- "@babel/core": "^7.28.0",
43
- "@babel/plugin-transform-runtime": "^7.28.0",
44
- "@babel/preset-env": "^7.28.0",
45
- "@babel/preset-typescript": "^7.27.1",
46
- "@dr.pogodin/eslint-configs": "^0.0.9",
41
+ "@babel/cli": "^7.28.3",
42
+ "@babel/core": "^7.28.5",
43
+ "@babel/plugin-transform-runtime": "^7.28.5",
44
+ "@babel/preset-env": "^7.28.5",
45
+ "@babel/preset-typescript": "^7.28.5",
46
+ "@dr.pogodin/eslint-configs": "^0.1.1",
47
47
  "@tsconfig/recommended": "^1.0.10",
48
48
  "@types/jest": "^30.0.0",
49
- "babel-jest": "^30.0.5",
50
- "jest": "^30.0.5",
49
+ "babel-jest": "^30.2.0",
50
+ "babel-plugin-add-import-extension": "^1.6.0",
51
+ "jest": "^30.2.0",
51
52
  "mockdate": "^3.0.5",
52
53
  "rimraf": "^6.0.1",
53
- "tstyche": "^4.3.0",
54
- "typescript": "^5.8.3"
54
+ "tstyche": "^5.0.0",
55
+ "typescript": "^5.9.3"
55
56
  },
56
57
  "dependencies": {
57
- "@babel/runtime": "^7.27.6"
58
+ "@babel/runtime": "^7.28.4"
58
59
  }
59
60
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://tstyche.org/schemas/config.json",
3
+ "checkDeclarationFiles": true,
3
4
  "checkSuppressedErrors": true,
4
- "checkSourceFiles": false,
5
5
  "testFileMatch": [
6
6
  "__tests__/**/*.{ts, tsx}"
7
7
  ]
package/cjs.js DELETED
@@ -1,10 +0,0 @@
1
- /* global module, require */
2
-
3
- // eslint-disable-next-line import/no-commonjs
4
- const jsUtils = require('./build/common/index.js').default;
5
-
6
- // eslint-disable-next-line import/no-commonjs
7
- module.exports = jsUtils;
8
-
9
- // eslint-disable-next-line import/no-commonjs
10
- module.exports.default = jsUtils;