Compare commits
4 Commits
a274fb77f6
...
9d35e8eef3
| Author | SHA1 | Date | |
|---|---|---|---|
| 9d35e8eef3 | |||
|
|
cb788952a4 | ||
|
|
cd18a9d108 | ||
|
|
a6d91a93a5 |
4
bun.lock
4
bun.lock
@@ -6,7 +6,7 @@
|
|||||||
"name": "@effect-fc/monorepo",
|
"name": "@effect-fc/monorepo",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@biomejs/biome": "^2.3.8",
|
"@biomejs/biome": "^2.3.8",
|
||||||
"@effect/language-service": "^0.64.0",
|
"@effect/language-service": "^0.65.0",
|
||||||
"@types/bun": "^1.3.3",
|
"@types/bun": "^1.3.3",
|
||||||
"npm-check-updates": "^19.1.2",
|
"npm-check-updates": "^19.1.2",
|
||||||
"npm-sort": "^0.0.4",
|
"npm-sort": "^0.0.4",
|
||||||
@@ -131,7 +131,7 @@
|
|||||||
|
|
||||||
"@effect-fc/example": ["@effect-fc/example@workspace:packages/example"],
|
"@effect-fc/example": ["@effect-fc/example@workspace:packages/example"],
|
||||||
|
|
||||||
"@effect/language-service": ["@effect/language-service@0.64.0", "", { "bin": { "effect-language-service": "cli.js" } }, "sha512-Ch6s0aAcrdaOWKmsXw0ys/MvYzz2DD5wf6qALnuyb8Tq1LO8livCUf2ax2cIWzPuEitRyvmIFb0byxKAYi1kcw=="],
|
"@effect/language-service": ["@effect/language-service@0.65.0", "", { "bin": { "effect-language-service": "cli.js" } }, "sha512-eHcpLNCZa1XEDRrXLZqTdky6jAQojL6zQEW53Ba6vJL35j77tJTnV9BFkk34G3rxKoplNo39U0Mum3RfuH9rsg=="],
|
||||||
|
|
||||||
"@effect/platform": ["@effect/platform@0.93.6", "", { "dependencies": { "find-my-way-ts": "^0.1.6", "msgpackr": "^1.11.4", "multipasta": "^0.2.7" }, "peerDependencies": { "effect": "^3.19.8" } }, "sha512-I5lBGQWzWXP4zlIdPs7z7WHmEFVBQhn+74emr/h16GZX96EEJ6I1rjGaKyZF7mtukbMuo9wEckDPssM8vskZ/w=="],
|
"@effect/platform": ["@effect/platform@0.93.6", "", { "dependencies": { "find-my-way-ts": "^0.1.6", "msgpackr": "^1.11.4", "multipasta": "^0.2.7" }, "peerDependencies": { "effect": "^3.19.8" } }, "sha512-I5lBGQWzWXP4zlIdPs7z7WHmEFVBQhn+74emr/h16GZX96EEJ6I1rjGaKyZF7mtukbMuo9wEckDPssM8vskZ/w=="],
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@biomejs/biome": "^2.3.8",
|
"@biomejs/biome": "^2.3.8",
|
||||||
"@effect/language-service": "^0.64.0",
|
"@effect/language-service": "^0.65.0",
|
||||||
"@types/bun": "^1.3.3",
|
"@types/bun": "^1.3.3",
|
||||||
"npm-check-updates": "^19.1.2",
|
"npm-check-updates": "^19.1.2",
|
||||||
"npm-sort": "^0.0.4",
|
"npm-sort": "^0.0.4",
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { type Cause, type Context, DateTime, type Duration, Effect, Fiber, HashMap, identity, Option, Pipeable, Predicate, type Scope, Stream, type Subscribable, SubscriptionRef } from "effect"
|
import { type Cause, type Context, DateTime, type Duration, Effect, Exit, Fiber, HashMap, identity, Option, Pipeable, Predicate, type Scope, Stream, Subscribable, SubscriptionRef } from "effect"
|
||||||
import * as QueryClient from "./QueryClient.js"
|
import * as QueryClient from "./QueryClient.js"
|
||||||
import * as Result from "./Result.js"
|
import * as Result from "./Result.js"
|
||||||
|
|
||||||
@@ -21,6 +21,7 @@ extends Pipeable.Pipeable {
|
|||||||
readonly fiber: Subscribable.Subscribable<Option.Option<Fiber.Fiber<A, E>>>
|
readonly fiber: Subscribable.Subscribable<Option.Option<Fiber.Fiber<A, E>>>
|
||||||
readonly result: Subscribable.Subscribable<Result.Result<A, E, P>>
|
readonly result: Subscribable.Subscribable<Result.Result<A, E, P>>
|
||||||
|
|
||||||
|
readonly run: Effect.Effect<void>
|
||||||
fetch(key: K): Effect.Effect<Result.Final<A, E, P>>
|
fetch(key: K): Effect.Effect<Result.Final<A, E, P>>
|
||||||
fetchSubscribable(key: K): Effect.Effect<Subscribable.Subscribable<Result.Result<A, E, P>>>
|
fetchSubscribable(key: K): Effect.Effect<Subscribable.Subscribable<Result.Result<A, E, P>>>
|
||||||
readonly refetch: Effect.Effect<Result.Final<A, E, P>, Cause.NoSuchElementException>
|
readonly refetch: Effect.Effect<Result.Final<A, E, P>, Cause.NoSuchElementException>
|
||||||
@@ -54,6 +55,16 @@ extends Pipeable.Class() implements Query<K, A, E, R, P> {
|
|||||||
super()
|
super()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get run(): Effect.Effect<void> {
|
||||||
|
return Stream.runForEach(this.key, key => this.interrupt.pipe(
|
||||||
|
Effect.andThen(SubscriptionRef.set(this.latestKey, Option.some(key))),
|
||||||
|
Effect.andThen(this.startCached(key, Result.initial(), false)),
|
||||||
|
Effect.andThen(sub => Effect.forkScoped(this.watch(sub))),
|
||||||
|
Effect.provide(this.context),
|
||||||
|
this.runSemaphore.withPermits(1),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
get interrupt(): Effect.Effect<void, never, never> {
|
get interrupt(): Effect.Effect<void, never, never> {
|
||||||
return Effect.andThen(this.fiber, Option.match({
|
return Effect.andThen(this.fiber, Option.match({
|
||||||
onSome: Fiber.interrupt,
|
onSome: Fiber.interrupt,
|
||||||
@@ -64,21 +75,21 @@ extends Pipeable.Class() implements Query<K, A, E, R, P> {
|
|||||||
fetch(key: K): Effect.Effect<Result.Final<A, E, P>> {
|
fetch(key: K): Effect.Effect<Result.Final<A, E, P>> {
|
||||||
return this.interrupt.pipe(
|
return this.interrupt.pipe(
|
||||||
Effect.andThen(SubscriptionRef.set(this.latestKey, Option.some(key))),
|
Effect.andThen(SubscriptionRef.set(this.latestKey, Option.some(key))),
|
||||||
Effect.andThen(Effect.provide(this.start(key), this.context)),
|
Effect.andThen(Effect.provide(this.startCached(key, Result.initial(), false), this.context)),
|
||||||
Effect.andThen(sub => this.watch(sub)),
|
Effect.andThen(sub => this.watch(sub)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
fetchSubscribable(key: K): Effect.Effect<Subscribable.Subscribable<Result.Result<A, E, P>>> {
|
fetchSubscribable(key: K): Effect.Effect<Subscribable.Subscribable<Result.Result<A, E, P>>> {
|
||||||
return this.interrupt.pipe(
|
return this.interrupt.pipe(
|
||||||
Effect.andThen(SubscriptionRef.set(this.latestKey, Option.some(key))),
|
Effect.andThen(SubscriptionRef.set(this.latestKey, Option.some(key))),
|
||||||
Effect.andThen(Effect.provide(this.start(key), this.context)),
|
Effect.andThen(Effect.provide(this.startCached(key, Result.initial(), false), this.context)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
get refetch(): Effect.Effect<Result.Final<A, E, P>, Cause.NoSuchElementException> {
|
get refetch(): Effect.Effect<Result.Final<A, E, P>, Cause.NoSuchElementException> {
|
||||||
return this.interrupt.pipe(
|
return this.interrupt.pipe(
|
||||||
Effect.andThen(this.latestKey),
|
Effect.andThen(this.latestKey),
|
||||||
Effect.andThen(identity),
|
Effect.andThen(identity),
|
||||||
Effect.andThen(key => Effect.provide(this.start(key), this.context)),
|
Effect.andThen(key => Effect.provide(this.start(key, Result.initial(), false), this.context)),
|
||||||
Effect.andThen(sub => this.watch(sub)),
|
Effect.andThen(sub => this.watch(sub)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -86,14 +97,14 @@ extends Pipeable.Class() implements Query<K, A, E, R, P> {
|
|||||||
return this.interrupt.pipe(
|
return this.interrupt.pipe(
|
||||||
Effect.andThen(this.latestKey),
|
Effect.andThen(this.latestKey),
|
||||||
Effect.andThen(identity),
|
Effect.andThen(identity),
|
||||||
Effect.andThen(key => Effect.provide(this.start(key), this.context)),
|
Effect.andThen(key => Effect.provide(this.start(key, Result.initial(), false), this.context)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
get refresh(): Effect.Effect<Result.Final<A, E, P>, Cause.NoSuchElementException> {
|
get refresh(): Effect.Effect<Result.Final<A, E, P>, Cause.NoSuchElementException> {
|
||||||
return this.interrupt.pipe(
|
return this.interrupt.pipe(
|
||||||
Effect.andThen(this.latestKey),
|
Effect.andThen(this.latestKey),
|
||||||
Effect.andThen(identity),
|
Effect.andThen(identity),
|
||||||
Effect.andThen(key => Effect.provide(this.start(key, true), this.context)),
|
Effect.andThen(key => Effect.provide(this.start(key, Result.initial(), true), this.context)),
|
||||||
Effect.andThen(sub => this.watch(sub)),
|
Effect.andThen(sub => this.watch(sub)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -101,26 +112,53 @@ extends Pipeable.Class() implements Query<K, A, E, R, P> {
|
|||||||
return this.interrupt.pipe(
|
return this.interrupt.pipe(
|
||||||
Effect.andThen(this.latestKey),
|
Effect.andThen(this.latestKey),
|
||||||
Effect.andThen(identity),
|
Effect.andThen(identity),
|
||||||
Effect.andThen(key => Effect.provide(this.start(key, true), this.context)),
|
Effect.andThen(key => Effect.provide(this.start(key, Result.initial(), true), this.context)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
startCached(
|
||||||
|
key: K,
|
||||||
|
initial: Result.Result<A, E, P>,
|
||||||
|
refresh: boolean,
|
||||||
|
): Effect.Effect<
|
||||||
|
Subscribable.Subscribable<Result.Result<A, E, P>>,
|
||||||
|
never,
|
||||||
|
Scope.Scope | QueryClient.QueryClient | R
|
||||||
|
> {
|
||||||
|
return Effect.andThen(this.getCacheEntry(key), Option.match({
|
||||||
|
onSome: entry => QueryClient.isQueryClientCacheEntryStale(entry, this.staleTime)
|
||||||
|
? Effect.map(
|
||||||
|
SubscriptionRef.set(this.result, entry.result as Result.Result<A, E, P>),
|
||||||
|
() => Subscribable.make({
|
||||||
|
get: Effect.succeed(entry.result as Result.Result<A, E, P>),
|
||||||
|
get changes() { return Stream.empty },
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
: this.start(key, Result.optimistic(entry.result) as Result.Result<A, E, P>, false),
|
||||||
|
onNone: () => this.start(key, initial, refresh),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
start(
|
start(
|
||||||
key: K,
|
key: K,
|
||||||
refresh?: boolean,
|
initial: Result.Result<A, E, P>,
|
||||||
|
refresh: boolean,
|
||||||
): Effect.Effect<
|
): Effect.Effect<
|
||||||
Subscribable.Subscribable<Result.Result<A, E, P>>,
|
Subscribable.Subscribable<Result.Result<A, E, P>>,
|
||||||
never,
|
never,
|
||||||
Scope.Scope | R
|
Scope.Scope | QueryClient.QueryClient | R
|
||||||
> {
|
> {
|
||||||
return this.result.pipe(
|
return this.result.pipe(
|
||||||
Effect.map(previous => Result.isFinal(previous)
|
Effect.map(previous => Result.isFinal(previous) ? previous : undefined),
|
||||||
? previous
|
|
||||||
: undefined
|
|
||||||
),
|
|
||||||
Effect.andThen(previous => Result.unsafeForkEffect(
|
Effect.andThen(previous => Result.unsafeForkEffect(
|
||||||
Effect.onExit(this.f(key), () => SubscriptionRef.set(this.fiber, Option.none())),
|
Effect.onExit(this.f(key), exit => Effect.andThen(
|
||||||
|
Exit.isSuccess(exit)
|
||||||
|
? this.updateCacheEntry(key, Result.succeed(exit.value))
|
||||||
|
: Effect.void,
|
||||||
|
SubscriptionRef.set(this.fiber, Option.none()),
|
||||||
|
)),
|
||||||
{
|
{
|
||||||
|
initial,
|
||||||
initialProgress: this.initialProgress,
|
initialProgress: this.initialProgress,
|
||||||
refresh: refresh && previous,
|
refresh: refresh && previous,
|
||||||
previous,
|
previous,
|
||||||
@@ -214,18 +252,5 @@ export const service = <K extends Query.AnyKey, A, E = never, R = never, P = nev
|
|||||||
Scope.Scope | QueryClient.QueryClient | Result.forkEffect.OutputContext<A, E, R, P>
|
Scope.Scope | QueryClient.QueryClient | Result.forkEffect.OutputContext<A, E, R, P>
|
||||||
> => Effect.tap(
|
> => Effect.tap(
|
||||||
make(options),
|
make(options),
|
||||||
query => Effect.forkScoped(run(query)),
|
query => Effect.forkScoped(query.run),
|
||||||
)
|
)
|
||||||
|
|
||||||
export const run = <K extends Query.AnyKey, A, E, R, P>(
|
|
||||||
self: Query<K, A, E, R, P>
|
|
||||||
): Effect.Effect<void> => {
|
|
||||||
const _self = self as QueryImpl<K, A, E, R, P>
|
|
||||||
return Stream.runForEach(_self.key, key => _self.interrupt.pipe(
|
|
||||||
Effect.andThen(SubscriptionRef.set(_self.latestKey, Option.some(key))),
|
|
||||||
Effect.andThen(_self.start(key)),
|
|
||||||
Effect.andThen(sub => Effect.forkScoped(_self.watch(sub))),
|
|
||||||
Effect.provide(_self.context),
|
|
||||||
_self.runSemaphore.withPermits(1),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { type DateTime, type Duration, Effect, Equal, Equivalence, Hash, HashMap, Pipeable, Predicate, type Scope, SubscriptionRef } from "effect"
|
import { DateTime, Duration, Effect, Equal, Equivalence, Hash, HashMap, Pipeable, Predicate, type Scope, SubscriptionRef } from "effect"
|
||||||
import type * as Query from "./Query.js"
|
import type * as Query from "./Query.js"
|
||||||
import type * as Result from "./Result.js"
|
import type * as Result from "./Result.js"
|
||||||
|
|
||||||
@@ -105,3 +105,11 @@ implements Pipeable.Pipeable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const isQueryClientCacheEntry = (u: unknown): u is QueryClientCacheEntry => Predicate.hasProperty(u, QueryClientCacheEntryTypeId)
|
export const isQueryClientCacheEntry = (u: unknown): u is QueryClientCacheEntry => Predicate.hasProperty(u, QueryClientCacheEntryTypeId)
|
||||||
|
|
||||||
|
export const isQueryClientCacheEntryStale = (
|
||||||
|
self: QueryClientCacheEntry,
|
||||||
|
staleTime: Duration.DurationInput,
|
||||||
|
): Effect.Effect<boolean> => Effect.andThen(
|
||||||
|
DateTime.now,
|
||||||
|
now => Duration.lessThan(DateTime.distanceDuration(self.createdAt, now), staleTime),
|
||||||
|
)
|
||||||
|
|||||||
@@ -5,18 +5,16 @@ export const ResultTypeId: unique symbol = Symbol.for("@effect-fc/Result/Result"
|
|||||||
export type ResultTypeId = typeof ResultTypeId
|
export type ResultTypeId = typeof ResultTypeId
|
||||||
|
|
||||||
export type Result<A, E = never, P = never> = (
|
export type Result<A, E = never, P = never> = (
|
||||||
| Initial
|
// biome-ignore lint/complexity/noBannedTypes: "{}" is relevant here
|
||||||
|
| (Initial & ({} | WillFetch))
|
||||||
| Running<P>
|
| Running<P>
|
||||||
| Final<A, E, P>
|
| Final<A, E, P>
|
||||||
// biome-ignore lint/complexity/noBannedTypes: relevant here
|
)
|
||||||
) & ({} | Optimistic)
|
|
||||||
|
|
||||||
export type Final<A, E = never, P = never> = (
|
export type Final<A, E = never, P = never> = (
|
||||||
& (Success<A> | Failure<A, E>)
|
& (Success<A> | Failure<A, E>)
|
||||||
// biome-ignore lint/complexity/noBannedTypes: relevant here
|
// biome-ignore lint/complexity/noBannedTypes: "{}" is relevant here
|
||||||
& ({} | Refreshing<P>)
|
& ({} | WillFetch | WillRefresh | Refreshing<P>)
|
||||||
// biome-ignore lint/complexity/noBannedTypes: relevant here
|
|
||||||
& ({} | Optimistic)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
export namespace Result {
|
export namespace Result {
|
||||||
@@ -49,13 +47,17 @@ export interface Failure<A, E = never> extends Result.Prototype {
|
|||||||
readonly previousSuccess: Option.Option<Success<A>>
|
readonly previousSuccess: Option.Option<Success<A>>
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Refreshing<P = never> {
|
export interface WillFetch extends Result.Prototype {
|
||||||
readonly refreshing: true
|
readonly willFetch: true
|
||||||
readonly progress: P
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Optimistic {
|
export interface WillRefresh extends Result.Prototype {
|
||||||
readonly optimistic: true
|
readonly willRefresh: true
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Refreshing<P = never> extends Result.Prototype {
|
||||||
|
readonly refreshing: true
|
||||||
|
readonly progress: P
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -111,8 +113,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 isRefreshing = (u: unknown): u is Refreshing<unknown> => isResult(u) && Predicate.hasProperty(u, "refreshing") && u.refreshing
|
export const isWillFetch = (u: unknown): u is WillFetch => isResult(u) && Predicate.hasProperty(u, "willFetch")
|
||||||
export const isOptimistic = (u: unknown): u is Optimistic => isResult(u) && Predicate.hasProperty(u, "optimistic") && u.optimistic
|
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 initial: {
|
export const initial: {
|
||||||
(): Initial
|
(): Initial
|
||||||
@@ -130,7 +133,21 @@ export const fail = <E, A = never>(
|
|||||||
previousSuccess: Option.fromNullable(previousSuccess),
|
previousSuccess: Option.fromNullable(previousSuccess),
|
||||||
}, ResultPrototype)
|
}, ResultPrototype)
|
||||||
|
|
||||||
export const refreshing = <R extends Success<any> | Failure<any, any>, P = 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 }),
|
||||||
|
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 }),
|
||||||
|
Object.getPrototypeOf(result),
|
||||||
|
)
|
||||||
|
|
||||||
|
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 Refreshing<Result.Progress<R>>> & Refreshing<P> => Object.setPrototypeOf(
|
||||||
@@ -138,13 +155,6 @@ export const refreshing = <R extends Success<any> | Failure<any, any>, P = never
|
|||||||
Object.getPrototypeOf(result),
|
Object.getPrototypeOf(result),
|
||||||
)
|
)
|
||||||
|
|
||||||
export const optimistic = <R extends Success<any> | Failure<any, any>>(
|
|
||||||
result: R
|
|
||||||
): Omit<R, keyof Optimistic> & Optimistic => Object.setPrototypeOf(
|
|
||||||
Object.assign({}, result, { optimistic: true }),
|
|
||||||
Object.getPrototypeOf(result),
|
|
||||||
)
|
|
||||||
|
|
||||||
export const fromExit = <A, E>(
|
export const fromExit = <A, E>(
|
||||||
exit: Exit.Exit<A, E>,
|
exit: Exit.Exit<A, E>,
|
||||||
previousSuccess?: Success<NoInfer<A>>,
|
previousSuccess?: Success<NoInfer<A>>,
|
||||||
@@ -214,6 +224,7 @@ 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 type Options<A, E, P> = {
|
||||||
|
readonly initial?: Result<A, E, P>
|
||||||
readonly initialProgress?: P
|
readonly initialProgress?: P
|
||||||
readonly previous?: Final<A, E, P>
|
readonly previous?: Final<A, E, P>
|
||||||
} & (
|
} & (
|
||||||
@@ -235,7 +246,7 @@ export const unsafeForkEffect = <A, E, R, P = never>(
|
|||||||
never,
|
never,
|
||||||
Scope.Scope | unsafeForkEffect.OutputContext<A, E, R, P>
|
Scope.Scope | unsafeForkEffect.OutputContext<A, E, R, P>
|
||||||
> => Effect.Do.pipe(
|
> => Effect.Do.pipe(
|
||||||
Effect.bind("ref", () => Ref.make(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(options?.refresh
|
||||||
|
|||||||
Reference in New Issue
Block a user