@terrygonguet/utils 0.10.1 → 0.12.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 → async.d.mts} +12 -11
- package/dist/async.mjs +82 -0
- package/dist/{index.d.ts → index.d.mts} +5 -4
- package/dist/index.mjs +66 -0
- package/dist/{json.d.ts → json.d.mts} +11 -18
- package/dist/json.mjs +87 -0
- package/dist/option.d.mts +52 -0
- package/dist/option.mjs +142 -0
- package/dist/{random.d.ts → random.d.mts} +3 -2
- package/dist/random.mjs +79 -0
- package/dist/result.d.mts +57 -0
- package/dist/result.mjs +129 -0
- package/dist/tableau.d.mts +41 -0
- package/dist/tableau.mjs +91 -0
- package/dist/task.d.mts +38 -0
- package/dist/task.mjs +178 -0
- package/package.json +80 -75
- package/dist/async.js +0 -105
- package/dist/index.js +0 -85
- package/dist/json.js +0 -63
- package/dist/option.d.ts +0 -45
- package/dist/option.js +0 -163
- package/dist/random.js +0 -86
- package/dist/result.d.ts +0 -39
- package/dist/result.js +0 -106
- package/dist/tableau.d.ts +0 -63
- package/dist/tableau.js +0 -125
package/dist/result.mjs
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
//#region 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 {
|
|
14
|
+
value: this.value,
|
|
15
|
+
error: this.error
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
andThen(f) {
|
|
19
|
+
if (this.error) return this;
|
|
20
|
+
try {
|
|
21
|
+
const newValue = f(this.value);
|
|
22
|
+
if (newValue instanceof Promise) return new AsyncResult(newValue);
|
|
23
|
+
else return new Result(newValue, null);
|
|
24
|
+
} catch (error) {
|
|
25
|
+
return new Result(null, RawError.wrap(error));
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
match(onValue, onError) {
|
|
29
|
+
if (this.error) return onError?.(this.error);
|
|
30
|
+
else return onError ? onValue(this.value) : void onValue(this.value);
|
|
31
|
+
}
|
|
32
|
+
recover(f) {
|
|
33
|
+
if (!this.error) return this;
|
|
34
|
+
try {
|
|
35
|
+
const newValue = f(this.error);
|
|
36
|
+
if (newValue instanceof Promise) return new AsyncResult(newValue);
|
|
37
|
+
else return new Result(newValue, null);
|
|
38
|
+
} catch (error) {
|
|
39
|
+
return new Result(null, RawError.wrap(error));
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
unwrap() {
|
|
43
|
+
if (!this.error) return this.value;
|
|
44
|
+
else throw new Error("Tried to unwrap a failed Result");
|
|
45
|
+
}
|
|
46
|
+
unwrapErr() {
|
|
47
|
+
if (this.error) return this.error;
|
|
48
|
+
else throw new Error("Tried to unwrapErr a successful Result");
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
var AsyncResult = class AsyncResult {
|
|
52
|
+
promise;
|
|
53
|
+
constructor(promise) {
|
|
54
|
+
this.promise = promise;
|
|
55
|
+
}
|
|
56
|
+
asTuple() {
|
|
57
|
+
return this.then((result) => result.asTuple());
|
|
58
|
+
}
|
|
59
|
+
asObject() {
|
|
60
|
+
return this.then((result) => result.asObject());
|
|
61
|
+
}
|
|
62
|
+
then(cb) {
|
|
63
|
+
return this.promise.then((value) => cb(new Result(value, null)), (error) => cb(new Result(null, RawError.wrap(error))));
|
|
64
|
+
}
|
|
65
|
+
andThen(f) {
|
|
66
|
+
return new AsyncResult(this.promise.then((value) => f(value)));
|
|
67
|
+
}
|
|
68
|
+
match(onValue, onError) {
|
|
69
|
+
return this.promise.then((value) => onError ? onValue(value) : void onValue(value), (error) => onError?.(error));
|
|
70
|
+
}
|
|
71
|
+
recover(f) {
|
|
72
|
+
return new AsyncResult(this.promise.then((value) => value, (error) => f(error)));
|
|
73
|
+
}
|
|
74
|
+
unwrap() {
|
|
75
|
+
return this.then((result) => result.unwrap());
|
|
76
|
+
}
|
|
77
|
+
unwrapErr() {
|
|
78
|
+
return this.then((result) => result.unwrapErr());
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
var RawError = class RawError extends Error {
|
|
82
|
+
name = "RawError";
|
|
83
|
+
value;
|
|
84
|
+
constructor(value) {
|
|
85
|
+
super();
|
|
86
|
+
this.value = value;
|
|
87
|
+
}
|
|
88
|
+
static wrap(error) {
|
|
89
|
+
if (error instanceof Error) return error;
|
|
90
|
+
else return new RawError(error);
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
function safe(promiseOrFunction, ...args) {
|
|
94
|
+
if (promiseOrFunction instanceof Promise) return new AsyncResult(promiseOrFunction);
|
|
95
|
+
try {
|
|
96
|
+
const value = promiseOrFunction(...args);
|
|
97
|
+
if (value instanceof Promise) return new AsyncResult(value);
|
|
98
|
+
else return new Result(value, null);
|
|
99
|
+
} catch (error) {
|
|
100
|
+
return new Result(null, RawError.wrap(error));
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
var SafeFunctionValidationError = class extends Error {
|
|
104
|
+
name = "SafeFunctionValidationError";
|
|
105
|
+
issues;
|
|
106
|
+
constructor(message, issues, options) {
|
|
107
|
+
super(message, options);
|
|
108
|
+
this.issues = issues;
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
function makeSafeFn(f, options) {
|
|
112
|
+
return function(...args) {
|
|
113
|
+
if (options?.paramsSchema) {
|
|
114
|
+
const parsed = options.paramsSchema["~standard"].validate(args);
|
|
115
|
+
if ("then" in parsed) return new Result(null, /* @__PURE__ */ new TypeError("[makeSafeFn] Parameters check failed: Async schemas are not supported"));
|
|
116
|
+
else if (parsed.issues) return new Result(null, new SafeFunctionValidationError("[makeSafeFn] Parameters check failed", parsed.issues));
|
|
117
|
+
else args = parsed.value;
|
|
118
|
+
}
|
|
119
|
+
if (options?.returnSchema) return safe(f, ...args).andThen((returned) => {
|
|
120
|
+
const parsed = options.returnSchema["~standard"].validate(returned);
|
|
121
|
+
if ("then" in parsed) throw new TypeError("[makeSafeFn] Return check failed: Async schemas are not supported");
|
|
122
|
+
else if (parsed.issues) throw new SafeFunctionValidationError("[makeSafeFn] Return check failed", parsed.issues);
|
|
123
|
+
else return parsed.value;
|
|
124
|
+
});
|
|
125
|
+
else return safe(f, ...args);
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
//#endregion
|
|
129
|
+
export { AsyncResult, Result, SafeFunctionValidationError, makeSafeFn, safe };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
//#region src/tableau.d.ts
|
|
2
|
+
type Predicate<T> = (value: T, index: number, tableau: Tableau<T>) => boolean;
|
|
3
|
+
type AssertPredicate<T, U extends T> = (value: T, index: number, tableau: Tableau<T>) => value is U;
|
|
4
|
+
type Reducer<T, U> = (previousValue: U, currentValue: T, index: number, tableau: Tableau<T>) => U;
|
|
5
|
+
type Mapper<T, U> = (value: T, index: number, tableau: Tableau<T>) => U;
|
|
6
|
+
type Comparer<T> = (a: T, b: T) => number;
|
|
7
|
+
type FlatTableau<Arr, Depth extends number> = {
|
|
8
|
+
done: Arr;
|
|
9
|
+
recur: Arr extends Tableau<infer InnerArr> ? FlatTableau<InnerArr, [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20][Depth]> : Arr;
|
|
10
|
+
}[Depth extends -1 ? "done" : "recur"];
|
|
11
|
+
declare class Tableau<T> extends Array<T> {
|
|
12
|
+
constructor(length?: number);
|
|
13
|
+
i(idx: number): T | undefined;
|
|
14
|
+
ientries(): IterableIterator<[number, T]>;
|
|
15
|
+
ievery<U extends T>(predicate: AssertPredicate<T, U>, thisArg?: any): this is Tableau<U>;
|
|
16
|
+
ievery(predicate: Predicate<T>, thisArg?: any): boolean;
|
|
17
|
+
ifilter<U extends T>(predicate: AssertPredicate<T, U>, thisArg?: any): Tableau<U>;
|
|
18
|
+
ifilter(predicate: Predicate<T>, thisArg?: any): Tableau<T>;
|
|
19
|
+
ifind<U extends T>(predicate: AssertPredicate<T, U>, thisArg?: any): U | undefined;
|
|
20
|
+
ifind(predicate: Predicate<T>, thisArg?: any): T | undefined;
|
|
21
|
+
ifindIndex(predicate: Predicate<T>, thisArg?: any): number | undefined;
|
|
22
|
+
ifindLast<U extends T>(predicate: AssertPredicate<T, U>, thisArg?: any): U | undefined;
|
|
23
|
+
ifindLast(predicate: Predicate<T>, thisArg?: any): T | undefined;
|
|
24
|
+
ifindLastIndex(predicate: Predicate<T>, thisArg?: any): number | undefined;
|
|
25
|
+
iflat<Depth extends number = 1>(depth?: Depth): FlatTableau<T, Depth>;
|
|
26
|
+
iflatMap<U>(callback: Mapper<T, U | Tableau<U>>, thisArg?: any): Tableau<U>;
|
|
27
|
+
iindexOf(searchElement: T, fromIndex?: number): number | undefined;
|
|
28
|
+
ikeys(): IterableIterator<number>;
|
|
29
|
+
ilastIndexOf(searchElement: T, fromIndex?: number): number | undefined;
|
|
30
|
+
imap<U>(callbackFn: Mapper<T, U>, thisArg?: any): Tableau<U>;
|
|
31
|
+
ireduce<U>(callbackFn: Reducer<T, U>, initialValue: U): U;
|
|
32
|
+
ireduceRight<U>(callbackFn: Reducer<T, U>, initialValue: U): U;
|
|
33
|
+
isome(predicate: Predicate<T>, thisArg?: any): boolean;
|
|
34
|
+
isort(compareFn: Comparer<T>): Tableau<T>;
|
|
35
|
+
isplice(start: number, deleteCount?: number, ...items: T[]): Tableau<T>;
|
|
36
|
+
iwith(index: number, value: T): Tableau<T>;
|
|
37
|
+
static from<T>(source: Iterable<T> | ArrayLike<T>): Tableau<T>;
|
|
38
|
+
static of<T>(...elements: T[]): Tableau<T>;
|
|
39
|
+
}
|
|
40
|
+
//#endregion
|
|
41
|
+
export { Tableau };
|
package/dist/tableau.mjs
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
//#region src/tableau.ts
|
|
2
|
+
var Tableau = class Tableau extends Array {
|
|
3
|
+
constructor(length) {
|
|
4
|
+
length == void 0 ? super() : super(length);
|
|
5
|
+
}
|
|
6
|
+
i(idx) {
|
|
7
|
+
if (idx == 0) throw new RangeError("Cannot access index 0 in a Tableau");
|
|
8
|
+
return this.at(idx - 1);
|
|
9
|
+
}
|
|
10
|
+
*ientries() {
|
|
11
|
+
for (let i = 0; i < this.length; i++) yield [i + 1, this[i]];
|
|
12
|
+
}
|
|
13
|
+
ievery(predicate, thisArg) {
|
|
14
|
+
return this.every((value, i) => predicate(value, i + 1, this), thisArg);
|
|
15
|
+
}
|
|
16
|
+
ifilter(predicate, thisArg) {
|
|
17
|
+
return this.filter((value, i) => predicate(value, i + 1, this), thisArg);
|
|
18
|
+
}
|
|
19
|
+
ifind(predicate, thisArg) {
|
|
20
|
+
return this.find((value, i) => predicate(value, i + 1, this), thisArg);
|
|
21
|
+
}
|
|
22
|
+
ifindIndex(predicate, thisArg) {
|
|
23
|
+
const idx = this.findIndex((value, i) => predicate(value, i + 1, this), thisArg);
|
|
24
|
+
return idx == -1 ? void 0 : idx + 1;
|
|
25
|
+
}
|
|
26
|
+
ifindLast(predicate, thisArg) {
|
|
27
|
+
return this.findLast((value, i) => predicate(value, i + 1, this), thisArg);
|
|
28
|
+
}
|
|
29
|
+
ifindLastIndex(predicate, thisArg) {
|
|
30
|
+
const idx = this.findLastIndex((value, i) => predicate(value, i + 1, this), thisArg);
|
|
31
|
+
return idx == -1 ? void 0 : idx + 1;
|
|
32
|
+
}
|
|
33
|
+
iflat(depth) {
|
|
34
|
+
return this.flat(depth);
|
|
35
|
+
}
|
|
36
|
+
iflatMap(callback, thisArg) {
|
|
37
|
+
return this.flatMap((value, i) => callback(value, i + 1, this), thisArg);
|
|
38
|
+
}
|
|
39
|
+
iindexOf(searchElement, fromIndex = 1) {
|
|
40
|
+
if (fromIndex == 0) throw new RangeError("Cannot access index 0 in a Tableau");
|
|
41
|
+
const idx = this.indexOf(searchElement, fromIndex - 1);
|
|
42
|
+
return idx == -1 ? void 0 : idx + 1;
|
|
43
|
+
}
|
|
44
|
+
*ikeys() {
|
|
45
|
+
for (const key of this.keys()) yield key + 1;
|
|
46
|
+
}
|
|
47
|
+
ilastIndexOf(searchElement, fromIndex = this.length) {
|
|
48
|
+
if (fromIndex == 0) throw new RangeError("Cannot access index 0 in a Tableau");
|
|
49
|
+
const idx = this.lastIndexOf(searchElement, fromIndex - 1);
|
|
50
|
+
return idx == -1 ? void 0 : idx + 1;
|
|
51
|
+
}
|
|
52
|
+
imap(callbackFn, thisArg) {
|
|
53
|
+
return this.map((value, i) => callbackFn(value, i + 1, this), thisArg);
|
|
54
|
+
}
|
|
55
|
+
ireduce(callbackFn, initialValue) {
|
|
56
|
+
return this.reduce((acc, cur, i) => callbackFn(acc, cur, i + 1, this), initialValue);
|
|
57
|
+
}
|
|
58
|
+
ireduceRight(callbackFn, initialValue) {
|
|
59
|
+
return this.reduceRight((acc, cur, i) => callbackFn(acc, cur, i + 1, this), initialValue);
|
|
60
|
+
}
|
|
61
|
+
isome(predicate, thisArg) {
|
|
62
|
+
return this.some((value, i) => predicate(value, i + 1, this), thisArg);
|
|
63
|
+
}
|
|
64
|
+
isort(compareFn) {
|
|
65
|
+
return this.toSorted(compareFn);
|
|
66
|
+
}
|
|
67
|
+
isplice(start, deleteCount, ...items) {
|
|
68
|
+
if (start == 0) throw new RangeError("Cannot access index 0 in a Tableau");
|
|
69
|
+
return this.toSpliced(start - 1, deleteCount, ...items);
|
|
70
|
+
}
|
|
71
|
+
iwith(index, value) {
|
|
72
|
+
if (index == 0) throw new RangeError("Cannot access index 0 in a Tableau");
|
|
73
|
+
return this.with(index - 1, value);
|
|
74
|
+
}
|
|
75
|
+
static from(source) {
|
|
76
|
+
if ("length" in source) {
|
|
77
|
+
const litanie = new Tableau(source.length);
|
|
78
|
+
for (let i = 0; i < source.length; i++) litanie[i] = source[i];
|
|
79
|
+
return litanie;
|
|
80
|
+
} else {
|
|
81
|
+
const litanie = new Tableau();
|
|
82
|
+
for (const element of source) litanie.push(element);
|
|
83
|
+
return litanie;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
static of(...elements) {
|
|
87
|
+
return Tableau.from(elements);
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
//#endregion
|
|
91
|
+
export { Tableau };
|
package/dist/task.d.mts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Option } from "./option.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/task.d.ts
|
|
4
|
+
declare class Task<T, E extends Error = Error> {
|
|
5
|
+
_state: {
|
|
6
|
+
type: "pending";
|
|
7
|
+
promise: Promise<void>;
|
|
8
|
+
} | {
|
|
9
|
+
type: "failed";
|
|
10
|
+
error: E;
|
|
11
|
+
} | {
|
|
12
|
+
type: "complete";
|
|
13
|
+
value: T;
|
|
14
|
+
};
|
|
15
|
+
private constructor();
|
|
16
|
+
[Symbol.iterator](): Iterator<Task<T, E>, T>;
|
|
17
|
+
static do<T, E extends Error>(f: () => Iterator<Task<any, E> | Promise<any> | E, T, any>): Task<T, E>;
|
|
18
|
+
static complete<T, E extends Error = Error>(value: T): Task<T, E>;
|
|
19
|
+
static failed<T, E extends Error = Error>(error: E): Task<T, E>;
|
|
20
|
+
static fromPromise<T, E extends Error = Error>(promise: Promise<T>): Task<T, E>;
|
|
21
|
+
static fromOption<T, E extends Error = Error>(option: Option<T>, whenNone: E): Task<T, E>;
|
|
22
|
+
static from<T, E extends Error = Error>(thing: T | E | Promise<T> | Task<T, E>): Task<T, E>;
|
|
23
|
+
static wrapFunction<Args extends any[], T, E extends Error = Error>(f: (...args: Args) => T | Promise<T>): (...args: Args) => Task<T, E>;
|
|
24
|
+
static isTask<T, E extends Error = Error>(maybeTask: unknown): maybeTask is Task<T, E>;
|
|
25
|
+
[Symbol.toPrimitive](): string;
|
|
26
|
+
isPending(): boolean;
|
|
27
|
+
isComplete(): boolean;
|
|
28
|
+
isFailed(): boolean;
|
|
29
|
+
then<U>(onResolve: (value: T) => U | Promise<U>, onReject: (error: E) => U | Promise<U>): U | Promise<U>;
|
|
30
|
+
map<U, E2 extends E>(f: (value: T) => U | Promise<U>): Task<U, E2>;
|
|
31
|
+
flatMap<U, E2 extends E>(f: (value: T) => Task<U, E2>): Task<U, E2>;
|
|
32
|
+
flatten(): T extends Task<infer U> ? Task<U> : Task<T>;
|
|
33
|
+
orDefault(defaultValue: T): Promise<T>;
|
|
34
|
+
unwrap(): T;
|
|
35
|
+
toString(): string;
|
|
36
|
+
}
|
|
37
|
+
//#endregion
|
|
38
|
+
export { Task };
|
package/dist/task.mjs
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
//#region src/task.ts
|
|
2
|
+
var Task = class Task {
|
|
3
|
+
_state;
|
|
4
|
+
constructor(state) {
|
|
5
|
+
if (state.type == "pending") {
|
|
6
|
+
const promise = state.promise.then((value) => {
|
|
7
|
+
this._state = {
|
|
8
|
+
type: "complete",
|
|
9
|
+
value
|
|
10
|
+
};
|
|
11
|
+
}, (error) => {
|
|
12
|
+
this._state = {
|
|
13
|
+
type: "failed",
|
|
14
|
+
error
|
|
15
|
+
};
|
|
16
|
+
});
|
|
17
|
+
this._state = {
|
|
18
|
+
type: "pending",
|
|
19
|
+
promise
|
|
20
|
+
};
|
|
21
|
+
} else this._state = state;
|
|
22
|
+
}
|
|
23
|
+
*[Symbol.iterator]() {
|
|
24
|
+
yield this;
|
|
25
|
+
if (this._state.type == "complete") return this._state.value;
|
|
26
|
+
else if (this._state.type == "pending") throw new Error("Tried to unwrap a pending Task via its iterator");
|
|
27
|
+
else throw new Error("Tried to unwrap a failed Task via its iterator");
|
|
28
|
+
}
|
|
29
|
+
static do(f) {
|
|
30
|
+
const { promise, resolve, reject } = Promise.withResolvers();
|
|
31
|
+
const root = Task.fromPromise(promise);
|
|
32
|
+
const gen = f();
|
|
33
|
+
let iter;
|
|
34
|
+
function step(value) {
|
|
35
|
+
try {
|
|
36
|
+
iter = gen.next(value);
|
|
37
|
+
} catch (error) {
|
|
38
|
+
return stop(error);
|
|
39
|
+
}
|
|
40
|
+
if (iter.done) return resolve(iter.value);
|
|
41
|
+
const yielded = iter.value;
|
|
42
|
+
if (Error.isError(yielded)) stop(yielded);
|
|
43
|
+
else if (Task.isTask(yielded)) switch (yielded._state.type) {
|
|
44
|
+
case "complete":
|
|
45
|
+
step(yielded._state.value);
|
|
46
|
+
break;
|
|
47
|
+
case "failed":
|
|
48
|
+
stop(yielded._state.error);
|
|
49
|
+
break;
|
|
50
|
+
case "pending":
|
|
51
|
+
yielded.then((value) => step(value), (error) => stop(error));
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
else if ("then" in yielded && typeof yielded.then == "function") yielded.then((value) => step(value), (error) => stop(error));
|
|
55
|
+
else step(yielded);
|
|
56
|
+
}
|
|
57
|
+
function stop(error) {
|
|
58
|
+
gen.return?.(void 0);
|
|
59
|
+
reject(error);
|
|
60
|
+
}
|
|
61
|
+
step();
|
|
62
|
+
return root;
|
|
63
|
+
}
|
|
64
|
+
static complete(value) {
|
|
65
|
+
return new Task({
|
|
66
|
+
type: "complete",
|
|
67
|
+
value
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
static failed(error) {
|
|
71
|
+
return new Task({
|
|
72
|
+
type: "failed",
|
|
73
|
+
error
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
static fromPromise(promise) {
|
|
77
|
+
return new Task({
|
|
78
|
+
type: "pending",
|
|
79
|
+
promise
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
static fromOption(option, whenNone) {
|
|
83
|
+
if (option._kind == "Some") return new Task({
|
|
84
|
+
type: "complete",
|
|
85
|
+
value: option.value
|
|
86
|
+
});
|
|
87
|
+
else return new Task({
|
|
88
|
+
type: "failed",
|
|
89
|
+
error: whenNone
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
static from(thing) {
|
|
93
|
+
if (thing instanceof Promise) return Task.fromPromise(thing);
|
|
94
|
+
else if (thing instanceof Error) return Task.failed(thing);
|
|
95
|
+
else if (thing instanceof Task) return thing;
|
|
96
|
+
else return Task.complete(thing);
|
|
97
|
+
}
|
|
98
|
+
static wrapFunction(f) {
|
|
99
|
+
return (...args) => {
|
|
100
|
+
try {
|
|
101
|
+
return Task.from(f(...args));
|
|
102
|
+
} catch (error) {
|
|
103
|
+
if (error instanceof Error) return Task.failed(error);
|
|
104
|
+
else return Task.failed(new Error("Wrapped", { cause: error }));
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
static isTask(maybeTask) {
|
|
109
|
+
return maybeTask instanceof Task;
|
|
110
|
+
}
|
|
111
|
+
[Symbol.toPrimitive]() {
|
|
112
|
+
return this.toString();
|
|
113
|
+
}
|
|
114
|
+
isPending() {
|
|
115
|
+
return this._state.type == "pending";
|
|
116
|
+
}
|
|
117
|
+
isComplete() {
|
|
118
|
+
return this._state.type == "complete";
|
|
119
|
+
}
|
|
120
|
+
isFailed() {
|
|
121
|
+
return this._state.type == "failed";
|
|
122
|
+
}
|
|
123
|
+
then(onResolve, onReject) {
|
|
124
|
+
if (this._state.type == "complete") return onResolve(this._state.value);
|
|
125
|
+
else if (this._state.type == "pending") return this._state.promise.then(() => {
|
|
126
|
+
if (this._state.type == "complete") return onResolve(this._state.value);
|
|
127
|
+
else if (this._state.type == "failed") return onReject(this._state.error);
|
|
128
|
+
else return onReject(/* @__PURE__ */ new Error("Task is in an invalid state"));
|
|
129
|
+
});
|
|
130
|
+
else return onReject(this._state.error);
|
|
131
|
+
}
|
|
132
|
+
map(f) {
|
|
133
|
+
if (this._state.type == "pending") return Task.fromPromise(this._state.promise.then(() => this.map(f)));
|
|
134
|
+
else if (this._state.type == "complete") try {
|
|
135
|
+
const result = f(this._state.value);
|
|
136
|
+
if (result instanceof Promise) return Task.fromPromise(result);
|
|
137
|
+
else return Task.complete(result);
|
|
138
|
+
} catch (error) {
|
|
139
|
+
return Task.failed(error);
|
|
140
|
+
}
|
|
141
|
+
else return this;
|
|
142
|
+
}
|
|
143
|
+
flatMap(f) {
|
|
144
|
+
if (this._state.type == "pending") return Task.fromPromise(this._state.promise.then(() => this.flatMap(f)));
|
|
145
|
+
else if (this._state.type == "complete") return f(this._state.value);
|
|
146
|
+
else return this;
|
|
147
|
+
}
|
|
148
|
+
flatten() {
|
|
149
|
+
if (this._state.type == "complete") return Task.isTask(this._state.value) ? this._state.value : this;
|
|
150
|
+
else if (this._state.type == "failed") return this;
|
|
151
|
+
else return Task.fromPromise(this._state.promise.then(() => this.flatten()));
|
|
152
|
+
}
|
|
153
|
+
orDefault(defaultValue) {
|
|
154
|
+
if (this._state.type == "complete") return Promise.resolve(this._state.value);
|
|
155
|
+
else if (this._state.type == "failed") return Promise.resolve(defaultValue);
|
|
156
|
+
else return this._state.promise.then(() => {
|
|
157
|
+
if (this._state.type == "complete") return this._state.value;
|
|
158
|
+
else return defaultValue;
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
unwrap() {
|
|
162
|
+
if (this._state.type == "complete") return this._state.value;
|
|
163
|
+
else if (this._state.type == "failed") throw new Error("Tried to unwrap a failed Task");
|
|
164
|
+
else throw new Error("Tried to unwrap a pending Task");
|
|
165
|
+
}
|
|
166
|
+
toString() {
|
|
167
|
+
if (this._state.type == "failed") return `Task(Failed: ${this._state.error.message})`;
|
|
168
|
+
else if (this._state.type == "pending") return "Task(Pending)";
|
|
169
|
+
switch (typeof this._state.value) {
|
|
170
|
+
case "string": return `Task(Complete: "${this._state.value}")`;
|
|
171
|
+
case "function":
|
|
172
|
+
case "object": return `Task(Complete: ${JSON.stringify(this._state.value)})`;
|
|
173
|
+
default: return `Task(Complete: ${this._state.value})`;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
//#endregion
|
|
178
|
+
export { Task };
|
package/package.json
CHANGED
|
@@ -1,75 +1,80 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@terrygonguet/utils",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"type": "module",
|
|
5
|
-
"license": "MIT",
|
|
6
|
-
"scripts": {
|
|
7
|
-
"dev": "vitest --watch --typecheck --update",
|
|
8
|
-
"build": "
|
|
9
|
-
"test": "vitest test --typecheck"
|
|
10
|
-
},
|
|
11
|
-
"files": [
|
|
12
|
-
"dist"
|
|
13
|
-
],
|
|
14
|
-
"exports": {
|
|
15
|
-
".": {
|
|
16
|
-
"types": "./dist/index.d.ts",
|
|
17
|
-
"import": "./dist/index.js",
|
|
18
|
-
"default": "./dist/index.js"
|
|
19
|
-
},
|
|
20
|
-
"./async": {
|
|
21
|
-
"types": "./dist/async.d.ts",
|
|
22
|
-
"import": "./dist/async.js",
|
|
23
|
-
"default": "./dist/async.js"
|
|
24
|
-
},
|
|
25
|
-
"./json": {
|
|
26
|
-
"types": "./dist/json.d.ts",
|
|
27
|
-
"import": "./dist/json.js",
|
|
28
|
-
"default": "./dist/json.js"
|
|
29
|
-
},
|
|
30
|
-
"./option": {
|
|
31
|
-
"types": "./dist/option.d.ts",
|
|
32
|
-
"import": "./dist/option.js",
|
|
33
|
-
"default": "./dist/option.js"
|
|
34
|
-
},
|
|
35
|
-
"./random": {
|
|
36
|
-
"types": "./dist/random.d.ts",
|
|
37
|
-
"import": "./dist/random.js",
|
|
38
|
-
"default": "./dist/random.js"
|
|
39
|
-
},
|
|
40
|
-
"./result": {
|
|
41
|
-
"types": "./dist/result.d.ts",
|
|
42
|
-
"import": "./dist/result.js",
|
|
43
|
-
"default": "./dist/result.js"
|
|
44
|
-
},
|
|
45
|
-
"./tableau": {
|
|
46
|
-
"types": "./dist/tableau.d.ts",
|
|
47
|
-
"import": "./dist/tableau.js",
|
|
48
|
-
"default": "./dist/tableau.js"
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
"
|
|
58
|
-
"
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
"
|
|
62
|
-
"
|
|
63
|
-
"
|
|
64
|
-
},
|
|
65
|
-
"
|
|
66
|
-
"
|
|
67
|
-
"
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "@terrygonguet/utils",
|
|
3
|
+
"version": "0.12.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "vitest --watch --typecheck --update",
|
|
8
|
+
"build": "tsdown",
|
|
9
|
+
"test": "vitest test --typecheck"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"dist"
|
|
13
|
+
],
|
|
14
|
+
"exports": {
|
|
15
|
+
".": {
|
|
16
|
+
"types": "./dist/index.d.ts",
|
|
17
|
+
"import": "./dist/index.js",
|
|
18
|
+
"default": "./dist/index.js"
|
|
19
|
+
},
|
|
20
|
+
"./async": {
|
|
21
|
+
"types": "./dist/async.d.ts",
|
|
22
|
+
"import": "./dist/async.js",
|
|
23
|
+
"default": "./dist/async.js"
|
|
24
|
+
},
|
|
25
|
+
"./json": {
|
|
26
|
+
"types": "./dist/json.d.ts",
|
|
27
|
+
"import": "./dist/json.js",
|
|
28
|
+
"default": "./dist/json.js"
|
|
29
|
+
},
|
|
30
|
+
"./option": {
|
|
31
|
+
"types": "./dist/option.d.ts",
|
|
32
|
+
"import": "./dist/option.js",
|
|
33
|
+
"default": "./dist/option.js"
|
|
34
|
+
},
|
|
35
|
+
"./random": {
|
|
36
|
+
"types": "./dist/random.d.ts",
|
|
37
|
+
"import": "./dist/random.js",
|
|
38
|
+
"default": "./dist/random.js"
|
|
39
|
+
},
|
|
40
|
+
"./result": {
|
|
41
|
+
"types": "./dist/result.d.ts",
|
|
42
|
+
"import": "./dist/result.js",
|
|
43
|
+
"default": "./dist/result.js"
|
|
44
|
+
},
|
|
45
|
+
"./tableau": {
|
|
46
|
+
"types": "./dist/tableau.d.ts",
|
|
47
|
+
"import": "./dist/tableau.js",
|
|
48
|
+
"default": "./dist/tableau.js"
|
|
49
|
+
},
|
|
50
|
+
"./task": {
|
|
51
|
+
"types": "./dist/task.d.ts",
|
|
52
|
+
"import": "./dist/task.js",
|
|
53
|
+
"default": "./dist/task.js"
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
"devDependencies": {
|
|
57
|
+
"@types/benchmark": "^2.1.5",
|
|
58
|
+
"benchmark": "^2.1.4",
|
|
59
|
+
"prettier": "^3.8.3",
|
|
60
|
+
"tsdown": "^0.21.10",
|
|
61
|
+
"typescript": "^6.0.3",
|
|
62
|
+
"vite": "^8.0.10",
|
|
63
|
+
"vitest": "^4.1.5"
|
|
64
|
+
},
|
|
65
|
+
"author": {
|
|
66
|
+
"email": "terry@gonguet.com",
|
|
67
|
+
"name": "Terry Gonguet",
|
|
68
|
+
"url": "https://terry.gonguet.com/"
|
|
69
|
+
},
|
|
70
|
+
"repository": {
|
|
71
|
+
"type": "git",
|
|
72
|
+
"url": "git+https://github.com/terrygonguet/utils.git"
|
|
73
|
+
},
|
|
74
|
+
"bugs": {
|
|
75
|
+
"url": "https://github.com/terrygonguet/utils/issues"
|
|
76
|
+
},
|
|
77
|
+
"dependencies": {
|
|
78
|
+
"@standard-schema/spec": "^1.1.0"
|
|
79
|
+
}
|
|
80
|
+
}
|