0.2.2 #31

Merged
Thilawyn merged 184 commits from next into master 2026-01-16 17:05:31 +01:00
2 changed files with 22 additions and 46 deletions
Showing only changes of commit a9ed86c4a8 - Show all commits

View File

@@ -1,4 +1,4 @@
import { type Cause, type Context, DateTime, type Duration, Effect, Exit, Fiber, HashMap, identity, Option, Pipeable, Predicate, type Scope, Stream, Subscribable, SubscriptionRef } from "effect"
import { type Cause, type Context, DateTime, type Duration, Effect, Equivalence, Exit, Fiber, HashMap, identity, Option, Pipeable, Predicate, type Scope, Stream, Subscribable, SubscriptionRef } from "effect"
import * as QueryClient from "./QueryClient.js"
import * as Result from "./Result.js"
@@ -25,10 +25,11 @@ extends Pipeable.Pipeable {
readonly run: Effect.Effect<void>
fetch(key: K): Effect.Effect<Result.Final<A, E, P>>
fetchSubscribable(key: K): Effect.Effect<Subscribable.Subscribable<Result.Result<A, E, P>>, never, Scope.Scope>
readonly refetch: Effect.Effect<Result.Final<A, E, P>, Cause.NoSuchElementException>
readonly refetchSubscribable: Effect.Effect<Subscribable.Subscribable<Result.Result<A, E, P>>, Cause.NoSuchElementException, Scope.Scope>
readonly refresh: Effect.Effect<Result.Final<A, E, P>, Cause.NoSuchElementException>
readonly refreshSubscribable: Effect.Effect<Subscribable.Subscribable<Result.Result<A, E, P>>, Cause.NoSuchElementException, Scope.Scope>
readonly invalidateCache: Effect.Effect<void>
invalidateCacheEntry(key: K): Effect.Effect<void>
}
export declare namespace Query {
@@ -114,42 +115,6 @@ extends Pipeable.Class() implements Query<K, A, E, R, P> {
)
}
get refetch(): Effect.Effect<Result.Final<A, E, P>, Cause.NoSuchElementException> {
return this.interrupt.pipe(
Effect.andThen(Effect.Do),
Effect.bind("latestKey", () => Effect.andThen(this.latestKey, identity)),
Effect.bind("latestFinalResult", () => this.latestFinalResult),
Effect.andThen(({ latestKey, latestFinalResult }) => Effect.provide(
this.startCached(latestKey, Option.isSome(latestFinalResult)
? Result.willFetch(latestFinalResult.value) as Result.Final<A, E, P>
: Result.initial()
),
this.context,
)),
Effect.andThen(sub => this.watch(sub)),
)
}
get refetchSubscribable(): Effect.Effect<
Subscribable.Subscribable<Result.Result<A, E, P>>,
Cause.NoSuchElementException,
Scope.Scope
> {
return this.interrupt.pipe(
Effect.andThen(Effect.Do),
Effect.bind("latestKey", () => Effect.andThen(this.latestKey, identity)),
Effect.bind("latestFinalResult", () => this.latestFinalResult),
Effect.andThen(({ latestKey, latestFinalResult }) => Effect.provide(
this.startCached(latestKey, Option.isSome(latestFinalResult)
? Result.willFetch(latestFinalResult.value) as Result.Final<A, E, P>
: Result.initial()
),
this.context,
)),
Effect.tap(sub => Effect.forkScoped(this.watch(sub))),
)
}
get refresh(): Effect.Effect<Result.Final<A, E, P>, Cause.NoSuchElementException> {
return this.interrupt.pipe(
Effect.andThen(Effect.Do),
@@ -218,10 +183,10 @@ extends Pipeable.Class() implements Query<K, A, E, R, P> {
> {
return Result.unsafeForkEffect(
Effect.onExit(this.f(key), exit => Effect.andThen(
SubscriptionRef.set(this.fiber, Option.none()),
Exit.isSuccess(exit)
? this.updateCacheEntry(key, Result.fromExit(exit))
: Effect.void,
SubscriptionRef.set(this.fiber, Option.none()),
)),
{
initial,
@@ -275,13 +240,23 @@ extends Pipeable.Class() implements Query<K, A, E, R, P> {
)
}
removeCacheEntry(key: K): Effect.Effect<void, never, QueryClient.QueryClient> {
return Effect.andThen(
QueryClient.QueryClient,
client => SubscriptionRef.update(
get invalidateCache(): Effect.Effect<void> {
return QueryClient.QueryClient.pipe(
Effect.andThen(client => SubscriptionRef.update(
client.cache,
HashMap.filter((_, key) => !Equivalence.strict()(key.f, this.f)),
)),
Effect.provide(this.context),
)
}
invalidateCacheEntry(key: K): Effect.Effect<void> {
return QueryClient.QueryClient.pipe(
Effect.andThen(client => SubscriptionRef.update(
client.cache,
HashMap.remove(this.makeCacheKey(key)),
),
)),
Effect.provide(this.context),
)
}
}

View File

@@ -28,7 +28,7 @@ const ResultView = Component.makeUntraced("Result")(function*() {
Effect.andThen(response => response.json),
Effect.andThen(Schema.decodeUnknown(Post)),
),
staleTime: "10 seconds",
staleTime: "1 minutes",
})
const mutation = yield* Mutation.make({
@@ -87,6 +87,7 @@ const ResultView = Component.makeUntraced("Result")(function*() {
<Flex direction="row" justify="center" align="center" gap="1">
<Button onClick={() => runPromise(query.refresh)}>Refresh</Button>
<Button onClick={() => runPromise(query.refetch)}>Refetch</Button>
<Button onClick={() => runPromise(query.invalidateCache)}>Invalidate cache</Button>
</Flex>
<div>