@planet-matrix/mobius-model 0.9.0 → 0.10.1
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/CHANGELOG.md +13 -0
- package/oxlint.config.ts +1 -2
- package/package.json +5 -5
- package/scripts/build.ts +2 -52
- package/src/basic/promise.ts +141 -71
- package/src/drizzle/pagination.ts +0 -2
- package/src/event/class-event-proxy.ts +0 -2
- package/src/event/instance-event-proxy.ts +0 -2
- package/src/exception/README.md +28 -19
- package/src/exception/error/error.ts +123 -0
- package/src/exception/error/index.ts +2 -0
- package/src/exception/error/match.ts +38 -0
- package/src/exception/error/must-fix.ts +17 -0
- package/src/exception/index.ts +2 -0
- package/src/file-system/find.ts +53 -0
- package/src/file-system/index.ts +2 -0
- package/src/file-system/path.ts +76 -0
- package/src/file-system/resolve.ts +22 -0
- package/src/form/inputor-controller/base.ts +0 -13
- package/src/form/inputor-controller/form.ts +0 -2
- package/src/http/api/api-type.ts +0 -3
- package/src/http/api-adapter/api-result-arktype.ts +0 -3
- package/src/index.ts +2 -0
- package/src/openai/openai.ts +0 -1
- package/src/request/fetch/browser.ts +0 -5
- package/src/request/fetch/nodejs.ts +0 -5
- package/src/request/request/base.ts +0 -4
- package/src/request/request/general.ts +0 -1
- package/src/result/controller.ts +11 -7
- package/src/result/either.ts +230 -60
- package/src/result/generator.ts +168 -0
- package/src/result/index.ts +1 -0
- package/src/route/router/router.ts +0 -1
- package/src/route/uri/hash.ts +0 -1
- package/src/route/uri/search.ts +0 -1
- package/src/service/README.md +1 -0
- package/src/service/index.ts +1 -0
- package/src/service/service.ts +110 -0
- package/src/socket/client/socket-unit.ts +0 -2
- package/src/socket/server/socket-unit.ts +0 -1
- package/src/tube/helper.ts +0 -1
- package/src/weixin/official-account/authorization.ts +0 -2
- package/src/weixin/official-account/js-api.ts +0 -2
- package/src/weixin/open/oauth2.ts +0 -2
- package/tests/unit/aio/json.spec.ts +0 -1
- package/tests/unit/basic/promise.spec.ts +158 -50
- package/tests/unit/credential/api-key.spec.ts +0 -1
- package/tests/unit/credential/password.spec.ts +0 -1
- package/tests/unit/exception/error/error.spec.ts +83 -0
- package/tests/unit/exception/error/match.spec.ts +81 -0
- package/tests/unit/http/api-adapter/node-http.spec.ts +0 -4
- package/tests/unit/identifier/uuid.spec.ts +0 -1
- package/tests/unit/request/request/base.spec.ts +0 -3
- package/tests/unit/request/request/general.spec.ts +0 -1
- package/tests/unit/result/controller.spec.ts +82 -0
- package/tests/unit/result/either.spec.ts +377 -0
- package/tests/unit/result/generator.spec.ts +273 -0
- package/tests/unit/route/router/route.spec.ts +0 -1
- package/tests/unit/route/uri/pathname.spec.ts +0 -1
- package/tests/unit/socket/server.spec.ts +0 -2
- package/vite.config.ts +2 -1
- package/dist/index.js +0 -720
- package/dist/index.js.map +0 -1005
|
@@ -229,7 +229,6 @@ export class NodejsFetch<
|
|
|
229
229
|
*/
|
|
230
230
|
async getJson(): Promise<FetchOutputJsonData<Output>> {
|
|
231
231
|
const response = await this.getResponse()
|
|
232
|
-
// oxlint-disable-next-line typescript/no-unsafe-type-assertion
|
|
233
232
|
return await response.json() as FetchOutputJsonData<Output>
|
|
234
233
|
}
|
|
235
234
|
|
|
@@ -238,7 +237,6 @@ export class NodejsFetch<
|
|
|
238
237
|
*/
|
|
239
238
|
async getText(): Promise<FetchOutputTextData<Output>> {
|
|
240
239
|
const response = await this.getResponse()
|
|
241
|
-
// oxlint-disable-next-line typescript/no-unsafe-type-assertion
|
|
242
240
|
return await response.text() as FetchOutputTextData<Output>
|
|
243
241
|
}
|
|
244
242
|
|
|
@@ -247,7 +245,6 @@ export class NodejsFetch<
|
|
|
247
245
|
*/
|
|
248
246
|
async getBlob(): Promise<FetchOutputBlobData<Output>> {
|
|
249
247
|
const response = await this.getResponse()
|
|
250
|
-
// oxlint-disable-next-line typescript/no-unsafe-type-assertion
|
|
251
248
|
return await response.blob() as FetchOutputBlobData<Output>
|
|
252
249
|
}
|
|
253
250
|
|
|
@@ -256,7 +253,6 @@ export class NodejsFetch<
|
|
|
256
253
|
*/
|
|
257
254
|
async getArrayBuffer(): Promise<FetchOutputArrayBufferData<Output>> {
|
|
258
255
|
const response = await this.getResponse()
|
|
259
|
-
// oxlint-disable-next-line typescript/no-unsafe-type-assertion
|
|
260
256
|
return await response.arrayBuffer() as FetchOutputArrayBufferData<Output>
|
|
261
257
|
}
|
|
262
258
|
|
|
@@ -270,7 +266,6 @@ export class NodejsFetch<
|
|
|
270
266
|
throw new Error("Response body stream is unavailable.")
|
|
271
267
|
}
|
|
272
268
|
|
|
273
|
-
// oxlint-disable-next-line typescript/no-unsafe-type-assertion
|
|
274
269
|
return response.body as FetchOutputStreamData<Output>
|
|
275
270
|
}
|
|
276
271
|
}
|
|
@@ -131,7 +131,6 @@ export abstract class BaseRequest<R extends Resource = Resource> {
|
|
|
131
131
|
* 从成功输出中提取成功数据。
|
|
132
132
|
*/
|
|
133
133
|
protected extractSuccessData(response: ResourceSuccessOutput<R>): ResourceSuccessData<R> {
|
|
134
|
-
// oxlint-disable-next-line typescript/no-unsafe-type-assertion
|
|
135
134
|
return response['data'] as ResourceSuccessData<R>
|
|
136
135
|
}
|
|
137
136
|
|
|
@@ -146,7 +145,6 @@ export abstract class BaseRequest<R extends Resource = Resource> {
|
|
|
146
145
|
* 从错误输出中提取错误数据。
|
|
147
146
|
*/
|
|
148
147
|
protected extractErrorData(response: ResourceErrorOutput<R>): ResourceErrorData<R> {
|
|
149
|
-
// oxlint-disable-next-line typescript/no-unsafe-type-assertion
|
|
150
148
|
return response['data'] as ResourceErrorData<R>
|
|
151
149
|
}
|
|
152
150
|
|
|
@@ -159,7 +157,6 @@ export abstract class BaseRequest<R extends Resource = Resource> {
|
|
|
159
157
|
const { fetchFactory, modifyRequestOptions } = this.options
|
|
160
158
|
|
|
161
159
|
const preparedOptions = modifyRequestOptions !== undefined
|
|
162
|
-
// oxlint-disable-next-line typescript/no-unsafe-type-assertion
|
|
163
160
|
? modifyRequestOptions(options as RequestOptions<R["path"], R>)
|
|
164
161
|
: options
|
|
165
162
|
|
|
@@ -184,7 +181,6 @@ export abstract class BaseRequest<R extends Resource = Resource> {
|
|
|
184
181
|
data: ResourceOutput<Extract<R, { path: Path }>>
|
|
185
182
|
}
|
|
186
183
|
}[typeof responseType]
|
|
187
|
-
// oxlint-disable-next-line typescript/no-unsafe-type-assertion
|
|
188
184
|
const preparedFetch = (fetchFactory ?? generalFetch)(preparedOptions) as BaseFetch<FetchInput, FetchOutput>
|
|
189
185
|
|
|
190
186
|
if (responseType === "json") {
|
|
@@ -50,7 +50,6 @@ export class GeneralRequest<R extends GeneralResource = GeneralResource>
|
|
|
50
50
|
extends BaseRequest<GeneralResourceToResource<R>> {
|
|
51
51
|
constructor(options: GeneralRequestOptions<R>) {
|
|
52
52
|
const generatePatchOutput = (context: GeneratePatchOutputContext): ResourcePatchOutput<GeneralResourceToResource<R>> => {
|
|
53
|
-
// oxlint-disable-next-line typescript/no-unsafe-type-assertion
|
|
54
53
|
return {
|
|
55
54
|
status: "unknown",
|
|
56
55
|
data: context
|
package/src/result/controller.ts
CHANGED
|
@@ -10,15 +10,19 @@ export class Controller<L, R> {
|
|
|
10
10
|
return Right.isRight(target)
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
protected promise: Promise<Either<L, R>>
|
|
14
|
+
protected resolve: (value: Either<L, R>) => void
|
|
15
|
+
protected reject: (value: L) => void
|
|
15
16
|
|
|
16
17
|
constructor() {
|
|
17
18
|
let _resolve: (value: Either<L, R>) => void
|
|
18
|
-
|
|
19
|
+
let _reject: (value: L) => void
|
|
20
|
+
this.promise = new Promise((resolve, reject) => {
|
|
19
21
|
_resolve = resolve
|
|
22
|
+
_reject = reject
|
|
20
23
|
})
|
|
21
24
|
this.resolve = _resolve!
|
|
25
|
+
this.reject = _reject!
|
|
22
26
|
}
|
|
23
27
|
|
|
24
28
|
get value(): Promise<Either<L, R>> {
|
|
@@ -46,9 +50,9 @@ export class Controller<L, R> {
|
|
|
46
50
|
}
|
|
47
51
|
}
|
|
48
52
|
|
|
49
|
-
type
|
|
50
|
-
type
|
|
53
|
+
type GetLeft<E> = E extends Either<infer L, infer _> ? L : never
|
|
54
|
+
type GetRight<E> = E extends Either<infer _, infer R> ? R : never
|
|
51
55
|
export const controllerFromEitherType = <E extends Either<unknown, unknown>>(
|
|
52
|
-
): Controller<
|
|
53
|
-
return new Controller<
|
|
56
|
+
): Controller<GetLeft<E>, GetRight<E>> => {
|
|
57
|
+
return new Controller<GetLeft<E>, GetRight<E>>()
|
|
54
58
|
}
|
package/src/result/either.ts
CHANGED
|
@@ -1,24 +1,26 @@
|
|
|
1
1
|
|
|
2
2
|
// oxlint-disable-next-line typescript/no-explicit-any
|
|
3
|
-
type AnyEither = Either<any, any>
|
|
4
|
-
type
|
|
3
|
+
export type AnyEither = Either<any, any>
|
|
4
|
+
export type GetLeft<T> = T extends Either<infer Left, unknown> ? Left : never
|
|
5
|
+
export type GetRight<T> = T extends Either<unknown, infer Right> ? Right : never
|
|
6
|
+
export type GetRights<Eithers> = Eithers extends []
|
|
5
7
|
? []
|
|
6
8
|
: (
|
|
7
|
-
Eithers extends [infer
|
|
9
|
+
Eithers extends [infer Item, ...infer xs]
|
|
8
10
|
? (
|
|
9
|
-
|
|
10
|
-
? [Right, ...
|
|
11
|
+
Item extends Either<unknown, infer Right>
|
|
12
|
+
? [Right, ...GetRights<xs>]
|
|
11
13
|
: never
|
|
12
14
|
)
|
|
13
15
|
: never
|
|
14
16
|
)
|
|
15
|
-
type
|
|
17
|
+
export type GetLefts<Eithers> = Eithers extends []
|
|
16
18
|
? []
|
|
17
19
|
: (
|
|
18
|
-
Eithers extends [infer
|
|
20
|
+
Eithers extends [infer Item, ...infer xs]
|
|
19
21
|
? (
|
|
20
|
-
|
|
21
|
-
? [Left, ...
|
|
22
|
+
Item extends Either<infer Left, unknown>
|
|
23
|
+
? [Left, ...GetLefts<xs>]
|
|
22
24
|
: never
|
|
23
25
|
)
|
|
24
26
|
: never
|
|
@@ -26,72 +28,115 @@ type GetLeft<Eithers> = Eithers extends []
|
|
|
26
28
|
type TupleToUnion<Tuple> = Tuple extends unknown[] ? Tuple[number] : never
|
|
27
29
|
|
|
28
30
|
export abstract class Either<L, R> {
|
|
31
|
+
static isEither<L, R>(target: unknown): target is Either<L, R> {
|
|
32
|
+
return target instanceof Either
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
static isLeft<L, R>(target: unknown): target is Left<L, R> {
|
|
36
|
+
return Left.isLeft(target)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
static isRight<L, R>(target: unknown): target is Right<L, R> {
|
|
40
|
+
return Right.isRight(target)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
static left<L>(value: L): Either<L, never>
|
|
44
|
+
static left<L, R>(value: L): Either<L, R>
|
|
29
45
|
static left<L, R>(value: L): Either<L, R> {
|
|
30
46
|
return new Left(value)
|
|
31
47
|
}
|
|
32
48
|
|
|
49
|
+
static right<R>(value: R): Either<never, R>
|
|
50
|
+
static right<L, R>(value: R): Either<L, R>
|
|
33
51
|
static right<L, R>(value: R): Either<L, R> {
|
|
34
52
|
return new Right(value)
|
|
35
53
|
}
|
|
36
54
|
|
|
55
|
+
static pure<R>(value: R): Either<never, R>
|
|
56
|
+
static pure<L, R>(value: R): Either<L, R>
|
|
37
57
|
static pure<L, R>(value: R): Either<L, R> {
|
|
38
58
|
return new Right(value)
|
|
39
59
|
}
|
|
40
60
|
|
|
41
61
|
static lift<NewR, Eithers extends AnyEither[]>(
|
|
42
62
|
eithers: [...Eithers],
|
|
43
|
-
map: (eitherRights:
|
|
44
|
-
): Either<TupleToUnion<
|
|
63
|
+
map: (eitherRights: GetRights<Eithers>) => NewR,
|
|
64
|
+
): Either<TupleToUnion<GetLefts<Eithers>>, NewR> {
|
|
45
65
|
const firstLeft = eithers.find(either => either.isLeft())
|
|
46
66
|
if (firstLeft !== undefined) {
|
|
47
|
-
return firstLeft as Either<TupleToUnion<
|
|
67
|
+
return firstLeft as Either<TupleToUnion<GetLefts<Eithers>>, NewR>
|
|
48
68
|
}
|
|
49
|
-
// oxlint-disable-next-line typescript/no-unsafe-type-assertion
|
|
50
69
|
const rights = eithers.map(either => {
|
|
51
70
|
// oxlint-disable-next-line typescript/no-unsafe-return
|
|
52
71
|
return either.assertRight().getRight()
|
|
53
|
-
}) as
|
|
72
|
+
}) as GetRights<Eithers>
|
|
54
73
|
const newRightValue = map(rights)
|
|
55
74
|
return Either.pure(newRightValue)
|
|
56
75
|
}
|
|
57
76
|
|
|
58
|
-
abstract
|
|
59
|
-
|
|
60
|
-
abstract
|
|
77
|
+
abstract getValue(): L | R
|
|
78
|
+
|
|
79
|
+
abstract getLeft(): L
|
|
80
|
+
abstract getRight(): R
|
|
81
|
+
abstract getRightOr(or: R): R
|
|
61
82
|
|
|
62
83
|
abstract isLeft(): this is Left<L, R>
|
|
63
84
|
abstract isRight(): this is Right<L, R>
|
|
64
|
-
abstract getValue(): L | R
|
|
65
85
|
|
|
66
86
|
abstract assertLeft(): Left<L, R>
|
|
67
87
|
abstract assertRight(): Right<L, R>
|
|
68
88
|
|
|
69
|
-
abstract
|
|
89
|
+
abstract tap(effects: {
|
|
90
|
+
left?: ((value: L) => void) | undefined
|
|
91
|
+
right?: ((value: R) => void) | undefined
|
|
92
|
+
}): Either<L, R>
|
|
93
|
+
abstract tapLeft(effect: (value: L) => void): Either<L, R>
|
|
94
|
+
abstract tapRight(effect: (value: R) => void): Either<L, R>
|
|
95
|
+
|
|
96
|
+
abstract mapLeft<NewL>(map: (value: L) => NewL): Either<NewL, R>
|
|
97
|
+
abstract mapRight<NewR>(map: (value: R) => NewR): Either<L, NewR>
|
|
98
|
+
abstract bind<NewL, NewR>(bind: (value: R) => Either<NewL, NewR>): Either<L | NewL, NewR>
|
|
99
|
+
abstract bindAsync<NewL, NewR>(bind: (value: R) => Promise<Either<NewL, NewR>>): Promise<Either<L | NewL, NewR>>
|
|
100
|
+
|
|
101
|
+
abstract match<X>(
|
|
102
|
+
left: (value: L) => X,
|
|
103
|
+
right: (value: R) => X
|
|
104
|
+
): X
|
|
105
|
+
abstract matchAsync<X>(
|
|
106
|
+
left: (value: L) => Promise<X>,
|
|
107
|
+
right: (value: R) => Promise<X>
|
|
108
|
+
): Promise<X>
|
|
70
109
|
|
|
71
110
|
abstract mplus(either: Either<L, R>): Either<L, R>
|
|
111
|
+
|
|
112
|
+
abstract [Symbol.iterator](): Generator<Either<L, R>, R, R>
|
|
113
|
+
// Async consumers can fall back to Symbol.iterator, but we still expose the
|
|
114
|
+
// same semantics explicitly so Either remains self-descriptive as an async iterable.
|
|
115
|
+
abstract [Symbol.asyncIterator](): AsyncGenerator<Either<L, R>, R, unknown>
|
|
72
116
|
}
|
|
73
|
-
export class Left<L, R> extends Either<L, R> {
|
|
74
|
-
static isLeft<L, R>(target: unknown): target is Left<L, R> {
|
|
75
|
-
return target instanceof Left
|
|
76
|
-
}
|
|
77
117
|
|
|
78
|
-
|
|
118
|
+
export class Left<L, R> extends Either<L, R> {
|
|
119
|
+
protected value: L
|
|
79
120
|
|
|
80
121
|
constructor(value: L) {
|
|
81
122
|
super()
|
|
82
123
|
this.value = value
|
|
83
124
|
}
|
|
84
125
|
|
|
85
|
-
|
|
86
|
-
return
|
|
126
|
+
getValue(): L | R {
|
|
127
|
+
return this.value
|
|
87
128
|
}
|
|
88
129
|
|
|
89
|
-
|
|
90
|
-
return
|
|
130
|
+
getLeft(): L {
|
|
131
|
+
return this.value
|
|
91
132
|
}
|
|
92
133
|
|
|
93
|
-
|
|
94
|
-
|
|
134
|
+
getRight(): R {
|
|
135
|
+
throw new Error("Cannot get right value from Left")
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
getRightOr(or: R): R {
|
|
139
|
+
return or
|
|
95
140
|
}
|
|
96
141
|
|
|
97
142
|
isLeft(): this is Left<L, R> {
|
|
@@ -102,53 +147,103 @@ export class Left<L, R> extends Either<L, R> {
|
|
|
102
147
|
return false
|
|
103
148
|
}
|
|
104
149
|
|
|
105
|
-
|
|
106
|
-
return this
|
|
150
|
+
assertLeft(): this {
|
|
151
|
+
return this
|
|
107
152
|
}
|
|
108
153
|
|
|
109
|
-
|
|
110
|
-
|
|
154
|
+
assertRight(): Right<L, R> {
|
|
155
|
+
throw new Error("Assert failed")
|
|
111
156
|
}
|
|
112
157
|
|
|
113
|
-
|
|
158
|
+
tap(effects: {
|
|
159
|
+
left?: ((value: L) => void) | undefined
|
|
160
|
+
right?: ((value: R) => void) | undefined
|
|
161
|
+
}): Either<L, R> {
|
|
162
|
+
if (effects.left !== undefined) {
|
|
163
|
+
effects.left(this.value)
|
|
164
|
+
}
|
|
114
165
|
return this
|
|
115
166
|
}
|
|
116
167
|
|
|
117
|
-
|
|
118
|
-
|
|
168
|
+
tapLeft(effect: (value: L) => void): Either<L, R> {
|
|
169
|
+
effect(this.value)
|
|
170
|
+
return this
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
tapRight(_effect: (value: R) => void): Either<L, R> {
|
|
174
|
+
return this
|
|
119
175
|
}
|
|
120
176
|
|
|
121
|
-
|
|
122
|
-
return
|
|
177
|
+
mapLeft<NewL>(map: (value: L) => NewL): Either<NewL, R> {
|
|
178
|
+
return new Left(map(this.value))
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
mapRight<NewR>(_map: (value: R) => NewR): Either<L, NewR> {
|
|
182
|
+
return new Left(this.value)
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
bind<NewL, NewR>(_map: (value: R) => Either<NewL, NewR>): Either<L | NewL, NewR> {
|
|
186
|
+
return new Left(this.value) as Either<L | NewL, NewR>
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
async bindAsync<NewL, NewR>(_bind: (value: R) => Promise<Either<NewL, NewR>>): Promise<Either<L | NewL, NewR>> {
|
|
190
|
+
return await Promise.resolve(new Left(this.value) as Either<L | NewL, NewR>)
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
match<X>(
|
|
194
|
+
left: (value: L) => X,
|
|
195
|
+
_right: (value: R) => X
|
|
196
|
+
): X {
|
|
197
|
+
return left(this.value)
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
async matchAsync<X>(
|
|
201
|
+
left: (value: L) => Promise<X>,
|
|
202
|
+
_right: (value: R) => Promise<X>
|
|
203
|
+
): Promise<X> {
|
|
204
|
+
return await left(this.value)
|
|
123
205
|
}
|
|
124
206
|
|
|
125
207
|
mplus(either: Either<L, R>): Either<L, R> {
|
|
126
208
|
return either
|
|
127
209
|
}
|
|
128
|
-
}
|
|
129
210
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
211
|
+
*[Symbol.iterator](): Generator<Either<L, R>, R, R> {
|
|
212
|
+
yield this
|
|
213
|
+
throw new Error("Cannot extract right value from Left")
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// This mirrors the sync iterator exactly; it is explicit protocol support,
|
|
217
|
+
// not a requirement for async yield* fallback.
|
|
218
|
+
async *[Symbol.asyncIterator](): AsyncGenerator<Either<L, R>, R, unknown> {
|
|
219
|
+
await Promise.resolve()
|
|
220
|
+
yield this
|
|
221
|
+
throw new Error("Cannot extract right value from Left")
|
|
133
222
|
}
|
|
223
|
+
}
|
|
134
224
|
|
|
135
|
-
|
|
225
|
+
export class Right<L, R> extends Either<L, R> {
|
|
226
|
+
protected value: R
|
|
136
227
|
|
|
137
228
|
constructor(value: R) {
|
|
138
229
|
super()
|
|
139
230
|
this.value = value
|
|
140
231
|
}
|
|
141
232
|
|
|
142
|
-
|
|
143
|
-
return
|
|
233
|
+
getValue(): L | R {
|
|
234
|
+
return this.value
|
|
144
235
|
}
|
|
145
236
|
|
|
146
|
-
|
|
147
|
-
|
|
237
|
+
getLeft(): L {
|
|
238
|
+
throw new Error("Cannot get left value from Right")
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
getRight(): R {
|
|
242
|
+
return this.value
|
|
148
243
|
}
|
|
149
244
|
|
|
150
|
-
|
|
151
|
-
return
|
|
245
|
+
getRightOr(_or: R): R {
|
|
246
|
+
return this.value
|
|
152
247
|
}
|
|
153
248
|
|
|
154
249
|
isLeft(): this is Left<L, R> {
|
|
@@ -159,35 +254,110 @@ export class Right<L, R> extends Either<L, R> {
|
|
|
159
254
|
return true
|
|
160
255
|
}
|
|
161
256
|
|
|
162
|
-
|
|
163
|
-
|
|
257
|
+
assertLeft(): Left<L, R> {
|
|
258
|
+
throw new Error("Assert failed")
|
|
164
259
|
}
|
|
165
260
|
|
|
166
|
-
|
|
167
|
-
return this
|
|
261
|
+
assertRight(): this {
|
|
262
|
+
return this
|
|
168
263
|
}
|
|
169
264
|
|
|
170
|
-
|
|
171
|
-
|
|
265
|
+
tap(effects: {
|
|
266
|
+
left?: ((value: L) => void) | undefined
|
|
267
|
+
right?: ((value: R) => void) | undefined
|
|
268
|
+
}): Either<L, R> {
|
|
269
|
+
if (effects.right !== undefined) {
|
|
270
|
+
effects.right(this.value)
|
|
271
|
+
}
|
|
272
|
+
return this
|
|
172
273
|
}
|
|
173
274
|
|
|
174
|
-
|
|
275
|
+
tapLeft(_effect: (value: L) => void): Either<L, R> {
|
|
175
276
|
return this
|
|
176
277
|
}
|
|
177
278
|
|
|
178
|
-
|
|
179
|
-
|
|
279
|
+
tapRight(effect: (value: R) => void): Either<L, R> {
|
|
280
|
+
effect(this.value)
|
|
281
|
+
return this
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
mapLeft<NewL>(_map: (value: L) => NewL): Either<NewL, R> {
|
|
285
|
+
return new Right(this.value)
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
mapRight<NewR>(map: (value: R) => NewR): Either<L, NewR> {
|
|
289
|
+
return new Right(map(this.value))
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
bind<NewL, NewR>(map: (value: R) => Either<NewL, NewR>): Either<L | NewL, NewR> {
|
|
293
|
+
return map(this.value) as Either<L | NewL, NewR>
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
async bindAsync<NewL, NewR>(bind: (value: R) => Promise<Either<NewL, NewR>>): Promise<Either<L | NewL, NewR>> {
|
|
297
|
+
return await bind(this.value) as Either<L | NewL, NewR>
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
match<X>(
|
|
301
|
+
_left: (value: L) => X,
|
|
302
|
+
right: (value: R) => X
|
|
303
|
+
): X {
|
|
304
|
+
return right(this.value)
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
async matchAsync<X>(
|
|
308
|
+
_left: (value: L) => Promise<X>,
|
|
309
|
+
right: (value: R) => Promise<X>
|
|
310
|
+
): Promise<X> {
|
|
311
|
+
return await right(this.value)
|
|
180
312
|
}
|
|
181
313
|
|
|
182
314
|
mplus(_either: Either<L, R>): Either<L, R> {
|
|
183
315
|
return this
|
|
184
316
|
}
|
|
317
|
+
|
|
318
|
+
*[Symbol.iterator](): Generator<Either<L, R>, R, R> {
|
|
319
|
+
return this.value
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// This mirrors the sync iterator exactly; async consumers could fall back to
|
|
323
|
+
// Symbol.iterator, but the explicit async form keeps the contract obvious.
|
|
324
|
+
async *[Symbol.asyncIterator](): AsyncGenerator<Either<L, R>, R, unknown> {
|
|
325
|
+
await Promise.resolve()
|
|
326
|
+
return this.value
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
export const isEither = <L, R>(target: unknown): target is Either<L, R> => {
|
|
331
|
+
return Either.isEither(target)
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
export const isLeft = <L, R>(target: unknown): target is Left<L, R> => {
|
|
335
|
+
return Left.isLeft(target)
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
export const isRight = <L, R>(target: unknown): target is Right<L, R> => {
|
|
339
|
+
return Right.isRight(target)
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
type LeftFunction = {
|
|
343
|
+
<L>(value: L): Either<L, never>
|
|
344
|
+
<L, R>(value: L): Either<L, R>
|
|
345
|
+
}
|
|
346
|
+
export const left = (<L, R>(value: L): Either<L, R> => {
|
|
347
|
+
return Either.left<L, R>(value)
|
|
348
|
+
}) as LeftFunction
|
|
349
|
+
|
|
350
|
+
type RightFunction = {
|
|
351
|
+
<R>(value: R): Either<never, R>
|
|
352
|
+
<L, R>(value: R): Either<L, R>
|
|
185
353
|
}
|
|
354
|
+
export const right = (<L, R>(value: R): Either<L, R> => {
|
|
355
|
+
return Either.right<L, R>(value)
|
|
356
|
+
}) as RightFunction
|
|
186
357
|
|
|
187
358
|
export type TupleOfEither<Left, Right> = [undefined, Right] | [Left, undefined]
|
|
188
359
|
export const eitherToTuple = <L, R>(either: Either<L, R>): TupleOfEither<L, R> => {
|
|
189
360
|
const left = either.isLeft() ? either.getLeft() : undefined
|
|
190
361
|
const right = either.isRight() ? either.getRight() : undefined
|
|
191
|
-
// oxlint-disable-next-line typescript/no-unsafe-type-assertion
|
|
192
362
|
return [left, right] as TupleOfEither<L, R>
|
|
193
363
|
}
|