@sha1n/about-time 0.0.5 → 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 CHANGED
@@ -10,8 +10,10 @@
10
10
  A collection of essential time related utilities.
11
11
 
12
12
  - [About-Time](#about-time)
13
- - [Install](#install)
13
+ - [Install](#install)
14
+ - [Utilities & Features](#utilities--features)
14
15
  - [Delay](#delay)
16
+ - [WithTimeout](#withtimeout)
15
17
  - [Sleep](#sleep)
16
18
  - [Stopwatch](#stopwatch)
17
19
  - [Until / Eventually](#until--eventually)
@@ -24,21 +26,34 @@ A collection of essential time related utilities.
24
26
  - [Retriable](#retriable)
25
27
 
26
28
 
27
- ## Install
29
+ # Install
28
30
  ```bash
29
31
  npm i @sha1n/about-time
30
32
  ```
31
33
 
34
+ # Utilities & Features
32
35
  ## Delay
33
36
  ```ts
34
37
  // Execute a function with delay and return it's value
35
- await delay(action, 10, TimeUnit.Milliseconds);
38
+ await delay(action, { time: 10 });
39
+ await delay(action, { time: 10, units: TimeUnit.Milliseconds });
40
+ await delay(action, { time: 10, units: TimeUnit.Milliseconds, unref: true });
41
+ ```
42
+
43
+ ## WithTimeout
44
+ ```ts
45
+ // Execute a function and guards it with a specified timeout
46
+ await withTimeout(action, { time: 10 });
47
+ await withTimeout(action, { time: 10, units: TimeUnit.Milliseconds });
48
+ await withTimeout(action, { time: 10, units: TimeUnit.Milliseconds, unref: true });
36
49
  ```
37
50
 
38
51
  ## Sleep
39
52
  ```ts
40
53
  // Pause execution for a specified amount of time
41
- await sleep(10, TimeUnit.Seconds);
54
+ await sleep(10);
55
+ await sleep(10, { units: TimeUnit.Seconds });
56
+ await sleep(10, { units: TimeUnit.Seconds, unref: true });
42
57
  ```
43
58
 
44
59
  ## Stopwatch
@@ -58,8 +73,10 @@ const elapsed2 = elapsed(TimeUnit.Seconds);
58
73
  ## Until / Eventually
59
74
  ```ts
60
75
  // Wait for a condition to become true
61
- await until(condition, {timeout: 1, units: TimeUnit.Minute});
62
- await eventually(condition, {timeout: 1, units: TimeUnit.Minute});
76
+ await until(condition, { deadline: 10000 });
77
+ await until(condition, { deadline: 10000, interval: 100 });
78
+ await until(condition, { deadline: 10000, interval: 100, units: TimeUnit.Milliseconds });
79
+ await until(condition, { deadline: 10000, interval: 100, units: TimeUnit.Milliseconds, unref: true });
63
80
  ```
64
81
 
65
82
  ## Retry
package/dist/index.js CHANGED
@@ -1,10 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.exponentialBackoffRetryPolicy = exports.simpleRetryPolicy = exports.fixedRetryPolicy = exports.retriable = exports.retryAround = exports.eventually = exports.until = exports.stopwatch = exports.delay = exports.sleep = exports.toMilliseconds = exports.TimeUnit = void 0;
3
+ exports.exponentialBackoffRetryPolicy = exports.simpleRetryPolicy = exports.fixedRetryPolicy = exports.retriable = exports.retryAround = exports.eventually = exports.until = exports.stopwatch = exports.delay = exports.sleep = exports.withTimeout = exports.toMilliseconds = exports.TimeUnit = void 0;
4
4
  var timeunit_1 = require("./lib/timeunit");
5
5
  Object.defineProperty(exports, "TimeUnit", { enumerable: true, get: function () { return timeunit_1.TimeUnit; } });
6
6
  Object.defineProperty(exports, "toMilliseconds", { enumerable: true, get: function () { return timeunit_1.toMilliseconds; } });
7
7
  var utilities_1 = require("./lib/utilities");
8
+ Object.defineProperty(exports, "withTimeout", { enumerable: true, get: function () { return utilities_1.withTimeout; } });
8
9
  Object.defineProperty(exports, "sleep", { enumerable: true, get: function () { return utilities_1.sleep; } });
9
10
  Object.defineProperty(exports, "delay", { enumerable: true, get: function () { return utilities_1.delay; } });
10
11
  Object.defineProperty(exports, "stopwatch", { enumerable: true, get: function () { return utilities_1.stopwatch; } });
@@ -1,17 +1,25 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.eventually = exports.until = exports.stopwatch = exports.delay = exports.sleep = void 0;
3
+ exports.eventually = exports.until = exports.stopwatch = exports.delay = exports.sleep = exports.withTimeout = void 0;
4
4
  const timeunit_1 = require("./timeunit");
5
+ class TimeoutError extends Error {
6
+ constructor(message) {
7
+ super(message || 'Timeout');
8
+ }
9
+ }
5
10
  /**
6
11
  * Zzzz...
7
12
  *
8
- * @param time time to sleep
9
- * @param units the units on time
13
+ * @param time the approximate time to sleep (expect it to be as accurate as setTimeout)
14
+ * @param options timer options minus the time property
10
15
  * @returns a promise that resolves when the specified time has elapsed.
11
16
  */
12
- function sleep(time, units) {
17
+ function sleep(time, options) {
13
18
  return new Promise(resolve => {
14
- setTimeout(resolve, (0, timeunit_1.toMilliseconds)(time, units));
19
+ const timeout = setTimeout(resolve, (0, timeunit_1.toMilliseconds)(time, options === null || options === void 0 ? void 0 : options.units));
20
+ if (options === null || options === void 0 ? void 0 : options.unref) {
21
+ timeout.unref();
22
+ }
15
23
  });
16
24
  }
17
25
  exports.sleep = sleep;
@@ -19,14 +27,17 @@ exports.sleep = sleep;
19
27
  * Delays the execution of the specified action and returns its value.
20
28
  *
21
29
  * @param action a function to execute with delay
22
- * @param time time to sleep
23
- * @param units the units on time
30
+ * @param options timer options
24
31
  * @returns a promise that resolves when the specified time has elapsed.
25
32
  */
26
- function delay(action, time, units) {
33
+ function delay(action, options) {
34
+ const { time, units, unref } = options;
27
35
  const delayMs = (0, timeunit_1.toMilliseconds)(time, units);
28
36
  return new Promise((resolve, reject) => {
29
- setTimeout(() => Promise.resolve(action()).then(resolve, reject), delayMs);
37
+ const timer = setTimeout(() => Promise.resolve(action()).then(resolve, reject), delayMs);
38
+ if (unref) {
39
+ timer.unref();
40
+ }
30
41
  });
31
42
  }
32
43
  exports.delay = delay;
@@ -45,18 +56,18 @@ exports.stopwatch = stopwatch;
45
56
  * Awaits a specified condition to evaluate to true with or without a timeout.
46
57
  *
47
58
  * @param condition the condition to wait for
48
- * @param opts options that control evaluation intervals and timeout
59
+ * @param options poll-options
49
60
  * @returns a promise that resolves when the condition becomes true, or rejects when a set timeout is crossed.
50
61
  */
51
- async function until(condition, opts) {
62
+ async function until(condition, options) {
52
63
  const defaultInterval = 50;
53
- const deadline = opts ? Date.now() + (0, timeunit_1.toMilliseconds)(opts.timeout, opts.units) : Number.MAX_VALUE;
54
- const interval = (opts === null || opts === void 0 ? void 0 : opts.interval) ? (0, timeunit_1.toMilliseconds)(opts.interval, opts.units) : defaultInterval;
64
+ const deadline = (options === null || options === void 0 ? void 0 : options.deadline) ? Date.now() + (0, timeunit_1.toMilliseconds)(options.deadline, options.units) : Number.MAX_VALUE;
65
+ const interval = (options === null || options === void 0 ? void 0 : options.interval) ? (0, timeunit_1.toMilliseconds)(options.interval, options.units) : defaultInterval;
55
66
  return new Promise((resolve, reject) => {
56
67
  const handle = setInterval(() => {
57
68
  if (Date.now() > deadline) {
58
69
  clearInterval(handle);
59
- reject(new Error('Timeout'));
70
+ reject(new TimeoutError());
60
71
  }
61
72
  try {
62
73
  if (condition()) {
@@ -69,6 +80,9 @@ async function until(condition, opts) {
69
80
  reject(e);
70
81
  }
71
82
  }, interval);
83
+ if (options === null || options === void 0 ? void 0 : options.unref) {
84
+ handle.unref();
85
+ }
72
86
  });
73
87
  }
74
88
  exports.until = until;
@@ -77,3 +91,37 @@ exports.until = until;
77
91
  */
78
92
  const eventually = until;
79
93
  exports.eventually = eventually;
94
+ /**
95
+ * Executes an action with a specified timeout. If the action times out, rejects with TimeoutError.
96
+ *
97
+ * @param action an action to execute with timeout
98
+ * @param options timer options
99
+ * @returns the action result
100
+ */
101
+ async function withTimeout(action, options) {
102
+ const promisedAction = new Promise((resolve, reject) => {
103
+ try {
104
+ resolve(action());
105
+ }
106
+ catch (e) {
107
+ reject(e);
108
+ }
109
+ });
110
+ const race = new Promise((resolve, reject) => {
111
+ const timer = setTimeout(() => {
112
+ reject(new TimeoutError());
113
+ }, (0, timeunit_1.toMilliseconds)(options.time, options.units));
114
+ if (options.unref) {
115
+ timer.unref();
116
+ }
117
+ return Promise.resolve(promisedAction).then(r => {
118
+ clearTimeout(timer);
119
+ resolve(r);
120
+ }, err => {
121
+ clearTimeout(timer);
122
+ reject(err);
123
+ });
124
+ });
125
+ return race;
126
+ }
127
+ exports.withTimeout = withTimeout;
@@ -1,3 +1,3 @@
1
1
  export { TimeUnit, toMilliseconds } from './lib/timeunit';
2
- export { sleep, delay, stopwatch, until, eventually } from './lib/utilities';
2
+ export { withTimeout, sleep, delay, stopwatch, until, eventually } from './lib/utilities';
3
3
  export { RetryPolicy, retryAround, retriable, fixedRetryPolicy, simpleRetryPolicy, exponentialBackoffRetryPolicy } from './lib/retry';
@@ -1,21 +1,52 @@
1
1
  import { TimeUnit } from './timeunit';
2
+ declare type TimerOptions = {
3
+ /**
4
+ * The time to set
5
+ */
6
+ readonly time: number;
7
+ /**
8
+ * Optional units for the specified time
9
+ */
10
+ readonly units?: TimeUnit;
11
+ /**
12
+ * Whether to call unref on the timer
13
+ */
14
+ readonly unref?: boolean;
15
+ };
16
+ declare type PollOptions = {
17
+ /**
18
+ * The poll interval to set
19
+ */
20
+ readonly interval?: number;
21
+ /**
22
+ * The overall deadline to set
23
+ */
24
+ readonly deadline?: number;
25
+ /**
26
+ * Time units for specified time properties
27
+ */
28
+ readonly units?: TimeUnit;
29
+ /**
30
+ * Whether to call unref on any intervals/timers
31
+ */
32
+ readonly unref?: boolean;
33
+ };
2
34
  /**
3
35
  * Zzzz...
4
36
  *
5
- * @param time time to sleep
6
- * @param units the units on time
37
+ * @param time the approximate time to sleep (expect it to be as accurate as setTimeout)
38
+ * @param options timer options minus the time property
7
39
  * @returns a promise that resolves when the specified time has elapsed.
8
40
  */
9
- declare function sleep(time: number, units?: TimeUnit): Promise<void>;
41
+ declare function sleep(time: number, options?: Omit<TimerOptions, 'time'>): Promise<void>;
10
42
  /**
11
43
  * Delays the execution of the specified action and returns its value.
12
44
  *
13
45
  * @param action a function to execute with delay
14
- * @param time time to sleep
15
- * @param units the units on time
46
+ * @param options timer options
16
47
  * @returns a promise that resolves when the specified time has elapsed.
17
48
  */
18
- declare function delay<T>(action: () => T | Promise<T>, time: number, units?: TimeUnit): Promise<T>;
49
+ declare function delay<T>(action: () => T | Promise<T>, options: TimerOptions): Promise<T>;
19
50
  /**
20
51
  * Return a function that returns the elapsed time relative to this call.
21
52
  * @returns a function
@@ -25,16 +56,20 @@ declare function stopwatch(): (units?: TimeUnit) => number;
25
56
  * Awaits a specified condition to evaluate to true with or without a timeout.
26
57
  *
27
58
  * @param condition the condition to wait for
28
- * @param opts options that control evaluation intervals and timeout
59
+ * @param options poll-options
29
60
  * @returns a promise that resolves when the condition becomes true, or rejects when a set timeout is crossed.
30
61
  */
31
- declare function until(condition: () => boolean, opts?: {
32
- interval?: number;
33
- timeout: number;
34
- units?: TimeUnit;
35
- }): Promise<void>;
62
+ declare function until(condition: () => boolean, options?: PollOptions): Promise<void>;
36
63
  /**
37
64
  * Alias to `until`
38
65
  */
39
66
  declare const eventually: typeof until;
40
- export { sleep, delay, stopwatch, until, eventually };
67
+ /**
68
+ * Executes an action with a specified timeout. If the action times out, rejects with TimeoutError.
69
+ *
70
+ * @param action an action to execute with timeout
71
+ * @param options timer options
72
+ * @returns the action result
73
+ */
74
+ declare function withTimeout<T>(action: () => T | Promise<T>, options: TimerOptions): Promise<T>;
75
+ export { withTimeout, sleep, delay, stopwatch, until, eventually };
package/index.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export { TimeUnit, toMilliseconds } from './lib/timeunit';
2
- export { sleep, delay, stopwatch, until, eventually } from './lib/utilities';
2
+ export { withTimeout, sleep, delay, stopwatch, until, eventually } from './lib/utilities';
3
3
  export {
4
4
  RetryPolicy,
5
5
  retryAround,
package/lib/utilities.ts CHANGED
@@ -1,15 +1,59 @@
1
1
  import { TimeUnit, toMilliseconds } from './timeunit';
2
2
 
3
+ class TimeoutError extends Error {
4
+ constructor(message?: string) {
5
+ super(message || 'Timeout');
6
+ }
7
+ }
8
+
9
+ type TimerOptions = {
10
+ /**
11
+ * The time to set
12
+ */
13
+ readonly time: number;
14
+ /**
15
+ * Optional units for the specified time
16
+ */
17
+ readonly units?: TimeUnit;
18
+ /**
19
+ * Whether to call unref on the timer
20
+ */
21
+ readonly unref?: boolean;
22
+ };
23
+
24
+ type PollOptions = {
25
+ /**
26
+ * The poll interval to set
27
+ */
28
+ readonly interval?: number;
29
+ /**
30
+ * The overall deadline to set
31
+ */
32
+ readonly deadline?: number;
33
+ /**
34
+ * Time units for specified time properties
35
+ */
36
+ readonly units?: TimeUnit;
37
+ /**
38
+ * Whether to call unref on any intervals/timers
39
+ */
40
+ readonly unref?: boolean;
41
+ };
42
+
3
43
  /**
4
44
  * Zzzz...
5
45
  *
6
- * @param time time to sleep
7
- * @param units the units on time
46
+ * @param time the approximate time to sleep (expect it to be as accurate as setTimeout)
47
+ * @param options timer options minus the time property
8
48
  * @returns a promise that resolves when the specified time has elapsed.
9
49
  */
10
- function sleep(time: number, units?: TimeUnit): Promise<void> {
50
+ function sleep(time: number, options?: Omit<TimerOptions, 'time'>): Promise<void> {
11
51
  return new Promise(resolve => {
12
- setTimeout(resolve, toMilliseconds(time, units));
52
+ const timeout = setTimeout(resolve, toMilliseconds(time, options?.units));
53
+
54
+ if (options?.unref) {
55
+ timeout.unref();
56
+ }
13
57
  });
14
58
  }
15
59
 
@@ -17,14 +61,18 @@ function sleep(time: number, units?: TimeUnit): Promise<void> {
17
61
  * Delays the execution of the specified action and returns its value.
18
62
  *
19
63
  * @param action a function to execute with delay
20
- * @param time time to sleep
21
- * @param units the units on time
64
+ * @param options timer options
22
65
  * @returns a promise that resolves when the specified time has elapsed.
23
66
  */
24
- function delay<T>(action: () => T | Promise<T>, time: number, units?: TimeUnit): Promise<T> {
67
+ function delay<T>(action: () => T | Promise<T>, options: TimerOptions): Promise<T> {
68
+ const { time, units, unref } = options;
25
69
  const delayMs = toMilliseconds(time, units);
26
70
  return new Promise((resolve, reject) => {
27
- setTimeout(() => Promise.resolve(action()).then(resolve, reject), delayMs);
71
+ const timer = setTimeout(() => Promise.resolve(action()).then(resolve, reject), delayMs);
72
+
73
+ if (unref) {
74
+ timer.unref();
75
+ }
28
76
  });
29
77
  }
30
78
 
@@ -44,22 +92,19 @@ function stopwatch(): (units?: TimeUnit) => number {
44
92
  * Awaits a specified condition to evaluate to true with or without a timeout.
45
93
  *
46
94
  * @param condition the condition to wait for
47
- * @param opts options that control evaluation intervals and timeout
95
+ * @param options poll-options
48
96
  * @returns a promise that resolves when the condition becomes true, or rejects when a set timeout is crossed.
49
97
  */
50
- async function until(
51
- condition: () => boolean,
52
- opts?: { interval?: number; timeout: number; units?: TimeUnit }
53
- ): Promise<void> {
98
+ async function until(condition: () => boolean, options?: PollOptions): Promise<void> {
54
99
  const defaultInterval = 50;
55
- const deadline = opts ? Date.now() + toMilliseconds(opts.timeout, opts.units) : Number.MAX_VALUE;
56
- const interval = opts?.interval ? toMilliseconds(opts.interval, opts.units) : defaultInterval;
100
+ const deadline = options?.deadline ? Date.now() + toMilliseconds(options.deadline, options.units) : Number.MAX_VALUE;
101
+ const interval = options?.interval ? toMilliseconds(options.interval, options.units) : defaultInterval;
57
102
 
58
103
  return new Promise<void>((resolve, reject) => {
59
104
  const handle = setInterval(() => {
60
105
  if (Date.now() > deadline) {
61
106
  clearInterval(handle);
62
- reject(new Error('Timeout'));
107
+ reject(new TimeoutError());
63
108
  }
64
109
 
65
110
  try {
@@ -72,6 +117,10 @@ async function until(
72
117
  reject(e);
73
118
  }
74
119
  }, interval);
120
+
121
+ if (options?.unref) {
122
+ handle.unref();
123
+ }
75
124
  });
76
125
  }
77
126
 
@@ -80,4 +129,44 @@ async function until(
80
129
  */
81
130
  const eventually = until;
82
131
 
83
- export { sleep, delay, stopwatch, until, eventually };
132
+ /**
133
+ * Executes an action with a specified timeout. If the action times out, rejects with TimeoutError.
134
+ *
135
+ * @param action an action to execute with timeout
136
+ * @param options timer options
137
+ * @returns the action result
138
+ */
139
+ async function withTimeout<T>(action: () => T | Promise<T>, options: TimerOptions): Promise<T> {
140
+ const promisedAction = new Promise<T>((resolve, reject) => {
141
+ try {
142
+ resolve(action());
143
+ } catch (e) {
144
+ reject(e);
145
+ }
146
+ });
147
+
148
+ const race = new Promise<T>((resolve, reject) => {
149
+ const timer = setTimeout(() => {
150
+ reject(new TimeoutError());
151
+ }, toMilliseconds(options.time, options.units));
152
+
153
+ if (options.unref) {
154
+ timer.unref();
155
+ }
156
+
157
+ return Promise.resolve(promisedAction).then(
158
+ r => {
159
+ clearTimeout(timer);
160
+ resolve(r);
161
+ },
162
+ err => {
163
+ clearTimeout(timer);
164
+ reject(err);
165
+ }
166
+ );
167
+ });
168
+
169
+ return race;
170
+ }
171
+
172
+ export { withTimeout, sleep, delay, stopwatch, until, eventually };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sha1n/about-time",
3
- "version": "0.0.5",
3
+ "version": "0.0.8",
4
4
  "description": "A set of essential time related utilities",
5
5
  "repository": "https://github.com/sha1n/about-time",
6
6
  "author": "Shai Nagar",
@@ -22,38 +22,38 @@
22
22
  ],
23
23
  "scripts": {
24
24
  "clean": "rm -rf ./dist",
25
- "prebuild": "yarn run clean",
26
25
  "build": "tsc",
27
- "test": "DEBUG=error:* jest --coverage",
26
+ "test": "DEBUG='error:*' jest --coverage && run lint",
28
27
  "lint": "eslint --fix --ext .js,.ts .",
29
- "posttest": "npm run lint -s",
30
- "prepublish": "yarn run build"
28
+ "prepublish": "run build"
31
29
  },
32
- "dependencies": {},
33
30
  "devDependencies": {
34
31
  "@types/chance": "^1.1.3",
32
+ "@types/is-ci": "^3.0.0",
35
33
  "@types/jest": "^27.4.0",
36
34
  "@types/node": "^17.0.8",
37
35
  "@typescript-eslint/eslint-plugin": "^5.1.0",
38
36
  "@typescript-eslint/parser": "^5.1.0",
39
37
  "chance": "^1.1.8",
40
- "eslint": "^7.32.0",
38
+ "eslint": "^8.9.0",
41
39
  "eslint-config-prettier": "^8.3.0",
42
40
  "eslint-plugin-import": "^2.25.2",
43
- "eslint-plugin-jest": "^25.7.0",
41
+ "eslint-plugin-jest": "^26.0.0",
44
42
  "eslint-plugin-no-floating-promise": "^1.0.2",
45
43
  "eslint-plugin-node": "^11.1.0",
46
44
  "eslint-plugin-prettier": "^4.0.0",
47
- "eslint-plugin-unused-imports": "^1.1.5",
48
- "jest": "~27.4.7",
45
+ "eslint-plugin-unused-imports": "^2.0.0",
46
+ "is-ci": "^3.0.1",
47
+ "jest": "^27.5.1",
49
48
  "jest-environment-node": "^27.2.0",
50
- "jest-extended": "^1.1.0",
51
- "jest-html-reporters": "^3.0.3",
49
+ "jest-extended": "^2.0.0",
50
+ "jest-html-reporters": "^3.0.5",
52
51
  "jest-mock-extended": "^2.0.4",
53
52
  "jest-summary-reporter": "^0.0.2",
54
53
  "prettier": "^2.4.1",
55
54
  "ts-jest": "^27.1.3",
56
55
  "ts-node": "^10.4.0",
57
56
  "typescript": "^4.5.4"
58
- }
57
+ },
58
+ "packageManager": "yarn@3.2.0"
59
59
  }