0.2.2 #31
@@ -11,13 +11,11 @@ export type Result<A, E = never, P = never> = (
|
||||
| Final<A, E, P>
|
||||
)
|
||||
|
||||
export type Final<A, E = never, P = never> = (
|
||||
& (Success<A> | Failure<A, E>)
|
||||
// biome-ignore lint/complexity/noBannedTypes: "{}" is relevant here
|
||||
& ({} | WillFetch | WillRefresh | Refreshing<P>)
|
||||
)
|
||||
export type Final<A, E = never, P = never> = (Success<A> | Failure<A, E>) & ({} | Flags<P>)
|
||||
export type Flags<P = never> = WillFetch | WillRefresh | Refreshing<P>
|
||||
|
||||
export namespace Result {
|
||||
export declare namespace Result {
|
||||
export interface Prototype extends Pipeable.Pipeable, Equal.Equal {
|
||||
readonly [ResultTypeId]: ResultTypeId
|
||||
}
|
||||
@@ -27,6 +25,10 @@ export namespace Result {
|
||||
export type Progress<R extends Result<any, any, any>> = [R] extends [Result<infer _A, infer _E, infer P>] ? P : never
|
||||
}
|
||||
|
||||
export declare namespace Flags {
|
||||
export type Keys = keyof WillFetch & WillRefresh & Refreshing<any>
|
||||
}
|
||||
|
||||
export interface Initial extends Result.Prototype {
|
||||
readonly _tag: "Initial"
|
||||
}
|
||||
@@ -47,16 +49,16 @@ export interface Failure<A, E = never> extends Result.Prototype {
|
||||
readonly previousSuccess: Option.Option<Success<A>>
|
||||
}
|
||||
|
||||
export interface WillFetch extends Result.Prototype {
|
||||
readonly willFetch: true
|
||||
export interface WillFetch {
|
||||
readonly _flag: "WillFetch"
|
||||
}
|
||||
|
||||
export interface WillRefresh extends Result.Prototype {
|
||||
readonly willRefresh: true
|
||||
export interface WillRefresh {
|
||||
readonly _flag: "WillRefresh"
|
||||
}
|
||||
|
||||
export interface Refreshing<P = never> extends Result.Prototype {
|
||||
readonly refreshing: true
|
||||
export interface Refreshing<P = never> {
|
||||
readonly _flag: "Refreshing"
|
||||
readonly progress: P
|
||||
}
|
||||
|
||||
@@ -113,9 +115,9 @@ export const isInitial = (u: unknown): u is Initial => isResult(u) && u._tag ===
|
||||
export const isRunning = (u: unknown): u is Running<unknown> => isResult(u) && u._tag === "Running"
|
||||
export const isSuccess = (u: unknown): u is Success<unknown> => isResult(u) && u._tag === "Success"
|
||||
export const isFailure = (u: unknown): u is Failure<unknown, unknown> => isResult(u) && u._tag === "Failure"
|
||||
export const isWillFetch = (u: unknown): u is WillFetch => isResult(u) && Predicate.hasProperty(u, "willFetch")
|
||||
export const isWillRefresh = (u: unknown): u is WillRefresh => isResult(u) && Predicate.hasProperty(u, "willRefresh")
|
||||
export const isRefreshing = (u: unknown): u is Refreshing<unknown> => isResult(u) && Predicate.hasProperty(u, "refreshing")
|
||||
export const hasWillFetchFlag = (u: unknown): u is WillFetch => isResult(u) && Predicate.hasProperty(u, "_flag") && u._flag === "WillFetch"
|
||||
export const hasWillRefreshFlag = (u: unknown): u is WillRefresh => isResult(u) && Predicate.hasProperty(u, "_flag") && u._flag === "WillRefresh"
|
||||
export const hasRefreshingFlag = (u: unknown): u is Refreshing<unknown> => isResult(u) && Predicate.hasProperty(u, "_flag") && u._flag === "Refreshing"
|
||||
|
||||
export const initial: {
|
||||
(): Initial
|
||||
@@ -135,23 +137,23 @@ export const fail = <E, A = never>(
|
||||
|
||||
export const willFetch = <R extends Initial | Final<any, any, any>>(
|
||||
result: R
|
||||
): Omit<R, keyof WillFetch> & WillFetch => Object.setPrototypeOf(
|
||||
Object.assign({}, result, { willFetch: true }),
|
||||
): Omit<R, keyof Flags.Keys> & WillFetch => Object.setPrototypeOf(
|
||||
Object.assign({}, result, { _flag: "WillFetch" }),
|
||||
Object.getPrototypeOf(result),
|
||||
)
|
||||
|
||||
export const willRefresh = <R extends Final<any, any, any>>(
|
||||
result: R
|
||||
): Omit<R, keyof WillRefresh> & WillRefresh => Object.setPrototypeOf(
|
||||
Object.assign({}, result, { willRefresh: true }),
|
||||
): Omit<R, keyof Flags.Keys> & WillRefresh => Object.setPrototypeOf(
|
||||
Object.assign({}, result, { _flag: "WillRefresh" }),
|
||||
Object.getPrototypeOf(result),
|
||||
)
|
||||
|
||||
export const refreshing = <R extends Final<any, any, any>, P = never>(
|
||||
result: R,
|
||||
progress?: P,
|
||||
): Omit<R, keyof Refreshing<Result.Progress<R>>> & Refreshing<P> => Object.setPrototypeOf(
|
||||
Object.assign({}, result, { refreshing: true, progress }),
|
||||
): Omit<R, keyof Flags.Keys> & Refreshing<P> => Object.setPrototypeOf(
|
||||
Object.assign({}, result, { _flag: "Refreshing", progress }),
|
||||
Object.getPrototypeOf(result),
|
||||
)
|
||||
|
||||
@@ -203,17 +205,17 @@ export const makeProgressLayer = <A, E, P = never>(): Layer.Layer<
|
||||
const state = yield* State<A, E, P>()
|
||||
|
||||
return {
|
||||
update: <E, R>(f: (previous: P) => Effect.Effect<P, E, R>) => Effect.Do.pipe(
|
||||
update: <FE, FR>(f: (previous: P) => Effect.Effect<P, FE, FR>) => Effect.Do.pipe(
|
||||
Effect.bind("previous", () => Effect.andThen(state.get, previous =>
|
||||
isRunning(previous) || isRefreshing(previous)
|
||||
(isRunning(previous) || hasRefreshingFlag(previous))
|
||||
? Effect.succeed(previous)
|
||||
: Effect.fail(new PreviousResultNotRunningNorRefreshing({ previous })),
|
||||
)),
|
||||
Effect.bind("progress", ({ previous }) => f(previous.progress)),
|
||||
Effect.let("next", ({ previous, progress }) => Object.setPrototypeOf(
|
||||
Object.assign({}, previous, { progress }),
|
||||
Object.getPrototypeOf(previous),
|
||||
)),
|
||||
Effect.let("next", ({ previous, progress }) => isRunning(previous)
|
||||
? running(progress)
|
||||
: refreshing(previous, progress) as Final<A, E, P> & Refreshing<P>
|
||||
),
|
||||
Effect.andThen(({ next }) => state.set(next)),
|
||||
),
|
||||
}
|
||||
@@ -223,19 +225,11 @@ export const makeProgressLayer = <A, E, P = never>(): Layer.Layer<
|
||||
export namespace unsafeForkEffect {
|
||||
export type OutputContext<A, E, R, P> = Exclude<R, State<A, E, P> | Progress<P> | Progress<never>>
|
||||
|
||||
export type Options<A, E, P> = {
|
||||
readonly initial?: Result<A, E, P>
|
||||
export interface Options<A, E, P> {
|
||||
// biome-ignore lint/complexity/noBannedTypes: "{}" is relevant here
|
||||
readonly initial?: (Initial | Success<A> | Failure<A, E>) & ({} | WillFetch | WillRefresh)
|
||||
readonly initialProgress?: P
|
||||
readonly previous?: Final<A, E, P>
|
||||
} & (
|
||||
| {
|
||||
readonly refresh: true
|
||||
readonly previous: Final<A, E, P>
|
||||
}
|
||||
| {
|
||||
readonly refresh?: false
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
export const unsafeForkEffect = <A, E, R, P = never>(
|
||||
@@ -249,13 +243,17 @@ export const unsafeForkEffect = <A, E, R, P = never>(
|
||||
Effect.bind("ref", () => Ref.make(options?.initial ?? initial<A, E, P>())),
|
||||
Effect.bind("pubsub", () => PubSub.unbounded<Result<A, E, P>>()),
|
||||
Effect.bind("fiber", ({ ref, pubsub }) => Effect.forkScoped(State<A, E, P>().pipe(
|
||||
Effect.andThen(state => state.set(options?.refresh
|
||||
? refreshing(options.previous, options?.initialProgress) as Result<A, E, P>
|
||||
Effect.andThen(state => state.set(
|
||||
(isFinal(options?.initial) && hasWillRefreshFlag(options?.initial))
|
||||
? refreshing(options.initial, options?.initialProgress) as Result<A, E, P>
|
||||
: running(options?.initialProgress)
|
||||
).pipe(
|
||||
Effect.andThen(effect),
|
||||
Effect.onExit(exit => Effect.andThen(
|
||||
state.set(fromExit(exit, (options?.previous && isSuccess(options.previous)) ? options.previous : undefined)),
|
||||
state.set(fromExit(
|
||||
exit,
|
||||
isSuccess(options?.initial) ? options.initial : undefined),
|
||||
),
|
||||
Effect.forkScoped(PubSub.shutdown(pubsub)),
|
||||
)),
|
||||
)),
|
||||
@@ -286,7 +284,7 @@ export const unsafeForkEffect = <A, E, R, P = never>(
|
||||
export namespace forkEffect {
|
||||
export type InputContext<R, P> = R extends Progress<infer X> ? [X] extends [P] ? R : never : R
|
||||
export type OutputContext<A, E, R, P> = unsafeForkEffect.OutputContext<A, E, R, P>
|
||||
export type Options<A, E, P> = unsafeForkEffect.Options<A, E, P>
|
||||
export interface Options<A, E, P> extends unsafeForkEffect.Options<A, E, P> {}
|
||||
}
|
||||
|
||||
export const forkEffect: {
|
||||
|
||||
Reference in New Issue
Block a user