guarden 1.0.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/LICENSE +21 -0
- package/README.md +370 -0
- package/dist/cjs/assert/assertions.js +82 -0
- package/dist/cjs/assert/assertions.js.map +1 -0
- package/dist/cjs/assert/index.js +13 -0
- package/dist/cjs/assert/index.js.map +1 -0
- package/dist/cjs/assert/invariant.js +43 -0
- package/dist/cjs/assert/invariant.js.map +1 -0
- package/dist/cjs/env/index.js +11 -0
- package/dist/cjs/env/index.js.map +1 -0
- package/dist/cjs/env/schema.js +313 -0
- package/dist/cjs/env/schema.js.map +1 -0
- package/dist/cjs/guards/advanced.js +190 -0
- package/dist/cjs/guards/advanced.js.map +1 -0
- package/dist/cjs/guards/combinators.js +195 -0
- package/dist/cjs/guards/combinators.js.map +1 -0
- package/dist/cjs/guards/index.js +68 -0
- package/dist/cjs/guards/index.js.map +1 -0
- package/dist/cjs/guards/primitives.js +123 -0
- package/dist/cjs/guards/primitives.js.map +1 -0
- package/dist/cjs/guards/structures.js +113 -0
- package/dist/cjs/guards/structures.js.map +1 -0
- package/dist/cjs/index.js +135 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/result/async.js +132 -0
- package/dist/cjs/result/async.js.map +1 -0
- package/dist/cjs/result/index.js +15 -0
- package/dist/cjs/result/index.js.map +1 -0
- package/dist/cjs/result/option.js +175 -0
- package/dist/cjs/result/option.js.map +1 -0
- package/dist/cjs/result/result.js +208 -0
- package/dist/cjs/result/result.js.map +1 -0
- package/dist/cjs/transform/coerce.js +151 -0
- package/dist/cjs/transform/coerce.js.map +1 -0
- package/dist/cjs/transform/index.js +36 -0
- package/dist/cjs/transform/index.js.map +1 -0
- package/dist/cjs/transform/pipe.js +18 -0
- package/dist/cjs/transform/pipe.js.map +1 -0
- package/dist/cjs/transform/sanitize.js +218 -0
- package/dist/cjs/transform/sanitize.js.map +1 -0
- package/dist/cjs/utils/errors.js +94 -0
- package/dist/cjs/utils/errors.js.map +1 -0
- package/dist/cjs/utils/types.js +6 -0
- package/dist/cjs/utils/types.js.map +1 -0
- package/dist/esm/assert/assertions.js +75 -0
- package/dist/esm/assert/assertions.js.map +1 -0
- package/dist/esm/assert/index.js +3 -0
- package/dist/esm/assert/index.js.map +1 -0
- package/dist/esm/assert/invariant.js +39 -0
- package/dist/esm/assert/invariant.js.map +1 -0
- package/dist/esm/env/index.js +2 -0
- package/dist/esm/env/index.js.map +1 -0
- package/dist/esm/env/schema.js +304 -0
- package/dist/esm/env/schema.js.map +1 -0
- package/dist/esm/guards/advanced.js +170 -0
- package/dist/esm/guards/advanced.js.map +1 -0
- package/dist/esm/guards/combinators.js +182 -0
- package/dist/esm/guards/combinators.js.map +1 -0
- package/dist/esm/guards/index.js +8 -0
- package/dist/esm/guards/index.js.map +1 -0
- package/dist/esm/guards/primitives.js +108 -0
- package/dist/esm/guards/primitives.js.map +1 -0
- package/dist/esm/guards/structures.js +97 -0
- package/dist/esm/guards/structures.js.map +1 -0
- package/dist/esm/index.js +17 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/result/async.js +127 -0
- package/dist/esm/result/async.js.map +1 -0
- package/dist/esm/result/index.js +4 -0
- package/dist/esm/result/index.js.map +1 -0
- package/dist/esm/result/option.js +170 -0
- package/dist/esm/result/option.js.map +1 -0
- package/dist/esm/result/result.js +203 -0
- package/dist/esm/result/result.js.map +1 -0
- package/dist/esm/transform/coerce.js +143 -0
- package/dist/esm/transform/coerce.js.map +1 -0
- package/dist/esm/transform/index.js +4 -0
- package/dist/esm/transform/index.js.map +1 -0
- package/dist/esm/transform/pipe.js +14 -0
- package/dist/esm/transform/pipe.js.map +1 -0
- package/dist/esm/transform/sanitize.js +195 -0
- package/dist/esm/transform/sanitize.js.map +1 -0
- package/dist/esm/utils/errors.js +84 -0
- package/dist/esm/utils/errors.js.map +1 -0
- package/dist/esm/utils/types.js +5 -0
- package/dist/esm/utils/types.js.map +1 -0
- package/dist/types/assert/assertions.d.ts +52 -0
- package/dist/types/assert/assertions.d.ts.map +1 -0
- package/dist/types/assert/index.d.ts +3 -0
- package/dist/types/assert/index.d.ts.map +1 -0
- package/dist/types/assert/invariant.d.ts +29 -0
- package/dist/types/assert/invariant.d.ts.map +1 -0
- package/dist/types/env/index.d.ts +2 -0
- package/dist/types/env/index.d.ts.map +1 -0
- package/dist/types/env/schema.d.ts +131 -0
- package/dist/types/env/schema.d.ts.map +1 -0
- package/dist/types/guards/advanced.d.ts +101 -0
- package/dist/types/guards/advanced.d.ts.map +1 -0
- package/dist/types/guards/combinators.d.ts +120 -0
- package/dist/types/guards/combinators.d.ts.map +1 -0
- package/dist/types/guards/index.d.ts +5 -0
- package/dist/types/guards/index.d.ts.map +1 -0
- package/dist/types/guards/primitives.d.ts +75 -0
- package/dist/types/guards/primitives.d.ts.map +1 -0
- package/dist/types/guards/structures.d.ts +58 -0
- package/dist/types/guards/structures.d.ts.map +1 -0
- package/dist/types/index.d.ts +8 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/result/async.d.ts +72 -0
- package/dist/types/result/async.d.ts.map +1 -0
- package/dist/types/result/index.d.ts +4 -0
- package/dist/types/result/index.d.ts.map +1 -0
- package/dist/types/result/option.d.ts +106 -0
- package/dist/types/result/option.d.ts.map +1 -0
- package/dist/types/result/result.d.ts +126 -0
- package/dist/types/result/result.d.ts.map +1 -0
- package/dist/types/transform/coerce.d.ts +73 -0
- package/dist/types/transform/coerce.d.ts.map +1 -0
- package/dist/types/transform/index.d.ts +4 -0
- package/dist/types/transform/index.d.ts.map +1 -0
- package/dist/types/transform/pipe.d.ts +44 -0
- package/dist/types/transform/pipe.d.ts.map +1 -0
- package/dist/types/transform/sanitize.d.ts +108 -0
- package/dist/types/transform/sanitize.d.ts.map +1 -0
- package/dist/types/utils/errors.d.ts +51 -0
- package/dist/types/utils/errors.d.ts.map +1 -0
- package/dist/types/utils/types.d.ts +29 -0
- package/dist/types/utils/types.d.ts.map +1 -0
- package/package.json +144 -0
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Guarden — Async Result & Option
|
|
3
|
+
// ============================================================================
|
|
4
|
+
import { Ok, Err, ResultUtils } from './result.js';
|
|
5
|
+
import { Some, None } from './option.js';
|
|
6
|
+
/**
|
|
7
|
+
* A Result wrapped in a Promise, with chainable async operations.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* const result = ResultAsync.from(fetch('/api/user'))
|
|
12
|
+
* .map(res => res.json())
|
|
13
|
+
* .mapErr(err => new ApiError(err.message));
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export class ResultAsync {
|
|
17
|
+
promise;
|
|
18
|
+
constructor(promise) {
|
|
19
|
+
this.promise = promise;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Create from a Promise that may reject.
|
|
23
|
+
*/
|
|
24
|
+
static from(promise) {
|
|
25
|
+
return new ResultAsync(ResultUtils.fromPromise(promise));
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Create from a Result.
|
|
29
|
+
*/
|
|
30
|
+
static fromResult(result) {
|
|
31
|
+
return new ResultAsync(Promise.resolve(result));
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Create an Ok ResultAsync.
|
|
35
|
+
*/
|
|
36
|
+
static ok(value) {
|
|
37
|
+
return new ResultAsync(Promise.resolve(Ok(value)));
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Create an Err ResultAsync.
|
|
41
|
+
*/
|
|
42
|
+
static err(error) {
|
|
43
|
+
return new ResultAsync(Promise.resolve(Err(error)));
|
|
44
|
+
}
|
|
45
|
+
/** Transform the success value. */
|
|
46
|
+
map(fn) {
|
|
47
|
+
return new ResultAsync(this.promise.then((r) => r.map(fn)));
|
|
48
|
+
}
|
|
49
|
+
/** Transform the error value. */
|
|
50
|
+
mapErr(fn) {
|
|
51
|
+
return new ResultAsync(this.promise.then((r) => r.mapErr(fn)));
|
|
52
|
+
}
|
|
53
|
+
/** Chain async operations. */
|
|
54
|
+
andThen(fn) {
|
|
55
|
+
return new ResultAsync(this.promise.then((r) => {
|
|
56
|
+
if (r.isErr())
|
|
57
|
+
return Err(r.unwrapErr());
|
|
58
|
+
return fn(r.unwrap()).toPromise();
|
|
59
|
+
}));
|
|
60
|
+
}
|
|
61
|
+
/** Extract the underlying Promise<Result>. */
|
|
62
|
+
toPromise() {
|
|
63
|
+
return this.promise;
|
|
64
|
+
}
|
|
65
|
+
/** Unwrap or throw. */
|
|
66
|
+
async unwrap() {
|
|
67
|
+
const result = await this.promise;
|
|
68
|
+
return result.unwrap();
|
|
69
|
+
}
|
|
70
|
+
/** Unwrap or return default. */
|
|
71
|
+
async unwrapOr(defaultValue) {
|
|
72
|
+
const result = await this.promise;
|
|
73
|
+
return result.unwrapOr(defaultValue);
|
|
74
|
+
}
|
|
75
|
+
/** Pattern match on the resolved Result. */
|
|
76
|
+
async match(handlers) {
|
|
77
|
+
const result = await this.promise;
|
|
78
|
+
return result.match(handlers);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* An Option wrapped in a Promise.
|
|
83
|
+
*/
|
|
84
|
+
export class OptionAsync {
|
|
85
|
+
promise;
|
|
86
|
+
constructor(promise) {
|
|
87
|
+
this.promise = promise;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Create from a Promise that resolves to a nullable value.
|
|
91
|
+
*/
|
|
92
|
+
static from(promise) {
|
|
93
|
+
return new OptionAsync(promise.then((v) => v === null || v === undefined ? None() : Some(v)));
|
|
94
|
+
}
|
|
95
|
+
static some(value) {
|
|
96
|
+
return new OptionAsync(Promise.resolve(Some(value)));
|
|
97
|
+
}
|
|
98
|
+
static none() {
|
|
99
|
+
return new OptionAsync(Promise.resolve(None()));
|
|
100
|
+
}
|
|
101
|
+
map(fn) {
|
|
102
|
+
return new OptionAsync(this.promise.then((o) => o.map(fn)));
|
|
103
|
+
}
|
|
104
|
+
andThen(fn) {
|
|
105
|
+
return new OptionAsync(this.promise.then((o) => {
|
|
106
|
+
if (o.isNone())
|
|
107
|
+
return None();
|
|
108
|
+
return fn(o.unwrap()).toPromise();
|
|
109
|
+
}));
|
|
110
|
+
}
|
|
111
|
+
toPromise() {
|
|
112
|
+
return this.promise;
|
|
113
|
+
}
|
|
114
|
+
async unwrap() {
|
|
115
|
+
const option = await this.promise;
|
|
116
|
+
return option.unwrap();
|
|
117
|
+
}
|
|
118
|
+
async unwrapOr(defaultValue) {
|
|
119
|
+
const option = await this.promise;
|
|
120
|
+
return option.unwrapOr(defaultValue);
|
|
121
|
+
}
|
|
122
|
+
async match(handlers) {
|
|
123
|
+
const option = await this.promise;
|
|
124
|
+
return option.match(handlers);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=async.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"async.js","sourceRoot":"","sources":["../../../src/result/async.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/result/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,WAAW,EAAe,MAAM,aAAa,CAAC;AAChE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,EAAe,MAAM,aAAa,CAAC;AACnE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Guarden — Option<T> Monadic Null Handling
|
|
3
|
+
// ============================================================================
|
|
4
|
+
class SomeOption {
|
|
5
|
+
value;
|
|
6
|
+
_tag = 'Some';
|
|
7
|
+
constructor(value) {
|
|
8
|
+
this.value = value;
|
|
9
|
+
}
|
|
10
|
+
isSome() {
|
|
11
|
+
return true;
|
|
12
|
+
}
|
|
13
|
+
isNone() {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
/** Transform the contained value. */
|
|
17
|
+
map(fn) {
|
|
18
|
+
return new SomeOption(fn(this.value));
|
|
19
|
+
}
|
|
20
|
+
/** Chain operations that return an Option (flatMap). */
|
|
21
|
+
andThen(fn) {
|
|
22
|
+
return fn(this.value);
|
|
23
|
+
}
|
|
24
|
+
/** Return this Option if Some, otherwise return the other. */
|
|
25
|
+
orElse(_fn) {
|
|
26
|
+
return this;
|
|
27
|
+
}
|
|
28
|
+
/** Get the value, or throw if None. */
|
|
29
|
+
unwrap() {
|
|
30
|
+
return this.value;
|
|
31
|
+
}
|
|
32
|
+
/** Get the value, or return a default. */
|
|
33
|
+
unwrapOr(_defaultValue) {
|
|
34
|
+
return this.value;
|
|
35
|
+
}
|
|
36
|
+
/** Get the value, or compute a default. */
|
|
37
|
+
unwrapOrElse(_fn) {
|
|
38
|
+
return this.value;
|
|
39
|
+
}
|
|
40
|
+
/** Pattern match on the Option. */
|
|
41
|
+
match(handlers) {
|
|
42
|
+
return handlers.some(this.value);
|
|
43
|
+
}
|
|
44
|
+
/** Filter: return None if the predicate fails. */
|
|
45
|
+
filter(predicate) {
|
|
46
|
+
return predicate(this.value) ? this : new NoneOption();
|
|
47
|
+
}
|
|
48
|
+
/** Apply a side-effect function if Some. */
|
|
49
|
+
tap(fn) {
|
|
50
|
+
fn(this.value);
|
|
51
|
+
return this;
|
|
52
|
+
}
|
|
53
|
+
/** Zip with another Option. */
|
|
54
|
+
zip(other) {
|
|
55
|
+
if (other.isSome()) {
|
|
56
|
+
return new SomeOption([this.value, other.value]);
|
|
57
|
+
}
|
|
58
|
+
return new NoneOption();
|
|
59
|
+
}
|
|
60
|
+
toJSON() {
|
|
61
|
+
return { tag: 'Some', value: this.value };
|
|
62
|
+
}
|
|
63
|
+
toString() {
|
|
64
|
+
return `Some(${JSON.stringify(this.value)})`;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
class NoneOption {
|
|
68
|
+
_tag = 'None';
|
|
69
|
+
isSome() {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
isNone() {
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
map(_fn) {
|
|
76
|
+
return new NoneOption();
|
|
77
|
+
}
|
|
78
|
+
andThen(_fn) {
|
|
79
|
+
return new NoneOption();
|
|
80
|
+
}
|
|
81
|
+
orElse(fn) {
|
|
82
|
+
return fn();
|
|
83
|
+
}
|
|
84
|
+
unwrap() {
|
|
85
|
+
throw new Error('Called unwrap on None');
|
|
86
|
+
}
|
|
87
|
+
unwrapOr(defaultValue) {
|
|
88
|
+
return defaultValue;
|
|
89
|
+
}
|
|
90
|
+
unwrapOrElse(fn) {
|
|
91
|
+
return fn();
|
|
92
|
+
}
|
|
93
|
+
match(handlers) {
|
|
94
|
+
return handlers.none();
|
|
95
|
+
}
|
|
96
|
+
filter(_predicate) {
|
|
97
|
+
return this;
|
|
98
|
+
}
|
|
99
|
+
tap(_fn) {
|
|
100
|
+
return this;
|
|
101
|
+
}
|
|
102
|
+
zip(_other) {
|
|
103
|
+
return new NoneOption();
|
|
104
|
+
}
|
|
105
|
+
toJSON() {
|
|
106
|
+
return { tag: 'None' };
|
|
107
|
+
}
|
|
108
|
+
toString() {
|
|
109
|
+
return 'None';
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
// -- Public constructors -----------------------------------------------------
|
|
113
|
+
/**
|
|
114
|
+
* Create an Option containing a value.
|
|
115
|
+
*/
|
|
116
|
+
export function Some(value) {
|
|
117
|
+
return new SomeOption(value);
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Create an empty Option.
|
|
121
|
+
*/
|
|
122
|
+
export function None() {
|
|
123
|
+
return new NoneOption();
|
|
124
|
+
}
|
|
125
|
+
// -- Static utilities --------------------------------------------------------
|
|
126
|
+
export const OptionUtils = {
|
|
127
|
+
/**
|
|
128
|
+
* Create an Option from a nullable value.
|
|
129
|
+
* null | undefined → None, everything else → Some.
|
|
130
|
+
*
|
|
131
|
+
* @example
|
|
132
|
+
* ```ts
|
|
133
|
+
* Option.from(null) // None
|
|
134
|
+
* Option.from(undefined) // None
|
|
135
|
+
* Option.from(42) // Some(42)
|
|
136
|
+
* Option.from('') // Some('') (empty string is still Some)
|
|
137
|
+
* ```
|
|
138
|
+
*/
|
|
139
|
+
from(value) {
|
|
140
|
+
return value === null || value === undefined
|
|
141
|
+
? new NoneOption()
|
|
142
|
+
: new SomeOption(value);
|
|
143
|
+
},
|
|
144
|
+
/**
|
|
145
|
+
* Create an Option from a predicate check.
|
|
146
|
+
*/
|
|
147
|
+
fromPredicate(value, predicate) {
|
|
148
|
+
return predicate(value) ? new SomeOption(value) : new NoneOption();
|
|
149
|
+
},
|
|
150
|
+
/**
|
|
151
|
+
* Check if a value is an Option.
|
|
152
|
+
*/
|
|
153
|
+
isOption(value) {
|
|
154
|
+
return value instanceof SomeOption || value instanceof NoneOption;
|
|
155
|
+
},
|
|
156
|
+
/**
|
|
157
|
+
* Collect an array of Options into an Option of array.
|
|
158
|
+
* Returns None if any Option is None.
|
|
159
|
+
*/
|
|
160
|
+
all(options) {
|
|
161
|
+
const values = [];
|
|
162
|
+
for (const opt of options) {
|
|
163
|
+
if (opt.isNone())
|
|
164
|
+
return new NoneOption();
|
|
165
|
+
values.push(opt.unwrap());
|
|
166
|
+
}
|
|
167
|
+
return new SomeOption(values);
|
|
168
|
+
},
|
|
169
|
+
};
|
|
170
|
+
//# sourceMappingURL=option.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"option.js","sourceRoot":"","sources":["../../../src/result/option.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Guarden — Result<T, E> Monadic Error Handling
|
|
3
|
+
// ============================================================================
|
|
4
|
+
// -- Internal implementations ------------------------------------------------
|
|
5
|
+
class OkResult {
|
|
6
|
+
value;
|
|
7
|
+
_tag = 'Ok';
|
|
8
|
+
constructor(value) {
|
|
9
|
+
this.value = value;
|
|
10
|
+
}
|
|
11
|
+
isOk() {
|
|
12
|
+
return true;
|
|
13
|
+
}
|
|
14
|
+
isErr() {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
/** Transform the success value. */
|
|
18
|
+
map(fn) {
|
|
19
|
+
return new OkResult(fn(this.value));
|
|
20
|
+
}
|
|
21
|
+
/** Transform the error value (no-op for Ok). */
|
|
22
|
+
mapErr(_fn) {
|
|
23
|
+
return new OkResult(this.value);
|
|
24
|
+
}
|
|
25
|
+
/** Chain operations that return a Result (flatMap). */
|
|
26
|
+
andThen(fn) {
|
|
27
|
+
return fn(this.value);
|
|
28
|
+
}
|
|
29
|
+
/** Return this Result if Ok, otherwise return the other. */
|
|
30
|
+
orElse(_fn) {
|
|
31
|
+
return new OkResult(this.value);
|
|
32
|
+
}
|
|
33
|
+
/** Get the value, or throw if Err. */
|
|
34
|
+
unwrap() {
|
|
35
|
+
return this.value;
|
|
36
|
+
}
|
|
37
|
+
/** Get the value, or return a default. */
|
|
38
|
+
unwrapOr(_defaultValue) {
|
|
39
|
+
return this.value;
|
|
40
|
+
}
|
|
41
|
+
/** Get the value, or compute a default from the error. */
|
|
42
|
+
unwrapOrElse(_fn) {
|
|
43
|
+
return this.value;
|
|
44
|
+
}
|
|
45
|
+
/** Get the error, or throw if Ok. */
|
|
46
|
+
unwrapErr() {
|
|
47
|
+
throw new Error(`Called unwrapErr on Ok value: ${JSON.stringify(this.value)}`);
|
|
48
|
+
}
|
|
49
|
+
/** Pattern match on the Result. */
|
|
50
|
+
match(handlers) {
|
|
51
|
+
return handlers.ok(this.value);
|
|
52
|
+
}
|
|
53
|
+
/** Convert to an Option, discarding the error. */
|
|
54
|
+
ok() {
|
|
55
|
+
return this.value;
|
|
56
|
+
}
|
|
57
|
+
/** Convert to an Option of the error (returns undefined for Ok). */
|
|
58
|
+
err() {
|
|
59
|
+
return undefined;
|
|
60
|
+
}
|
|
61
|
+
/** Apply a function to the value if Ok, used for side effects. */
|
|
62
|
+
tap(fn) {
|
|
63
|
+
fn(this.value);
|
|
64
|
+
return this;
|
|
65
|
+
}
|
|
66
|
+
/** Apply a function to the error if Err (no-op for Ok). */
|
|
67
|
+
tapErr(_fn) {
|
|
68
|
+
return this;
|
|
69
|
+
}
|
|
70
|
+
/** Convert to a JSON-friendly representation. */
|
|
71
|
+
toJSON() {
|
|
72
|
+
return { tag: 'Ok', value: this.value };
|
|
73
|
+
}
|
|
74
|
+
toString() {
|
|
75
|
+
return `Ok(${JSON.stringify(this.value)})`;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
class ErrResult {
|
|
79
|
+
error;
|
|
80
|
+
_tag = 'Err';
|
|
81
|
+
constructor(error) {
|
|
82
|
+
this.error = error;
|
|
83
|
+
}
|
|
84
|
+
isOk() {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
isErr() {
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
map(_fn) {
|
|
91
|
+
return new ErrResult(_fn);
|
|
92
|
+
}
|
|
93
|
+
mapErr(fn) {
|
|
94
|
+
return new ErrResult(fn(this.error));
|
|
95
|
+
}
|
|
96
|
+
andThen(_fn) {
|
|
97
|
+
return new ErrResult(this.error);
|
|
98
|
+
}
|
|
99
|
+
orElse(fn) {
|
|
100
|
+
return fn(this.error);
|
|
101
|
+
}
|
|
102
|
+
unwrap() {
|
|
103
|
+
throw new Error(`Called unwrap on Err value: ${JSON.stringify(this.error)}`);
|
|
104
|
+
}
|
|
105
|
+
unwrapOr(defaultValue) {
|
|
106
|
+
return defaultValue;
|
|
107
|
+
}
|
|
108
|
+
unwrapOrElse(fn) {
|
|
109
|
+
return fn(this.error);
|
|
110
|
+
}
|
|
111
|
+
unwrapErr() {
|
|
112
|
+
return this.error;
|
|
113
|
+
}
|
|
114
|
+
match(handlers) {
|
|
115
|
+
return handlers.err(this.error);
|
|
116
|
+
}
|
|
117
|
+
ok() {
|
|
118
|
+
return undefined;
|
|
119
|
+
}
|
|
120
|
+
err() {
|
|
121
|
+
return this.error;
|
|
122
|
+
}
|
|
123
|
+
tap(_fn) {
|
|
124
|
+
return this;
|
|
125
|
+
}
|
|
126
|
+
tapErr(fn) {
|
|
127
|
+
fn(this.error);
|
|
128
|
+
return this;
|
|
129
|
+
}
|
|
130
|
+
toJSON() {
|
|
131
|
+
return { tag: 'Err', error: this.error };
|
|
132
|
+
}
|
|
133
|
+
toString() {
|
|
134
|
+
return `Err(${JSON.stringify(this.error)})`;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
// -- Public constructors -----------------------------------------------------
|
|
138
|
+
/**
|
|
139
|
+
* Create a successful Result.
|
|
140
|
+
*/
|
|
141
|
+
export function Ok(value) {
|
|
142
|
+
return new OkResult(value);
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Create a failed Result.
|
|
146
|
+
*/
|
|
147
|
+
export function Err(error) {
|
|
148
|
+
return new ErrResult(error);
|
|
149
|
+
}
|
|
150
|
+
// -- Static utilities --------------------------------------------------------
|
|
151
|
+
/**
|
|
152
|
+
* Result namespace with static utility methods.
|
|
153
|
+
*/
|
|
154
|
+
export const ResultUtils = {
|
|
155
|
+
/**
|
|
156
|
+
* Wrap a function that may throw into a Result.
|
|
157
|
+
*
|
|
158
|
+
* @example
|
|
159
|
+
* ```ts
|
|
160
|
+
* const result = Result.from(() => JSON.parse(input));
|
|
161
|
+
* ```
|
|
162
|
+
*/
|
|
163
|
+
from(fn) {
|
|
164
|
+
try {
|
|
165
|
+
return Ok(fn());
|
|
166
|
+
}
|
|
167
|
+
catch (e) {
|
|
168
|
+
return Err(e instanceof Error ? e : new Error(String(e)));
|
|
169
|
+
}
|
|
170
|
+
},
|
|
171
|
+
/**
|
|
172
|
+
* Wrap a Promise into a ResultAsync.
|
|
173
|
+
*/
|
|
174
|
+
async fromPromise(promise) {
|
|
175
|
+
try {
|
|
176
|
+
const value = await promise;
|
|
177
|
+
return Ok(value);
|
|
178
|
+
}
|
|
179
|
+
catch (e) {
|
|
180
|
+
return Err(e instanceof Error ? e : new Error(String(e)));
|
|
181
|
+
}
|
|
182
|
+
},
|
|
183
|
+
/**
|
|
184
|
+
* Collect an array of Results into a Result of an array.
|
|
185
|
+
* Returns the first Err encountered, or Ok with all values.
|
|
186
|
+
*/
|
|
187
|
+
all(results) {
|
|
188
|
+
const values = [];
|
|
189
|
+
for (const result of results) {
|
|
190
|
+
if (result.isErr())
|
|
191
|
+
return Err(result.unwrapErr());
|
|
192
|
+
values.push(result.unwrap());
|
|
193
|
+
}
|
|
194
|
+
return Ok(values);
|
|
195
|
+
},
|
|
196
|
+
/**
|
|
197
|
+
* Check if a value is a Result.
|
|
198
|
+
*/
|
|
199
|
+
isResult(value) {
|
|
200
|
+
return value instanceof OkResult || value instanceof ErrResult;
|
|
201
|
+
},
|
|
202
|
+
};
|
|
203
|
+
//# sourceMappingURL=result.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"result.js","sourceRoot":"","sources":["../../../src/result/result.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,gDAAgD;AAChD,+EAA+E;AAsB/E,+EAA+E;AAE/E,MAAM,QAAQ;IAEgB;IADnB,IAAI,GAAG,IAAa,CAAC;IAC9B,YAA4B,KAAQ;QAAR,UAAK,GAAL,KAAK,CAAG;IAAG,CAAC;IAExC,IAAI;QACF,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK;QACH,OAAO,KAAK,CAAC;IACf,CAAC;IAED,mCAAmC;IACnC,GAAG,CAAI,EAAmB;QACxB,OAAO,IAAI,QAAQ,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IACtC,CAAC;IAED,gDAAgD;IAChD,MAAM,CAAI,GAAoB;QAC5B,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClC,CAAC;IAED,uDAAuD;IACvD,OAAO,CAAI,EAA8B;QACvC,OAAO,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACxB,CAAC;IAED,4DAA4D;IAC5D,MAAM,CAAI,GAA+B;QACvC,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClC,CAAC;IAED,sCAAsC;IACtC,MAAM;QACJ,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED,0CAA0C;IAC1C,QAAQ,CAAC,aAAgB;QACvB,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED,0DAA0D;IAC1D,YAAY,CAAC,GAAoB;QAC/B,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED,qCAAqC;IACrC,SAAS;QACP,MAAM,IAAI,KAAK,CAAC,iCAAiC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACjF,CAAC;IAED,mCAAmC;IACnC,KAAK,CAAI,QAAuD;QAC9D,OAAO,QAAQ,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACjC,CAAC;IAED,kDAAkD;IAClD,EAAE;QACA,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED,oEAAoE;IACpE,GAAG;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,kEAAkE;IAClE,GAAG,CAAC,EAAsB;QACxB,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACf,OAAO,IAAI,CAAC;IACd,CAAC;IAED,2DAA2D;IAC3D,MAAM,CAAC,GAAuB;QAC5B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,iDAAiD;IACjD,MAAM;QACJ,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC;IAC1C,CAAC;IAED,QAAQ;QACN,OAAO,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC;IAC7C,CAAC;CACF;AAED,MAAM,SAAS;IAEe;IADnB,IAAI,GAAG,KAAc,CAAC;IAC/B,YAA4B,KAAQ;QAAR,UAAK,GAAL,KAAK,CAAG;IAAG,CAAC;IAExC,IAAI;QACF,OAAO,KAAK,CAAC;IACf,CAAC;IAED,KAAK;QACH,OAAO,IAAI,CAAC;IACd,CAAC;IAED,GAAG,CAAI,GAAoB;QACzB,OAAO,IAAI,SAAS,CAAC,GAAY,CAAC,CAAC;IACrC,CAAC;IAED,MAAM,CAAI,EAAmB;QAC3B,OAAO,IAAI,SAAS,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IACvC,CAAC;IAED,OAAO,CAAI,GAA+B;QACxC,OAAO,IAAI,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACnC,CAAC;IAED,MAAM,CAAI,EAA8B;QACtC,OAAO,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACxB,CAAC;IAED,MAAM;QACJ,MAAM,IAAI,KAAK,CAAC,+BAA+B,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC/E,CAAC;IAED,QAAQ,CAAC,YAAe;QACtB,OAAO,YAAY,CAAC;IACtB,CAAC;IAED,YAAY,CAAC,EAAmB;QAC9B,OAAO,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACxB,CAAC;IAED,SAAS;QACP,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED,KAAK,CAAI,QAAuD;QAC9D,OAAO,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClC,CAAC;IAED,EAAE;QACA,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,GAAG;QACD,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED,GAAG,CAAC,GAAuB;QACzB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,CAAC,EAAsB;QAC3B,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACf,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM;QACJ,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC;IAC3C,CAAC;IAED,QAAQ;QACN,OAAO,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC;IAC9C,CAAC;CACF;AAED,+EAA+E;AAE/E;;GAEG;AACH,MAAM,UAAU,EAAE,CAAI,KAAQ;IAC5B,OAAO,IAAI,QAAQ,CAAC,KAAK,CAAC,CAAC;AAC7B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,GAAG,CAAI,KAAQ;IAC7B,OAAO,IAAI,SAAS,CAAC,KAAK,CAAC,CAAC;AAC9B,CAAC;AAED,+EAA+E;AAE/E;;GAEG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB;;;;;;;OAOG;IACH,IAAI,CAAI,EAAW;QACjB,IAAI,CAAC;YACH,OAAO,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QAClB,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,GAAG,CAAC,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,WAAW,CAAI,OAAmB;QACtC,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC;YAC5B,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC;QACnB,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,GAAG,CAAC,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,GAAG,CAAO,OAAuB;QAC/B,MAAM,MAAM,GAAQ,EAAE,CAAC;QACvB,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC7B,IAAI,MAAM,CAAC,KAAK,EAAE;gBAAE,OAAO,GAAG,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC;YACnD,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;QAC/B,CAAC;QACD,OAAO,EAAE,CAAC,MAAM,CAAC,CAAC;IACpB,CAAC;IAED;;OAEG;IACH,QAAQ,CAAO,KAAc;QAC3B,OAAO,KAAK,YAAY,QAAQ,IAAI,KAAK,YAAY,SAAS,CAAC;IACjE,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Guarden — Type Coercion Utilities
|
|
3
|
+
// ============================================================================
|
|
4
|
+
import { Ok, Err } from '../result/result.js';
|
|
5
|
+
import { CoercionError } from '../utils/errors.js';
|
|
6
|
+
/**
|
|
7
|
+
* Coerce a value to a number.
|
|
8
|
+
* Handles strings, booleans, and Date objects.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* toNumber("42") // Ok(42)
|
|
13
|
+
* toNumber("abc") // Err(CoercionError)
|
|
14
|
+
* toNumber(true) // Ok(1)
|
|
15
|
+
* toNumber(null) // Err(CoercionError)
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export function toNumber(value) {
|
|
19
|
+
if (typeof value === 'number') {
|
|
20
|
+
return Number.isNaN(value) ? Err(new CoercionError(value, 'number')) : Ok(value);
|
|
21
|
+
}
|
|
22
|
+
if (typeof value === 'string') {
|
|
23
|
+
const trimmed = value.trim();
|
|
24
|
+
if (trimmed === '')
|
|
25
|
+
return Err(new CoercionError(value, 'number'));
|
|
26
|
+
const n = Number(trimmed);
|
|
27
|
+
return Number.isNaN(n) ? Err(new CoercionError(value, 'number')) : Ok(n);
|
|
28
|
+
}
|
|
29
|
+
if (typeof value === 'boolean')
|
|
30
|
+
return Ok(value ? 1 : 0);
|
|
31
|
+
if (value instanceof Date) {
|
|
32
|
+
const time = value.getTime();
|
|
33
|
+
return Number.isNaN(time) ? Err(new CoercionError(value, 'number')) : Ok(time);
|
|
34
|
+
}
|
|
35
|
+
return Err(new CoercionError(value, 'number'));
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Coerce a value to a string.
|
|
39
|
+
* Handles numbers, booleans, null, undefined, and objects.
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```ts
|
|
43
|
+
* toString(42) // "42"
|
|
44
|
+
* toString(null) // ""
|
|
45
|
+
* toString(undefined) // ""
|
|
46
|
+
* toString(true) // "true"
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
export function toString(value) {
|
|
50
|
+
if (typeof value === 'string')
|
|
51
|
+
return value;
|
|
52
|
+
if (value === null || value === undefined)
|
|
53
|
+
return '';
|
|
54
|
+
if (typeof value === 'object') {
|
|
55
|
+
try {
|
|
56
|
+
return JSON.stringify(value);
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
return String(value);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return String(value);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Coerce a value to a boolean.
|
|
66
|
+
* Handles common truthy/falsy string representations.
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* ```ts
|
|
70
|
+
* toBoolean("true") // true
|
|
71
|
+
* toBoolean("yes") // true
|
|
72
|
+
* toBoolean("1") // true
|
|
73
|
+
* toBoolean("false") // false
|
|
74
|
+
* toBoolean("no") // false
|
|
75
|
+
* toBoolean("0") // false
|
|
76
|
+
* toBoolean(1) // true
|
|
77
|
+
* toBoolean(0) // false
|
|
78
|
+
* ```
|
|
79
|
+
*/
|
|
80
|
+
export function toBoolean(value) {
|
|
81
|
+
if (typeof value === 'boolean')
|
|
82
|
+
return value;
|
|
83
|
+
if (typeof value === 'number')
|
|
84
|
+
return value !== 0;
|
|
85
|
+
if (typeof value === 'string') {
|
|
86
|
+
const lower = value.trim().toLowerCase();
|
|
87
|
+
return ['true', '1', 'yes', 'on', 'y'].includes(lower);
|
|
88
|
+
}
|
|
89
|
+
return Boolean(value);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Coerce a value to a Date.
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* ```ts
|
|
96
|
+
* toDate("2024-01-15") // Ok(Date)
|
|
97
|
+
* toDate(1705276800000) // Ok(Date)
|
|
98
|
+
* toDate("not-a-date") // Err(CoercionError)
|
|
99
|
+
* ```
|
|
100
|
+
*/
|
|
101
|
+
export function toDate(value) {
|
|
102
|
+
if (value instanceof Date) {
|
|
103
|
+
return Number.isNaN(value.getTime())
|
|
104
|
+
? Err(new CoercionError(value, 'Date'))
|
|
105
|
+
: Ok(value);
|
|
106
|
+
}
|
|
107
|
+
if (typeof value === 'string' || typeof value === 'number') {
|
|
108
|
+
const date = new Date(value);
|
|
109
|
+
return Number.isNaN(date.getTime())
|
|
110
|
+
? Err(new CoercionError(value, 'Date'))
|
|
111
|
+
: Ok(date);
|
|
112
|
+
}
|
|
113
|
+
return Err(new CoercionError(value, 'Date'));
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Wrap a non-array value in an array. Arrays are returned as-is.
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* ```ts
|
|
120
|
+
* toArray(42) // [42]
|
|
121
|
+
* toArray([1, 2]) // [1, 2]
|
|
122
|
+
* toArray(null) // []
|
|
123
|
+
* toArray(undefined)// []
|
|
124
|
+
* ```
|
|
125
|
+
*/
|
|
126
|
+
export function toArray(value) {
|
|
127
|
+
if (value === null || value === undefined)
|
|
128
|
+
return [];
|
|
129
|
+
if (Array.isArray(value))
|
|
130
|
+
return value;
|
|
131
|
+
return [value];
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Coerce a value to an integer.
|
|
135
|
+
*/
|
|
136
|
+
export function toInteger(value) {
|
|
137
|
+
const numResult = toNumber(value);
|
|
138
|
+
if (numResult.isErr())
|
|
139
|
+
return numResult;
|
|
140
|
+
const n = numResult.unwrap();
|
|
141
|
+
return Ok(Math.trunc(n));
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=coerce.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coerce.js","sourceRoot":"","sources":["../../../src/transform/coerce.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { pipe, flow } from './pipe.js';
|
|
2
|
+
export { toNumber, toString, toBoolean, toDate, toArray, toInteger } from './coerce.js';
|
|
3
|
+
export { trim, trimStart, trimEnd, lowercase, uppercase, capitalize, titleCase, camelCase, kebabCase, snakeCase, stripHtml, escapeHtml, unescapeHtml, truncate, slugify, removeWhitespace, collapseWhitespace, padStart, padEnd, reverse, countOccurrences, } from './sanitize.js';
|
|
4
|
+
//# sourceMappingURL=index.js.map
|