@ls-stack/utils 3.28.0 → 3.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -14,7 +14,7 @@
14
14
  type RetryOptions = object;
15
15
  ```
16
16
 
17
- Defined in: [packages/utils/src/retryOnError.ts:6](https://github.com/lucasols/utils/blob/main/packages/utils/src/retryOnError.ts#L6)
17
+ Defined in: [packages/utils/src/retryOnError.ts:7](https://github.com/lucasols/utils/blob/main/packages/utils/src/retryOnError.ts#L7)
18
18
 
19
19
  Configuration options for retryOnError function.
20
20
 
@@ -26,7 +26,7 @@ Configuration options for retryOnError function.
26
26
  optional debugId: string;
27
27
  ```
28
28
 
29
- Defined in: [packages/utils/src/retryOnError.ts:15](https://github.com/lucasols/utils/blob/main/packages/utils/src/retryOnError.ts#L15)
29
+ Defined in: [packages/utils/src/retryOnError.ts:16](https://github.com/lucasols/utils/blob/main/packages/utils/src/retryOnError.ts#L16)
30
30
 
31
31
  Optional ID for debug logging
32
32
 
@@ -36,17 +36,27 @@ Optional ID for debug logging
36
36
  optional delayBetweenRetriesMs: number | (retry) => number;
37
37
  ```
38
38
 
39
- Defined in: [packages/utils/src/retryOnError.ts:8](https://github.com/lucasols/utils/blob/main/packages/utils/src/retryOnError.ts#L8)
39
+ Defined in: [packages/utils/src/retryOnError.ts:9](https://github.com/lucasols/utils/blob/main/packages/utils/src/retryOnError.ts#L9)
40
40
 
41
41
  Delay between retries in milliseconds or function returning delay
42
42
 
43
+ ##### disableRetries?
44
+
45
+ ```ts
46
+ optional disableRetries: boolean;
47
+ ```
48
+
49
+ Defined in: [packages/utils/src/retryOnError.ts:18](https://github.com/lucasols/utils/blob/main/packages/utils/src/retryOnError.ts#L18)
50
+
51
+ Disable retries
52
+
43
53
  ##### retryCondition()?
44
54
 
45
55
  ```ts
46
56
  optional retryCondition: (error, lastAttempt) => boolean;
47
57
  ```
48
58
 
49
- Defined in: [packages/utils/src/retryOnError.ts:10](https://github.com/lucasols/utils/blob/main/packages/utils/src/retryOnError.ts#L10)
59
+ Defined in: [packages/utils/src/retryOnError.ts:11](https://github.com/lucasols/utils/blob/main/packages/utils/src/retryOnError.ts#L11)
50
60
 
51
61
  Function to determine if retry should happen, receives error and duration of last attempt
52
62
 
@@ -54,7 +64,7 @@ Function to determine if retry should happen, receives error and duration of las
54
64
 
55
65
  ###### error
56
66
 
57
- `unknown`
67
+ `Error`
58
68
 
59
69
  ###### lastAttempt
60
70
 
@@ -23,7 +23,7 @@ function retryOnError<T>(
23
23
  originalMaxRetries): Promise<T>;
24
24
  ```
25
25
 
26
- Defined in: [packages/utils/src/retryOnError.ts:38](https://github.com/lucasols/utils/blob/main/packages/utils/src/retryOnError.ts#L38)
26
+ Defined in: [packages/utils/src/retryOnError.ts:41](https://github.com/lucasols/utils/blob/main/packages/utils/src/retryOnError.ts#L41)
27
27
 
28
28
  Retries a function on error with configurable retry logic.
29
29
 
@@ -57,10 +57,14 @@ Configuration options
57
57
 
58
58
  `number` = `0`
59
59
 
60
+ internal use only
61
+
60
62
  ##### originalMaxRetries
61
63
 
62
64
  `number` = `maxRetries`
63
65
 
66
+ internal use only
67
+
64
68
  #### Returns
65
69
 
66
70
  `Promise`\<`T`\>
@@ -79,3 +83,82 @@ await retryOnError(
79
83
  { delayBetweenRetriesMs: 1000 }
80
84
  );
81
85
  ```
86
+
87
+ ***
88
+
89
+ ### retryResultOnError()
90
+
91
+ ```ts
92
+ function retryResultOnError<T, E>(
93
+ fn,
94
+ maxRetries,
95
+ options,
96
+ __retry,
97
+ __originalMaxRetries): Promise<Result<T, E>>;
98
+ ```
99
+
100
+ Defined in: [packages/utils/src/retryOnError.ts:116](https://github.com/lucasols/utils/blob/main/packages/utils/src/retryOnError.ts#L116)
101
+
102
+ Retries a result function on error with configurable retry logic.
103
+
104
+ #### Type Parameters
105
+
106
+ ##### T
107
+
108
+ `T`
109
+
110
+ ##### E
111
+
112
+ `E` *extends* `ResultValidErrors`
113
+
114
+ #### Parameters
115
+
116
+ ##### fn
117
+
118
+ (`ctx`) => `Promise`\<`Result`\<`T`, `E`\>\>
119
+
120
+ Function to retry that receives context with retry count
121
+
122
+ ##### maxRetries
123
+
124
+ `number`
125
+
126
+ Maximum number of retries
127
+
128
+ ##### options
129
+
130
+ Configuration options
131
+
132
+ ###### debugId?
133
+
134
+ `string`
135
+
136
+ ###### delayBetweenRetriesMs?
137
+
138
+ `number` \| (`retry`) => `number`
139
+
140
+ ###### disableRetries?
141
+
142
+ `boolean`
143
+
144
+ ###### retryCondition?
145
+
146
+ (`error`, `lastAttempt`) => `boolean`
147
+
148
+ ##### \_\_retry
149
+
150
+ `number` = `0`
151
+
152
+ internal use only
153
+
154
+ ##### \_\_originalMaxRetries
155
+
156
+ `number` = `maxRetries`
157
+
158
+ internal use only
159
+
160
+ #### Returns
161
+
162
+ `Promise`\<`Result`\<`T`, `E`\>\>
163
+
164
+ Promise resolving to the function result or rejecting with the final error
@@ -20,9 +20,11 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/retryOnError.ts
21
21
  var retryOnError_exports = {};
22
22
  __export(retryOnError_exports, {
23
- retryOnError: () => retryOnError
23
+ retryOnError: () => retryOnError,
24
+ retryResultOnError: () => retryResultOnError
24
25
  });
25
26
  module.exports = __toCommonJS(retryOnError_exports);
27
+ var import_t_result = require("t-result");
26
28
 
27
29
  // src/sleep.ts
28
30
  function sleep(ms) {
@@ -31,7 +33,7 @@ function sleep(ms) {
31
33
 
32
34
  // src/retryOnError.ts
33
35
  async function retryOnError(fn, maxRetries, options = {}, retry = 0, originalMaxRetries = maxRetries) {
34
- const { delayBetweenRetriesMs, retryCondition } = options;
36
+ const { delayBetweenRetriesMs, retryCondition, disableRetries } = options;
35
37
  if (options.debugId) {
36
38
  if (retry > 0) {
37
39
  console.info(
@@ -43,9 +45,12 @@ async function retryOnError(fn, maxRetries, options = {}, retry = 0, originalMax
43
45
  try {
44
46
  return await fn({ retry });
45
47
  } catch (error) {
46
- if (maxRetries > 0) {
48
+ if (maxRetries > 0 && !disableRetries) {
47
49
  const errorDuration = Date.now() - startTime;
48
- const shouldRetry = retryCondition ? retryCondition(error, { duration: errorDuration, retry }) : true;
50
+ const shouldRetry = retryCondition ? retryCondition((0, import_t_result.unknownToError)(error), {
51
+ duration: errorDuration,
52
+ retry
53
+ }) : true;
49
54
  if (!shouldRetry) {
50
55
  throw error;
51
56
  }
@@ -66,7 +71,47 @@ async function retryOnError(fn, maxRetries, options = {}, retry = 0, originalMax
66
71
  }
67
72
  }
68
73
  }
74
+ async function retryResultOnError(fn, maxRetries, options = {}, __retry = 0, __originalMaxRetries = maxRetries) {
75
+ const { delayBetweenRetriesMs, retryCondition } = options;
76
+ if (options.debugId) {
77
+ if (__retry > 0) {
78
+ console.info(
79
+ `Retrying ${options.debugId} (retry ${__retry}/${__originalMaxRetries}) after error`
80
+ );
81
+ }
82
+ }
83
+ const startTime = Date.now();
84
+ const result = await fn({ retry: __retry });
85
+ if (result.ok) {
86
+ return result;
87
+ }
88
+ if (maxRetries > 0 && !options.disableRetries) {
89
+ const errorDuration = Date.now() - startTime;
90
+ const shouldRetry = retryCondition ? retryCondition(result.error, {
91
+ duration: errorDuration,
92
+ retry: __retry
93
+ }) : true;
94
+ if (!shouldRetry) {
95
+ return result;
96
+ }
97
+ if (delayBetweenRetriesMs) {
98
+ await sleep(
99
+ typeof delayBetweenRetriesMs === "function" ? delayBetweenRetriesMs(__retry) : delayBetweenRetriesMs
100
+ );
101
+ }
102
+ return retryResultOnError(
103
+ fn,
104
+ maxRetries - 1,
105
+ options,
106
+ __retry + 1,
107
+ __originalMaxRetries
108
+ );
109
+ } else {
110
+ return result;
111
+ }
112
+ }
69
113
  // Annotate the CommonJS export names for ESM import in node:
70
114
  0 && (module.exports = {
71
- retryOnError
115
+ retryOnError,
116
+ retryResultOnError
72
117
  });
@@ -1,3 +1,5 @@
1
+ import { ResultValidErrors, Result } from 't-result';
2
+
1
3
  /**
2
4
  * Configuration options for retryOnError function.
3
5
  */
@@ -5,12 +7,14 @@ type RetryOptions = {
5
7
  /** Delay between retries in milliseconds or function returning delay */
6
8
  delayBetweenRetriesMs?: number | ((retry: number) => number);
7
9
  /** Function to determine if retry should happen, receives error and duration of last attempt */
8
- retryCondition?: (error: unknown, lastAttempt: {
10
+ retryCondition?: (error: Error, lastAttempt: {
9
11
  duration: number;
10
12
  retry: number;
11
13
  }) => boolean;
12
14
  /** Optional ID for debug logging */
13
15
  debugId?: string;
16
+ /** Disable retries */
17
+ disableRetries?: boolean;
14
18
  };
15
19
  /**
16
20
  * Retries a function on error with configurable retry logic.
@@ -18,8 +22,8 @@ type RetryOptions = {
18
22
  * @param fn - Function to retry that receives context with retry count
19
23
  * @param maxRetries - Maximum number of retries
20
24
  * @param options - Configuration options
21
- * @param retry
22
- * @param originalMaxRetries
25
+ * @param retry - internal use only
26
+ * @param originalMaxRetries - internal use only
23
27
  * @returns Promise resolving to the function result or rejecting with the final error
24
28
  *
25
29
  * @example
@@ -36,5 +40,31 @@ declare function retryOnError<T>(fn: (ctx: {
36
40
  /** Current retry count, (0 for first attempt) */
37
41
  retry: number;
38
42
  }) => Promise<T>, maxRetries: number, options?: RetryOptions, retry?: number, originalMaxRetries?: number): Promise<T>;
43
+ /**
44
+ * Retries a result function on error with configurable retry logic.
45
+ *
46
+ * @param fn - Function to retry that receives context with retry count
47
+ * @param maxRetries - Maximum number of retries
48
+ * @param options - Configuration options
49
+ * @param options.delayBetweenRetriesMs
50
+ * @param options.retryCondition
51
+ * @param options.debugId
52
+ * @param options.disableRetries
53
+ * @param __retry - internal use only
54
+ * @param __originalMaxRetries - internal use only
55
+ * @returns Promise resolving to the function result or rejecting with the final error
56
+ */
57
+ declare function retryResultOnError<T, E extends ResultValidErrors>(fn: (ctx: {
58
+ /** Current retry count, (0 for first attempt) */
59
+ retry: number;
60
+ }) => Promise<Result<T, E>>, maxRetries: number, options?: {
61
+ delayBetweenRetriesMs?: number | ((retry: number) => number);
62
+ retryCondition?: (error: E, lastAttempt: {
63
+ duration: number;
64
+ retry: number;
65
+ }) => boolean;
66
+ debugId?: string;
67
+ disableRetries?: boolean;
68
+ }, __retry?: number, __originalMaxRetries?: number): Promise<Result<T, E>>;
39
69
 
40
- export { retryOnError };
70
+ export { retryOnError, retryResultOnError };
@@ -1,3 +1,5 @@
1
+ import { ResultValidErrors, Result } from 't-result';
2
+
1
3
  /**
2
4
  * Configuration options for retryOnError function.
3
5
  */
@@ -5,12 +7,14 @@ type RetryOptions = {
5
7
  /** Delay between retries in milliseconds or function returning delay */
6
8
  delayBetweenRetriesMs?: number | ((retry: number) => number);
7
9
  /** Function to determine if retry should happen, receives error and duration of last attempt */
8
- retryCondition?: (error: unknown, lastAttempt: {
10
+ retryCondition?: (error: Error, lastAttempt: {
9
11
  duration: number;
10
12
  retry: number;
11
13
  }) => boolean;
12
14
  /** Optional ID for debug logging */
13
15
  debugId?: string;
16
+ /** Disable retries */
17
+ disableRetries?: boolean;
14
18
  };
15
19
  /**
16
20
  * Retries a function on error with configurable retry logic.
@@ -18,8 +22,8 @@ type RetryOptions = {
18
22
  * @param fn - Function to retry that receives context with retry count
19
23
  * @param maxRetries - Maximum number of retries
20
24
  * @param options - Configuration options
21
- * @param retry
22
- * @param originalMaxRetries
25
+ * @param retry - internal use only
26
+ * @param originalMaxRetries - internal use only
23
27
  * @returns Promise resolving to the function result or rejecting with the final error
24
28
  *
25
29
  * @example
@@ -36,5 +40,31 @@ declare function retryOnError<T>(fn: (ctx: {
36
40
  /** Current retry count, (0 for first attempt) */
37
41
  retry: number;
38
42
  }) => Promise<T>, maxRetries: number, options?: RetryOptions, retry?: number, originalMaxRetries?: number): Promise<T>;
43
+ /**
44
+ * Retries a result function on error with configurable retry logic.
45
+ *
46
+ * @param fn - Function to retry that receives context with retry count
47
+ * @param maxRetries - Maximum number of retries
48
+ * @param options - Configuration options
49
+ * @param options.delayBetweenRetriesMs
50
+ * @param options.retryCondition
51
+ * @param options.debugId
52
+ * @param options.disableRetries
53
+ * @param __retry - internal use only
54
+ * @param __originalMaxRetries - internal use only
55
+ * @returns Promise resolving to the function result or rejecting with the final error
56
+ */
57
+ declare function retryResultOnError<T, E extends ResultValidErrors>(fn: (ctx: {
58
+ /** Current retry count, (0 for first attempt) */
59
+ retry: number;
60
+ }) => Promise<Result<T, E>>, maxRetries: number, options?: {
61
+ delayBetweenRetriesMs?: number | ((retry: number) => number);
62
+ retryCondition?: (error: E, lastAttempt: {
63
+ duration: number;
64
+ retry: number;
65
+ }) => boolean;
66
+ debugId?: string;
67
+ disableRetries?: boolean;
68
+ }, __retry?: number, __originalMaxRetries?: number): Promise<Result<T, E>>;
39
69
 
40
- export { retryOnError };
70
+ export { retryOnError, retryResultOnError };
@@ -3,8 +3,9 @@ import {
3
3
  } from "./chunk-5DZT3Z5Z.js";
4
4
 
5
5
  // src/retryOnError.ts
6
+ import { unknownToError } from "t-result";
6
7
  async function retryOnError(fn, maxRetries, options = {}, retry = 0, originalMaxRetries = maxRetries) {
7
- const { delayBetweenRetriesMs, retryCondition } = options;
8
+ const { delayBetweenRetriesMs, retryCondition, disableRetries } = options;
8
9
  if (options.debugId) {
9
10
  if (retry > 0) {
10
11
  console.info(
@@ -16,9 +17,12 @@ async function retryOnError(fn, maxRetries, options = {}, retry = 0, originalMax
16
17
  try {
17
18
  return await fn({ retry });
18
19
  } catch (error) {
19
- if (maxRetries > 0) {
20
+ if (maxRetries > 0 && !disableRetries) {
20
21
  const errorDuration = Date.now() - startTime;
21
- const shouldRetry = retryCondition ? retryCondition(error, { duration: errorDuration, retry }) : true;
22
+ const shouldRetry = retryCondition ? retryCondition(unknownToError(error), {
23
+ duration: errorDuration,
24
+ retry
25
+ }) : true;
22
26
  if (!shouldRetry) {
23
27
  throw error;
24
28
  }
@@ -39,6 +43,46 @@ async function retryOnError(fn, maxRetries, options = {}, retry = 0, originalMax
39
43
  }
40
44
  }
41
45
  }
46
+ async function retryResultOnError(fn, maxRetries, options = {}, __retry = 0, __originalMaxRetries = maxRetries) {
47
+ const { delayBetweenRetriesMs, retryCondition } = options;
48
+ if (options.debugId) {
49
+ if (__retry > 0) {
50
+ console.info(
51
+ `Retrying ${options.debugId} (retry ${__retry}/${__originalMaxRetries}) after error`
52
+ );
53
+ }
54
+ }
55
+ const startTime = Date.now();
56
+ const result = await fn({ retry: __retry });
57
+ if (result.ok) {
58
+ return result;
59
+ }
60
+ if (maxRetries > 0 && !options.disableRetries) {
61
+ const errorDuration = Date.now() - startTime;
62
+ const shouldRetry = retryCondition ? retryCondition(result.error, {
63
+ duration: errorDuration,
64
+ retry: __retry
65
+ }) : true;
66
+ if (!shouldRetry) {
67
+ return result;
68
+ }
69
+ if (delayBetweenRetriesMs) {
70
+ await sleep(
71
+ typeof delayBetweenRetriesMs === "function" ? delayBetweenRetriesMs(__retry) : delayBetweenRetriesMs
72
+ );
73
+ }
74
+ return retryResultOnError(
75
+ fn,
76
+ maxRetries - 1,
77
+ options,
78
+ __retry + 1,
79
+ __originalMaxRetries
80
+ );
81
+ } else {
82
+ return result;
83
+ }
84
+ }
42
85
  export {
43
- retryOnError
86
+ retryOnError,
87
+ retryResultOnError
44
88
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ls-stack/utils",
3
3
  "description": "Universal TypeScript utilities for browser and Node.js",
4
- "version": "3.28.0",
4
+ "version": "3.29.0",
5
5
  "license": "MIT",
6
6
  "files": [
7
7
  "lib",