@typed/async-data 0.3.0 → 0.3.2
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/cjs/AsyncData.js.map +1 -1
- package/dist/cjs/Progress.js +15 -3
- package/dist/cjs/Progress.js.map +1 -1
- package/dist/cjs/Schema.js +223 -13
- package/dist/cjs/Schema.js.map +1 -1
- package/dist/dts/AsyncData.d.ts +9 -5
- package/dist/dts/AsyncData.d.ts.map +1 -1
- package/dist/dts/Progress.d.ts +7 -1
- package/dist/dts/Progress.d.ts.map +1 -1
- package/dist/dts/Schema.d.ts +128 -1
- package/dist/dts/Schema.d.ts.map +1 -1
- package/dist/esm/AsyncData.js.map +1 -1
- package/dist/esm/Progress.js +12 -2
- package/dist/esm/Progress.js.map +1 -1
- package/dist/esm/Schema.js +219 -11
- package/dist/esm/Schema.js.map +1 -1
- package/package.json +3 -3
- package/src/AsyncData.ts +7 -5
- package/src/Progress.ts +25 -6
- package/src/Schema.ts +447 -28
package/src/Schema.ts
CHANGED
|
@@ -4,60 +4,433 @@
|
|
|
4
4
|
|
|
5
5
|
import * as Arbitrary from "@effect/schema/Arbitrary"
|
|
6
6
|
import * as AST from "@effect/schema/AST"
|
|
7
|
+
import * as Eq from "@effect/schema/Equivalence"
|
|
7
8
|
import * as ParseResult from "@effect/schema/ParseResult"
|
|
8
9
|
import * as Pretty from "@effect/schema/Pretty"
|
|
9
10
|
import * as Schema from "@effect/schema/Schema"
|
|
10
11
|
import * as AsyncData from "@typed/async-data/AsyncData"
|
|
12
|
+
import { Equal } from "effect"
|
|
11
13
|
import type * as Cause from "effect/Cause"
|
|
12
14
|
import * as Effect from "effect/Effect"
|
|
13
15
|
import * as Option from "effect/Option"
|
|
16
|
+
import * as P from "./Progress.js"
|
|
14
17
|
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
NoData: () => `AsyncData.NoData`,
|
|
21
|
-
Loading: () => `AsyncData.Loading`,
|
|
22
|
-
Failure: (cause, data) =>
|
|
23
|
-
`AsyncData.Failure(refreshing=${Option.isSome(data.refreshing)}, cause=${prettyCause(cause)})`,
|
|
24
|
-
Success: (value, data) =>
|
|
25
|
-
`AsyncData.Success(refreshing=${Option.isSome(data.refreshing)}, value=${prettyValue(value)})`
|
|
18
|
+
const NO_DATA_PRETTY = "AsyncData.NoData"
|
|
19
|
+
const LOADING_PRETTY = (loading: AsyncData.Loading) =>
|
|
20
|
+
Option.match(loading.progress, {
|
|
21
|
+
onNone: () => `AsyncData.Loading(timestamp=${loading.timestamp})`,
|
|
22
|
+
onSome: (progress) => `AsyncData.Loading(timestamp=${loading.timestamp}, progress=${P.pretty(progress)})`
|
|
26
23
|
})
|
|
24
|
+
const FAILURE_PRETTY = <E>(print: Pretty.Pretty<Cause.Cause<E>>) => (failure: AsyncData.Failure<E>) =>
|
|
25
|
+
Option.match(failure.refreshing, {
|
|
26
|
+
onNone: () => `AsyncData.Failure(timestamp=${failure.timestamp}, cause=${print(failure.cause)})`,
|
|
27
|
+
onSome: (loading) =>
|
|
28
|
+
`AsyncData.Failure(timestamp=${failure.timestamp}, refreshing=${LOADING_PRETTY(loading)}, cause=${
|
|
29
|
+
print(failure.cause)
|
|
30
|
+
})`
|
|
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: (loading) =>
|
|
36
|
+
`AsyncData.Success(timestamp=${success.timestamp}, refreshing=${LOADING_PRETTY(loading)}, value=${
|
|
37
|
+
print(success.value)
|
|
38
|
+
})`
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
const NoDataSchemaJson = Schema.struct({
|
|
42
|
+
_tag: Schema.literal("NoData")
|
|
43
|
+
})
|
|
44
|
+
const NoDataSchema = Schema.instanceOf(AsyncData.NoData)
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* @since 1.0.0
|
|
48
|
+
*/
|
|
49
|
+
export const NoData: Schema.Schema<{ readonly _tag: "NoData" }, AsyncData.NoData> = NoDataSchemaJson
|
|
50
|
+
.pipe(
|
|
51
|
+
Schema.transform(
|
|
52
|
+
NoDataSchema,
|
|
53
|
+
(): AsyncData.NoData => AsyncData.noData(),
|
|
54
|
+
(): Schema.Schema.To<typeof NoDataSchemaJson> => ({
|
|
55
|
+
_tag: "NoData"
|
|
56
|
+
})
|
|
57
|
+
),
|
|
58
|
+
Schema.annotations({
|
|
59
|
+
[AST.IdentifierAnnotationId]: NO_DATA_PRETTY,
|
|
60
|
+
[Pretty.PrettyHookId]: () => NO_DATA_PRETTY,
|
|
61
|
+
[Arbitrary.ArbitraryHookId]: (): Arbitrary.Arbitrary<AsyncData.NoData> => (fc) => fc.constant(AsyncData.noData()),
|
|
62
|
+
[Eq.EquivalenceHookId]: () => Equal.equals
|
|
63
|
+
})
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* @since 1.0.0
|
|
68
|
+
*/
|
|
69
|
+
export type NoDataFrom = Schema.Schema.From<typeof NoData>
|
|
70
|
+
|
|
71
|
+
const ProgressSchemaJson = Schema.struct({
|
|
72
|
+
loaded: Schema.bigint,
|
|
73
|
+
total: Schema.optional(Schema.bigint)
|
|
74
|
+
})
|
|
75
|
+
type ProgressFromTo = Schema.Schema.To<typeof ProgressSchemaJson>
|
|
76
|
+
|
|
77
|
+
const ProgressSchema: Schema.Schema<
|
|
78
|
+
{
|
|
79
|
+
readonly loaded: bigint
|
|
80
|
+
readonly total: Option.Option<bigint>
|
|
81
|
+
},
|
|
82
|
+
P.Progress
|
|
83
|
+
> = Schema.data(Schema.struct({
|
|
84
|
+
loaded: Schema.bigintFromSelf,
|
|
85
|
+
total: Schema.optionFromSelf(Schema.bigintFromSelf)
|
|
86
|
+
}))
|
|
87
|
+
|
|
88
|
+
const progressArbitrary: Arbitrary.Arbitrary<P.Progress> = (fc) =>
|
|
89
|
+
fc.bigInt().chain((loaded) => fc.option(fc.bigInt({ min: loaded })).map((total) => P.make(loaded, total)))
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* @since 1.0.0
|
|
93
|
+
*/
|
|
94
|
+
export const Progress: Schema.Schema<{ readonly loaded: string; readonly total?: string | undefined }, P.Progress> =
|
|
95
|
+
ProgressSchemaJson.pipe(
|
|
96
|
+
Schema.transform(
|
|
97
|
+
ProgressSchema,
|
|
98
|
+
(json): P.Progress => P.make(json.loaded, json.total),
|
|
99
|
+
(progress) => ({
|
|
100
|
+
loaded: progress.loaded,
|
|
101
|
+
total: Option.getOrUndefined(progress.total)
|
|
102
|
+
})
|
|
103
|
+
),
|
|
104
|
+
Schema.annotations({
|
|
105
|
+
[AST.IdentifierAnnotationId]: "Progress",
|
|
106
|
+
[Pretty.PrettyHookId]: () => "Progress",
|
|
107
|
+
[Arbitrary.ArbitraryHookId]: (): Arbitrary.Arbitrary<P.Progress> => progressArbitrary,
|
|
108
|
+
[Eq.EquivalenceHookId]: () => Equal.equals
|
|
109
|
+
})
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* @since 1.0.0
|
|
114
|
+
*/
|
|
115
|
+
export type ProgressFrom = Schema.Schema.From<typeof Progress>
|
|
116
|
+
|
|
117
|
+
const LoadingSchemaJson = Schema.struct({
|
|
118
|
+
_tag: Schema.literal("Loading"),
|
|
119
|
+
timestamp: Schema.number,
|
|
120
|
+
progress: Schema.optional(ProgressSchemaJson)
|
|
121
|
+
})
|
|
122
|
+
const LoadingSchema = Schema.instanceOf(AsyncData.Loading)
|
|
123
|
+
|
|
124
|
+
const loadingFromJson = (json: Schema.Schema.To<typeof LoadingSchemaJson>): AsyncData.Loading =>
|
|
125
|
+
AsyncData.loading({ timestamp: json.timestamp, progress: progressFromJson(json.progress) })
|
|
126
|
+
|
|
127
|
+
const loadingToJson = (loading: AsyncData.Loading): Schema.Schema.To<typeof LoadingSchemaJson> => ({
|
|
128
|
+
_tag: "Loading",
|
|
129
|
+
timestamp: loading.timestamp,
|
|
130
|
+
progress: progressToJson(loading.progress)
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
const loadingArbitrary: Arbitrary.Arbitrary<AsyncData.Loading> = (fc) =>
|
|
134
|
+
fc.option(progressArbitrary(fc)).map((progress) =>
|
|
135
|
+
AsyncData.loading({
|
|
136
|
+
timestamp: Date.now(),
|
|
137
|
+
progress: progress || undefined
|
|
138
|
+
})
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* @since 1.0.0
|
|
143
|
+
*/
|
|
144
|
+
export const Loading: Schema.Schema<
|
|
145
|
+
{
|
|
146
|
+
readonly _tag: "Loading"
|
|
147
|
+
readonly timestamp: number
|
|
148
|
+
readonly progress?: ProgressFrom | undefined
|
|
149
|
+
},
|
|
150
|
+
AsyncData.Loading
|
|
151
|
+
> = LoadingSchemaJson
|
|
152
|
+
.pipe(
|
|
153
|
+
Schema.transform(
|
|
154
|
+
LoadingSchema,
|
|
155
|
+
loadingFromJson,
|
|
156
|
+
loadingToJson
|
|
157
|
+
),
|
|
158
|
+
Schema.annotations({
|
|
159
|
+
[AST.IdentifierAnnotationId]: "AsyncData.Loading",
|
|
160
|
+
[Pretty.PrettyHookId]: () => LOADING_PRETTY,
|
|
161
|
+
[Arbitrary.ArbitraryHookId]: () => loadingArbitrary,
|
|
162
|
+
[Eq.EquivalenceHookId]: () => Equal.equals
|
|
163
|
+
})
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* @since 1.0.0
|
|
168
|
+
*/
|
|
169
|
+
export type LoadingFrom = Schema.Schema.From<typeof Loading>
|
|
170
|
+
|
|
171
|
+
const FailureSchemaJson = <EI, E>(cause: Schema.Schema<Schema.CauseFrom<EI>, Cause.Cause<E>>) =>
|
|
172
|
+
Schema.struct({
|
|
173
|
+
_tag: Schema.literal("Failure"),
|
|
174
|
+
cause,
|
|
175
|
+
timestamp: Schema.number,
|
|
176
|
+
refreshing: Schema.optional(LoadingSchemaJson)
|
|
177
|
+
})
|
|
178
|
+
|
|
179
|
+
const FailureSchema = <EI, E>(
|
|
180
|
+
error: Schema.Schema<EI, E>
|
|
181
|
+
): Schema.Schema<AsyncData.Failure<EI>, AsyncData.Failure<E>> =>
|
|
182
|
+
Schema.declare(
|
|
183
|
+
[Schema.cause(error)],
|
|
184
|
+
Schema.struct({}),
|
|
185
|
+
(isDecoding, causeSchema) => {
|
|
186
|
+
const parseCause = isDecoding ? Schema.parse(causeSchema) : Schema.encode(causeSchema)
|
|
187
|
+
|
|
188
|
+
return (input, options) => {
|
|
189
|
+
return Effect.gen(function*(_) {
|
|
190
|
+
if (!AsyncData.isAsyncData(input)) return yield* _(ParseResult.fail(ParseResult.forbidden(input)))
|
|
27
191
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
192
|
+
switch (input._tag) {
|
|
193
|
+
case "Failure": {
|
|
194
|
+
const cause = yield* _(parseCause(input.cause, options))
|
|
195
|
+
|
|
196
|
+
return AsyncData.failCause(cause, {
|
|
197
|
+
timestamp: input.timestamp,
|
|
198
|
+
refreshing: Option.getOrUndefined(input.refreshing)
|
|
199
|
+
})
|
|
200
|
+
}
|
|
201
|
+
default:
|
|
202
|
+
return yield* _(ParseResult.fail(ParseResult.forbidden(input)))
|
|
203
|
+
}
|
|
204
|
+
})
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
const failureArbitrary = <E>(
|
|
210
|
+
cause: Arbitrary.Arbitrary<Cause.Cause<E>>
|
|
211
|
+
): Arbitrary.Arbitrary<AsyncData.Failure<E>> =>
|
|
32
212
|
(fc) =>
|
|
33
|
-
fc.
|
|
34
|
-
fc.
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
213
|
+
fc.option(loadingArbitrary(fc)).chain((refreshing) =>
|
|
214
|
+
cause(fc).chain((cause) =>
|
|
215
|
+
fc.date().map((date) =>
|
|
216
|
+
AsyncData.failCause(cause, {
|
|
217
|
+
timestamp: date.getTime(),
|
|
218
|
+
refreshing: refreshing || undefined
|
|
219
|
+
})
|
|
220
|
+
)
|
|
221
|
+
)
|
|
38
222
|
)
|
|
39
223
|
|
|
224
|
+
/**
|
|
225
|
+
* @since 1.0.0
|
|
226
|
+
*/
|
|
227
|
+
export const Failure = <EI, E>(
|
|
228
|
+
error: Schema.Schema<EI, E>
|
|
229
|
+
): Schema.Schema<
|
|
230
|
+
{
|
|
231
|
+
readonly _tag: "Failure"
|
|
232
|
+
readonly cause: Schema.CauseFrom<EI>
|
|
233
|
+
readonly timestamp: number
|
|
234
|
+
readonly refreshing?: {
|
|
235
|
+
readonly _tag: "Loading"
|
|
236
|
+
readonly timestamp: number
|
|
237
|
+
readonly progress?: { readonly loaded: string; readonly total?: string | undefined } | undefined
|
|
238
|
+
} | undefined
|
|
239
|
+
},
|
|
240
|
+
AsyncData.Failure<E>
|
|
241
|
+
> =>
|
|
242
|
+
FailureSchemaJson(Schema.cause(Schema.from(error)))
|
|
243
|
+
.pipe(
|
|
244
|
+
Schema.transform(
|
|
245
|
+
FailureSchema(error),
|
|
246
|
+
(json): AsyncData.Failure<EI> =>
|
|
247
|
+
AsyncData.failCause(json.cause, {
|
|
248
|
+
timestamp: json.timestamp,
|
|
249
|
+
refreshing: json.refreshing ? loadingFromJson(json.refreshing) : undefined
|
|
250
|
+
}),
|
|
251
|
+
(failure) => ({
|
|
252
|
+
_tag: "Failure",
|
|
253
|
+
cause: failure.cause,
|
|
254
|
+
timestamp: failure.timestamp,
|
|
255
|
+
refreshing: Option.getOrUndefined(Option.map(failure.refreshing, loadingToJson))
|
|
256
|
+
} as const)
|
|
257
|
+
),
|
|
258
|
+
Schema.annotations({
|
|
259
|
+
[AST.IdentifierAnnotationId]: "AsyncData.Failure",
|
|
260
|
+
[Pretty.PrettyHookId]: FAILURE_PRETTY,
|
|
261
|
+
[Arbitrary.ArbitraryHookId]: failureArbitrary,
|
|
262
|
+
[Eq.EquivalenceHookId]: () => Equal.equals
|
|
263
|
+
})
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* @since 1.0.0
|
|
268
|
+
*/
|
|
269
|
+
export type FailureFrom<E> = Schema.Schema.From<ReturnType<typeof FailureSchemaJson<E, E>>>
|
|
270
|
+
|
|
271
|
+
const SuccessSchemaJson = <AI, A>(
|
|
272
|
+
value: Schema.Schema<AI, A>
|
|
273
|
+
): Schema.Schema<
|
|
274
|
+
{
|
|
275
|
+
readonly timestamp: number
|
|
276
|
+
readonly _tag: "Success"
|
|
277
|
+
readonly value: AI
|
|
278
|
+
readonly refreshing?: {
|
|
279
|
+
readonly timestamp: number
|
|
280
|
+
readonly _tag: "Loading"
|
|
281
|
+
readonly progress?: { readonly loaded: string; readonly total?: string | undefined } | undefined
|
|
282
|
+
} | undefined
|
|
283
|
+
},
|
|
284
|
+
{
|
|
285
|
+
readonly timestamp: number
|
|
286
|
+
readonly _tag: "Success"
|
|
287
|
+
readonly value: A
|
|
288
|
+
readonly refreshing?: {
|
|
289
|
+
readonly timestamp: number
|
|
290
|
+
readonly _tag: "Loading"
|
|
291
|
+
readonly progress?: { readonly loaded: bigint; readonly total?: bigint | undefined } | undefined
|
|
292
|
+
} | undefined
|
|
293
|
+
}
|
|
294
|
+
> =>
|
|
295
|
+
Schema.struct({
|
|
296
|
+
_tag: Schema.literal("Success"),
|
|
297
|
+
value,
|
|
298
|
+
timestamp: Schema.number,
|
|
299
|
+
refreshing: Schema.optional(LoadingSchemaJson)
|
|
300
|
+
})
|
|
301
|
+
|
|
302
|
+
const SuccessSchema = <AI, A>(
|
|
303
|
+
value: Schema.Schema<AI, A>
|
|
304
|
+
): Schema.Schema<AsyncData.Success<AI>, AsyncData.Success<A>> =>
|
|
305
|
+
Schema.declare(
|
|
306
|
+
[value],
|
|
307
|
+
Schema.struct({
|
|
308
|
+
_tag: Schema.literal("Success"),
|
|
309
|
+
timestamp: Schema.number
|
|
310
|
+
}),
|
|
311
|
+
(isDecoding, valueSchema) => {
|
|
312
|
+
const parseValue = isDecoding ? Schema.parse(valueSchema) : Schema.encode(valueSchema)
|
|
313
|
+
|
|
314
|
+
return (input, options) => {
|
|
315
|
+
return Effect.gen(function*(_) {
|
|
316
|
+
if (!AsyncData.isAsyncData(input)) return yield* _(ParseResult.fail(ParseResult.forbidden(input)))
|
|
317
|
+
|
|
318
|
+
switch (input._tag) {
|
|
319
|
+
case "Success": {
|
|
320
|
+
const value = yield* _(parseValue(input.value, options))
|
|
321
|
+
|
|
322
|
+
return AsyncData.success(value, {
|
|
323
|
+
timestamp: input.timestamp,
|
|
324
|
+
refreshing: Option.getOrUndefined(input.refreshing)
|
|
325
|
+
})
|
|
326
|
+
}
|
|
327
|
+
default:
|
|
328
|
+
return yield* _(ParseResult.fail(ParseResult.forbidden(input)))
|
|
329
|
+
}
|
|
330
|
+
})
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
)
|
|
334
|
+
|
|
335
|
+
const successArbitrary = <A>(
|
|
336
|
+
value: Arbitrary.Arbitrary<A>
|
|
337
|
+
): Arbitrary.Arbitrary<AsyncData.Success<A>> =>
|
|
338
|
+
(fc) =>
|
|
339
|
+
fc.option(loadingArbitrary(fc)).chain((refreshing) =>
|
|
340
|
+
value(fc).chain((a) =>
|
|
341
|
+
fc.date().map((date) =>
|
|
342
|
+
AsyncData.success(a, {
|
|
343
|
+
timestamp: date.getTime(),
|
|
344
|
+
refreshing: refreshing || undefined
|
|
345
|
+
})
|
|
346
|
+
)
|
|
347
|
+
)
|
|
348
|
+
)
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* @since 1.0.0
|
|
352
|
+
*/
|
|
353
|
+
export const Success = <AI, A>(
|
|
354
|
+
value: Schema.Schema<AI, A>
|
|
355
|
+
): Schema.Schema<
|
|
356
|
+
{
|
|
357
|
+
readonly timestamp: number
|
|
358
|
+
readonly _tag: "Success"
|
|
359
|
+
readonly value: AI
|
|
360
|
+
readonly refreshing?: LoadingFrom | undefined
|
|
361
|
+
},
|
|
362
|
+
AsyncData.Success<A>
|
|
363
|
+
> =>
|
|
364
|
+
SuccessSchemaJson(Schema.from(value))
|
|
365
|
+
.pipe(
|
|
366
|
+
Schema.transform(
|
|
367
|
+
SuccessSchema(value),
|
|
368
|
+
(json): AsyncData.Success<AI> =>
|
|
369
|
+
AsyncData.success(json.value, {
|
|
370
|
+
timestamp: json.timestamp,
|
|
371
|
+
refreshing: json.refreshing ? loadingFromJson(json.refreshing) : undefined
|
|
372
|
+
}),
|
|
373
|
+
(success) => ({
|
|
374
|
+
_tag: "Success",
|
|
375
|
+
value: success.value,
|
|
376
|
+
timestamp: success.timestamp,
|
|
377
|
+
refreshing: Option.getOrUndefined(Option.map(success.refreshing, loadingToJson))
|
|
378
|
+
} as const)
|
|
379
|
+
),
|
|
380
|
+
Schema.annotations({
|
|
381
|
+
[AST.IdentifierAnnotationId]: "AsyncData.Success",
|
|
382
|
+
[Pretty.PrettyHookId]: SUCCESS_PRETTY,
|
|
383
|
+
[Arbitrary.ArbitraryHookId]: successArbitrary,
|
|
384
|
+
[Eq.EquivalenceHookId]: () => Equal.equals
|
|
385
|
+
})
|
|
386
|
+
)
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* @since 1.0.0
|
|
390
|
+
*/
|
|
391
|
+
export type SuccessFrom<A> = Schema.Schema.From<ReturnType<typeof SuccessSchemaJson<A, A>>>
|
|
392
|
+
|
|
393
|
+
/**
|
|
394
|
+
* @since 1.0.0
|
|
395
|
+
*/
|
|
396
|
+
export type AsyncDataFrom<E, A> = NoDataFrom | LoadingFrom | FailureFrom<E> | SuccessFrom<A>
|
|
397
|
+
|
|
40
398
|
/**
|
|
41
399
|
* @since 1.0.0
|
|
42
400
|
*/
|
|
43
401
|
export const asyncData = <EI, E, AI, A>(
|
|
44
402
|
error: Schema.Schema<EI, E>,
|
|
45
403
|
value: Schema.Schema<AI, A>
|
|
404
|
+
): Schema.Schema<AsyncDataFrom<EI, AI>, AsyncData.AsyncData<E, A>> => {
|
|
405
|
+
return Schema.union(
|
|
406
|
+
NoData,
|
|
407
|
+
Loading,
|
|
408
|
+
Failure(error),
|
|
409
|
+
Success(value)
|
|
410
|
+
)
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
/**
|
|
414
|
+
* @since 1.0.0
|
|
415
|
+
*/
|
|
416
|
+
export const asyncDataFromSelf = <EI, E, AI, A>(
|
|
417
|
+
error: Schema.Schema<EI, E>,
|
|
418
|
+
value: Schema.Schema<AI, A>
|
|
46
419
|
): Schema.Schema<AsyncData.AsyncData<EI, AI>, AsyncData.AsyncData<E, A>> => {
|
|
47
420
|
return Schema.declare(
|
|
48
421
|
[Schema.cause(error), value],
|
|
49
422
|
Schema.struct({}),
|
|
50
|
-
(
|
|
423
|
+
(isDecoding, ...params) => {
|
|
51
424
|
const [causeSchema, valueSchema] = params as readonly [
|
|
52
|
-
Schema.Schema<Cause.Cause<
|
|
53
|
-
Schema.Schema<
|
|
425
|
+
Schema.Schema<Cause.Cause<any>, Cause.Cause<any>>,
|
|
426
|
+
Schema.Schema<any, any>
|
|
54
427
|
]
|
|
55
|
-
const parseCause = Schema.parse(causeSchema)
|
|
56
|
-
const parseValue = Schema.parse(valueSchema)
|
|
428
|
+
const parseCause = isDecoding ? Schema.parse(causeSchema) : Schema.encode(causeSchema)
|
|
429
|
+
const parseValue = isDecoding ? Schema.parse(valueSchema) : Schema.encode(valueSchema)
|
|
57
430
|
|
|
58
431
|
return (input, options) => {
|
|
59
432
|
return Effect.gen(function*(_) {
|
|
60
|
-
if (!AsyncData.isAsyncData
|
|
433
|
+
if (!AsyncData.isAsyncData(input)) return yield* _(ParseResult.fail(ParseResult.forbidden(input)))
|
|
61
434
|
|
|
62
435
|
switch (input._tag) {
|
|
63
436
|
case "NoData":
|
|
@@ -67,6 +440,7 @@ export const asyncData = <EI, E, AI, A>(
|
|
|
67
440
|
const cause = yield* _(parseCause(input.cause, options))
|
|
68
441
|
|
|
69
442
|
return AsyncData.failCause(cause, {
|
|
443
|
+
timestamp: input.timestamp,
|
|
70
444
|
refreshing: Option.getOrUndefined(input.refreshing)
|
|
71
445
|
})
|
|
72
446
|
}
|
|
@@ -74,6 +448,7 @@ export const asyncData = <EI, E, AI, A>(
|
|
|
74
448
|
const a = yield* _(parseValue(input.value, options))
|
|
75
449
|
|
|
76
450
|
return AsyncData.success(a, {
|
|
451
|
+
timestamp: input.timestamp,
|
|
77
452
|
refreshing: Option.getOrUndefined(input.refreshing)
|
|
78
453
|
})
|
|
79
454
|
}
|
|
@@ -83,8 +458,52 @@ export const asyncData = <EI, E, AI, A>(
|
|
|
83
458
|
},
|
|
84
459
|
{
|
|
85
460
|
[AST.IdentifierAnnotationId]: "AsyncData",
|
|
86
|
-
[
|
|
87
|
-
[
|
|
461
|
+
[Pretty.PrettyHookId]: asyncDataPretty,
|
|
462
|
+
[Arbitrary.ArbitraryHookId]: asyncDataArbitrary,
|
|
463
|
+
[Eq.EquivalenceHookId]: () => Equal.equals
|
|
88
464
|
}
|
|
89
465
|
)
|
|
90
466
|
}
|
|
467
|
+
|
|
468
|
+
function asyncDataPretty<E, A>(
|
|
469
|
+
E: Pretty.Pretty<Cause.Cause<E>>,
|
|
470
|
+
A: Pretty.Pretty<A>
|
|
471
|
+
): Pretty.Pretty<AsyncData.AsyncData<E, A>> {
|
|
472
|
+
return AsyncData.match({
|
|
473
|
+
NoData: () => NO_DATA_PRETTY,
|
|
474
|
+
Loading: LOADING_PRETTY,
|
|
475
|
+
Failure: (_, data) => FAILURE_PRETTY(E)(data),
|
|
476
|
+
Success: (_, data) => SUCCESS_PRETTY(A)(data)
|
|
477
|
+
})
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
function asyncDataArbitrary<E, A>(
|
|
481
|
+
E: Arbitrary.Arbitrary<Cause.Cause<E>>,
|
|
482
|
+
A: Arbitrary.Arbitrary<A>
|
|
483
|
+
): Arbitrary.Arbitrary<AsyncData.AsyncData<E, A>> {
|
|
484
|
+
const noDataArb = Arbitrary.make(NoData)
|
|
485
|
+
const loadingArb = Arbitrary.make(Loading)
|
|
486
|
+
const failureArb = failureArbitrary(E)
|
|
487
|
+
const successArb = successArbitrary(A)
|
|
488
|
+
|
|
489
|
+
return (fc) =>
|
|
490
|
+
fc.oneof(
|
|
491
|
+
noDataArb(fc),
|
|
492
|
+
loadingArb(fc),
|
|
493
|
+
failureArb(fc),
|
|
494
|
+
successArb(fc)
|
|
495
|
+
)
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
function progressFromJson(json: ProgressFromTo | undefined): P.Progress | undefined {
|
|
499
|
+
if (json === undefined) return
|
|
500
|
+
return P.make(json.loaded, json.total)
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
function progressToJson(progres: Option.Option<P.Progress>): ProgressFromTo | undefined {
|
|
504
|
+
if (Option.isNone(progres)) return
|
|
505
|
+
return {
|
|
506
|
+
loaded: progres.value.loaded,
|
|
507
|
+
total: Option.getOrUndefined(progres.value.total)
|
|
508
|
+
}
|
|
509
|
+
}
|