@dr.pogodin/js-utils 0.0.6 → 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -9
- package/build/Emitter.js +1 -1
- package/build/index.d.ts +1 -0
- package/build/index.js +3 -1
- package/build/time.d.ts +4 -4
- package/build/time.js +8 -4
- package/build/withRetries.d.ts +12 -0
- package/build/withRetries.js +42 -0
- package/jest.config-types.js +4 -0
- package/jest.config.js +3 -0
- package/package.json +23 -18
- package/src/Emitter.ts +1 -1
- package/src/index.ts +1 -0
- package/src/time.ts +8 -4
- package/src/withRetries.ts +30 -0
package/README.md
CHANGED
|
@@ -22,8 +22,8 @@ very well documented as such.
|
|
|
22
22
|
|
|
23
23
|
Yeah, the source code will be written in TypeScript, and for the library
|
|
24
24
|
version released to NPM it will be also compiled into plain JavaScript.
|
|
25
|
-
Consumers of that NPM package thus will have access to both TS (`/
|
|
26
|
-
and JS (`/
|
|
25
|
+
Consumers of that NPM package thus will have access to both TS (`/src` folder)
|
|
26
|
+
and JS (`/build` folder) version of the library.
|
|
27
27
|
|
|
28
28
|
[](https://github.com/sponsors/birdofpreyru)
|
|
29
29
|
|
|
@@ -33,10 +33,6 @@ The library currently exports (links below lead to [React Utils] docs,
|
|
|
33
33
|
but the same stuff can be imported from this `@dr.pogodin/js-utils`,
|
|
34
34
|
and used in the same way):
|
|
35
35
|
|
|
36
|
-
[Barrier]: https://dr.pogodin.studio/docs/react-utils/docs/api/classes/Barrier
|
|
37
|
-
[Promise]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
|
|
38
|
-
[timer]: https://dr.pogodin.studio/docs/react-utils/docs/api/utils/time#timer
|
|
39
|
-
|
|
40
36
|
### Constants
|
|
41
37
|
- [SEC_MS](https://dr.pogodin.studio/docs/react-utils/docs/api/utils/time#sec_ms)
|
|
42
38
|
— One second expressed in milliseconds.
|
|
@@ -50,8 +46,8 @@ and used in the same way):
|
|
|
50
46
|
— One year expressed in milliseconds.
|
|
51
47
|
|
|
52
48
|
### Functions
|
|
53
|
-
- [timer]
|
|
54
|
-
|
|
49
|
+
- [timer()] — Creates a [Barrier] which resolves after the specified timeout.
|
|
50
|
+
- [withRetries()] — Attempts a given action multiple times until its succeeds.
|
|
55
51
|
|
|
56
52
|
### Classes
|
|
57
53
|
- [Barrier] — A [Promise] with **resolve()** and **reject()** exposed as
|
|
@@ -60,5 +56,12 @@ and used in the same way):
|
|
|
60
56
|
— Simple listeneable data emitter.
|
|
61
57
|
- [Semaphore](https://dr.pogodin.studio/docs/react-utils/docs/api/classes/Semaphore)
|
|
62
58
|
— Synchronization primitive.
|
|
63
|
-
- `Timer` — The core implementation of [timer] functionality, allowing
|
|
59
|
+
- `Timer` — The core implementation of [timer()] functionality, allowing
|
|
64
60
|
to create further customized timer objects. _To be documented_.
|
|
61
|
+
|
|
62
|
+
<!-- References -->
|
|
63
|
+
|
|
64
|
+
[Barrier]: https://dr.pogodin.studio/docs/react-utils/docs/api/classes/Barrier
|
|
65
|
+
[Promise]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
|
|
66
|
+
[timer()]: https://dr.pogodin.studio/docs/react-utils/docs/api/utils/time#timer
|
|
67
|
+
[withRetries()]: https://dr.pogodin.studio/docs/react-utils/docs/api/functions/withretries
|
package/build/Emitter.js
CHANGED
package/build/index.d.ts
CHANGED
package/build/index.js
CHANGED
|
@@ -17,7 +17,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
17
17
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
18
18
|
};
|
|
19
19
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
-
exports.Semaphore = exports.Emitter = exports.Barrier = void 0;
|
|
20
|
+
exports.withRetries = exports.Semaphore = exports.Emitter = exports.Barrier = void 0;
|
|
21
21
|
var Barrier_1 = require("./Barrier");
|
|
22
22
|
Object.defineProperty(exports, "Barrier", { enumerable: true, get: function () { return __importDefault(Barrier_1).default; } });
|
|
23
23
|
var Emitter_1 = require("./Emitter");
|
|
@@ -25,3 +25,5 @@ Object.defineProperty(exports, "Emitter", { enumerable: true, get: function () {
|
|
|
25
25
|
var Semaphore_1 = require("./Semaphore");
|
|
26
26
|
Object.defineProperty(exports, "Semaphore", { enumerable: true, get: function () { return __importDefault(Semaphore_1).default; } });
|
|
27
27
|
__exportStar(require("./time"), exports);
|
|
28
|
+
var withRetries_1 = require("./withRetries");
|
|
29
|
+
Object.defineProperty(exports, "withRetries", { enumerable: true, get: function () { return __importDefault(withRetries_1).default; } });
|
package/build/time.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import Barrier, { type Executor } from './Barrier';
|
|
2
2
|
export declare const SEC_MS = 1000;
|
|
3
|
-
export declare const MIN_MS
|
|
4
|
-
export declare const HOUR_MS
|
|
5
|
-
export declare const DAY_MS
|
|
6
|
-
export declare const YEAR_MS
|
|
3
|
+
export declare const MIN_MS = 60000;
|
|
4
|
+
export declare const HOUR_MS = 3600000;
|
|
5
|
+
export declare const DAY_MS = 86400000;
|
|
6
|
+
export declare const YEAR_MS = 31536000000;
|
|
7
7
|
export declare class Timer<T> extends Barrier<void, T> {
|
|
8
8
|
private p_abort;
|
|
9
9
|
private p_timeout?;
|
package/build/time.js
CHANGED
|
@@ -5,11 +5,15 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.timer = exports.Timer = exports.YEAR_MS = exports.DAY_MS = exports.HOUR_MS = exports.MIN_MS = exports.SEC_MS = void 0;
|
|
7
7
|
const Barrier_1 = __importDefault(require("./Barrier"));
|
|
8
|
+
// This is not very elegant, but as of now TypeScript does not support type
|
|
9
|
+
// arithmetic, thus we can't have constants assigned like `MIN_MS = 60 * SEC_MS`
|
|
10
|
+
// and have the result type to be 60000 (number literal), it would be just
|
|
11
|
+
// the generic number type.
|
|
8
12
|
exports.SEC_MS = 1000;
|
|
9
|
-
exports.MIN_MS = 60 *
|
|
10
|
-
exports.HOUR_MS = 60 *
|
|
11
|
-
exports.DAY_MS = 24 *
|
|
12
|
-
exports.YEAR_MS = 365 *
|
|
13
|
+
exports.MIN_MS = 60000; // 60 * SEC_MS
|
|
14
|
+
exports.HOUR_MS = 3600000; // 60 * MIN_MS
|
|
15
|
+
exports.DAY_MS = 86400000; // 24 * HOUR_MS
|
|
16
|
+
exports.YEAR_MS = 31536000000; // 365 * DAY_MS
|
|
13
17
|
// TODO: Ok, as we have ended up with a Timer class, mostly to achieve a good
|
|
14
18
|
// TypeScript typing for timer() function, it makes sense to expose the class
|
|
15
19
|
// from the library as well, and it should be documented later.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Attempts to perform the given async `action` up to `maxRetries` times with
|
|
3
|
+
* the specified `interval`, stopping at the first successful (non-throwing)
|
|
4
|
+
* execution.
|
|
5
|
+
* @param action
|
|
6
|
+
* @param maxRetries Optional. The maximum number of re-tries. Defaults 3.
|
|
7
|
+
* @param interval Optional. The interval between re-tries (in milliseconds).
|
|
8
|
+
* Defaults to 300ms.
|
|
9
|
+
* @returns Resolves to the result of the successful `action` execution;
|
|
10
|
+
* or rejects with the error from the last faileda attempt.
|
|
11
|
+
*/
|
|
12
|
+
export default function withRetries(action: () => unknown, maxRetries?: number, interval?: number): Promise<any>;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const time_1 = require("./time");
|
|
13
|
+
/**
|
|
14
|
+
* Attempts to perform the given async `action` up to `maxRetries` times with
|
|
15
|
+
* the specified `interval`, stopping at the first successful (non-throwing)
|
|
16
|
+
* execution.
|
|
17
|
+
* @param action
|
|
18
|
+
* @param maxRetries Optional. The maximum number of re-tries. Defaults 3.
|
|
19
|
+
* @param interval Optional. The interval between re-tries (in milliseconds).
|
|
20
|
+
* Defaults to 300ms.
|
|
21
|
+
* @returns Resolves to the result of the successful `action` execution;
|
|
22
|
+
* or rejects with the error from the last faileda attempt.
|
|
23
|
+
*/
|
|
24
|
+
function withRetries(action, maxRetries = 3, interval = 300) {
|
|
25
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
26
|
+
/* eslint-disable no-await-in-loop */
|
|
27
|
+
for (let n = 1;; ++n) {
|
|
28
|
+
try {
|
|
29
|
+
const res = action();
|
|
30
|
+
return res instanceof Promise ? yield res : res;
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
if (n < maxRetries)
|
|
34
|
+
yield (0, time_1.timer)(interval);
|
|
35
|
+
else
|
|
36
|
+
throw error;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/* eslint-enable no-await-in-loop */
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
exports.default = withRetries;
|
package/jest.config.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dr.pogodin/js-utils",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.8",
|
|
4
4
|
"description": "Collection of JavaScript (TypeScript) utilities.",
|
|
5
5
|
"main": "build/index",
|
|
6
6
|
"react-native": "src/index",
|
|
@@ -8,9 +8,11 @@
|
|
|
8
8
|
"types": "build/index.d.ts",
|
|
9
9
|
"scripts": {
|
|
10
10
|
"build": "rimraf build && tsc",
|
|
11
|
-
"jest": "jest
|
|
11
|
+
"jest": "npm run jest:types && npm run jest:logic",
|
|
12
|
+
"jest:logic": "jest --config jest.config.js",
|
|
13
|
+
"jest:types": "jest --config jest.config-types.js",
|
|
12
14
|
"lint": "eslint . --ext .js,.ts",
|
|
13
|
-
"test": "npm run
|
|
15
|
+
"test": "npm run lint && npm run typecheck && npm run jest",
|
|
14
16
|
"typecheck": "tsc --noEmit && tsc --project __tests__/tsconfig.json"
|
|
15
17
|
},
|
|
16
18
|
"repository": {
|
|
@@ -29,21 +31,24 @@
|
|
|
29
31
|
},
|
|
30
32
|
"homepage": "https://github.com/birdofpreyru/js-utils#readme",
|
|
31
33
|
"devDependencies": {
|
|
32
|
-
"@babel/core": "^7.
|
|
33
|
-
"@babel/preset-env": "^7.
|
|
34
|
-
"@babel/preset-typescript": "^7.
|
|
35
|
-
"@tsconfig/recommended": "^1.0.
|
|
36
|
-
"@
|
|
37
|
-
"@
|
|
38
|
-
"@typescript-eslint/
|
|
39
|
-
"
|
|
40
|
-
"
|
|
34
|
+
"@babel/core": "^7.23.9",
|
|
35
|
+
"@babel/preset-env": "^7.23.9",
|
|
36
|
+
"@babel/preset-typescript": "^7.23.3",
|
|
37
|
+
"@tsconfig/recommended": "^1.0.3",
|
|
38
|
+
"@tsd/typescript": "^5.3.3",
|
|
39
|
+
"@types/jest": "^29.5.12",
|
|
40
|
+
"@typescript-eslint/eslint-plugin": "^6.21.0",
|
|
41
|
+
"@typescript-eslint/parser": "^6.21.0",
|
|
42
|
+
"babel-jest": "^29.7.0",
|
|
43
|
+
"eslint": "^8.56.0",
|
|
41
44
|
"eslint-config-airbnb-base": "^15.0.0",
|
|
42
|
-
"eslint-config-airbnb-typescript": "^17.
|
|
43
|
-
"eslint-import-resolver-typescript": "^3.
|
|
44
|
-
"eslint-plugin-import": "^2.
|
|
45
|
-
"jest": "^29.
|
|
46
|
-
"
|
|
47
|
-
"
|
|
45
|
+
"eslint-config-airbnb-typescript": "^17.1.0",
|
|
46
|
+
"eslint-import-resolver-typescript": "^3.6.1",
|
|
47
|
+
"eslint-plugin-import": "^2.29.1",
|
|
48
|
+
"jest": "^29.7.0",
|
|
49
|
+
"jest-runner-tsd": "^6.0.0",
|
|
50
|
+
"rimraf": "^5.0.5",
|
|
51
|
+
"tsd-lite": "^0.8.2",
|
|
52
|
+
"typescript": "^5.3.3"
|
|
48
53
|
}
|
|
49
54
|
}
|
package/src/Emitter.ts
CHANGED
|
@@ -33,7 +33,7 @@ export default class Emitter<T extends unknown[] = unknown[]> {
|
|
|
33
33
|
* @param args
|
|
34
34
|
*/
|
|
35
35
|
emit(...args: T) {
|
|
36
|
-
const
|
|
36
|
+
const listeners = this.p_listeners.slice();
|
|
37
37
|
for (let i = 0; i < listeners.length; ++i) {
|
|
38
38
|
listeners[i](...args);
|
|
39
39
|
}
|
package/src/index.ts
CHANGED
package/src/time.ts
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import Barrier, { type Executor } from './Barrier';
|
|
2
2
|
|
|
3
|
+
// This is not very elegant, but as of now TypeScript does not support type
|
|
4
|
+
// arithmetic, thus we can't have constants assigned like `MIN_MS = 60 * SEC_MS`
|
|
5
|
+
// and have the result type to be 60000 (number literal), it would be just
|
|
6
|
+
// the generic number type.
|
|
3
7
|
export const SEC_MS = 1000;
|
|
4
|
-
export const MIN_MS = 60 * SEC_MS
|
|
5
|
-
export const HOUR_MS = 60 * MIN_MS
|
|
6
|
-
export const DAY_MS = 24 * HOUR_MS
|
|
7
|
-
export const YEAR_MS = 365 * DAY_MS
|
|
8
|
+
export const MIN_MS = 60000; // 60 * SEC_MS
|
|
9
|
+
export const HOUR_MS = 3600000; // 60 * MIN_MS
|
|
10
|
+
export const DAY_MS = 86400000; // 24 * HOUR_MS
|
|
11
|
+
export const YEAR_MS = 31536000000; // 365 * DAY_MS
|
|
8
12
|
|
|
9
13
|
// TODO: Ok, as we have ended up with a Timer class, mostly to achieve a good
|
|
10
14
|
// TypeScript typing for timer() function, it makes sense to expose the class
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { timer } from './time';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Attempts to perform the given async `action` up to `maxRetries` times with
|
|
5
|
+
* the specified `interval`, stopping at the first successful (non-throwing)
|
|
6
|
+
* execution.
|
|
7
|
+
* @param action
|
|
8
|
+
* @param maxRetries Optional. The maximum number of re-tries. Defaults 3.
|
|
9
|
+
* @param interval Optional. The interval between re-tries (in milliseconds).
|
|
10
|
+
* Defaults to 300ms.
|
|
11
|
+
* @returns Resolves to the result of the successful `action` execution;
|
|
12
|
+
* or rejects with the error from the last faileda attempt.
|
|
13
|
+
*/
|
|
14
|
+
export default async function withRetries(
|
|
15
|
+
action: () => unknown,
|
|
16
|
+
maxRetries = 3,
|
|
17
|
+
interval = 300,
|
|
18
|
+
) {
|
|
19
|
+
/* eslint-disable no-await-in-loop */
|
|
20
|
+
for (let n = 1; ; ++n) {
|
|
21
|
+
try {
|
|
22
|
+
const res = action();
|
|
23
|
+
return res instanceof Promise ? await res : res;
|
|
24
|
+
} catch (error) {
|
|
25
|
+
if (n < maxRetries) await timer(interval);
|
|
26
|
+
else throw error;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/* eslint-enable no-await-in-loop */
|
|
30
|
+
}
|