@ls-stack/utils 3.29.0 → 3.30.1

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.
@@ -47,6 +47,8 @@
47
47
  - [timers](timers.md)
48
48
  - [tsResult](tsResult/README.md)
49
49
  - [typeGuards](typeGuards.md)
50
+ - [typeUtils](typeUtils/README.md)
51
+ - [typeUtils.typesTest](typeUtils.typesTest.md)
50
52
  - [typingFnUtils](typingFnUtils/README.md)
51
53
  - [typingTestUtils](typingTestUtils.md)
52
54
  - [typingUtils](typingUtils.md)
package/docs/modules.md CHANGED
@@ -47,6 +47,8 @@
47
47
  - [timers](timers.md)
48
48
  - [tsResult](tsResult/README.md)
49
49
  - [typeGuards](typeGuards.md)
50
+ - [typeUtils](typeUtils/README.md)
51
+ - [typeUtils.typesTest](typeUtils.typesTest.md)
50
52
  - [typingFnUtils](typingFnUtils/README.md)
51
53
  - [typingTestUtils](typingTestUtils.md)
52
54
  - [typingUtils](typingUtils.md)
@@ -50,6 +50,36 @@ Defined in: [packages/utils/src/retryOnError.ts:18](https://github.com/lucasols/
50
50
 
51
51
  Disable retries
52
52
 
53
+ ##### onRetry()?
54
+
55
+ ```ts
56
+ optional onRetry: (error, lastAttempt) => void;
57
+ ```
58
+
59
+ Defined in: [packages/utils/src/retryOnError.ts:20](https://github.com/lucasols/utils/blob/main/packages/utils/src/retryOnError.ts#L20)
60
+
61
+ Function to call when retry happens
62
+
63
+ ###### Parameters
64
+
65
+ ###### error
66
+
67
+ `Error`
68
+
69
+ ###### lastAttempt
70
+
71
+ ###### duration
72
+
73
+ `number`
74
+
75
+ ###### retry
76
+
77
+ `number`
78
+
79
+ ###### Returns
80
+
81
+ `void`
82
+
53
83
  ##### retryCondition()?
54
84
 
55
85
  ```ts
@@ -23,7 +23,7 @@ function retryOnError<T>(
23
23
  originalMaxRetries): Promise<T>;
24
24
  ```
25
25
 
26
- Defined in: [packages/utils/src/retryOnError.ts:41](https://github.com/lucasols/utils/blob/main/packages/utils/src/retryOnError.ts#L41)
26
+ Defined in: [packages/utils/src/retryOnError.ts:46](https://github.com/lucasols/utils/blob/main/packages/utils/src/retryOnError.ts#L46)
27
27
 
28
28
  Retries a function on error with configurable retry logic.
29
29
 
@@ -97,7 +97,7 @@ function retryResultOnError<T, E>(
97
97
  __originalMaxRetries): Promise<Result<T, E>>;
98
98
  ```
99
99
 
100
- Defined in: [packages/utils/src/retryOnError.ts:116](https://github.com/lucasols/utils/blob/main/packages/utils/src/retryOnError.ts#L116)
100
+ Defined in: [packages/utils/src/retryOnError.ts:132](https://github.com/lucasols/utils/blob/main/packages/utils/src/retryOnError.ts#L132)
101
101
 
102
102
  Retries a result function on error with configurable retry logic.
103
103
 
@@ -141,6 +141,10 @@ Configuration options
141
141
 
142
142
  `boolean`
143
143
 
144
+ ###### onRetry?
145
+
146
+ (`error`, `lastAttempt`) => `void`
147
+
144
148
  ###### retryCondition?
145
149
 
146
150
  (`error`, `lastAttempt`) => `boolean`
@@ -0,0 +1,99 @@
1
+ [**@ls-stack/utils**](../README.md)
2
+
3
+ ***
4
+
5
+ [@ls-stack/utils](../modules.md) / [typeUtils](README.md) / \<internal\>
6
+
7
+ # \<internal\>
8
+
9
+ ## Type Aliases
10
+
11
+ ### BuildArrayPath\<BasePath\>
12
+
13
+ ```ts
14
+ type BuildArrayPath<BasePath> = BasePath extends "$" ? "[*]" : `${BasePath}[*]`;
15
+ ```
16
+
17
+ Defined in: [packages/utils/src/typeUtils.ts:62](https://github.com/lucasols/utils/blob/main/packages/utils/src/typeUtils.ts#L62)
18
+
19
+ #### Type Parameters
20
+
21
+ ##### BasePath
22
+
23
+ `BasePath` *extends* `string`
24
+
25
+ ***
26
+
27
+ ### BuildPath\<BasePath, Key\>
28
+
29
+ ```ts
30
+ type BuildPath<BasePath, Key> = BasePath extends "$" ? Key extends string | number ? `${Key}` : never : Key extends string | number ? `${BasePath}.${Key}` : never;
31
+ ```
32
+
33
+ Defined in: [packages/utils/src/typeUtils.ts:54](https://github.com/lucasols/utils/blob/main/packages/utils/src/typeUtils.ts#L54)
34
+
35
+ #### Type Parameters
36
+
37
+ ##### BasePath
38
+
39
+ `BasePath` *extends* `string`
40
+
41
+ ##### Key
42
+
43
+ `Key` *extends* `PropertyKey`
44
+
45
+ ***
46
+
47
+ ### DeepReplaceValueImpl\<T, ReplaceType, NewType, SkipPaths, SkipType, Path\>
48
+
49
+ ```ts
50
+ type DeepReplaceValueImpl<T, ReplaceType, NewType, SkipPaths, SkipType, Path> = SkipPaths extends string ? PathMatches<Path, SkipPaths> extends true ? T : T extends ReplaceType ? T extends SkipType ? T : NewType : T extends readonly infer U[] ? DeepReplaceValueImpl<U, ReplaceType, NewType, SkipPaths, SkipType, BuildArrayPath<Path>>[] : T extends SkipType ? T : T extends Record<string, any> ? { [K in keyof T]: DeepReplaceValueImpl<T[K], ReplaceType, NewType, SkipPaths, SkipType, BuildPath<Path, K>> } : T : T extends ReplaceType ? T extends SkipType ? T : NewType : T extends readonly infer U[] ? DeepReplaceValueImpl<U, ReplaceType, NewType, SkipPaths, SkipType, BuildArrayPath<Path>>[] : T extends SkipType ? T : T extends Record<string, any> ? { [K in keyof T]: DeepReplaceValueImpl<T[K], ReplaceType, NewType, SkipPaths, SkipType, BuildPath<Path, K>> } : T;
51
+ ```
52
+
53
+ Defined in: [packages/utils/src/typeUtils.ts:65](https://github.com/lucasols/utils/blob/main/packages/utils/src/typeUtils.ts#L65)
54
+
55
+ #### Type Parameters
56
+
57
+ ##### T
58
+
59
+ `T`
60
+
61
+ ##### ReplaceType
62
+
63
+ `ReplaceType`
64
+
65
+ ##### NewType
66
+
67
+ `NewType`
68
+
69
+ ##### SkipPaths
70
+
71
+ `SkipPaths` *extends* `string` \| `undefined`
72
+
73
+ ##### SkipType
74
+
75
+ `SkipType`
76
+
77
+ ##### Path
78
+
79
+ `Path` *extends* `string` = `"$"`
80
+
81
+ ***
82
+
83
+ ### PathMatches\<CurrentPath, SkipPaths\>
84
+
85
+ ```ts
86
+ type PathMatches<CurrentPath, SkipPaths> = true extends SkipPaths extends any ? CurrentPath extends SkipPaths ? true : SkipPaths extends `${infer Prefix}[*]${infer Suffix}` ? CurrentPath extends `${Prefix}[${string}]${Suffix}` ? true : false : false : false ? true : false;
87
+ ```
88
+
89
+ Defined in: [packages/utils/src/typeUtils.ts:40](https://github.com/lucasols/utils/blob/main/packages/utils/src/typeUtils.ts#L40)
90
+
91
+ #### Type Parameters
92
+
93
+ ##### CurrentPath
94
+
95
+ `CurrentPath` *extends* `string`
96
+
97
+ ##### SkipPaths
98
+
99
+ `SkipPaths` *extends* `string`
@@ -0,0 +1,177 @@
1
+ [**@ls-stack/utils**](../README.md)
2
+
3
+ ***
4
+
5
+ [@ls-stack/utils](../modules.md) / typeUtils
6
+
7
+ # typeUtils
8
+
9
+ ## Modules
10
+
11
+ - [\<internal\>](-internal-.md)
12
+
13
+ ## Type Aliases
14
+
15
+ ### DeepPrettify\<T\>
16
+
17
+ ```ts
18
+ type DeepPrettify<T> = { [K in keyof T]: T[K] extends Record<string, unknown> ? DeepPrettify<T[K]> : T[K] } & object;
19
+ ```
20
+
21
+ Defined in: [packages/utils/src/typeUtils.ts:25](https://github.com/lucasols/utils/blob/main/packages/utils/src/typeUtils.ts#L25)
22
+
23
+ #### Type Parameters
24
+
25
+ ##### T
26
+
27
+ `T`
28
+
29
+ ***
30
+
31
+ ### DeepReplaceValue\<T, ReplaceType, NewType, SkipPaths, SkipTypes\>
32
+
33
+ ```ts
34
+ type DeepReplaceValue<T, ReplaceType, NewType, SkipPaths, SkipTypes> = DeepReplaceValueImpl<T, ReplaceType, NewType, SkipPaths, SkipTypes>;
35
+ ```
36
+
37
+ Defined in: [packages/utils/src/typeUtils.ts:141](https://github.com/lucasols/utils/blob/main/packages/utils/src/typeUtils.ts#L141)
38
+
39
+ Replaces all values that extends `ReplaceType` with `NewType` in a deeply nested object or array.
40
+
41
+ #### Type Parameters
42
+
43
+ ##### T
44
+
45
+ `T`
46
+
47
+ The object or array to replace values in.
48
+
49
+ ##### ReplaceType
50
+
51
+ `ReplaceType`
52
+
53
+ The type to replace.
54
+
55
+ ##### NewType
56
+
57
+ `NewType`
58
+
59
+ The new type to replace with.
60
+
61
+ ##### SkipPaths
62
+
63
+ `SkipPaths` *extends* `string` \| `undefined` = `undefined`
64
+
65
+ The paths to skip in transverse. e.g. 'a.b.c' | 'array[*].b'
66
+
67
+ ##### SkipTypes
68
+
69
+ `SkipTypes` = [`DefaultSkipTransverseDeepReplace`](#defaultskiptransversedeepreplace)
70
+
71
+ The types to skip in transverse and replace.
72
+
73
+ ***
74
+
75
+ ### DefaultSkipTransverseDeepReplace
76
+
77
+ ```ts
78
+ type DefaultSkipTransverseDeepReplace =
79
+ | Date
80
+ | RegExp
81
+ | (...args) => any
82
+ | Error
83
+ | Set<any>
84
+ | Map<any, any>
85
+ | WeakSet<any>
86
+ | WeakMap<any, any>;
87
+ ```
88
+
89
+ Defined in: [packages/utils/src/typeUtils.ts:30](https://github.com/lucasols/utils/blob/main/packages/utils/src/typeUtils.ts#L30)
90
+
91
+ ***
92
+
93
+ ### IsAny\<T\>
94
+
95
+ ```ts
96
+ type IsAny<T> = unknown extends T ? [keyof T] extends [never] ? false : true : false;
97
+ ```
98
+
99
+ Defined in: [packages/utils/src/typeUtils.ts:14](https://github.com/lucasols/utils/blob/main/packages/utils/src/typeUtils.ts#L14)
100
+
101
+ #### Type Parameters
102
+
103
+ ##### T
104
+
105
+ `T`
106
+
107
+ ***
108
+
109
+ ### NonPartial\<T\>
110
+
111
+ ```ts
112
+ type NonPartial<T> = { [K in keyof Required<T>]: T[K] };
113
+ ```
114
+
115
+ Defined in: [packages/utils/src/typeUtils.ts:5](https://github.com/lucasols/utils/blob/main/packages/utils/src/typeUtils.ts#L5)
116
+
117
+ #### Type Parameters
118
+
119
+ ##### T
120
+
121
+ `T`
122
+
123
+ ***
124
+
125
+ ### ObjKeysWithValuesOfType\<Obj, ValueType\>
126
+
127
+ ```ts
128
+ type ObjKeysWithValuesOfType<Obj, ValueType> = { [K in keyof Obj]: Obj[K] extends ValueType ? K : never }[keyof Obj];
129
+ ```
130
+
131
+ Defined in: [packages/utils/src/typeUtils.ts:7](https://github.com/lucasols/utils/blob/main/packages/utils/src/typeUtils.ts#L7)
132
+
133
+ #### Type Parameters
134
+
135
+ ##### Obj
136
+
137
+ `Obj` *extends* `Record`\<`PropertyKey`, `unknown`\>
138
+
139
+ ##### ValueType
140
+
141
+ `ValueType`
142
+
143
+ ***
144
+
145
+ ### PartialRecord\<K, T\>
146
+
147
+ ```ts
148
+ type PartialRecord<K, T> = { [P in K]?: T };
149
+ ```
150
+
151
+ Defined in: [packages/utils/src/typeUtils.ts:1](https://github.com/lucasols/utils/blob/main/packages/utils/src/typeUtils.ts#L1)
152
+
153
+ #### Type Parameters
154
+
155
+ ##### K
156
+
157
+ `K` *extends* keyof `any`
158
+
159
+ ##### T
160
+
161
+ `T`
162
+
163
+ ***
164
+
165
+ ### Prettify\<T\>
166
+
167
+ ```ts
168
+ type Prettify<T> = { [P in keyof T]: T[P] } & object;
169
+ ```
170
+
171
+ Defined in: [packages/utils/src/typeUtils.ts:21](https://github.com/lucasols/utils/blob/main/packages/utils/src/typeUtils.ts#L21)
172
+
173
+ #### Type Parameters
174
+
175
+ ##### T
176
+
177
+ `T` *extends* `Record`\<`string`, `unknown`\>
@@ -0,0 +1,7 @@
1
+ [**@ls-stack/utils**](README.md)
2
+
3
+ ***
4
+
5
+ [@ls-stack/utils](modules.md) / typeUtils.typesTest
6
+
7
+ # typeUtils.typesTest
@@ -8,13 +8,13 @@
8
8
 
9
9
  ## Type Aliases
10
10
 
11
- ### DeepPrettify\<T\>
11
+ ### ~~DeepPrettify\<T\>~~
12
12
 
13
13
  ```ts
14
14
  type DeepPrettify<T> = { [K in keyof T]: T[K] extends Record<string, unknown> ? DeepPrettify<T[K]> : T[K] } & object;
15
15
  ```
16
16
 
17
- Defined in: [packages/utils/src/typingUtils.ts:25](https://github.com/lucasols/utils/blob/main/packages/utils/src/typingUtils.ts#L25)
17
+ Defined in: [packages/utils/src/typingUtils.ts:31](https://github.com/lucasols/utils/blob/main/packages/utils/src/typingUtils.ts#L31)
18
18
 
19
19
  #### Type Parameters
20
20
 
@@ -22,15 +22,19 @@ Defined in: [packages/utils/src/typingUtils.ts:25](https://github.com/lucasols/u
22
22
 
23
23
  `T`
24
24
 
25
+ #### Deprecated
26
+
27
+ Use `DeepPrettify` from `@ls-stack/utils/typeUtils` instead
28
+
25
29
  ***
26
30
 
27
- ### IsAny\<T\>
31
+ ### ~~IsAny\<T\>~~
28
32
 
29
33
  ```ts
30
34
  type IsAny<T> = unknown extends T ? [keyof T] extends [never] ? false : true : false;
31
35
  ```
32
36
 
33
- Defined in: [packages/utils/src/typingUtils.ts:14](https://github.com/lucasols/utils/blob/main/packages/utils/src/typingUtils.ts#L14)
37
+ Defined in: [packages/utils/src/typingUtils.ts:18](https://github.com/lucasols/utils/blob/main/packages/utils/src/typingUtils.ts#L18)
34
38
 
35
39
  #### Type Parameters
36
40
 
@@ -38,15 +42,19 @@ Defined in: [packages/utils/src/typingUtils.ts:14](https://github.com/lucasols/u
38
42
 
39
43
  `T`
40
44
 
45
+ #### Deprecated
46
+
47
+ Use `IsAny` from `@ls-stack/utils/typeUtils` instead
48
+
41
49
  ***
42
50
 
43
- ### NonPartial\<T\>
51
+ ### ~~NonPartial\<T\>~~
44
52
 
45
53
  ```ts
46
54
  type NonPartial<T> = { [K in keyof Required<T>]: T[K] };
47
55
  ```
48
56
 
49
- Defined in: [packages/utils/src/typingUtils.ts:5](https://github.com/lucasols/utils/blob/main/packages/utils/src/typingUtils.ts#L5)
57
+ Defined in: [packages/utils/src/typingUtils.ts:7](https://github.com/lucasols/utils/blob/main/packages/utils/src/typingUtils.ts#L7)
50
58
 
51
59
  #### Type Parameters
52
60
 
@@ -54,15 +62,19 @@ Defined in: [packages/utils/src/typingUtils.ts:5](https://github.com/lucasols/ut
54
62
 
55
63
  `T`
56
64
 
65
+ #### Deprecated
66
+
67
+ Use `NonPartial` from `@ls-stack/utils/typeUtils` instead
68
+
57
69
  ***
58
70
 
59
- ### ObjKeysWithValuesOfType\<Obj, ValueType\>
71
+ ### ~~ObjKeysWithValuesOfType\<Obj, ValueType\>~~
60
72
 
61
73
  ```ts
62
74
  type ObjKeysWithValuesOfType<Obj, ValueType> = { [K in keyof Obj]: Obj[K] extends ValueType ? K : never }[keyof Obj];
63
75
  ```
64
76
 
65
- Defined in: [packages/utils/src/typingUtils.ts:7](https://github.com/lucasols/utils/blob/main/packages/utils/src/typingUtils.ts#L7)
77
+ Defined in: [packages/utils/src/typingUtils.ts:10](https://github.com/lucasols/utils/blob/main/packages/utils/src/typingUtils.ts#L10)
66
78
 
67
79
  #### Type Parameters
68
80
 
@@ -74,15 +86,19 @@ Defined in: [packages/utils/src/typingUtils.ts:7](https://github.com/lucasols/ut
74
86
 
75
87
  `ValueType`
76
88
 
89
+ #### Deprecated
90
+
91
+ Use `ObjKeysWithValuesOfType` from `@ls-stack/utils/typeUtils` instead
92
+
77
93
  ***
78
94
 
79
- ### PartialRecord\<K, T\>
95
+ ### ~~PartialRecord\<K, T\>~~
80
96
 
81
97
  ```ts
82
98
  type PartialRecord<K, T> = { [P in K]?: T };
83
99
  ```
84
100
 
85
- Defined in: [packages/utils/src/typingUtils.ts:1](https://github.com/lucasols/utils/blob/main/packages/utils/src/typingUtils.ts#L1)
101
+ Defined in: [packages/utils/src/typingUtils.ts:2](https://github.com/lucasols/utils/blob/main/packages/utils/src/typingUtils.ts#L2)
86
102
 
87
103
  #### Type Parameters
88
104
 
@@ -94,18 +110,26 @@ Defined in: [packages/utils/src/typingUtils.ts:1](https://github.com/lucasols/ut
94
110
 
95
111
  `T`
96
112
 
113
+ #### Deprecated
114
+
115
+ Use `PartialRecord` from `@ls-stack/utils/typeUtils` instead
116
+
97
117
  ***
98
118
 
99
- ### Prettify\<T\>
119
+ ### ~~Prettify\<T\>~~
100
120
 
101
121
  ```ts
102
122
  type Prettify<T> = { [P in keyof T]: T[P] } & object;
103
123
  ```
104
124
 
105
- Defined in: [packages/utils/src/typingUtils.ts:21](https://github.com/lucasols/utils/blob/main/packages/utils/src/typingUtils.ts#L21)
125
+ Defined in: [packages/utils/src/typingUtils.ts:26](https://github.com/lucasols/utils/blob/main/packages/utils/src/typingUtils.ts#L26)
106
126
 
107
127
  #### Type Parameters
108
128
 
109
129
  ##### T
110
130
 
111
131
  `T` *extends* `Record`\<`string`, `unknown`\>
132
+
133
+ #### Deprecated
134
+
135
+ Use `DeepPrettify` from `@ls-stack/utils/typeUtils` instead
@@ -33,7 +33,7 @@ function sleep(ms) {
33
33
 
34
34
  // src/retryOnError.ts
35
35
  async function retryOnError(fn, maxRetries, options = {}, retry = 0, originalMaxRetries = maxRetries) {
36
- const { delayBetweenRetriesMs, retryCondition, disableRetries } = options;
36
+ const { delayBetweenRetriesMs, retryCondition, disableRetries, onRetry } = options;
37
37
  if (options.debugId) {
38
38
  if (retry > 0) {
39
39
  console.info(
@@ -47,12 +47,19 @@ async function retryOnError(fn, maxRetries, options = {}, retry = 0, originalMax
47
47
  } catch (error) {
48
48
  if (maxRetries > 0 && !disableRetries) {
49
49
  const errorDuration = Date.now() - startTime;
50
- const shouldRetry = retryCondition ? retryCondition((0, import_t_result.unknownToError)(error), {
50
+ const normalizedError = (0, import_t_result.unknownToError)(error);
51
+ const shouldRetry = retryCondition ? retryCondition(normalizedError, {
51
52
  duration: errorDuration,
52
53
  retry
53
54
  }) : true;
54
55
  if (!shouldRetry) {
55
- throw error;
56
+ throw normalizedError;
57
+ }
58
+ if (onRetry) {
59
+ onRetry(normalizedError, {
60
+ duration: errorDuration,
61
+ retry
62
+ });
56
63
  }
57
64
  if (delayBetweenRetriesMs) {
58
65
  await sleep(
@@ -72,7 +79,7 @@ async function retryOnError(fn, maxRetries, options = {}, retry = 0, originalMax
72
79
  }
73
80
  }
74
81
  async function retryResultOnError(fn, maxRetries, options = {}, __retry = 0, __originalMaxRetries = maxRetries) {
75
- const { delayBetweenRetriesMs, retryCondition } = options;
82
+ const { delayBetweenRetriesMs, retryCondition, onRetry } = options;
76
83
  if (options.debugId) {
77
84
  if (__retry > 0) {
78
85
  console.info(
@@ -94,6 +101,12 @@ async function retryResultOnError(fn, maxRetries, options = {}, __retry = 0, __o
94
101
  if (!shouldRetry) {
95
102
  return result;
96
103
  }
104
+ if (onRetry) {
105
+ onRetry(result.error, {
106
+ duration: errorDuration,
107
+ retry: __retry
108
+ });
109
+ }
97
110
  if (delayBetweenRetriesMs) {
98
111
  await sleep(
99
112
  typeof delayBetweenRetriesMs === "function" ? delayBetweenRetriesMs(__retry) : delayBetweenRetriesMs
@@ -15,6 +15,11 @@ type RetryOptions = {
15
15
  debugId?: string;
16
16
  /** Disable retries */
17
17
  disableRetries?: boolean;
18
+ /** Function to call when retry happens */
19
+ onRetry?: (error: Error, lastAttempt: {
20
+ duration: number;
21
+ retry: number;
22
+ }) => void;
18
23
  };
19
24
  /**
20
25
  * Retries a function on error with configurable retry logic.
@@ -50,6 +55,7 @@ declare function retryOnError<T>(fn: (ctx: {
50
55
  * @param options.retryCondition
51
56
  * @param options.debugId
52
57
  * @param options.disableRetries
58
+ * @param options.onRetry
53
59
  * @param __retry - internal use only
54
60
  * @param __originalMaxRetries - internal use only
55
61
  * @returns Promise resolving to the function result or rejecting with the final error
@@ -65,6 +71,10 @@ declare function retryResultOnError<T, E extends ResultValidErrors>(fn: (ctx: {
65
71
  }) => boolean;
66
72
  debugId?: string;
67
73
  disableRetries?: boolean;
74
+ onRetry?: (error: E, lastAttempt: {
75
+ duration: number;
76
+ retry: number;
77
+ }) => void;
68
78
  }, __retry?: number, __originalMaxRetries?: number): Promise<Result<T, E>>;
69
79
 
70
80
  export { retryOnError, retryResultOnError };
@@ -15,6 +15,11 @@ type RetryOptions = {
15
15
  debugId?: string;
16
16
  /** Disable retries */
17
17
  disableRetries?: boolean;
18
+ /** Function to call when retry happens */
19
+ onRetry?: (error: Error, lastAttempt: {
20
+ duration: number;
21
+ retry: number;
22
+ }) => void;
18
23
  };
19
24
  /**
20
25
  * Retries a function on error with configurable retry logic.
@@ -50,6 +55,7 @@ declare function retryOnError<T>(fn: (ctx: {
50
55
  * @param options.retryCondition
51
56
  * @param options.debugId
52
57
  * @param options.disableRetries
58
+ * @param options.onRetry
53
59
  * @param __retry - internal use only
54
60
  * @param __originalMaxRetries - internal use only
55
61
  * @returns Promise resolving to the function result or rejecting with the final error
@@ -65,6 +71,10 @@ declare function retryResultOnError<T, E extends ResultValidErrors>(fn: (ctx: {
65
71
  }) => boolean;
66
72
  debugId?: string;
67
73
  disableRetries?: boolean;
74
+ onRetry?: (error: E, lastAttempt: {
75
+ duration: number;
76
+ retry: number;
77
+ }) => void;
68
78
  }, __retry?: number, __originalMaxRetries?: number): Promise<Result<T, E>>;
69
79
 
70
80
  export { retryOnError, retryResultOnError };
@@ -5,7 +5,7 @@ import {
5
5
  // src/retryOnError.ts
6
6
  import { unknownToError } from "t-result";
7
7
  async function retryOnError(fn, maxRetries, options = {}, retry = 0, originalMaxRetries = maxRetries) {
8
- const { delayBetweenRetriesMs, retryCondition, disableRetries } = options;
8
+ const { delayBetweenRetriesMs, retryCondition, disableRetries, onRetry } = options;
9
9
  if (options.debugId) {
10
10
  if (retry > 0) {
11
11
  console.info(
@@ -19,12 +19,19 @@ async function retryOnError(fn, maxRetries, options = {}, retry = 0, originalMax
19
19
  } catch (error) {
20
20
  if (maxRetries > 0 && !disableRetries) {
21
21
  const errorDuration = Date.now() - startTime;
22
- const shouldRetry = retryCondition ? retryCondition(unknownToError(error), {
22
+ const normalizedError = unknownToError(error);
23
+ const shouldRetry = retryCondition ? retryCondition(normalizedError, {
23
24
  duration: errorDuration,
24
25
  retry
25
26
  }) : true;
26
27
  if (!shouldRetry) {
27
- throw error;
28
+ throw normalizedError;
29
+ }
30
+ if (onRetry) {
31
+ onRetry(normalizedError, {
32
+ duration: errorDuration,
33
+ retry
34
+ });
28
35
  }
29
36
  if (delayBetweenRetriesMs) {
30
37
  await sleep(
@@ -44,7 +51,7 @@ async function retryOnError(fn, maxRetries, options = {}, retry = 0, originalMax
44
51
  }
45
52
  }
46
53
  async function retryResultOnError(fn, maxRetries, options = {}, __retry = 0, __originalMaxRetries = maxRetries) {
47
- const { delayBetweenRetriesMs, retryCondition } = options;
54
+ const { delayBetweenRetriesMs, retryCondition, onRetry } = options;
48
55
  if (options.debugId) {
49
56
  if (__retry > 0) {
50
57
  console.info(
@@ -66,6 +73,12 @@ async function retryResultOnError(fn, maxRetries, options = {}, __retry = 0, __o
66
73
  if (!shouldRetry) {
67
74
  return result;
68
75
  }
76
+ if (onRetry) {
77
+ onRetry(result.error, {
78
+ duration: errorDuration,
79
+ retry: __retry
80
+ });
81
+ }
69
82
  if (delayBetweenRetriesMs) {
70
83
  await sleep(
71
84
  typeof delayBetweenRetriesMs === "function" ? delayBetweenRetriesMs(__retry) : delayBetweenRetriesMs
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __copyProps = (to, from, except, desc) => {
7
+ if (from && typeof from === "object" || typeof from === "function") {
8
+ for (let key of __getOwnPropNames(from))
9
+ if (!__hasOwnProp.call(to, key) && key !== except)
10
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
11
+ }
12
+ return to;
13
+ };
14
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
15
+
16
+ // src/typeUtils.ts
17
+ var typeUtils_exports = {};
18
+ module.exports = __toCommonJS(typeUtils_exports);
@@ -0,0 +1,39 @@
1
+ type PartialRecord<K extends keyof any, T> = {
2
+ [P in K]?: T;
3
+ };
4
+ type NonPartial<T> = {
5
+ [K in keyof Required<T>]: T[K];
6
+ };
7
+ type ObjKeysWithValuesOfType<Obj extends Record<PropertyKey, unknown>, ValueType> = {
8
+ [K in keyof Obj]: Obj[K] extends ValueType ? K : never;
9
+ }[keyof Obj];
10
+ type IsAny<T> = unknown extends T ? [
11
+ keyof T
12
+ ] extends [never] ? false : true : false;
13
+ type Prettify<T extends Record<string, unknown>> = {
14
+ [P in keyof T]: T[P];
15
+ } & {};
16
+ type DeepPrettify<T> = {
17
+ [K in keyof T]: T[K] extends Record<string, unknown> ? DeepPrettify<T[K]> : T[K];
18
+ } & {};
19
+ type DefaultSkipTransverseDeepReplace = Date | RegExp | ((...args: any[]) => any) | Error | Set<any> | Map<any, any> | WeakSet<any> | WeakMap<any, any>;
20
+ type PathMatches<CurrentPath extends string, SkipPaths extends string> = true extends (SkipPaths extends any ? CurrentPath extends SkipPaths ? true : SkipPaths extends `${infer Prefix}[*]${infer Suffix}` ? CurrentPath extends `${Prefix}[${string}]${Suffix}` ? true : false : false : false) ? true : false;
21
+ type BuildPath<BasePath extends string, Key extends PropertyKey> = BasePath extends '$' ? Key extends string | number ? `${Key}` : never : Key extends string | number ? `${BasePath}.${Key}` : never;
22
+ type BuildArrayPath<BasePath extends string> = BasePath extends '$' ? '[*]' : `${BasePath}[*]`;
23
+ type DeepReplaceValueImpl<T, ReplaceType, NewType, SkipPaths extends string | undefined, SkipType, Path extends string = '$'> = SkipPaths extends string ? PathMatches<Path, SkipPaths> extends true ? T : T extends ReplaceType ? T extends SkipType ? T : NewType : T extends readonly (infer U)[] ? Array<DeepReplaceValueImpl<U, ReplaceType, NewType, SkipPaths, SkipType, BuildArrayPath<Path>>> : T extends SkipType ? T : T extends Record<string, any> ? {
24
+ [K in keyof T]: DeepReplaceValueImpl<T[K], ReplaceType, NewType, SkipPaths, SkipType, BuildPath<Path, K>>;
25
+ } : T : T extends ReplaceType ? T extends SkipType ? T : NewType : T extends readonly (infer U)[] ? Array<DeepReplaceValueImpl<U, ReplaceType, NewType, SkipPaths, SkipType, BuildArrayPath<Path>>> : T extends SkipType ? T : T extends Record<string, any> ? {
26
+ [K in keyof T]: DeepReplaceValueImpl<T[K], ReplaceType, NewType, SkipPaths, SkipType, BuildPath<Path, K>>;
27
+ } : T;
28
+ /**
29
+ * Replaces all values that extends `ReplaceType` with `NewType` in a deeply nested object or array.
30
+ *
31
+ * @template T - The object or array to replace values in.
32
+ * @template ReplaceType - The type to replace.
33
+ * @template NewType - The new type to replace with.
34
+ * @template SkipPaths - The paths to skip in transverse. e.g. 'a.b.c' | 'array[*].b'
35
+ * @template SkipTypes - The types to skip in transverse and replace.
36
+ */
37
+ type DeepReplaceValue<T, ReplaceType, NewType, SkipPaths extends string | undefined = undefined, SkipTypes = DefaultSkipTransverseDeepReplace> = DeepReplaceValueImpl<T, ReplaceType, NewType, SkipPaths, SkipTypes>;
38
+
39
+ export type { DeepPrettify, DeepReplaceValue, DefaultSkipTransverseDeepReplace, IsAny, NonPartial, ObjKeysWithValuesOfType, PartialRecord, Prettify };
@@ -0,0 +1,39 @@
1
+ type PartialRecord<K extends keyof any, T> = {
2
+ [P in K]?: T;
3
+ };
4
+ type NonPartial<T> = {
5
+ [K in keyof Required<T>]: T[K];
6
+ };
7
+ type ObjKeysWithValuesOfType<Obj extends Record<PropertyKey, unknown>, ValueType> = {
8
+ [K in keyof Obj]: Obj[K] extends ValueType ? K : never;
9
+ }[keyof Obj];
10
+ type IsAny<T> = unknown extends T ? [
11
+ keyof T
12
+ ] extends [never] ? false : true : false;
13
+ type Prettify<T extends Record<string, unknown>> = {
14
+ [P in keyof T]: T[P];
15
+ } & {};
16
+ type DeepPrettify<T> = {
17
+ [K in keyof T]: T[K] extends Record<string, unknown> ? DeepPrettify<T[K]> : T[K];
18
+ } & {};
19
+ type DefaultSkipTransverseDeepReplace = Date | RegExp | ((...args: any[]) => any) | Error | Set<any> | Map<any, any> | WeakSet<any> | WeakMap<any, any>;
20
+ type PathMatches<CurrentPath extends string, SkipPaths extends string> = true extends (SkipPaths extends any ? CurrentPath extends SkipPaths ? true : SkipPaths extends `${infer Prefix}[*]${infer Suffix}` ? CurrentPath extends `${Prefix}[${string}]${Suffix}` ? true : false : false : false) ? true : false;
21
+ type BuildPath<BasePath extends string, Key extends PropertyKey> = BasePath extends '$' ? Key extends string | number ? `${Key}` : never : Key extends string | number ? `${BasePath}.${Key}` : never;
22
+ type BuildArrayPath<BasePath extends string> = BasePath extends '$' ? '[*]' : `${BasePath}[*]`;
23
+ type DeepReplaceValueImpl<T, ReplaceType, NewType, SkipPaths extends string | undefined, SkipType, Path extends string = '$'> = SkipPaths extends string ? PathMatches<Path, SkipPaths> extends true ? T : T extends ReplaceType ? T extends SkipType ? T : NewType : T extends readonly (infer U)[] ? Array<DeepReplaceValueImpl<U, ReplaceType, NewType, SkipPaths, SkipType, BuildArrayPath<Path>>> : T extends SkipType ? T : T extends Record<string, any> ? {
24
+ [K in keyof T]: DeepReplaceValueImpl<T[K], ReplaceType, NewType, SkipPaths, SkipType, BuildPath<Path, K>>;
25
+ } : T : T extends ReplaceType ? T extends SkipType ? T : NewType : T extends readonly (infer U)[] ? Array<DeepReplaceValueImpl<U, ReplaceType, NewType, SkipPaths, SkipType, BuildArrayPath<Path>>> : T extends SkipType ? T : T extends Record<string, any> ? {
26
+ [K in keyof T]: DeepReplaceValueImpl<T[K], ReplaceType, NewType, SkipPaths, SkipType, BuildPath<Path, K>>;
27
+ } : T;
28
+ /**
29
+ * Replaces all values that extends `ReplaceType` with `NewType` in a deeply nested object or array.
30
+ *
31
+ * @template T - The object or array to replace values in.
32
+ * @template ReplaceType - The type to replace.
33
+ * @template NewType - The new type to replace with.
34
+ * @template SkipPaths - The paths to skip in transverse. e.g. 'a.b.c' | 'array[*].b'
35
+ * @template SkipTypes - The types to skip in transverse and replace.
36
+ */
37
+ type DeepReplaceValue<T, ReplaceType, NewType, SkipPaths extends string | undefined = undefined, SkipTypes = DefaultSkipTransverseDeepReplace> = DeepReplaceValueImpl<T, ReplaceType, NewType, SkipPaths, SkipTypes>;
38
+
39
+ export type { DeepPrettify, DeepReplaceValue, DefaultSkipTransverseDeepReplace, IsAny, NonPartial, ObjKeysWithValuesOfType, PartialRecord, Prettify };
File without changes
@@ -1,18 +1,24 @@
1
+ /** @deprecated Use `PartialRecord` from `@ls-stack/utils/typeUtils` instead */
1
2
  type PartialRecord<K extends keyof any, T> = {
2
3
  [P in K]?: T;
3
4
  };
5
+ /** @deprecated Use `NonPartial` from `@ls-stack/utils/typeUtils` instead */
4
6
  type NonPartial<T> = {
5
7
  [K in keyof Required<T>]: T[K];
6
8
  };
9
+ /** @deprecated Use `ObjKeysWithValuesOfType` from `@ls-stack/utils/typeUtils` instead */
7
10
  type ObjKeysWithValuesOfType<Obj extends Record<PropertyKey, unknown>, ValueType> = {
8
11
  [K in keyof Obj]: Obj[K] extends ValueType ? K : never;
9
12
  }[keyof Obj];
13
+ /** @deprecated Use `IsAny` from `@ls-stack/utils/typeUtils` instead */
10
14
  type IsAny<T> = unknown extends T ? [
11
15
  keyof T
12
16
  ] extends [never] ? false : true : false;
17
+ /** @deprecated Use `DeepPrettify` from `@ls-stack/utils/typeUtils` instead */
13
18
  type Prettify<T extends Record<string, unknown>> = {
14
19
  [P in keyof T]: T[P];
15
20
  } & {};
21
+ /** @deprecated Use `DeepPrettify` from `@ls-stack/utils/typeUtils` instead */
16
22
  type DeepPrettify<T> = {
17
23
  [K in keyof T]: T[K] extends Record<string, unknown> ? DeepPrettify<T[K]> : T[K];
18
24
  } & {};
@@ -1,18 +1,24 @@
1
+ /** @deprecated Use `PartialRecord` from `@ls-stack/utils/typeUtils` instead */
1
2
  type PartialRecord<K extends keyof any, T> = {
2
3
  [P in K]?: T;
3
4
  };
5
+ /** @deprecated Use `NonPartial` from `@ls-stack/utils/typeUtils` instead */
4
6
  type NonPartial<T> = {
5
7
  [K in keyof Required<T>]: T[K];
6
8
  };
9
+ /** @deprecated Use `ObjKeysWithValuesOfType` from `@ls-stack/utils/typeUtils` instead */
7
10
  type ObjKeysWithValuesOfType<Obj extends Record<PropertyKey, unknown>, ValueType> = {
8
11
  [K in keyof Obj]: Obj[K] extends ValueType ? K : never;
9
12
  }[keyof Obj];
13
+ /** @deprecated Use `IsAny` from `@ls-stack/utils/typeUtils` instead */
10
14
  type IsAny<T> = unknown extends T ? [
11
15
  keyof T
12
16
  ] extends [never] ? false : true : false;
17
+ /** @deprecated Use `DeepPrettify` from `@ls-stack/utils/typeUtils` instead */
13
18
  type Prettify<T extends Record<string, unknown>> = {
14
19
  [P in keyof T]: T[P];
15
20
  } & {};
21
+ /** @deprecated Use `DeepPrettify` from `@ls-stack/utils/typeUtils` instead */
16
22
  type DeepPrettify<T> = {
17
23
  [K in keyof T]: T[K] extends Record<string, unknown> ? DeepPrettify<T[K]> : T[K];
18
24
  } & {};
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.29.0",
4
+ "version": "3.30.1",
5
5
  "license": "MIT",
6
6
  "files": [
7
7
  "lib",
@@ -184,6 +184,14 @@
184
184
  "import": "./lib/typeGuards.js",
185
185
  "require": "./lib/typeGuards.cjs"
186
186
  },
187
+ "./typeUtils": {
188
+ "import": "./lib/typeUtils.js",
189
+ "require": "./lib/typeUtils.cjs"
190
+ },
191
+ "./typeUtils.typesTest": {
192
+ "import": "./lib/typeUtils.typesTest.js",
193
+ "require": "./lib/typeUtils.typesTest.cjs"
194
+ },
187
195
  "./typingFnUtils": {
188
196
  "import": "./lib/typingFnUtils.js",
189
197
  "require": "./lib/typingFnUtils.cjs"