@terrygonguet/utils 0.7.1 → 0.9.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/index.d.ts +3 -1
- package/dist/index.js +13 -0
- package/dist/json.d.ts +22 -1
- package/dist/json.js +53 -1
- package/dist/option.d.ts +45 -0
- package/dist/option.js +163 -0
- package/package.json +20 -11
package/dist/index.d.ts
CHANGED
|
@@ -8,8 +8,10 @@ declare function exhaustive(_: never): never;
|
|
|
8
8
|
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
|
+
declare function mapListPush<Key, T>(map: Map<Key, T[]>, key: Key, value: T): Map<Key, T[]>;
|
|
12
|
+
declare function recordListPush<Key extends string, T>(record: Record<Key, T[]>, key: Key, value: T): Record<Key, T[]>;
|
|
11
13
|
type ExecResult<T, Err = Error> = [null, T] | [Err, null];
|
|
12
14
|
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
15
|
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>;
|
|
14
16
|
|
|
15
|
-
export { type ExecResult, clamp, createNoopProxy, exhaustive, hash, noop, range, tryCatch, yesno };
|
|
17
|
+
export { type ExecResult, clamp, createNoopProxy, exhaustive, hash, mapListPush, noop, range, recordListPush, tryCatch, yesno };
|
package/dist/index.js
CHANGED
|
@@ -47,6 +47,17 @@ function yesno(value) {
|
|
|
47
47
|
return false;
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
|
+
function mapListPush(map, key, value) {
|
|
51
|
+
const arr = map.get(key) ?? [];
|
|
52
|
+
arr.push(value);
|
|
53
|
+
return map.set(key, arr);
|
|
54
|
+
}
|
|
55
|
+
function recordListPush(record, key, value) {
|
|
56
|
+
const arr = record[key] ?? [];
|
|
57
|
+
arr.push(value);
|
|
58
|
+
record[key] = arr;
|
|
59
|
+
return record;
|
|
60
|
+
}
|
|
50
61
|
function tryCatch(f, ...args) {
|
|
51
62
|
try {
|
|
52
63
|
const promiseOrResult = f(...args);
|
|
@@ -65,8 +76,10 @@ export {
|
|
|
65
76
|
createNoopProxy,
|
|
66
77
|
exhaustive,
|
|
67
78
|
hash,
|
|
79
|
+
mapListPush,
|
|
68
80
|
noop,
|
|
69
81
|
range,
|
|
82
|
+
recordListPush,
|
|
70
83
|
tryCatch,
|
|
71
84
|
yesno
|
|
72
85
|
};
|
package/dist/json.d.ts
CHANGED
|
@@ -1,7 +1,28 @@
|
|
|
1
|
+
import { StandardSchemaV1 } from '@standard-schema/spec';
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* This function does no runtime type checking,
|
|
3
5
|
* make sure that the parsed value is valid
|
|
4
6
|
*/
|
|
5
7
|
declare function safeParse<T>(str: string, defaultValue: T, reviver?: (key: string, value: any) => any): T;
|
|
8
|
+
type SchemaParseReturn<Schema extends StandardSchemaV1> = [parseError: Error, validationFailure: null, output: null] | [
|
|
9
|
+
parseError: null,
|
|
10
|
+
validationFailure: StandardSchemaV1.FailureResult,
|
|
11
|
+
output: null
|
|
12
|
+
] | [
|
|
13
|
+
parseError: null,
|
|
14
|
+
validationFailure: null,
|
|
15
|
+
output: StandardSchemaV1.InferOutput<Schema>
|
|
16
|
+
];
|
|
17
|
+
declare function schemaParse<Schema extends StandardSchemaV1, Async extends boolean = false>(schema: Schema, str: string, options?: {
|
|
18
|
+
reviver?(key: string, value: any): any;
|
|
19
|
+
async?: Async;
|
|
20
|
+
}): Async extends true ? Promise<SchemaParseReturn<Schema>> : SchemaParseReturn<Schema>;
|
|
21
|
+
declare function schemaParseWithDefault<Schema extends StandardSchemaV1, Async extends boolean = false>(schema: Schema, str: string, defaultValue: StandardSchemaV1.InferOutput<Schema>, options?: {
|
|
22
|
+
reviver?(key: string, value: any): any;
|
|
23
|
+
async?: Async;
|
|
24
|
+
out_parseError?: Error[];
|
|
25
|
+
out_validationFailure?: StandardSchemaV1.FailureResult[];
|
|
26
|
+
}): Async extends true ? Promise<StandardSchemaV1.InferOutput<Schema>> : StandardSchemaV1.InferOutput<Schema>;
|
|
6
27
|
|
|
7
|
-
export { safeParse };
|
|
28
|
+
export { safeParse, schemaParse, schemaParseWithDefault };
|
package/dist/json.js
CHANGED
|
@@ -6,6 +6,58 @@ function safeParse(str, defaultValue, reviver) {
|
|
|
6
6
|
return defaultValue;
|
|
7
7
|
}
|
|
8
8
|
}
|
|
9
|
+
function schemaParse(schema, str, options) {
|
|
10
|
+
try {
|
|
11
|
+
const parsed = JSON.parse(str, options?.reviver);
|
|
12
|
+
const result = schema["~standard"].validate(parsed);
|
|
13
|
+
if (options?.async) {
|
|
14
|
+
if (result instanceof Promise) {
|
|
15
|
+
return result.then(
|
|
16
|
+
(result2) => result2.issues ? [null, result2, null] : [null, null, result2.value],
|
|
17
|
+
(err) => [err, null, null]
|
|
18
|
+
);
|
|
19
|
+
} else {
|
|
20
|
+
return Promise.resolve(
|
|
21
|
+
result.issues ? [null, result, null] : [null, null, result.value]
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
} else {
|
|
25
|
+
if (result instanceof Promise)
|
|
26
|
+
throw new Error(
|
|
27
|
+
"Function schemaParse() whas called with an async schema but without the async flag"
|
|
28
|
+
);
|
|
29
|
+
else if (result.issues) return [null, result, null];
|
|
30
|
+
else return [null, null, result.value];
|
|
31
|
+
}
|
|
32
|
+
} catch (error) {
|
|
33
|
+
return [error, null, null];
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function schemaParseWithDefault(schema, str, defaultValue, options) {
|
|
37
|
+
const result = schemaParse(schema, str, options);
|
|
38
|
+
if (result instanceof Promise) {
|
|
39
|
+
return result.then(([error, failure, value]) => {
|
|
40
|
+
if (failure) {
|
|
41
|
+
options?.out_validationFailure?.push(failure);
|
|
42
|
+
return defaultValue;
|
|
43
|
+
} else if (error) {
|
|
44
|
+
options?.out_parseError?.push(error);
|
|
45
|
+
return defaultValue;
|
|
46
|
+
} else return value;
|
|
47
|
+
});
|
|
48
|
+
} else {
|
|
49
|
+
const [error, failure, value] = result;
|
|
50
|
+
if (failure) {
|
|
51
|
+
options?.out_validationFailure?.push(failure);
|
|
52
|
+
return defaultValue;
|
|
53
|
+
} else if (error) {
|
|
54
|
+
options?.out_parseError?.push(error);
|
|
55
|
+
return defaultValue;
|
|
56
|
+
} else return value;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
9
59
|
export {
|
|
10
|
-
safeParse
|
|
60
|
+
safeParse,
|
|
61
|
+
schemaParse,
|
|
62
|
+
schemaParseWithDefault
|
|
11
63
|
};
|
package/dist/option.d.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
declare class Option<T> {
|
|
2
|
+
#private;
|
|
3
|
+
readonly _kind: "Some" | "None";
|
|
4
|
+
readonly value: T;
|
|
5
|
+
private constructor();
|
|
6
|
+
static do<T>(f: () => Iterator<Option<any>, T, any>): Option<T>;
|
|
7
|
+
static from<T>(maybeValue: unknown, { allowOptionLikePOJO }?: {
|
|
8
|
+
allowOptionLikePOJO?: boolean | undefined;
|
|
9
|
+
}): Option<T>;
|
|
10
|
+
static wrapFunction<T, Args extends any[]>(f: (...args: Args) => T | undefined | null, { allowOptionLikePOJO }?: {
|
|
11
|
+
allowOptionLikePOJO?: boolean | undefined;
|
|
12
|
+
}): (...args: Args) => Option<T>;
|
|
13
|
+
static isOption<T>(maybeOption: unknown): maybeOption is Option<T>;
|
|
14
|
+
static Some<T>(value: T): Option<T>;
|
|
15
|
+
static None<T>(): Option<T>;
|
|
16
|
+
[Symbol.iterator](): Iterator<Option<T>, T>;
|
|
17
|
+
[Symbol.toPrimitive](): string;
|
|
18
|
+
isSome(): boolean;
|
|
19
|
+
isNone(): boolean;
|
|
20
|
+
equals(other: Option<T>): boolean;
|
|
21
|
+
map<U>(f: (value: T) => U, { coalesce }?: {
|
|
22
|
+
coalesce?: boolean | undefined;
|
|
23
|
+
}): Option<U>;
|
|
24
|
+
flatMap<U>(f: (value: T) => Option<U>): Option<U>;
|
|
25
|
+
flatten(): T extends Option<infer U> ? Option<U> : Option<T>;
|
|
26
|
+
orDefault(defaultValue: T): T;
|
|
27
|
+
orNull(): T | null;
|
|
28
|
+
orUndefined(): T | undefined;
|
|
29
|
+
or<U>(other: Option<U>): Option<T> | Option<U>;
|
|
30
|
+
unwrap(): T;
|
|
31
|
+
filter<U extends T>(predicate: (value: T) => value is U): Option<U>;
|
|
32
|
+
filter(predicate: (value: T) => boolean): Option<T>;
|
|
33
|
+
toString(): string;
|
|
34
|
+
}
|
|
35
|
+
declare function arrayGet<T>(arr: T[], i: number): Option<T>;
|
|
36
|
+
declare function arrayFind<T>(arr: T[], predicate: (item: T, i: number, arr: T[]) => boolean, thisArg?: any): Option<T>;
|
|
37
|
+
declare function arrayFindLast<T>(arr: T[], predicate: (item: T, i: number, arr: T[]) => boolean, thisArg?: any): Option<T>;
|
|
38
|
+
declare function arrayFindIndex<T>(arr: T[], predicate: (item: T, i: number, arr: T[]) => boolean, thisArg?: any): Option<number>;
|
|
39
|
+
declare function arrayFindLastIndex<T>(arr: T[], predicate: (item: T, i: number, arr: T[]) => boolean, thisArg?: any): Option<number>;
|
|
40
|
+
declare function arrayIndexOf<T>(arr: T[], item: T, fromIndex?: number): Option<number>;
|
|
41
|
+
declare function arrayLastIndexOf<T>(arr: T[], item: T, fromIndex?: number): Option<number>;
|
|
42
|
+
declare function arrPop<T>(arr: T[]): Option<T>;
|
|
43
|
+
declare function arrShift<T>(arr: T[]): Option<T>;
|
|
44
|
+
|
|
45
|
+
export { Option, arrPop, arrShift, arrayFind, arrayFindIndex, arrayFindLast, arrayFindLastIndex, arrayGet, arrayIndexOf, arrayLastIndexOf };
|
package/dist/option.js
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
// src/option.ts
|
|
2
|
+
var Option = class _Option {
|
|
3
|
+
_kind;
|
|
4
|
+
value;
|
|
5
|
+
constructor(_kind, value = void 0) {
|
|
6
|
+
this._kind = _kind;
|
|
7
|
+
this.value = value;
|
|
8
|
+
}
|
|
9
|
+
static do(f) {
|
|
10
|
+
const gen = f();
|
|
11
|
+
let iter = gen.next();
|
|
12
|
+
while (!iter.done) {
|
|
13
|
+
switch (iter.value._kind) {
|
|
14
|
+
case "Some":
|
|
15
|
+
iter = gen.next(iter.value.value);
|
|
16
|
+
break;
|
|
17
|
+
case "None":
|
|
18
|
+
gen.return?.(void 0);
|
|
19
|
+
return _Option.None();
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return _Option.Some(iter.value);
|
|
23
|
+
}
|
|
24
|
+
static from(maybeValue, { allowOptionLikePOJO = false } = {}) {
|
|
25
|
+
if (maybeValue === void 0 || maybeValue === null)
|
|
26
|
+
return _Option.None();
|
|
27
|
+
else if (_Option.isOption(maybeValue)) return maybeValue;
|
|
28
|
+
else if (allowOptionLikePOJO && maybeValue && typeof maybeValue == "object" && "_kind" in maybeValue && (maybeValue._kind == "Some" || maybeValue._kind == "None"))
|
|
29
|
+
return new _Option(
|
|
30
|
+
maybeValue._kind,
|
|
31
|
+
maybeValue.value
|
|
32
|
+
);
|
|
33
|
+
else return _Option.Some(maybeValue);
|
|
34
|
+
}
|
|
35
|
+
static wrapFunction(f, { allowOptionLikePOJO = false } = {}) {
|
|
36
|
+
return (...args) => _Option.from(f(...args), { allowOptionLikePOJO });
|
|
37
|
+
}
|
|
38
|
+
static isOption(maybeOption) {
|
|
39
|
+
return maybeOption instanceof _Option;
|
|
40
|
+
}
|
|
41
|
+
static Some(value) {
|
|
42
|
+
return new _Option("Some", value);
|
|
43
|
+
}
|
|
44
|
+
static #None = new _Option("None");
|
|
45
|
+
static None() {
|
|
46
|
+
return this.#None;
|
|
47
|
+
}
|
|
48
|
+
*[Symbol.iterator]() {
|
|
49
|
+
yield this;
|
|
50
|
+
if (this.isNone())
|
|
51
|
+
throw new Error("Tried to unwrap a None() via its iterator");
|
|
52
|
+
else return this.value;
|
|
53
|
+
}
|
|
54
|
+
[Symbol.toPrimitive]() {
|
|
55
|
+
return this.toString();
|
|
56
|
+
}
|
|
57
|
+
isSome() {
|
|
58
|
+
return this._kind == "Some";
|
|
59
|
+
}
|
|
60
|
+
isNone() {
|
|
61
|
+
return this._kind == "None";
|
|
62
|
+
}
|
|
63
|
+
equals(other) {
|
|
64
|
+
if (this.isNone()) return other.isNone();
|
|
65
|
+
else if (other.isNone()) return false;
|
|
66
|
+
else return this.value == other.value;
|
|
67
|
+
}
|
|
68
|
+
map(f, { coalesce = false } = {}) {
|
|
69
|
+
if (this.isNone()) return _Option.None();
|
|
70
|
+
else if (coalesce) return _Option.from(f(this.value));
|
|
71
|
+
else return _Option.Some(f(this.value));
|
|
72
|
+
}
|
|
73
|
+
flatMap(f) {
|
|
74
|
+
if (this.isNone()) return _Option.None();
|
|
75
|
+
else return f(this.value);
|
|
76
|
+
}
|
|
77
|
+
flatten() {
|
|
78
|
+
if (this.isNone()) return _Option.None();
|
|
79
|
+
else return _Option.isOption(this.value) ? this.value : this;
|
|
80
|
+
}
|
|
81
|
+
orDefault(defaultValue) {
|
|
82
|
+
if (this.isNone()) return defaultValue;
|
|
83
|
+
else return this.value;
|
|
84
|
+
}
|
|
85
|
+
orNull() {
|
|
86
|
+
if (this.isNone()) return null;
|
|
87
|
+
else return this.value;
|
|
88
|
+
}
|
|
89
|
+
orUndefined() {
|
|
90
|
+
if (this.isNone()) return void 0;
|
|
91
|
+
else return this.value;
|
|
92
|
+
}
|
|
93
|
+
or(other) {
|
|
94
|
+
if (this.isNone()) return other;
|
|
95
|
+
else return this;
|
|
96
|
+
}
|
|
97
|
+
unwrap() {
|
|
98
|
+
if (this.isNone()) throw new Error("Tried to unwrap a None()");
|
|
99
|
+
else return this.value;
|
|
100
|
+
}
|
|
101
|
+
filter(predicate) {
|
|
102
|
+
if (this.isNone()) return this;
|
|
103
|
+
else return predicate(this.value) ? this : _Option.None();
|
|
104
|
+
}
|
|
105
|
+
toString() {
|
|
106
|
+
if (this.isNone()) return "None()";
|
|
107
|
+
switch (typeof this.value) {
|
|
108
|
+
case "string":
|
|
109
|
+
return `Some("${this.value}")`;
|
|
110
|
+
case "function":
|
|
111
|
+
case "object":
|
|
112
|
+
return `Some(${JSON.stringify(this.value)})`;
|
|
113
|
+
default:
|
|
114
|
+
return `Some(${this.value})`;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
function arrayGet(arr, i) {
|
|
119
|
+
if (i >= arr.length || i < 0) return Option.None();
|
|
120
|
+
else return Option.Some(arr[i]);
|
|
121
|
+
}
|
|
122
|
+
function arrayFind(arr, predicate, thisArg) {
|
|
123
|
+
return Option.from(arr.find(predicate, thisArg));
|
|
124
|
+
}
|
|
125
|
+
function arrayFindLast(arr, predicate, thisArg) {
|
|
126
|
+
return Option.from(arr.findLast(predicate, thisArg));
|
|
127
|
+
}
|
|
128
|
+
function arrayFindIndex(arr, predicate, thisArg) {
|
|
129
|
+
const idx = arr.findIndex(predicate, thisArg);
|
|
130
|
+
return idx == -1 ? Option.None() : Option.Some(idx);
|
|
131
|
+
}
|
|
132
|
+
function arrayFindLastIndex(arr, predicate, thisArg) {
|
|
133
|
+
const idx = arr.findLastIndex(predicate, thisArg);
|
|
134
|
+
return idx == -1 ? Option.None() : Option.Some(idx);
|
|
135
|
+
}
|
|
136
|
+
function arrayIndexOf(arr, item, fromIndex) {
|
|
137
|
+
const idx = arr.indexOf(item, fromIndex);
|
|
138
|
+
return idx == -1 ? Option.None() : Option.Some(idx);
|
|
139
|
+
}
|
|
140
|
+
function arrayLastIndexOf(arr, item, fromIndex) {
|
|
141
|
+
const idx = arr.lastIndexOf(item, fromIndex);
|
|
142
|
+
return idx == -1 ? Option.None() : Option.Some(idx);
|
|
143
|
+
}
|
|
144
|
+
function arrPop(arr) {
|
|
145
|
+
if (arr.length == 0) return Option.None();
|
|
146
|
+
else return Option.Some(arr.pop());
|
|
147
|
+
}
|
|
148
|
+
function arrShift(arr) {
|
|
149
|
+
if (arr.length == 0) return Option.None();
|
|
150
|
+
else return Option.Some(arr.shift());
|
|
151
|
+
}
|
|
152
|
+
export {
|
|
153
|
+
Option,
|
|
154
|
+
arrPop,
|
|
155
|
+
arrShift,
|
|
156
|
+
arrayFind,
|
|
157
|
+
arrayFindIndex,
|
|
158
|
+
arrayFindLast,
|
|
159
|
+
arrayFindLastIndex,
|
|
160
|
+
arrayGet,
|
|
161
|
+
arrayIndexOf,
|
|
162
|
+
arrayLastIndexOf
|
|
163
|
+
};
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@terrygonguet/utils",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"dev": "vite",
|
|
8
8
|
"build": "tsup",
|
|
9
|
-
"test": "vitest test --
|
|
9
|
+
"test": "vitest test --typecheck"
|
|
10
10
|
},
|
|
11
11
|
"files": [
|
|
12
12
|
"dist"
|
|
@@ -24,25 +24,31 @@
|
|
|
24
24
|
"types": "./dist/json.d.ts",
|
|
25
25
|
"import": "./dist/json.js"
|
|
26
26
|
},
|
|
27
|
+
"./option": {
|
|
28
|
+
"types": "./dist/option.d.ts",
|
|
29
|
+
"import": "./dist/option.js"
|
|
30
|
+
},
|
|
27
31
|
"./random": {
|
|
28
32
|
"types": "./dist/random.d.ts",
|
|
29
33
|
"import": "./dist/random.js"
|
|
30
34
|
},
|
|
31
|
-
"./tableau": {
|
|
32
|
-
"types": "./dist/tableau.d.ts",
|
|
33
|
-
"import": "./dist/tableau.js"
|
|
34
|
-
},
|
|
35
35
|
"./result": {
|
|
36
36
|
"types": "./dist/result.d.ts",
|
|
37
37
|
"import": "./dist/result.js"
|
|
38
|
+
},
|
|
39
|
+
"./tableau": {
|
|
40
|
+
"types": "./dist/tableau.d.ts",
|
|
41
|
+
"import": "./dist/tableau.js"
|
|
38
42
|
}
|
|
39
43
|
},
|
|
40
44
|
"devDependencies": {
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
45
|
+
"@types/benchmark": "^2.1.5",
|
|
46
|
+
"benchmark": "^2.1.4",
|
|
47
|
+
"prettier": "^3.6.2",
|
|
48
|
+
"tsup": "^8.5.0",
|
|
49
|
+
"typescript": "^5.9.3",
|
|
50
|
+
"vite": "^6.3.6",
|
|
51
|
+
"vitest": "^3.2.4"
|
|
46
52
|
},
|
|
47
53
|
"author": {
|
|
48
54
|
"email": "terry@gonguet.com",
|
|
@@ -55,5 +61,8 @@
|
|
|
55
61
|
},
|
|
56
62
|
"bugs": {
|
|
57
63
|
"url": "https://github.com/terrygonguet/utils/issues"
|
|
64
|
+
},
|
|
65
|
+
"dependencies": {
|
|
66
|
+
"@standard-schema/spec": "^1.0.0"
|
|
58
67
|
}
|
|
59
68
|
}
|