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