@typed/async-data 0.12.0 → 0.13.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/.nvmrc +1 -0
- package/biome.json +36 -0
- package/dist/AsyncData.d.ts +203 -0
- package/dist/AsyncData.js +294 -0
- package/dist/AsyncData.js.map +1 -0
- package/dist/LazyRef.d.ts +22 -0
- package/dist/LazyRef.js +28 -0
- package/dist/LazyRef.js.map +1 -0
- package/dist/Progress.d.ts +25 -0
- package/dist/Progress.js +22 -0
- package/dist/Progress.js.map +1 -0
- package/dist/{dts/TypeId.d.ts → TypeId.d.ts} +0 -1
- package/dist/TypeId.js +8 -0
- package/dist/TypeId.js.map +1 -0
- package/dist/_internal.d.ts +20 -0
- package/dist/_internal.js +58 -0
- package/dist/_internal.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/package.json +31 -49
- package/readme.md +218 -0
- package/src/AsyncData.test.ts +89 -0
- package/src/AsyncData.ts +552 -595
- package/src/LazyRef.ts +89 -0
- package/src/Progress.ts +20 -66
- package/src/TypeId.ts +1 -1
- package/src/_internal.ts +111 -0
- package/src/index.ts +4 -0
- package/tsconfig.json +27 -0
- package/AsyncData/package.json +0 -6
- package/LICENSE +0 -21
- package/Progress/package.json +0 -6
- package/README.md +0 -5
- package/Schema/package.json +0 -6
- package/TypeId/package.json +0 -6
- package/dist/cjs/AsyncData.js +0 -399
- package/dist/cjs/AsyncData.js.map +0 -1
- package/dist/cjs/Progress.js +0 -62
- package/dist/cjs/Progress.js.map +0 -1
- package/dist/cjs/Schema.js +0 -539
- package/dist/cjs/Schema.js.map +0 -1
- package/dist/cjs/TypeId.js +0 -14
- package/dist/cjs/TypeId.js.map +0 -1
- package/dist/cjs/internal/async-data.js +0 -94
- package/dist/cjs/internal/async-data.js.map +0 -1
- package/dist/cjs/internal/tag.js +0 -12
- package/dist/cjs/internal/tag.js.map +0 -1
- package/dist/dts/AsyncData.d.ts +0 -386
- package/dist/dts/AsyncData.d.ts.map +0 -1
- package/dist/dts/Progress.d.ts +0 -43
- package/dist/dts/Progress.d.ts.map +0 -1
- package/dist/dts/Schema.d.ts +0 -78
- package/dist/dts/Schema.d.ts.map +0 -1
- package/dist/dts/TypeId.d.ts.map +0 -1
- package/dist/dts/internal/async-data.d.ts +0 -43
- package/dist/dts/internal/async-data.d.ts.map +0 -1
- package/dist/dts/internal/tag.d.ts +0 -6
- package/dist/dts/internal/tag.d.ts.map +0 -1
- package/dist/esm/AsyncData.js +0 -372
- package/dist/esm/AsyncData.js.map +0 -1
- package/dist/esm/Progress.js +0 -49
- package/dist/esm/Progress.js.map +0 -1
- package/dist/esm/Schema.js +0 -500
- package/dist/esm/Schema.js.map +0 -1
- package/dist/esm/TypeId.js +0 -8
- package/dist/esm/TypeId.js.map +0 -1
- package/dist/esm/internal/async-data.js +0 -91
- package/dist/esm/internal/async-data.js.map +0 -1
- package/dist/esm/internal/tag.js +0 -6
- package/dist/esm/internal/tag.js.map +0 -1
- package/dist/esm/package.json +0 -4
- package/src/Schema.ts +0 -754
- package/src/internal/async-data.ts +0 -114
- package/src/internal/tag.ts +0 -9
package/src/Schema.ts
DELETED
|
@@ -1,754 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @since 1.0.0
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import * as Arbitrary from "@effect/schema/Arbitrary"
|
|
6
|
-
import * as AST from "@effect/schema/AST"
|
|
7
|
-
import * as Eq from "@effect/schema/Equivalence"
|
|
8
|
-
import * as ParseResult from "@effect/schema/ParseResult"
|
|
9
|
-
import * as Pretty from "@effect/schema/Pretty"
|
|
10
|
-
import * as Schema from "@effect/schema/Schema"
|
|
11
|
-
import * as Cause from "effect/Cause"
|
|
12
|
-
import * as Data from "effect/Data"
|
|
13
|
-
import * as Effect from "effect/Effect"
|
|
14
|
-
import * as Equal from "effect/Equal"
|
|
15
|
-
import * as FiberId from "effect/FiberId"
|
|
16
|
-
import * as Option from "effect/Option"
|
|
17
|
-
import { hasProperty } from "effect/Predicate"
|
|
18
|
-
import * as _AsyncData from "./AsyncData.js"
|
|
19
|
-
import * as P from "./Progress.js"
|
|
20
|
-
|
|
21
|
-
const NO_DATA_PRETTY = "AsyncData.NoData"
|
|
22
|
-
const LOADING_PRETTY = (loading: _AsyncData.Loading) =>
|
|
23
|
-
Option.match(loading.progress, {
|
|
24
|
-
onNone: () => `AsyncData.Loading(timestamp=${loading.timestamp})`,
|
|
25
|
-
onSome: (progress) => `AsyncData.Loading(timestamp=${loading.timestamp}, progress=${P.pretty(progress)})`
|
|
26
|
-
})
|
|
27
|
-
const FAILURE_PRETTY = <E>(print: Pretty.Pretty<Cause.Cause<E>>) => (failure: _AsyncData.Failure<E>) =>
|
|
28
|
-
Option.match(failure.refreshing, {
|
|
29
|
-
onNone: () => `AsyncData.Failure(timestamp=${failure.timestamp}, cause=${print(failure.cause)})`,
|
|
30
|
-
onSome: () => `AsyncData.Failure(timestamp=${failure.timestamp}, refreshing=true, cause=${print(failure.cause)})`
|
|
31
|
-
})
|
|
32
|
-
const SUCCESS_PRETTY = <A>(print: Pretty.Pretty<A>) => (success: _AsyncData.Success<A>) =>
|
|
33
|
-
Option.match(success.refreshing, {
|
|
34
|
-
onNone: () => `AsyncData.Success(timestamp=${success.timestamp}, value=${print(success.value)})`,
|
|
35
|
-
onSome: () => `AsyncData.Success(timestamp=${success.timestamp}, refreshing=true, value=${print(success.value)})`
|
|
36
|
-
})
|
|
37
|
-
|
|
38
|
-
const OPTIMISTIC_PRETTY =
|
|
39
|
-
<E, A>(printValue: Pretty.Pretty<A>, printError: Pretty.Pretty<Cause.Cause<E>>) =>
|
|
40
|
-
(optimistic: _AsyncData.Optimistic<A, E>) =>
|
|
41
|
-
`AsyncData.Optimistic(timestamp=${optimistic.timestamp}, value=${printValue(optimistic.value)}, previous=${
|
|
42
|
-
asyncDataPretty(printValue, printError)(optimistic.previous)
|
|
43
|
-
})`
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* @since 1.0.0
|
|
47
|
-
*/
|
|
48
|
-
export type NoDataFrom = { readonly _tag: "NoData" }
|
|
49
|
-
|
|
50
|
-
const ProgressSchemaJson = Schema.Struct({
|
|
51
|
-
loaded: Schema.BigInt,
|
|
52
|
-
total: Schema.optional(Schema.BigInt)
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
const ProgressSchema: Schema.Schema<
|
|
56
|
-
P.Progress,
|
|
57
|
-
{
|
|
58
|
-
readonly loaded: bigint
|
|
59
|
-
readonly total: Option.Option<bigint>
|
|
60
|
-
}
|
|
61
|
-
> = Schema.Data(Schema.Struct({
|
|
62
|
-
loaded: Schema.BigIntFromSelf,
|
|
63
|
-
total: Schema.OptionFromSelf(Schema.BigIntFromSelf)
|
|
64
|
-
}))
|
|
65
|
-
|
|
66
|
-
const progressArbitrary: Arbitrary.LazyArbitrary<P.Progress> = (fc) =>
|
|
67
|
-
fc.bigInt().chain((loaded) => fc.option(fc.bigInt({ min: loaded })).map((total) => P.make(loaded, total)))
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* @since 1.0.0
|
|
71
|
-
*/
|
|
72
|
-
export const Progress: Schema.Schema<
|
|
73
|
-
P.Progress,
|
|
74
|
-
{ readonly loaded: string; readonly total?: string | undefined }
|
|
75
|
-
> = ProgressSchemaJson.pipe(
|
|
76
|
-
Schema.transform(
|
|
77
|
-
ProgressSchema,
|
|
78
|
-
{
|
|
79
|
-
decode: (json): P.Progress => P.make(json.loaded, json.total),
|
|
80
|
-
encode: (progress) => ({
|
|
81
|
-
loaded: progress.loaded,
|
|
82
|
-
total: Option.getOrUndefined(progress.total)
|
|
83
|
-
})
|
|
84
|
-
}
|
|
85
|
-
),
|
|
86
|
-
Schema.annotations({
|
|
87
|
-
[AST.IdentifierAnnotationId]: "Progress",
|
|
88
|
-
[Pretty.PrettyHookId]: () => "Progress",
|
|
89
|
-
[Arbitrary.ArbitraryHookId]: (): Arbitrary.LazyArbitrary<P.Progress> => progressArbitrary,
|
|
90
|
-
[Eq.EquivalenceHookId]: () => Equal.equals
|
|
91
|
-
})
|
|
92
|
-
)
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* @since 1.0.0
|
|
96
|
-
*/
|
|
97
|
-
export type ProgressFrom = {
|
|
98
|
-
readonly loaded: string
|
|
99
|
-
readonly total?: string | undefined
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
const loadingArbitrary: Arbitrary.LazyArbitrary<_AsyncData.Loading> = (fc) =>
|
|
103
|
-
fc.option(progressArbitrary(fc)).map((progress) =>
|
|
104
|
-
_AsyncData.loading({
|
|
105
|
-
timestamp: Date.now(),
|
|
106
|
-
progress: progress || undefined
|
|
107
|
-
})
|
|
108
|
-
)
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* @since 1.0.0
|
|
112
|
-
*/
|
|
113
|
-
export type LoadingFrom = {
|
|
114
|
-
readonly _tag: "Loading"
|
|
115
|
-
readonly timestamp: number
|
|
116
|
-
readonly progress?: ProgressFrom | undefined
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
const failureArbitrary = <E>(
|
|
120
|
-
cause: Arbitrary.LazyArbitrary<Cause.Cause<E>>
|
|
121
|
-
): Arbitrary.LazyArbitrary<_AsyncData.Failure<E>> =>
|
|
122
|
-
(fc) =>
|
|
123
|
-
fc.option(loadingArbitrary(fc)).chain((refreshing) =>
|
|
124
|
-
cause(fc).chain((cause) =>
|
|
125
|
-
fc.date().map((date) =>
|
|
126
|
-
_AsyncData.failCause(cause, {
|
|
127
|
-
timestamp: date.getTime(),
|
|
128
|
-
refreshing: refreshing || undefined
|
|
129
|
-
})
|
|
130
|
-
)
|
|
131
|
-
)
|
|
132
|
-
)
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* @since 1.0.0
|
|
136
|
-
*/
|
|
137
|
-
export type FailureFrom<E> = {
|
|
138
|
-
readonly _tag: "Failure"
|
|
139
|
-
readonly cause: Schema.CauseEncoded<E, unknown>
|
|
140
|
-
readonly timestamp: number
|
|
141
|
-
readonly refreshing?: LoadingFrom | undefined
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
const FailureFrom = <E>(
|
|
145
|
-
cause: Schema.CauseEncoded<E, unknown>,
|
|
146
|
-
timestamp: number,
|
|
147
|
-
refreshing?: LoadingFrom
|
|
148
|
-
): FailureFrom<E> => {
|
|
149
|
-
const base = {
|
|
150
|
-
_tag: "Failure",
|
|
151
|
-
cause,
|
|
152
|
-
timestamp
|
|
153
|
-
} as const
|
|
154
|
-
|
|
155
|
-
if (refreshing !== undefined) {
|
|
156
|
-
return { ...base, refreshing }
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
return base
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
const successArbitrary = <A>(
|
|
163
|
-
value: Arbitrary.LazyArbitrary<A>
|
|
164
|
-
): Arbitrary.LazyArbitrary<_AsyncData.Success<A>> =>
|
|
165
|
-
(fc) =>
|
|
166
|
-
fc.option(loadingArbitrary(fc)).chain((refreshing) =>
|
|
167
|
-
value(fc).chain((a) =>
|
|
168
|
-
fc.date().map((date) =>
|
|
169
|
-
_AsyncData.success(a, {
|
|
170
|
-
timestamp: date.getTime(),
|
|
171
|
-
refreshing: refreshing || undefined
|
|
172
|
-
})
|
|
173
|
-
)
|
|
174
|
-
)
|
|
175
|
-
)
|
|
176
|
-
|
|
177
|
-
/**
|
|
178
|
-
* @since 1.0.0
|
|
179
|
-
*/
|
|
180
|
-
export type SuccessFrom<A> = {
|
|
181
|
-
readonly timestamp: number
|
|
182
|
-
readonly _tag: "Success"
|
|
183
|
-
readonly value: A
|
|
184
|
-
readonly refreshing?: LoadingFrom | undefined
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
const SuccessFrom = <A>(value: A, timestamp: number, refreshing?: LoadingFrom): SuccessFrom<A> => {
|
|
188
|
-
const base = {
|
|
189
|
-
_tag: "Success",
|
|
190
|
-
value,
|
|
191
|
-
timestamp
|
|
192
|
-
} as const
|
|
193
|
-
|
|
194
|
-
if (refreshing !== undefined) {
|
|
195
|
-
return { ...base, refreshing }
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
return base
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
/**
|
|
202
|
-
* @since 1.0.0
|
|
203
|
-
*/
|
|
204
|
-
export type OptimisticFrom<A, E> = {
|
|
205
|
-
readonly timestamp: number
|
|
206
|
-
readonly _tag: "Optimistic"
|
|
207
|
-
readonly value: A
|
|
208
|
-
readonly previous: AsyncDataFrom<A, E>
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
const OptimisticFrom = <A, E>(value: A, timestamp: number, previous: AsyncDataFrom<A, E>): OptimisticFrom<A, E> => ({
|
|
212
|
-
_tag: "Optimistic",
|
|
213
|
-
value,
|
|
214
|
-
timestamp,
|
|
215
|
-
previous
|
|
216
|
-
})
|
|
217
|
-
|
|
218
|
-
const optimisticArbitrary = <A, E>(
|
|
219
|
-
valueArb: Arbitrary.LazyArbitrary<A>,
|
|
220
|
-
causeArb: Arbitrary.LazyArbitrary<Cause.Cause<E>>
|
|
221
|
-
): Arbitrary.LazyArbitrary<_AsyncData.Optimistic<A, E>> =>
|
|
222
|
-
(fc) =>
|
|
223
|
-
asyncDataArbitrary(valueArb, causeArb)(fc).chain((previous) =>
|
|
224
|
-
valueArb(fc).chain((value) =>
|
|
225
|
-
fc.date().map((date) => _AsyncData.optimistic(previous, value, { timestamp: date.getTime() }))
|
|
226
|
-
)
|
|
227
|
-
)
|
|
228
|
-
|
|
229
|
-
/**
|
|
230
|
-
* @since 1.0.0
|
|
231
|
-
*/
|
|
232
|
-
export type AsyncDataFrom<A, E> = NoDataFrom | LoadingFrom | FailureFrom<E> | SuccessFrom<A> | OptimisticFrom<A, E>
|
|
233
|
-
|
|
234
|
-
const fromEq = (a: AsyncDataFrom<any, any>, b: AsyncDataFrom<any, any>): boolean => {
|
|
235
|
-
if (a._tag !== b._tag) return false
|
|
236
|
-
|
|
237
|
-
switch (a._tag) {
|
|
238
|
-
case "NoData":
|
|
239
|
-
return true
|
|
240
|
-
case "Loading": {
|
|
241
|
-
const loadingB = b as LoadingFrom
|
|
242
|
-
|
|
243
|
-
if (a.timestamp !== loadingB.timestamp) return false
|
|
244
|
-
|
|
245
|
-
if (a.progress === undefined && loadingB.progress === undefined) return true
|
|
246
|
-
if (a.progress === undefined || loadingB.progress === undefined) return false
|
|
247
|
-
|
|
248
|
-
return Equal.equals(Data.struct(a.progress), Data.struct(loadingB.progress))
|
|
249
|
-
}
|
|
250
|
-
case "Failure": {
|
|
251
|
-
const failureB = b as FailureFrom<any>
|
|
252
|
-
|
|
253
|
-
if (
|
|
254
|
-
!(
|
|
255
|
-
Equal.equals(Data.struct(a.cause), Data.struct(failureB.cause)) && a.timestamp === failureB.timestamp
|
|
256
|
-
)
|
|
257
|
-
) return false
|
|
258
|
-
|
|
259
|
-
if (a.refreshing === undefined && failureB.refreshing === undefined) return true
|
|
260
|
-
if (a.refreshing === undefined || failureB.refreshing === undefined) return false
|
|
261
|
-
|
|
262
|
-
return Equal.equals(Data.struct(a.refreshing), Data.struct(failureB.refreshing))
|
|
263
|
-
}
|
|
264
|
-
case "Success": {
|
|
265
|
-
const successB = b as SuccessFrom<any>
|
|
266
|
-
return Equal.equals(a.value, successB.value) &&
|
|
267
|
-
a.timestamp === successB.timestamp &&
|
|
268
|
-
Equal.equals(a.refreshing, successB.refreshing)
|
|
269
|
-
}
|
|
270
|
-
case "Optimistic": {
|
|
271
|
-
const optimisticB = b as OptimisticFrom<any, any>
|
|
272
|
-
return Equal.equals(a.value, optimisticB.value) &&
|
|
273
|
-
a.timestamp === optimisticB.timestamp &&
|
|
274
|
-
fromEq(a.previous, optimisticB.previous)
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
function isNoDataFrom(value: unknown): value is NoDataFrom {
|
|
280
|
-
return hasProperty(value, "_tag") && value._tag === "NoData"
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
function isProgressFrom(value: unknown): value is ProgressFrom {
|
|
284
|
-
if (!(hasProperty(value, "loaded") && typeof value.loaded === "string")) return false
|
|
285
|
-
|
|
286
|
-
if (hasProperty(value, "total")) {
|
|
287
|
-
if (typeof value.total !== "string") return false
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
return true
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
function isLoadingFrom(value: unknown): value is LoadingFrom {
|
|
294
|
-
return hasProperty(value, "_tag")
|
|
295
|
-
&& value._tag === "Loading"
|
|
296
|
-
&& hasProperty(value, "timestamp")
|
|
297
|
-
&& typeof value.timestamp === "number"
|
|
298
|
-
&& (hasProperty(value, "progress") ? isProgressFrom(value.progress) : true)
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
const isCauseEncoded = Schema.is(Schema.encodedSchema(Schema.Cause({ defect: Schema.Unknown, error: Schema.Unknown })))
|
|
302
|
-
|
|
303
|
-
function isFailureFrom(value: unknown): value is FailureFrom<any> {
|
|
304
|
-
return hasProperty(value, "_tag")
|
|
305
|
-
&& value._tag === "Failure"
|
|
306
|
-
&& hasProperty(value, "cause")
|
|
307
|
-
&& isCauseEncoded(value.cause)
|
|
308
|
-
&& hasProperty(value, "timestamp")
|
|
309
|
-
&& typeof value.timestamp === "number"
|
|
310
|
-
&& (hasProperty(value, "refreshing") ? value.refreshing === undefined || isLoadingFrom(value.refreshing) : true)
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
function isSuccessFrom(value: unknown): value is SuccessFrom<any> {
|
|
314
|
-
return hasProperty(value, "_tag")
|
|
315
|
-
&& value._tag === "Success"
|
|
316
|
-
&& hasProperty(value, "value")
|
|
317
|
-
&& hasProperty(value, "timestamp")
|
|
318
|
-
&& typeof value.timestamp === "number"
|
|
319
|
-
&& (hasProperty(value, "refreshing") ? value.refreshing === undefined || isLoadingFrom(value.refreshing) : true)
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
function isOptimisticFrom(value: unknown): value is OptimisticFrom<any, any> {
|
|
323
|
-
return hasProperty(value, "_tag")
|
|
324
|
-
&& value._tag === "Optimistic"
|
|
325
|
-
&& hasProperty(value, "value")
|
|
326
|
-
&& hasProperty(value, "previous")
|
|
327
|
-
&& isAsyncDataFrom(value.previous)
|
|
328
|
-
&& hasProperty(value, "timestamp")
|
|
329
|
-
&& typeof value.timestamp === "number"
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
function isAsyncDataFrom<A = unknown, E = unknown>(value: unknown): value is AsyncDataFrom<A, E> {
|
|
333
|
-
return isNoDataFrom(value)
|
|
334
|
-
|| isLoadingFrom(value)
|
|
335
|
-
|| isFailureFrom(value)
|
|
336
|
-
|| isSuccessFrom(value)
|
|
337
|
-
|| isOptimisticFrom(value)
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
/**
|
|
341
|
-
* @since 1.0.0
|
|
342
|
-
*/
|
|
343
|
-
export const asyncDataFromJson = <A, AI, R1, E, EI, R2>(
|
|
344
|
-
value: Schema.Schema<A, AI, R1>,
|
|
345
|
-
error: Schema.Schema<E, EI, R2>
|
|
346
|
-
): Schema.Schema<AsyncDataFrom<A, E>, AsyncDataFrom<AI, EI>, R1 | R2> => {
|
|
347
|
-
const schema = Schema.declare(
|
|
348
|
-
[value, Schema.Cause({ error, defect: Schema.Unknown })],
|
|
349
|
-
{
|
|
350
|
-
decode: (valueSchema, causeSchema) => {
|
|
351
|
-
const parseCause = ParseResult.decode(causeSchema)
|
|
352
|
-
const parseValue = ParseResult.decode(valueSchema)
|
|
353
|
-
|
|
354
|
-
const parseAsyncData = (
|
|
355
|
-
input: unknown,
|
|
356
|
-
options?: AST.ParseOptions | undefined
|
|
357
|
-
): Effect.Effect<
|
|
358
|
-
AsyncDataFrom<A, E>,
|
|
359
|
-
ParseResult.ParseIssue,
|
|
360
|
-
never
|
|
361
|
-
> => {
|
|
362
|
-
return Effect.gen(function*() {
|
|
363
|
-
if (!isAsyncDataFrom<AI, EI>(input)) {
|
|
364
|
-
return yield* Effect.fail<ParseResult.ParseIssue>(new ParseResult.Forbidden(schema.ast, input))
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
switch (input._tag) {
|
|
368
|
-
case "NoData":
|
|
369
|
-
case "Loading":
|
|
370
|
-
return input
|
|
371
|
-
case "Failure": {
|
|
372
|
-
const cause = yield* parseCause(input.cause, options)
|
|
373
|
-
return FailureFrom(cause, input.timestamp, input.refreshing)
|
|
374
|
-
}
|
|
375
|
-
case "Success": {
|
|
376
|
-
const a = yield* parseValue(input.value, options)
|
|
377
|
-
return SuccessFrom(a, input.timestamp, input.refreshing)
|
|
378
|
-
}
|
|
379
|
-
case "Optimistic": {
|
|
380
|
-
const previous = yield* parseAsyncData(input.previous, options)
|
|
381
|
-
const value = yield* parseValue(input.value, options)
|
|
382
|
-
return OptimisticFrom(value, input.timestamp, previous)
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
})
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
return parseAsyncData
|
|
389
|
-
},
|
|
390
|
-
encode: (valueSchema, causeSchema) => {
|
|
391
|
-
const parseCause = ParseResult.encode(causeSchema)
|
|
392
|
-
const parseValue = ParseResult.encode(valueSchema)
|
|
393
|
-
|
|
394
|
-
const parseAsyncData = (
|
|
395
|
-
input: unknown,
|
|
396
|
-
options?: AST.ParseOptions
|
|
397
|
-
): Effect.Effect<
|
|
398
|
-
AsyncDataFrom<AI, EI>,
|
|
399
|
-
ParseResult.ParseIssue,
|
|
400
|
-
never
|
|
401
|
-
> => {
|
|
402
|
-
return Effect.gen(function*() {
|
|
403
|
-
if (!isAsyncDataFrom<A, E>(input)) {
|
|
404
|
-
return yield* Effect.fail<ParseResult.ParseIssue>(new ParseResult.Forbidden(schema.ast, input))
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
switch (input._tag) {
|
|
408
|
-
case "NoData":
|
|
409
|
-
case "Loading":
|
|
410
|
-
return input
|
|
411
|
-
case "Failure": {
|
|
412
|
-
const cause = yield* parseCause(causeFromToCause(input.cause), options)
|
|
413
|
-
return FailureFrom(cause, input.timestamp, input.refreshing)
|
|
414
|
-
}
|
|
415
|
-
case "Success": {
|
|
416
|
-
const a = yield* parseValue(input.value, options)
|
|
417
|
-
return SuccessFrom(a, input.timestamp, input.refreshing)
|
|
418
|
-
}
|
|
419
|
-
case "Optimistic": {
|
|
420
|
-
const previous = yield* parseAsyncData(input.previous, options)
|
|
421
|
-
const value = yield* parseValue(input.value, options)
|
|
422
|
-
return OptimisticFrom(value, input.timestamp, previous)
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
})
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
return parseAsyncData
|
|
429
|
-
}
|
|
430
|
-
},
|
|
431
|
-
{
|
|
432
|
-
title: "AsyncDataFrom",
|
|
433
|
-
equivalence: () => fromEq,
|
|
434
|
-
arbitrary: (valueArb, causeArb) => (fc) =>
|
|
435
|
-
asyncDataArbitrary(valueArb, causeArb)(fc).map(asyncDataToAsyncDataFrom),
|
|
436
|
-
pretty: (valuePretty, causePretty) => (from) =>
|
|
437
|
-
asyncDataPretty(valuePretty, causePretty)(asyncDataFromToAsyncData(from))
|
|
438
|
-
}
|
|
439
|
-
)
|
|
440
|
-
|
|
441
|
-
return schema
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
/**
|
|
445
|
-
* @since 1.0.0
|
|
446
|
-
*/
|
|
447
|
-
export const AsyncData = <A, AI, R1, E, EI, R2>(
|
|
448
|
-
valueSchema: Schema.Schema<A, AI, R2>,
|
|
449
|
-
errorSchema: Schema.Schema<E, EI, R1>
|
|
450
|
-
): Schema.Schema<_AsyncData.AsyncData<A, E>, AsyncDataFrom<AI, EI>, R1 | R2> => {
|
|
451
|
-
const from = asyncDataFromJson(valueSchema, errorSchema)
|
|
452
|
-
const to = AsyncDataFromSelf(Schema.typeSchema(valueSchema), Schema.typeSchema(errorSchema))
|
|
453
|
-
|
|
454
|
-
return from
|
|
455
|
-
.pipe(Schema.transform(
|
|
456
|
-
to,
|
|
457
|
-
{
|
|
458
|
-
decode: asyncDataFromToAsyncData,
|
|
459
|
-
encode: asyncDataToAsyncDataFrom
|
|
460
|
-
}
|
|
461
|
-
))
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
/**
|
|
465
|
-
* @since 1.0.0
|
|
466
|
-
*/
|
|
467
|
-
export const AsyncDataFromSelf = <A, AI, R1, E, EI, R2>(
|
|
468
|
-
value: Schema.Schema<A, AI, R2>,
|
|
469
|
-
error: Schema.Schema<E, EI, R1>
|
|
470
|
-
): Schema.Schema<_AsyncData.AsyncData<A, E>, _AsyncData.AsyncData<AI, EI>, R1 | R2> => {
|
|
471
|
-
const schema = Schema.declare(
|
|
472
|
-
[value, Schema.CauseFromSelf({ error, defect: Schema.Unknown })],
|
|
473
|
-
{
|
|
474
|
-
decode: (valueSchema, causeSchema) => {
|
|
475
|
-
const parseCause = ParseResult.decode(causeSchema)
|
|
476
|
-
const parseValue = ParseResult.decode(valueSchema)
|
|
477
|
-
|
|
478
|
-
const parseAsyncData = (
|
|
479
|
-
input: unknown,
|
|
480
|
-
options?: AST.ParseOptions
|
|
481
|
-
): Effect.Effect<
|
|
482
|
-
_AsyncData.AsyncData<A, E>,
|
|
483
|
-
ParseResult.ParseIssue,
|
|
484
|
-
never
|
|
485
|
-
> => {
|
|
486
|
-
return Effect.gen(function*() {
|
|
487
|
-
if (!_AsyncData.isAsyncData<AI, EI>(input)) {
|
|
488
|
-
return yield* Effect.fail<ParseResult.ParseIssue>(new ParseResult.Forbidden(schema.ast, input))
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
switch (input._tag) {
|
|
492
|
-
case "NoData":
|
|
493
|
-
case "Loading":
|
|
494
|
-
return input
|
|
495
|
-
case "Failure": {
|
|
496
|
-
const cause = yield* parseCause(input.cause, options)
|
|
497
|
-
|
|
498
|
-
return _AsyncData.failCause(cause, {
|
|
499
|
-
timestamp: input.timestamp,
|
|
500
|
-
refreshing: Option.getOrUndefined(input.refreshing)
|
|
501
|
-
})
|
|
502
|
-
}
|
|
503
|
-
case "Success": {
|
|
504
|
-
const a = yield* parseValue(input.value, options)
|
|
505
|
-
|
|
506
|
-
return _AsyncData.success(a, {
|
|
507
|
-
timestamp: input.timestamp,
|
|
508
|
-
refreshing: Option.getOrUndefined(input.refreshing)
|
|
509
|
-
})
|
|
510
|
-
}
|
|
511
|
-
case "Optimistic": {
|
|
512
|
-
const previous = yield* parseAsyncData(input.previous, options)
|
|
513
|
-
const value = yield* parseValue(input.value, options)
|
|
514
|
-
|
|
515
|
-
return _AsyncData.optimistic(previous, value, {
|
|
516
|
-
timestamp: input.timestamp
|
|
517
|
-
})
|
|
518
|
-
}
|
|
519
|
-
}
|
|
520
|
-
})
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
return parseAsyncData
|
|
524
|
-
},
|
|
525
|
-
encode: (valueSchema, causeSchema) => {
|
|
526
|
-
const parseCause = ParseResult.encode(causeSchema)
|
|
527
|
-
const parseValue = ParseResult.encode(valueSchema)
|
|
528
|
-
|
|
529
|
-
const parseAsyncData = (
|
|
530
|
-
input: unknown,
|
|
531
|
-
options?: AST.ParseOptions
|
|
532
|
-
): Effect.Effect<
|
|
533
|
-
_AsyncData.AsyncData<AI, EI>,
|
|
534
|
-
ParseResult.ParseIssue,
|
|
535
|
-
never
|
|
536
|
-
> => {
|
|
537
|
-
return Effect.gen(function*() {
|
|
538
|
-
if (!_AsyncData.isAsyncData<A, E>(input)) {
|
|
539
|
-
return yield* Effect.fail(new ParseResult.Forbidden(schema.ast, input))
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
switch (input._tag) {
|
|
543
|
-
case "NoData":
|
|
544
|
-
case "Loading":
|
|
545
|
-
return input
|
|
546
|
-
case "Failure": {
|
|
547
|
-
const cause = yield* parseCause(input.cause, options)
|
|
548
|
-
|
|
549
|
-
return _AsyncData.failCause(cause, {
|
|
550
|
-
timestamp: input.timestamp,
|
|
551
|
-
refreshing: Option.getOrUndefined(input.refreshing)
|
|
552
|
-
})
|
|
553
|
-
}
|
|
554
|
-
case "Success": {
|
|
555
|
-
const a = yield* parseValue(input.value, options)
|
|
556
|
-
|
|
557
|
-
return _AsyncData.success(a, {
|
|
558
|
-
timestamp: input.timestamp,
|
|
559
|
-
refreshing: Option.getOrUndefined(input.refreshing)
|
|
560
|
-
})
|
|
561
|
-
}
|
|
562
|
-
case "Optimistic": {
|
|
563
|
-
const previous = yield* parseAsyncData(input.previous, options)
|
|
564
|
-
const value = yield* parseValue(input.value, options)
|
|
565
|
-
|
|
566
|
-
return _AsyncData.optimistic(previous, value, {
|
|
567
|
-
timestamp: input.timestamp
|
|
568
|
-
})
|
|
569
|
-
}
|
|
570
|
-
}
|
|
571
|
-
})
|
|
572
|
-
}
|
|
573
|
-
|
|
574
|
-
return parseAsyncData
|
|
575
|
-
}
|
|
576
|
-
},
|
|
577
|
-
{
|
|
578
|
-
title: "AsyncData",
|
|
579
|
-
pretty: asyncDataPretty,
|
|
580
|
-
arbitrary: asyncDataArbitrary,
|
|
581
|
-
equivalence: () => Equal.equals
|
|
582
|
-
}
|
|
583
|
-
)
|
|
584
|
-
return schema as any
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
function asyncDataPretty<A, E>(
|
|
588
|
-
A: Pretty.Pretty<A>,
|
|
589
|
-
E: Pretty.Pretty<Cause.Cause<E>>
|
|
590
|
-
): Pretty.Pretty<_AsyncData.AsyncData<A, E>> {
|
|
591
|
-
return _AsyncData.match({
|
|
592
|
-
NoData: () => NO_DATA_PRETTY,
|
|
593
|
-
Loading: LOADING_PRETTY,
|
|
594
|
-
Failure: (_, data) => FAILURE_PRETTY(E)(data),
|
|
595
|
-
Success: (_, data) => SUCCESS_PRETTY(A)(data),
|
|
596
|
-
Optimistic: (_, data) => OPTIMISTIC_PRETTY(A, E)(data)
|
|
597
|
-
})
|
|
598
|
-
}
|
|
599
|
-
|
|
600
|
-
function asyncDataArbitrary<A, E>(
|
|
601
|
-
A: Arbitrary.LazyArbitrary<A>,
|
|
602
|
-
E: Arbitrary.LazyArbitrary<Cause.Cause<E>>
|
|
603
|
-
): Arbitrary.LazyArbitrary<_AsyncData.AsyncData<A, E>> {
|
|
604
|
-
const failureArb = failureArbitrary(E)
|
|
605
|
-
const successArb = successArbitrary(A)
|
|
606
|
-
const optimisticArb = optimisticArbitrary(A, E)
|
|
607
|
-
|
|
608
|
-
return (fc) =>
|
|
609
|
-
fc.oneof(
|
|
610
|
-
fc.constant(_AsyncData.noData()),
|
|
611
|
-
fc.constant(_AsyncData.loading()),
|
|
612
|
-
failureArb(fc),
|
|
613
|
-
successArb(fc),
|
|
614
|
-
optimisticArb(fc)
|
|
615
|
-
)
|
|
616
|
-
}
|
|
617
|
-
|
|
618
|
-
function progressFromJson(json: ProgressFrom | undefined): Option.Option<P.Progress> {
|
|
619
|
-
if (json === undefined) return Option.none()
|
|
620
|
-
return Option.some(P.make(BigInt(json.loaded), json.total === undefined ? undefined : BigInt(json.total)))
|
|
621
|
-
}
|
|
622
|
-
|
|
623
|
-
function progressToJson(progres: Option.Option<P.Progress>): ProgressFrom | undefined {
|
|
624
|
-
if (Option.isNone(progres)) return
|
|
625
|
-
return {
|
|
626
|
-
loaded: progres.value.loaded.toString(),
|
|
627
|
-
total: Option.getOrUndefined(progres.value.total)?.toString()
|
|
628
|
-
}
|
|
629
|
-
}
|
|
630
|
-
|
|
631
|
-
function loadingFromJson(json: LoadingFrom | undefined): _AsyncData.Loading | undefined {
|
|
632
|
-
if (json === undefined) return
|
|
633
|
-
return _AsyncData.loading({
|
|
634
|
-
timestamp: json.timestamp,
|
|
635
|
-
progress: Option.getOrUndefined(progressFromJson(json.progress))
|
|
636
|
-
})
|
|
637
|
-
}
|
|
638
|
-
|
|
639
|
-
function loadingToJson(loading: _AsyncData.Loading): LoadingFrom {
|
|
640
|
-
const from: LoadingFrom = {
|
|
641
|
-
_tag: "Loading",
|
|
642
|
-
timestamp: loading.timestamp
|
|
643
|
-
}
|
|
644
|
-
|
|
645
|
-
if (Option.isSome(loading.progress)) {
|
|
646
|
-
return { ...from, progress: progressToJson(loading.progress) }
|
|
647
|
-
}
|
|
648
|
-
|
|
649
|
-
return from
|
|
650
|
-
}
|
|
651
|
-
|
|
652
|
-
function causeFromToCause<E>(from: Schema.CauseEncoded<E, unknown>): Cause.Cause<E> {
|
|
653
|
-
switch (from._tag) {
|
|
654
|
-
case "Die":
|
|
655
|
-
return Cause.die(from.defect)
|
|
656
|
-
case "Empty":
|
|
657
|
-
return Cause.empty
|
|
658
|
-
case "Fail":
|
|
659
|
-
return Cause.fail(from.error)
|
|
660
|
-
case "Interrupt":
|
|
661
|
-
return Cause.interrupt(fiberIdFromToFiberId(from.fiberId))
|
|
662
|
-
case "Parallel":
|
|
663
|
-
return Cause.parallel(causeFromToCause(from.left), causeFromToCause(from.right))
|
|
664
|
-
case "Sequential":
|
|
665
|
-
return Cause.sequential(causeFromToCause(from.left), causeFromToCause(from.right))
|
|
666
|
-
}
|
|
667
|
-
}
|
|
668
|
-
|
|
669
|
-
function fiberIdFromToFiberId(id: Schema.FiberIdEncoded): FiberId.FiberId {
|
|
670
|
-
switch (id._tag) {
|
|
671
|
-
case "None":
|
|
672
|
-
return FiberId.none
|
|
673
|
-
case "Runtime":
|
|
674
|
-
return FiberId.runtime(id.id, id.startTimeMillis)
|
|
675
|
-
case "Composite":
|
|
676
|
-
return FiberId.composite(fiberIdFromToFiberId(id.left), fiberIdFromToFiberId(id.right))
|
|
677
|
-
}
|
|
678
|
-
}
|
|
679
|
-
|
|
680
|
-
function causeToCauseEncoded<E>(cause: Cause.Cause<E>): Schema.CauseEncoded<E, unknown> {
|
|
681
|
-
switch (cause._tag) {
|
|
682
|
-
case "Die":
|
|
683
|
-
return { _tag: "Die", defect: cause.defect }
|
|
684
|
-
case "Empty":
|
|
685
|
-
return { _tag: "Empty" }
|
|
686
|
-
case "Fail":
|
|
687
|
-
return { _tag: "Fail", error: cause.error }
|
|
688
|
-
case "Interrupt":
|
|
689
|
-
return { _tag: "Interrupt", fiberId: fiberIdToFiberIdFrom(cause.fiberId) }
|
|
690
|
-
case "Parallel":
|
|
691
|
-
return { _tag: "Parallel", left: causeToCauseEncoded(cause.left), right: causeToCauseEncoded(cause.right) }
|
|
692
|
-
case "Sequential":
|
|
693
|
-
return { _tag: "Sequential", left: causeToCauseEncoded(cause.left), right: causeToCauseEncoded(cause.right) }
|
|
694
|
-
}
|
|
695
|
-
}
|
|
696
|
-
|
|
697
|
-
function fiberIdToFiberIdFrom(id: FiberId.FiberId): Schema.FiberIdEncoded {
|
|
698
|
-
switch (id._tag) {
|
|
699
|
-
case "None":
|
|
700
|
-
return { _tag: "None" }
|
|
701
|
-
case "Runtime":
|
|
702
|
-
return { _tag: "Runtime", id: id.id, startTimeMillis: id.startTimeMillis }
|
|
703
|
-
case "Composite":
|
|
704
|
-
return { _tag: "Composite", left: fiberIdToFiberIdFrom(id.left), right: fiberIdToFiberIdFrom(id.right) }
|
|
705
|
-
}
|
|
706
|
-
}
|
|
707
|
-
|
|
708
|
-
const NO_DATA_FROM: NoDataFrom = { _tag: "NoData" } as const
|
|
709
|
-
|
|
710
|
-
function asyncDataToAsyncDataFrom<A, E>(data: _AsyncData.AsyncData<A, E>): AsyncDataFrom<A, E> {
|
|
711
|
-
switch (data._tag) {
|
|
712
|
-
case "NoData":
|
|
713
|
-
return NO_DATA_FROM
|
|
714
|
-
case "Loading":
|
|
715
|
-
return loadingToJson(data)
|
|
716
|
-
case "Failure":
|
|
717
|
-
return FailureFrom(
|
|
718
|
-
causeToCauseEncoded(data.cause),
|
|
719
|
-
data.timestamp,
|
|
720
|
-
Option.getOrUndefined(Option.map(data.refreshing, loadingToJson))
|
|
721
|
-
)
|
|
722
|
-
case "Success":
|
|
723
|
-
return SuccessFrom(
|
|
724
|
-
data.value,
|
|
725
|
-
data.timestamp,
|
|
726
|
-
Option.getOrUndefined(Option.map(data.refreshing, loadingToJson))
|
|
727
|
-
)
|
|
728
|
-
case "Optimistic":
|
|
729
|
-
return OptimisticFrom(data.value, data.timestamp, asyncDataToAsyncDataFrom(data.previous))
|
|
730
|
-
}
|
|
731
|
-
}
|
|
732
|
-
|
|
733
|
-
function asyncDataFromToAsyncData<A, E>(data: AsyncDataFrom<A, E>): _AsyncData.AsyncData<A, E> {
|
|
734
|
-
switch (data._tag) {
|
|
735
|
-
case "NoData":
|
|
736
|
-
return _AsyncData.noData()
|
|
737
|
-
case "Loading":
|
|
738
|
-
return loadingFromJson(data)!
|
|
739
|
-
case "Failure":
|
|
740
|
-
return _AsyncData.failCause(causeFromToCause(data.cause), {
|
|
741
|
-
timestamp: data.timestamp,
|
|
742
|
-
refreshing: loadingFromJson(data.refreshing)
|
|
743
|
-
})
|
|
744
|
-
case "Success":
|
|
745
|
-
return _AsyncData.success(data.value, {
|
|
746
|
-
timestamp: data.timestamp,
|
|
747
|
-
refreshing: loadingFromJson(data.refreshing)
|
|
748
|
-
})
|
|
749
|
-
case "Optimistic":
|
|
750
|
-
return _AsyncData.optimistic(asyncDataFromToAsyncData(data.previous), data.value, {
|
|
751
|
-
timestamp: data.timestamp
|
|
752
|
-
})
|
|
753
|
-
}
|
|
754
|
-
}
|