@terrygonguet/utils 0.4.1 → 0.6.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/async.d.ts +13 -3
- package/dist/async.js +46 -18
- package/dist/index.d.ts +3 -5
- package/dist/index.js +2 -6
- package/dist/result.d.ts +37 -0
- package/dist/result.js +87 -0
- package/package.json +11 -7
package/dist/async.d.ts
CHANGED
|
@@ -5,11 +5,21 @@ interface RetryOptions {
|
|
|
5
5
|
}
|
|
6
6
|
declare function retry(options: RetryOptions): <T>(provider: () => Promise<T>) => Promise<T>;
|
|
7
7
|
declare function retry<T>(provider: () => Promise<T>, options?: RetryOptions): Promise<T>;
|
|
8
|
-
interface AsyncMapOptions {
|
|
8
|
+
interface AsyncMapOptions<FailFast extends boolean = false, WithSourceIndexes extends boolean = false> {
|
|
9
9
|
concurrent?: number;
|
|
10
|
+
failFast?: FailFast;
|
|
11
|
+
withSourceIndexes?: WithSourceIndexes;
|
|
12
|
+
}
|
|
13
|
+
interface AsyncMapResultWithIndexes<U> {
|
|
14
|
+
results: [i: number, value: U][];
|
|
15
|
+
errors: [i: number, error: unknown][];
|
|
16
|
+
}
|
|
17
|
+
interface AsyncMapResult<U> {
|
|
18
|
+
results: U[];
|
|
19
|
+
errors: unknown[];
|
|
10
20
|
}
|
|
11
|
-
declare function asyncMap<T, U>(f: AsyncMapFn<T, U>, options?: AsyncMapOptions): (data: T[]) => Promise<U[]>;
|
|
12
|
-
declare function asyncMap<T, U>(data: T[], f: AsyncMapFn<T, U>, options?: AsyncMapOptions): Promise<U[]>;
|
|
13
21
|
type AsyncMapFn<T, U> = (el: T, i: number, data: T[]) => Promise<U>;
|
|
22
|
+
declare function asyncMap<T, U, FailFast extends boolean = false, WithSourceIndexes extends boolean = false>(f: AsyncMapFn<T, U>, options?: AsyncMapOptions<FailFast, WithSourceIndexes>): (data: T[]) => Promise<FailFast extends true ? WithSourceIndexes extends true ? [i: number, value: U][] : U[] : WithSourceIndexes extends true ? AsyncMapResultWithIndexes<U> : AsyncMapResult<U>>;
|
|
23
|
+
declare function asyncMap<T, U, FailFast extends boolean = false, WithSourceIndexes extends boolean = false>(data: T[], f: AsyncMapFn<T, U>, options?: AsyncMapOptions<FailFast, WithSourceIndexes>): Promise<FailFast extends true ? WithSourceIndexes extends true ? [i: number, value: U][] : U[] : WithSourceIndexes extends true ? AsyncMapResultWithIndexes<U> : AsyncMapResult<U>>;
|
|
14
24
|
|
|
15
25
|
export { asyncMap, pause, retry };
|
package/dist/async.js
CHANGED
|
@@ -40,34 +40,62 @@ function asyncMap(dataOrF, ForOptions, options) {
|
|
|
40
40
|
return asyncMap_(data, f, options);
|
|
41
41
|
} else throw new Error("Invalid arguments passed to asyncMap");
|
|
42
42
|
}
|
|
43
|
-
async function asyncMap_(data, f, {
|
|
43
|
+
async function asyncMap_(data, f, {
|
|
44
|
+
concurrent = 5,
|
|
45
|
+
failFast = false,
|
|
46
|
+
withSourceIndexes = false
|
|
47
|
+
} = {}) {
|
|
44
48
|
return new Promise((resolve, reject) => {
|
|
45
49
|
const resolved = [];
|
|
46
|
-
const
|
|
50
|
+
const errors = [];
|
|
51
|
+
const inFlight = /* @__PURE__ */ new Map();
|
|
47
52
|
let next = 0;
|
|
53
|
+
let stop = false;
|
|
48
54
|
function queue(i) {
|
|
49
|
-
if (
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
const el = data[i];
|
|
53
|
-
inFlight.push([
|
|
55
|
+
if (!stop && i > 0 && inFlight.size == 0) return finish();
|
|
56
|
+
if (stop || i >= data.length) return;
|
|
57
|
+
inFlight.set(
|
|
54
58
|
i,
|
|
55
|
-
f(
|
|
56
|
-
resolved.push([i, result])
|
|
57
|
-
|
|
58
|
-
|
|
59
|
+
f(data[i], i, data).then(
|
|
60
|
+
(result) => void resolved.push([i, result]),
|
|
61
|
+
(error) => {
|
|
62
|
+
if (!failFast) errors.push([i, error]);
|
|
63
|
+
else {
|
|
64
|
+
stop = true;
|
|
65
|
+
reject(error);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
).finally(() => {
|
|
69
|
+
inFlight.delete(i);
|
|
59
70
|
queue(next);
|
|
60
|
-
}
|
|
61
|
-
|
|
71
|
+
})
|
|
72
|
+
);
|
|
62
73
|
next++;
|
|
63
74
|
}
|
|
64
75
|
function finish() {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
76
|
+
resolved.sort(([a], [b]) => a - b);
|
|
77
|
+
if (failFast) {
|
|
78
|
+
if (withSourceIndexes) resolve(resolved);
|
|
79
|
+
else resolve(resolved.map(([, value]) => value));
|
|
80
|
+
} else {
|
|
81
|
+
errors.sort(([a], [b]) => a - b);
|
|
82
|
+
if (withSourceIndexes)
|
|
83
|
+
resolve({
|
|
84
|
+
results: resolved,
|
|
85
|
+
errors
|
|
86
|
+
});
|
|
87
|
+
else
|
|
88
|
+
resolve({
|
|
89
|
+
results: resolved.map(([, value]) => value),
|
|
90
|
+
errors: errors.map(([, error]) => error)
|
|
91
|
+
});
|
|
92
|
+
}
|
|
70
93
|
}
|
|
94
|
+
if (data.length == 0) finish();
|
|
95
|
+
else
|
|
96
|
+
for (let i = 0; i < concurrent; i++) {
|
|
97
|
+
queue(next);
|
|
98
|
+
}
|
|
71
99
|
});
|
|
72
100
|
}
|
|
73
101
|
export {
|
package/dist/index.d.ts
CHANGED
|
@@ -9,9 +9,7 @@ declare function hash(message: string): Promise<ArrayBuffer>;
|
|
|
9
9
|
declare function range(start: number, end: number, step?: number): Generator<number, void, unknown>;
|
|
10
10
|
declare function yesno(value?: string): boolean;
|
|
11
11
|
type ExecResult<T, Err = Error> = [null, T] | [Err, null];
|
|
12
|
-
declare function
|
|
13
|
-
declare function
|
|
14
|
-
declare const exec: typeof safe;
|
|
15
|
-
declare const run: typeof safe;
|
|
12
|
+
declare function tryCatch<F extends (...args: any) => any>(f: F, ...args: Parameters<F>): ReturnType<F> extends Promise<any> ? Promise<ExecResult<Awaited<ReturnType<F>>>> : ExecResult<ReturnType<F>>;
|
|
13
|
+
declare function tryCatch<Err, F extends (...args: any) => any>(f: F, ...args: Parameters<F>): ReturnType<F> extends Promise<any> ? Promise<ExecResult<Awaited<ReturnType<F>>, Err>> : ExecResult<ReturnType<F>, Err>;
|
|
16
14
|
|
|
17
|
-
export { type ExecResult, clamp, createNoopProxy,
|
|
15
|
+
export { type ExecResult, clamp, createNoopProxy, exhaustive, hash, noop, range, tryCatch, yesno };
|
package/dist/index.js
CHANGED
|
@@ -47,7 +47,7 @@ function yesno(value) {
|
|
|
47
47
|
return false;
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
|
-
function
|
|
50
|
+
function tryCatch(f, ...args) {
|
|
51
51
|
try {
|
|
52
52
|
const promiseOrResult = f(...args);
|
|
53
53
|
if (promiseOrResult instanceof Promise)
|
|
@@ -60,17 +60,13 @@ function safe(f, ...args) {
|
|
|
60
60
|
return [error, null];
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
|
-
var exec = safe;
|
|
64
|
-
var run = safe;
|
|
65
63
|
export {
|
|
66
64
|
clamp,
|
|
67
65
|
createNoopProxy,
|
|
68
|
-
exec,
|
|
69
66
|
exhaustive,
|
|
70
67
|
hash,
|
|
71
68
|
noop,
|
|
72
69
|
range,
|
|
73
|
-
|
|
74
|
-
safe,
|
|
70
|
+
tryCatch,
|
|
75
71
|
yesno
|
|
76
72
|
};
|
package/dist/result.d.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
declare class Result<Err extends Error, T> {
|
|
2
|
+
value: T | null;
|
|
3
|
+
error: Err | null;
|
|
4
|
+
constructor(value: T | null, error: Err | null);
|
|
5
|
+
asTuple(): [Err, null] | [null, T];
|
|
6
|
+
asObject(): {
|
|
7
|
+
value: null;
|
|
8
|
+
error: Err;
|
|
9
|
+
} | {
|
|
10
|
+
value: T;
|
|
11
|
+
error: null;
|
|
12
|
+
};
|
|
13
|
+
andThen<Err2 extends Error, F extends (value: T) => any>(f: F): ReturnType<F> extends Promise<any> ? AsyncResult<Err | Err2, Awaited<ReturnType<F>>> : Result<Err | Err2, ReturnType<F>>;
|
|
14
|
+
unwrap(): T;
|
|
15
|
+
unwrapErr(): Err;
|
|
16
|
+
}
|
|
17
|
+
declare class AsyncResult<Err extends Error, T> {
|
|
18
|
+
promise: Promise<T>;
|
|
19
|
+
constructor(promise: Promise<T>);
|
|
20
|
+
asTuple(): Promise<[Err, null] | [null, T]>;
|
|
21
|
+
asObject(): Promise<{
|
|
22
|
+
value: null;
|
|
23
|
+
error: Err;
|
|
24
|
+
} | {
|
|
25
|
+
value: T;
|
|
26
|
+
error: null;
|
|
27
|
+
}>;
|
|
28
|
+
then<U>(cb: (value: Result<Err, T>) => U | Promise<U>): Promise<U>;
|
|
29
|
+
andThen<Err2 extends Error, F extends (value: T) => any>(f: F): AsyncResult<Err | Err2, Awaited<ReturnType<F>>>;
|
|
30
|
+
unwrap(): Promise<T>;
|
|
31
|
+
unwrapErr(): Promise<Err>;
|
|
32
|
+
}
|
|
33
|
+
declare function safe<Err extends Error, T>(promise: Promise<T>): AsyncResult<Error, T>;
|
|
34
|
+
declare function safe<Err extends Error, F extends (...args: any) => Promise<any>>(f: F, ...args: Parameters<F>): AsyncResult<Err, Awaited<ReturnType<F>>>;
|
|
35
|
+
declare function safe<Err extends Error, F extends (...args: any) => any>(f: F, ...args: Parameters<F>): Result<Err, ReturnType<F>>;
|
|
36
|
+
|
|
37
|
+
export { safe };
|
package/dist/result.js
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
// src/result.ts
|
|
2
|
+
var Result = class _Result {
|
|
3
|
+
value;
|
|
4
|
+
error;
|
|
5
|
+
constructor(value, error) {
|
|
6
|
+
this.value = value;
|
|
7
|
+
this.error = error;
|
|
8
|
+
}
|
|
9
|
+
asTuple() {
|
|
10
|
+
return [this.error, this.value];
|
|
11
|
+
}
|
|
12
|
+
asObject() {
|
|
13
|
+
return { value: this.value, error: this.error };
|
|
14
|
+
}
|
|
15
|
+
andThen(f) {
|
|
16
|
+
if (this.error || !this.value) return this;
|
|
17
|
+
try {
|
|
18
|
+
const newValue = f(this.value);
|
|
19
|
+
if (newValue instanceof Promise)
|
|
20
|
+
return new AsyncResult(newValue);
|
|
21
|
+
else return new _Result(newValue, null);
|
|
22
|
+
} catch (error) {
|
|
23
|
+
return new _Result(null, RawError.wrap(error));
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
unwrap() {
|
|
27
|
+
if (this.value && !this.error) return this.value;
|
|
28
|
+
else throw new Error("Tried to unwrap a failed Result");
|
|
29
|
+
}
|
|
30
|
+
unwrapErr() {
|
|
31
|
+
if (this.error) return this.error;
|
|
32
|
+
else throw new Error("Tried to unwrapErr a successful Result");
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
var AsyncResult = class _AsyncResult {
|
|
36
|
+
promise;
|
|
37
|
+
constructor(promise) {
|
|
38
|
+
this.promise = promise;
|
|
39
|
+
}
|
|
40
|
+
asTuple() {
|
|
41
|
+
return this.then((result) => result.asTuple());
|
|
42
|
+
}
|
|
43
|
+
asObject() {
|
|
44
|
+
return this.then((result) => result.asObject());
|
|
45
|
+
}
|
|
46
|
+
then(cb) {
|
|
47
|
+
return this.promise.then(
|
|
48
|
+
(value) => cb(new Result(value, null)),
|
|
49
|
+
(error) => cb(new Result(null, RawError.wrap(error)))
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
andThen(f) {
|
|
53
|
+
return new _AsyncResult(this.promise.then((value) => f(value)));
|
|
54
|
+
}
|
|
55
|
+
unwrap() {
|
|
56
|
+
return this.then((result) => result.unwrap());
|
|
57
|
+
}
|
|
58
|
+
unwrapErr() {
|
|
59
|
+
return this.then((result) => result.unwrapErr());
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
var RawError = class _RawError extends Error {
|
|
63
|
+
name = "RawError";
|
|
64
|
+
value;
|
|
65
|
+
constructor(value) {
|
|
66
|
+
super();
|
|
67
|
+
this.value = value;
|
|
68
|
+
}
|
|
69
|
+
static wrap(error) {
|
|
70
|
+
if (error instanceof Error) return error;
|
|
71
|
+
else return new _RawError(error);
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
function safe(promiseOrFunction, ...args) {
|
|
75
|
+
if (promiseOrFunction instanceof Promise)
|
|
76
|
+
return new AsyncResult(promiseOrFunction);
|
|
77
|
+
try {
|
|
78
|
+
const value = promiseOrFunction(...args);
|
|
79
|
+
if (value instanceof Promise) return new AsyncResult(value);
|
|
80
|
+
else return new Result(value, null);
|
|
81
|
+
} catch (error) {
|
|
82
|
+
return new Result(null, RawError.wrap(error));
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
export {
|
|
86
|
+
safe
|
|
87
|
+
};
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@terrygonguet/utils",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"dev": "vite",
|
|
8
8
|
"build": "tsup",
|
|
9
|
-
"test": "vitest test --update"
|
|
9
|
+
"test": "vitest test --update --typecheck"
|
|
10
10
|
},
|
|
11
11
|
"files": [
|
|
12
12
|
"dist"
|
|
@@ -31,14 +31,18 @@
|
|
|
31
31
|
"./tableau": {
|
|
32
32
|
"types": "./dist/tableau.d.ts",
|
|
33
33
|
"import": "./dist/tableau.js"
|
|
34
|
+
},
|
|
35
|
+
"./result": {
|
|
36
|
+
"types": "./dist/result.d.ts",
|
|
37
|
+
"import": "./dist/result.js"
|
|
34
38
|
}
|
|
35
39
|
},
|
|
36
40
|
"devDependencies": {
|
|
37
|
-
"prettier": "^
|
|
38
|
-
"tsup": "^8.
|
|
39
|
-
"typescript": "^5.
|
|
40
|
-
"vite": "^
|
|
41
|
-
"vitest": "^
|
|
41
|
+
"prettier": "^3.5.3",
|
|
42
|
+
"tsup": "^8.4.0",
|
|
43
|
+
"typescript": "^5.8.2",
|
|
44
|
+
"vite": "^6.2.3",
|
|
45
|
+
"vitest": "^3.0.9"
|
|
42
46
|
},
|
|
43
47
|
"author": {
|
|
44
48
|
"email": "terry@gonguet.com",
|