@oscarpalmer/atoms 0.184.1 → 0.185.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.
- package/dist/array/index.d.mts +2 -2
- package/dist/array/index.mjs +2 -2
- package/dist/array/{position.d.mts → match.d.mts} +9 -6
- package/dist/array/{position.mjs → match.mjs} +16 -16
- package/dist/array/move.mjs +1 -1
- package/dist/array/single.mjs +2 -2
- package/dist/array/sort.d.mts +9 -4
- package/dist/array/sort.mjs +6 -6
- package/dist/array/swap.mjs +1 -1
- package/dist/beacon.d.mts +12 -0
- package/dist/beacon.mjs +9 -0
- package/dist/color/instance.d.mts +8 -0
- package/dist/color/instance.mjs +5 -2
- package/dist/color/misc/get.mjs +8 -8
- package/dist/color/misc/state.d.mts +2 -2
- package/dist/color/misc/state.mjs +2 -2
- package/dist/color/models.d.mts +30 -0
- package/dist/function/assert.d.mts +29 -8
- package/dist/function/assert.mjs +29 -8
- package/dist/function/memoize.d.mts +3 -0
- package/dist/function/memoize.mjs +3 -0
- package/dist/function/once.mjs +9 -9
- package/dist/function/retry.d.mts +3 -0
- package/dist/function/retry.mjs +11 -8
- package/dist/function/work.mjs +1 -1
- package/dist/index.d.mts +272 -160
- package/dist/index.mjs +279 -216
- package/dist/internal/number.d.mts +2 -1
- package/dist/internal/number.mjs +4 -1
- package/dist/internal/value/compare.d.mts +2 -1
- package/dist/internal/value/equal.d.mts +5 -0
- package/dist/internal/value/equal.mjs +5 -5
- package/dist/internal/value/get.d.mts +2 -2
- package/dist/internal/value/has.d.mts +3 -3
- package/dist/internal/value/has.mjs +1 -1
- package/dist/internal/value/misc.d.mts +2 -2
- package/dist/internal/value/misc.mjs +10 -4
- package/dist/logger.d.mts +11 -0
- package/dist/logger.mjs +11 -0
- package/dist/models.d.mts +1 -1
- package/dist/promise/helpers.mjs +3 -5
- package/dist/promise/index.d.mts +0 -6
- package/dist/promise/models.d.mts +36 -0
- package/dist/promise/models.mjs +6 -0
- package/dist/queue.d.mts +13 -1
- package/dist/queue.mjs +14 -7
- package/dist/result/index.d.mts +0 -8
- package/dist/result/index.mjs +0 -8
- package/dist/result/match.d.mts +4 -4
- package/dist/result/work/flow.d.mts +12 -36
- package/dist/result/work/pipe.d.mts +11 -33
- package/dist/sized/set.d.mts +3 -2
- package/dist/sized/set.mjs +3 -2
- package/dist/string/fuzzy.mjs +2 -2
- package/dist/value/handle.mjs +1 -1
- package/dist/value/merge.d.mts +0 -1
- package/dist/value/merge.mjs +0 -1
- package/dist/value/shake.d.mts +3 -0
- package/dist/value/smush.d.mts +3 -0
- package/dist/value/transform.d.mts +9 -0
- package/dist/value/unsmush.d.mts +3 -0
- package/package.json +3 -3
- package/src/array/difference.ts +4 -0
- package/src/array/from.ts +4 -0
- package/src/array/index.ts +1 -1
- package/src/array/intersection.ts +4 -0
- package/src/array/{position.ts → match.ts} +28 -25
- package/src/array/move.ts +5 -1
- package/src/array/reverse.ts +4 -0
- package/src/array/select.ts +2 -0
- package/src/array/single.ts +2 -2
- package/src/array/sort.ts +14 -9
- package/src/array/swap.ts +5 -1
- package/src/array/toggle.ts +4 -0
- package/src/array/union.ts +4 -0
- package/src/beacon.ts +12 -0
- package/src/color/index.ts +0 -3
- package/src/color/instance.ts +11 -3
- package/src/color/misc/get.ts +8 -8
- package/src/color/misc/state.ts +1 -1
- package/src/color/models.ts +30 -0
- package/src/function/assert.ts +66 -7
- package/src/function/memoize.ts +3 -0
- package/src/function/once.ts +13 -9
- package/src/function/retry.ts +11 -8
- package/src/internal/number.ts +6 -0
- package/src/internal/value/compare.ts +2 -1
- package/src/internal/value/equal.ts +10 -5
- package/src/internal/value/get.ts +2 -2
- package/src/internal/value/has.ts +6 -6
- package/src/internal/value/misc.ts +24 -13
- package/src/logger.ts +11 -0
- package/src/models.ts +1 -1
- package/src/promise/helpers.ts +3 -6
- package/src/promise/index.ts +0 -6
- package/src/promise/models.ts +36 -0
- package/src/queue.ts +23 -11
- package/src/result/index.ts +0 -8
- package/src/result/match.ts +4 -4
- package/src/result/work/flow.ts +12 -36
- package/src/result/work/pipe.ts +11 -33
- package/src/sized/set.ts +4 -3
- package/src/string/fuzzy.ts +2 -2
- package/src/value/merge.ts +0 -1
- package/src/value/shake.ts +3 -0
- package/src/value/smush.ts +3 -0
- package/src/value/transform.ts +9 -0
- package/src/value/unsmush.ts +3 -0
package/src/function/once.ts
CHANGED
|
@@ -39,7 +39,7 @@ type OnceState<Value> = {
|
|
|
39
39
|
export function asyncOnce<Callback extends GenericAsyncCallback>(
|
|
40
40
|
callback: Callback,
|
|
41
41
|
): OnceAsyncCallback<Callback> {
|
|
42
|
-
assert(() => typeof callback === 'function',
|
|
42
|
+
assert(() => typeof callback === 'function', ONCE_MESSAGE_EXPECTATION);
|
|
43
43
|
|
|
44
44
|
const state: OnceAsyncState<Awaited<ReturnType<Callback>>> = {
|
|
45
45
|
called: false,
|
|
@@ -52,7 +52,7 @@ export function asyncOnce<Callback extends GenericAsyncCallback>(
|
|
|
52
52
|
|
|
53
53
|
const fn = (...parameters: Parameters<Callback>): Promise<Awaited<ReturnType<Callback>>> => {
|
|
54
54
|
if (state.cleared) {
|
|
55
|
-
return Promise.reject(new Error(
|
|
55
|
+
return Promise.reject(new Error(ONCE_MESSAGE_CLEARED));
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
if (state.finished) {
|
|
@@ -72,10 +72,10 @@ export function asyncOnce<Callback extends GenericAsyncCallback>(
|
|
|
72
72
|
|
|
73
73
|
void callback(...parameters)
|
|
74
74
|
.then(value => {
|
|
75
|
-
|
|
75
|
+
handleOnceResult(state, value, false);
|
|
76
76
|
})
|
|
77
77
|
.catch(error => {
|
|
78
|
-
|
|
78
|
+
handleOnceResult(state, error, true);
|
|
79
79
|
});
|
|
80
80
|
});
|
|
81
81
|
};
|
|
@@ -107,7 +107,11 @@ export function asyncOnce<Callback extends GenericAsyncCallback>(
|
|
|
107
107
|
return fn as OnceAsyncCallback<Callback>;
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
-
function
|
|
110
|
+
function handleOnceResult<Value>(
|
|
111
|
+
state: OnceAsyncState<Value>,
|
|
112
|
+
value: unknown,
|
|
113
|
+
error: boolean,
|
|
114
|
+
): void {
|
|
111
115
|
state.error = error;
|
|
112
116
|
state.finished = true;
|
|
113
117
|
state.value = value as Value;
|
|
@@ -132,7 +136,7 @@ function handleResult<Value>(state: OnceAsyncState<Value>, value: unknown, error
|
|
|
132
136
|
* @returns Once callback
|
|
133
137
|
*/
|
|
134
138
|
export function once<Callback extends GenericCallback>(callback: Callback): OnceCallback<Callback> {
|
|
135
|
-
assert(() => typeof callback === 'function',
|
|
139
|
+
assert(() => typeof callback === 'function', ONCE_MESSAGE_EXPECTATION);
|
|
136
140
|
|
|
137
141
|
const state: OnceState<ReturnType<Callback>> = {
|
|
138
142
|
called: false,
|
|
@@ -142,7 +146,7 @@ export function once<Callback extends GenericCallback>(callback: Callback): Once
|
|
|
142
146
|
|
|
143
147
|
const fn = (...parameters: Parameters<Callback>): ReturnType<Callback> => {
|
|
144
148
|
if (state.cleared) {
|
|
145
|
-
throw new Error(
|
|
149
|
+
throw new Error(ONCE_MESSAGE_CLEARED);
|
|
146
150
|
}
|
|
147
151
|
|
|
148
152
|
if (state.called) {
|
|
@@ -183,8 +187,8 @@ once.async = asyncOnce;
|
|
|
183
187
|
|
|
184
188
|
// #region Variables
|
|
185
189
|
|
|
186
|
-
const
|
|
190
|
+
const ONCE_MESSAGE_CLEARED = 'Once has been cleared';
|
|
187
191
|
|
|
188
|
-
const
|
|
192
|
+
const ONCE_MESSAGE_EXPECTATION = 'Once expected a function';
|
|
189
193
|
|
|
190
194
|
// #endregion
|
package/src/function/retry.ts
CHANGED
|
@@ -4,6 +4,9 @@ import type {GenericAsyncCallback, GenericCallback} from '../models';
|
|
|
4
4
|
|
|
5
5
|
// #region Types
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
* An error thrown when a retry fails
|
|
9
|
+
*/
|
|
7
10
|
export class RetryError extends Error {
|
|
8
11
|
constructor(
|
|
9
12
|
message: string,
|
|
@@ -11,7 +14,7 @@ export class RetryError extends Error {
|
|
|
11
14
|
) {
|
|
12
15
|
super(message);
|
|
13
16
|
|
|
14
|
-
this.name =
|
|
17
|
+
this.name = RETRY_ERROR_NAME;
|
|
15
18
|
}
|
|
16
19
|
}
|
|
17
20
|
|
|
@@ -64,7 +67,7 @@ async function asyncRetry<Callback extends GenericCallback>(
|
|
|
64
67
|
options?: RetryOptions,
|
|
65
68
|
): Promise<ReturnType<Callback>> {
|
|
66
69
|
if (typeof callback !== 'function') {
|
|
67
|
-
throw new TypeError(
|
|
70
|
+
throw new TypeError(RETRY_MESSAGE_EXPECTATION);
|
|
68
71
|
}
|
|
69
72
|
|
|
70
73
|
async function handle(): Promise<void> {
|
|
@@ -74,7 +77,7 @@ async function asyncRetry<Callback extends GenericCallback>(
|
|
|
74
77
|
resolver(result);
|
|
75
78
|
} catch (error) {
|
|
76
79
|
if (attempts >= times || !when(error)) {
|
|
77
|
-
rejector(new RetryError(
|
|
80
|
+
rejector(new RetryError(RETRY_MESSAGE_FAILED, error));
|
|
78
81
|
} else {
|
|
79
82
|
attempts += 1;
|
|
80
83
|
|
|
@@ -125,7 +128,7 @@ export function retry<Callback extends GenericCallback>(
|
|
|
125
128
|
options?: Omit<RetryOptions, 'delay'>,
|
|
126
129
|
): ReturnType<Callback> {
|
|
127
130
|
if (typeof callback !== 'function') {
|
|
128
|
-
throw new TypeError(
|
|
131
|
+
throw new TypeError(RETRY_MESSAGE_EXPECTATION);
|
|
129
132
|
}
|
|
130
133
|
|
|
131
134
|
const {times, when} = getRetryOptions(options);
|
|
@@ -146,7 +149,7 @@ export function retry<Callback extends GenericCallback>(
|
|
|
146
149
|
}
|
|
147
150
|
}
|
|
148
151
|
|
|
149
|
-
throw new RetryError(
|
|
152
|
+
throw new RetryError(RETRY_MESSAGE_FAILED, last);
|
|
150
153
|
}
|
|
151
154
|
|
|
152
155
|
retry.async = asyncRetry;
|
|
@@ -159,10 +162,10 @@ function shouldRetry(): boolean {
|
|
|
159
162
|
|
|
160
163
|
// #region Variables
|
|
161
164
|
|
|
162
|
-
const
|
|
165
|
+
const RETRY_ERROR_NAME = 'RetryError';
|
|
163
166
|
|
|
164
|
-
const
|
|
167
|
+
const RETRY_MESSAGE_EXPECTATION = 'Retry expected a function';
|
|
165
168
|
|
|
166
|
-
const
|
|
169
|
+
const RETRY_MESSAGE_FAILED = 'Retry failed';
|
|
167
170
|
|
|
168
171
|
// #endregion
|
package/src/internal/number.ts
CHANGED
|
@@ -97,6 +97,12 @@ export function getNumber(value: unknown): number {
|
|
|
97
97
|
return Number(trimmed);
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
+
export function getNumberOrDefault(value: unknown, defaultValue: number, minimum?: number): number {
|
|
101
|
+
return typeof value === 'number' && !Number.isNaN(value) && value >= (minimum ?? 0)
|
|
102
|
+
? Math.floor(value)
|
|
103
|
+
: defaultValue;
|
|
104
|
+
}
|
|
105
|
+
|
|
100
106
|
// #endregion
|
|
101
107
|
|
|
102
108
|
// #region Variables
|
|
@@ -45,6 +45,7 @@ export function compare(first: unknown, second: unknown): number {
|
|
|
45
45
|
const firstParts = getComparisonParts(first);
|
|
46
46
|
const secondParts = getComparisonParts(second);
|
|
47
47
|
const length = max([firstParts.length, secondParts.length]);
|
|
48
|
+
|
|
48
49
|
const lastIndex = length - 1;
|
|
49
50
|
|
|
50
51
|
for (let index = 0; index < length; index += 1) {
|
|
@@ -147,7 +148,7 @@ function getComparisonParts(value: unknown): unknown[] {
|
|
|
147
148
|
*/
|
|
148
149
|
export function registerComparator<Instance>(
|
|
149
150
|
constructor: Constructor<Instance>,
|
|
150
|
-
handler?: string |
|
|
151
|
+
handler?: string | Comparator<Instance>,
|
|
151
152
|
): void {
|
|
152
153
|
compare.handlers.register(constructor, handler);
|
|
153
154
|
}
|
|
@@ -22,6 +22,11 @@ export type EqualOptions = {
|
|
|
22
22
|
relaxedNullish?: boolean;
|
|
23
23
|
};
|
|
24
24
|
|
|
25
|
+
/**
|
|
26
|
+
* An equalizer function for comparing values for equality, with predefined options
|
|
27
|
+
*
|
|
28
|
+
* Can be used to compare values, and register or deregister equality comparison handlers for specific classes
|
|
29
|
+
*/
|
|
25
30
|
type Equalizer = {
|
|
26
31
|
/**
|
|
27
32
|
* Are two strings equal?
|
|
@@ -141,9 +146,9 @@ function equalArray(first: unknown[], second: unknown[], options: Options): bool
|
|
|
141
146
|
|
|
142
147
|
let offset = 0;
|
|
143
148
|
|
|
144
|
-
if (length >=
|
|
145
|
-
offset = Math.round(length /
|
|
146
|
-
offset = offset >
|
|
149
|
+
if (length >= EQUAL_ARRAY_THRESHOLD) {
|
|
150
|
+
offset = Math.round(length / EQUAL_ARRAY_PEEK_PERCENTAGE);
|
|
151
|
+
offset = offset > EQUAL_ARRAY_THRESHOLD ? EQUAL_ARRAY_THRESHOLD : offset;
|
|
147
152
|
|
|
148
153
|
for (let index = 0; index < offset; index += 1) {
|
|
149
154
|
if (
|
|
@@ -438,9 +443,9 @@ export function registerEqualizer<Instance>(
|
|
|
438
443
|
|
|
439
444
|
// #region Variables
|
|
440
445
|
|
|
441
|
-
const
|
|
446
|
+
const EQUAL_ARRAY_PEEK_PERCENTAGE = 10;
|
|
442
447
|
|
|
443
|
-
const
|
|
448
|
+
const EQUAL_ARRAY_THRESHOLD = 100;
|
|
444
449
|
|
|
445
450
|
const ERROR_PROPERTIES: string[] = ['name', 'message'];
|
|
446
451
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {NestedKeys, NestedValue, PlainObject
|
|
1
|
+
import type {NestedKeys, NestedValue, PlainObject} from '../../models';
|
|
2
2
|
import type {Ok} from '../../result/models';
|
|
3
3
|
import {getNestedValue} from './misc';
|
|
4
4
|
|
|
@@ -13,7 +13,7 @@ import {getNestedValue} from './misc';
|
|
|
13
13
|
export function getValue<Data extends PlainObject, Path extends NestedKeys<Data>>(
|
|
14
14
|
data: Data,
|
|
15
15
|
path: Path,
|
|
16
|
-
): NestedValue<Data,
|
|
16
|
+
): NestedValue<Data, Path>;
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
19
|
* Get the value from an object using an unknown path
|
|
@@ -43,11 +43,11 @@ hasValue.get = hasValueResult;
|
|
|
43
43
|
* @param ignoreCase If `true`, the path matching is case-insensitive
|
|
44
44
|
* @return Result object
|
|
45
45
|
*/
|
|
46
|
-
function hasValueResult<Data extends PlainObject, Path extends NestedKeys<Data>>(
|
|
46
|
+
export function hasValueResult<Data extends PlainObject, Path extends NestedKeys<Data>>(
|
|
47
47
|
data: Data,
|
|
48
48
|
path: Path,
|
|
49
49
|
ignoreCase?: boolean,
|
|
50
|
-
): Result<NestedValue<Data, ToString<Path>>,
|
|
50
|
+
): Result<NestedValue<Data, ToString<Path>>, string>;
|
|
51
51
|
|
|
52
52
|
/**
|
|
53
53
|
* Check if a nested property is defined in an object, and get its value if it is
|
|
@@ -58,17 +58,17 @@ function hasValueResult<Data extends PlainObject, Path extends NestedKeys<Data>>
|
|
|
58
58
|
* @param ignoreCase If `true`, the path matching is case-insensitive
|
|
59
59
|
* @return Result object
|
|
60
60
|
*/
|
|
61
|
-
function hasValueResult<Data extends PlainObject>(
|
|
61
|
+
export function hasValueResult<Data extends PlainObject>(
|
|
62
62
|
data: Data,
|
|
63
63
|
path: string,
|
|
64
64
|
ignoreCase?: boolean,
|
|
65
|
-
): Result<unknown,
|
|
65
|
+
): Result<unknown, string>;
|
|
66
66
|
|
|
67
|
-
function hasValueResult(
|
|
67
|
+
export function hasValueResult(
|
|
68
68
|
data: PlainObject,
|
|
69
69
|
path: string,
|
|
70
70
|
ignoreCase?: boolean,
|
|
71
|
-
): Result<unknown,
|
|
71
|
+
): Result<unknown, string> {
|
|
72
72
|
return getNestedValue(data, path, ignoreCase === true);
|
|
73
73
|
}
|
|
74
74
|
|
|
@@ -17,14 +17,13 @@ export function getNestedValue(
|
|
|
17
17
|
data: object,
|
|
18
18
|
path: string,
|
|
19
19
|
ignoreCase: boolean,
|
|
20
|
-
): Result<unknown,
|
|
21
|
-
if (
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
return error(undefined);
|
|
20
|
+
): Result<unknown, string> {
|
|
21
|
+
if (typeof data !== 'object' || data === null) {
|
|
22
|
+
return error(NESTED_MESSAGE_INPUT);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (typeof path !== 'string' || path.trim().length === 0) {
|
|
26
|
+
return error(NESTED_MESSAGE_PATH);
|
|
28
27
|
}
|
|
29
28
|
|
|
30
29
|
const shouldIgnoreCase = ignoreCase === true;
|
|
@@ -69,7 +68,7 @@ export function handleValue(
|
|
|
69
68
|
value: unknown,
|
|
70
69
|
get: true,
|
|
71
70
|
ignoreCase: boolean,
|
|
72
|
-
): Result<unknown,
|
|
71
|
+
): Result<unknown, string>;
|
|
73
72
|
|
|
74
73
|
export function handleValue(
|
|
75
74
|
data: object,
|
|
@@ -85,19 +84,23 @@ export function handleValue(
|
|
|
85
84
|
value: unknown,
|
|
86
85
|
get: boolean,
|
|
87
86
|
ignoreCase: boolean,
|
|
88
|
-
): Result<unknown,
|
|
89
|
-
if (typeof data === 'object' && data !== null
|
|
87
|
+
): Result<unknown, string> | void {
|
|
88
|
+
if (typeof data === 'object' && data !== null) {
|
|
89
|
+
if (ignoreKey(path)) {
|
|
90
|
+
return error(NESTED_MESSAGE_UNSAFE);
|
|
91
|
+
}
|
|
92
|
+
|
|
90
93
|
const key = ignoreCase ? findKey(path, data) : path;
|
|
91
94
|
|
|
92
95
|
if (get) {
|
|
93
|
-
return key in data ? ok(data[key as never]) : error(
|
|
96
|
+
return key in data ? ok(data[key as never]) : error(NESTED_MESSAGE_MISSING);
|
|
94
97
|
}
|
|
95
98
|
|
|
96
99
|
(data as PlainObject)[key] = typeof value === 'function' ? value(data[key as never]) : value;
|
|
97
100
|
}
|
|
98
101
|
|
|
99
102
|
if (get) {
|
|
100
|
-
return error(
|
|
103
|
+
return error(NESTED_MESSAGE_MISSING);
|
|
101
104
|
}
|
|
102
105
|
}
|
|
103
106
|
|
|
@@ -111,4 +114,12 @@ const EXPRESSION_DOTS = /^\.|\.$/g;
|
|
|
111
114
|
|
|
112
115
|
const EXPRESSION_NESTED = /\.|\[\w+\]/;
|
|
113
116
|
|
|
117
|
+
const NESTED_MESSAGE_INPUT = 'Expected data to be an object';
|
|
118
|
+
|
|
119
|
+
const NESTED_MESSAGE_MISSING = 'Expected property to exist in object';
|
|
120
|
+
|
|
121
|
+
const NESTED_MESSAGE_PATH = 'Expected path to be a string';
|
|
122
|
+
|
|
123
|
+
const NESTED_MESSAGE_UNSAFE = 'Access to this property is not allowed';
|
|
124
|
+
|
|
114
125
|
// #endregion
|
package/src/logger.ts
CHANGED
|
@@ -2,6 +2,11 @@ import {noop} from './internal/function/misc';
|
|
|
2
2
|
|
|
3
3
|
// #region Types
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* A logger that can be used to log messages to the console
|
|
7
|
+
*
|
|
8
|
+
* _(Logging can be enabled or disabled by setting the `enabled` property)_
|
|
9
|
+
*/
|
|
5
10
|
class Logger {
|
|
6
11
|
/**
|
|
7
12
|
* Log any number of values at the "debug" log level
|
|
@@ -83,12 +88,18 @@ class Logger {
|
|
|
83
88
|
}
|
|
84
89
|
}
|
|
85
90
|
|
|
91
|
+
/**
|
|
92
|
+
* A named timer that can be used to log durations to the console
|
|
93
|
+
*/
|
|
86
94
|
class Time {
|
|
87
95
|
#logger: typeof console.timeLog | undefined;
|
|
88
96
|
#stopper: typeof console.timeEnd | undefined;
|
|
89
97
|
|
|
90
98
|
readonly #state: TimeState;
|
|
91
99
|
|
|
100
|
+
/**
|
|
101
|
+
* Is the timer active? _(i.e. has it been started and not stopped, and is logging enabled?)_
|
|
102
|
+
*/
|
|
92
103
|
get active(): boolean {
|
|
93
104
|
return this.#state.started && !this.#state.stopped && enabled;
|
|
94
105
|
}
|
package/src/models.ts
CHANGED
|
@@ -19,7 +19,7 @@ export type AsyncCancelableCallback<Callback extends GenericAsyncCallback | Gene
|
|
|
19
19
|
};
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
|
-
* For
|
|
22
|
+
* For matching any `void`, `Date`, primitive, or `RegExp` values
|
|
23
23
|
*
|
|
24
24
|
* (Thanks, type-fest!)
|
|
25
25
|
*/
|
package/src/promise/helpers.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import {getNumberOrDefault} from '../internal/number';
|
|
1
2
|
import type {RequiredKeys} from '../models';
|
|
2
3
|
import {error, ok} from '../result/misc';
|
|
3
4
|
import type {Result} from '../result/models';
|
|
@@ -16,14 +17,10 @@ import {
|
|
|
16
17
|
|
|
17
18
|
// #region Functions
|
|
18
19
|
|
|
19
|
-
function getNumberOrDefault(value: unknown): number {
|
|
20
|
-
return typeof value === 'number' && value > 0 ? value : 0;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
20
|
export function getPromiseOptions(input: unknown): RequiredKeys<PromiseOptions, 'time'> {
|
|
24
21
|
if (typeof input === 'number') {
|
|
25
22
|
return {
|
|
26
|
-
time: getNumberOrDefault(input),
|
|
23
|
+
time: getNumberOrDefault(input, 0),
|
|
27
24
|
};
|
|
28
25
|
}
|
|
29
26
|
|
|
@@ -35,7 +32,7 @@ export function getPromiseOptions(input: unknown): RequiredKeys<PromiseOptions,
|
|
|
35
32
|
|
|
36
33
|
return {
|
|
37
34
|
signal: options.signal instanceof AbortSignal ? options.signal : undefined,
|
|
38
|
-
time: getNumberOrDefault(options.time),
|
|
35
|
+
time: getNumberOrDefault(options.time, 0),
|
|
39
36
|
};
|
|
40
37
|
}
|
|
41
38
|
|
package/src/promise/index.ts
CHANGED
|
@@ -24,8 +24,6 @@ import {getTimedPromise} from './timed';
|
|
|
24
24
|
|
|
25
25
|
/**
|
|
26
26
|
* Wrap a promise with safety handlers, with optional abort capabilities and timeout
|
|
27
|
-
*
|
|
28
|
-
* Available as `attemptPromise` and `attempt.promise`
|
|
29
27
|
* @param promise Promise to wrap
|
|
30
28
|
* @param options Options for the promise
|
|
31
29
|
* @returns Wrapped promise
|
|
@@ -37,8 +35,6 @@ export async function attemptPromise<Value>(
|
|
|
37
35
|
|
|
38
36
|
/**
|
|
39
37
|
* Wrap a promise-returning callback with safety handlers, with optional abort capabilities and timeout
|
|
40
|
-
*
|
|
41
|
-
* Available as `attemptPromise` and `attempt.promise`
|
|
42
38
|
* @param callback Callback to wrap
|
|
43
39
|
* @param options Options for the promise
|
|
44
40
|
* @returns Promise-wrapped callback
|
|
@@ -50,8 +46,6 @@ export async function attemptPromise<Value>(
|
|
|
50
46
|
|
|
51
47
|
/**
|
|
52
48
|
* Wrap a callback with a promise and safety handlers, with optional abort capabilities and timeout
|
|
53
|
-
*
|
|
54
|
-
* Available as `attemptPromise` and `attempt.promise`
|
|
55
49
|
* @param callback Callback to wrap
|
|
56
50
|
* @param options Options for the promise
|
|
57
51
|
* @returns Promise-wrapped callback
|
package/src/promise/models.ts
CHANGED
|
@@ -3,6 +3,9 @@ import type {Result} from '../result/models';
|
|
|
3
3
|
|
|
4
4
|
// #region Types
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* A promise that can be canceled
|
|
8
|
+
*/
|
|
6
9
|
export class CancelablePromise<Value = void> extends Promise<Value> {
|
|
7
10
|
#rejector!: (reason: unknown) => void;
|
|
8
11
|
|
|
@@ -29,8 +32,17 @@ export class CancelablePromise<Value = void> extends Promise<Value> {
|
|
|
29
32
|
}
|
|
30
33
|
}
|
|
31
34
|
|
|
35
|
+
/**
|
|
36
|
+
* A promise that was fulfilled
|
|
37
|
+
*/
|
|
32
38
|
export type FulfilledPromise<Value> = {
|
|
39
|
+
/**
|
|
40
|
+
* Status of the promise
|
|
41
|
+
*/
|
|
33
42
|
status: typeof PROMISE_TYPE_FULFILLED;
|
|
43
|
+
/**
|
|
44
|
+
* Value of the promise
|
|
45
|
+
*/
|
|
34
46
|
value: Awaited<Value>;
|
|
35
47
|
};
|
|
36
48
|
|
|
@@ -44,6 +56,9 @@ export type PromiseHandlers = {
|
|
|
44
56
|
reject: (reason: unknown) => void;
|
|
45
57
|
};
|
|
46
58
|
|
|
59
|
+
/**
|
|
60
|
+
* Options for a promise-handling function
|
|
61
|
+
*/
|
|
47
62
|
export type PromiseOptions = {
|
|
48
63
|
/**
|
|
49
64
|
* AbortSignal for aborting the promise; when aborted, the promise will reject with the reason of the signal
|
|
@@ -75,6 +90,9 @@ export type PromiseParameters = {
|
|
|
75
90
|
*/
|
|
76
91
|
export type PromiseStrategy = 'complete' | 'first';
|
|
77
92
|
|
|
93
|
+
/**
|
|
94
|
+
* An error thrown when a promise times out
|
|
95
|
+
*/
|
|
78
96
|
export class PromiseTimeoutError extends Error {
|
|
79
97
|
constructor() {
|
|
80
98
|
super(PROMISE_MESSAGE_TIMEOUT);
|
|
@@ -93,8 +111,17 @@ export type PromisesItems<Items extends unknown[]> = {
|
|
|
93
111
|
: Promise<Items[ItemsKey]>;
|
|
94
112
|
};
|
|
95
113
|
|
|
114
|
+
/**
|
|
115
|
+
* Options for handling multiple promises
|
|
116
|
+
*/
|
|
96
117
|
export type PromisesOptions = {
|
|
118
|
+
/**
|
|
119
|
+
* AbortSignal for aborting the promises; when aborted, the promises will reject with the reason of the signal
|
|
120
|
+
*/
|
|
97
121
|
signal?: AbortSignal;
|
|
122
|
+
/**
|
|
123
|
+
* Strategy for handling the promises; defaults to `complete`
|
|
124
|
+
*/
|
|
98
125
|
strategy?: PromiseStrategy;
|
|
99
126
|
};
|
|
100
127
|
|
|
@@ -126,8 +153,17 @@ export type PromisesValues<Items extends unknown[]> = {
|
|
|
126
153
|
: never;
|
|
127
154
|
};
|
|
128
155
|
|
|
156
|
+
/**
|
|
157
|
+
* A promise that was rejected
|
|
158
|
+
*/
|
|
129
159
|
export type RejectedPromise = {
|
|
160
|
+
/**
|
|
161
|
+
* Status of the promise
|
|
162
|
+
*/
|
|
130
163
|
status: typeof PROMISE_TYPE_REJECTED;
|
|
164
|
+
/**
|
|
165
|
+
* Reason for the rejection
|
|
166
|
+
*/
|
|
131
167
|
reason: unknown;
|
|
132
168
|
};
|
|
133
169
|
|
package/src/queue.ts
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
|
+
import {getNumberOrDefault} from './internal/number';
|
|
1
2
|
import type {GenericAsyncCallback, GenericCallback} from './models';
|
|
2
3
|
|
|
3
4
|
// #region Types
|
|
4
5
|
|
|
5
6
|
type HandleType = 'clear' | 'pause' | 'resume';
|
|
6
7
|
|
|
8
|
+
/**
|
|
9
|
+
* A queue that can be used to manage (a)synchronous tasks with a specific key
|
|
10
|
+
*/
|
|
7
11
|
class KeyedQueue<CallbackParameters extends Parameters<GenericAsyncCallback>, CallbackResult> {
|
|
8
12
|
readonly #callback: GenericAsyncCallback;
|
|
9
13
|
|
|
@@ -239,6 +243,9 @@ class KeyedQueue<CallbackParameters extends Parameters<GenericAsyncCallback>, Ca
|
|
|
239
243
|
}
|
|
240
244
|
}
|
|
241
245
|
|
|
246
|
+
/**
|
|
247
|
+
* A queue that can be used to manage (a)synchronous tasks
|
|
248
|
+
*/
|
|
242
249
|
class Queue<CallbackParameters extends Parameters<GenericAsyncCallback>, CallbackResult> {
|
|
243
250
|
readonly #callback: GenericAsyncCallback;
|
|
244
251
|
|
|
@@ -471,13 +478,13 @@ class Queue<CallbackParameters extends Parameters<GenericAsyncCallback>, Callbac
|
|
|
471
478
|
const paused = item;
|
|
472
479
|
|
|
473
480
|
this.#handled.push(() => {
|
|
474
|
-
|
|
481
|
+
handleQueuedResult(paused, error, result, this.#items.length === 0);
|
|
475
482
|
});
|
|
476
483
|
|
|
477
484
|
break;
|
|
478
485
|
}
|
|
479
486
|
|
|
480
|
-
|
|
487
|
+
handleQueuedResult(item, error, result, this.#items.length === 0);
|
|
481
488
|
|
|
482
489
|
item = this.#items.shift();
|
|
483
490
|
}
|
|
@@ -486,6 +493,9 @@ class Queue<CallbackParameters extends Parameters<GenericAsyncCallback>, Callbac
|
|
|
486
493
|
}
|
|
487
494
|
}
|
|
488
495
|
|
|
496
|
+
/**
|
|
497
|
+
* An error thrown by the Queue when an operation fails
|
|
498
|
+
*/
|
|
489
499
|
class QueueError extends Error {
|
|
490
500
|
constructor(message: string) {
|
|
491
501
|
super(message);
|
|
@@ -509,9 +519,12 @@ type QueueOptions = {
|
|
|
509
519
|
maximum?: number;
|
|
510
520
|
};
|
|
511
521
|
|
|
522
|
+
/**
|
|
523
|
+
* A queued item
|
|
524
|
+
*/
|
|
512
525
|
type Queued<Value> = {
|
|
513
526
|
/**
|
|
514
|
-
* ID of the queued
|
|
527
|
+
* ID of the queued item _(can be used to remove it from the queue)_
|
|
515
528
|
*/
|
|
516
529
|
readonly id: number;
|
|
517
530
|
/**
|
|
@@ -554,21 +567,20 @@ function getBooleanOrDefault(value: unknown, defaultValue: boolean): boolean {
|
|
|
554
567
|
return typeof value === 'boolean' ? value : defaultValue;
|
|
555
568
|
}
|
|
556
569
|
|
|
557
|
-
function getNumberOrDefault(value: unknown, defaultValue: number): number {
|
|
558
|
-
return typeof value === 'number' && value > 0 ? Math.floor(value) : defaultValue;
|
|
559
|
-
}
|
|
560
|
-
|
|
561
570
|
function getOptions(input?: QueueOptions): Required<QueueOptions> {
|
|
562
571
|
const options = typeof input === 'object' && input != null ? input : {};
|
|
563
572
|
|
|
564
573
|
return {
|
|
565
574
|
autostart: getBooleanOrDefault(options.autostart, true),
|
|
566
|
-
concurrency: getNumberOrDefault(options.concurrency, 1),
|
|
575
|
+
concurrency: getNumberOrDefault(options.concurrency, 1, 1),
|
|
567
576
|
maximum: getNumberOrDefault(options.maximum, 0),
|
|
568
577
|
};
|
|
569
578
|
}
|
|
570
579
|
|
|
571
|
-
function
|
|
580
|
+
function handleQueuedResult<
|
|
581
|
+
CallbackParameters extends Parameters<GenericAsyncCallback>,
|
|
582
|
+
CallbackResult,
|
|
583
|
+
>(
|
|
572
584
|
item: QueuedItem<CallbackParameters, CallbackResult>,
|
|
573
585
|
error: boolean,
|
|
574
586
|
result: unknown,
|
|
@@ -676,11 +688,11 @@ const STATUS_PAUSED: StatusKey = 'paused';
|
|
|
676
688
|
|
|
677
689
|
export {
|
|
678
690
|
type KeyedQueue,
|
|
679
|
-
type QueueError,
|
|
680
691
|
type Queue,
|
|
681
692
|
type Queued,
|
|
682
|
-
type QueueOptions,
|
|
683
693
|
type QueuedResult,
|
|
694
|
+
type QueueError,
|
|
695
|
+
type QueueOptions,
|
|
684
696
|
};
|
|
685
697
|
|
|
686
698
|
// #endregion
|
package/src/result/index.ts
CHANGED
|
@@ -1,9 +1,5 @@
|
|
|
1
|
-
import {attemptPromise} from '../promise';
|
|
2
|
-
import {matchResult} from './match';
|
|
3
1
|
import {getError, ok} from './misc';
|
|
4
2
|
import type {ExtendedErr, ExtendedResult, Result} from './models';
|
|
5
|
-
import {attemptFlow} from './work/flow';
|
|
6
|
-
import {attemptPipe} from './work/pipe';
|
|
7
3
|
|
|
8
4
|
// #region Functions
|
|
9
5
|
|
|
@@ -99,9 +95,5 @@ export function attempt<Value, E>(
|
|
|
99
95
|
}
|
|
100
96
|
|
|
101
97
|
attempt.async = asyncAttempt;
|
|
102
|
-
attempt.flow = attemptFlow;
|
|
103
|
-
attempt.match = matchResult;
|
|
104
|
-
attempt.pipe = attemptPipe;
|
|
105
|
-
attempt.promise = attemptPromise;
|
|
106
98
|
|
|
107
99
|
// #endregion
|
package/src/result/match.ts
CHANGED
|
@@ -5,6 +5,8 @@ import type {AnyResult, ExtendedErr, ResultMatch} from './models';
|
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Handles a result with match callbacks
|
|
8
|
+
*
|
|
9
|
+
* Available as `asyncMatchResult` and `matchResult.async`
|
|
8
10
|
* @param result Result to handle
|
|
9
11
|
* @param handler Match callbacks
|
|
10
12
|
*/
|
|
@@ -15,6 +17,8 @@ export async function asyncMatchResult<Value, Returned, E = Error>(
|
|
|
15
17
|
|
|
16
18
|
/**
|
|
17
19
|
* Handles a result with match callbacks
|
|
20
|
+
*
|
|
21
|
+
* Available as `asyncMatchResult` and `matchResult.async`
|
|
18
22
|
* @param result Result to handle
|
|
19
23
|
* @param ok Ok callback
|
|
20
24
|
* @param error Error callback
|
|
@@ -58,8 +62,6 @@ export async function asyncMatchResult<Value, Returned, E = Error>(
|
|
|
58
62
|
|
|
59
63
|
/**
|
|
60
64
|
* Handles a result with match callbacks
|
|
61
|
-
*
|
|
62
|
-
* Available as `matchResult` and `attempt.match`
|
|
63
65
|
* @param result Result to handle
|
|
64
66
|
* @param handler Match callbacks
|
|
65
67
|
*/
|
|
@@ -70,8 +72,6 @@ export function matchResult<Value, Returned, E = Error>(
|
|
|
70
72
|
|
|
71
73
|
/**
|
|
72
74
|
* Handles a result with match callbacks
|
|
73
|
-
*
|
|
74
|
-
* Available as `matchResult` and `attempt.match`
|
|
75
75
|
* @param result Result to handle
|
|
76
76
|
* @param ok Ok callback
|
|
77
77
|
* @param error Error callback
|