@reffuse/extension-query 0.1.5 #16

Merged
Thilawyn merged 347 commits from next into master 2025-06-01 05:28:47 +02:00
2 changed files with 50 additions and 36 deletions
Showing only changes of commit f9bd5d4d6b - Show all commits

View File

@@ -35,12 +35,13 @@ export const make = <EH, K extends readonly unknown[], A, E, HandledE, R>(
const context = yield* Effect.context<R | QueryClient.TagClassShape<EH, HandledE> | EH>() const context = yield* Effect.context<R | QueryClient.TagClassShape<EH, HandledE> | EH>()
const globalStateRef = yield* SubscriptionRef.make(AsyncData.noData<A, Exclude<E, HandledE>>()) const globalStateRef = yield* SubscriptionRef.make(AsyncData.noData<A, Exclude<E, HandledE>>())
const queryStateTag = QueryState.makeTag<A, Exclude<E, HandledE>>()
const run = (key: K) => Effect.all([ const run = (key: K) => Effect.all([
QueryClient, queryStateTag,
QueryState.makeTag<A, Exclude<E, HandledE>>(), QueryClient.pipe(Effect.flatMap(client => client.ErrorHandler)),
]).pipe( ]).pipe(
Effect.flatMap(([client, state]) => client.ErrorHandler.pipe( Effect.flatMap(([state, errorHandler]) => state.set(AsyncData.loading()).pipe(
Effect.flatMap(errorHandler => state.set(AsyncData.loading()).pipe(
Effect.andThen(mutation(key)), Effect.andThen(mutation(key)),
errorHandler.handle, errorHandler.handle,
Effect.matchCauseEffect({ Effect.matchCauseEffect({
@@ -51,7 +52,6 @@ export const make = <EH, K extends readonly unknown[], A, E, HandledE, R>(
Effect.tap(state.set) Effect.tap(state.set)
), ),
}), }),
))
)), )),
Effect.provide(context), Effect.provide(context),
@@ -60,7 +60,7 @@ export const make = <EH, K extends readonly unknown[], A, E, HandledE, R>(
const mutate = (...key: K) => run(key).pipe( const mutate = (...key: K) => run(key).pipe(
Effect.provide(QueryState.layer( Effect.provide(QueryState.layer(
QueryState.makeTag<A, Exclude<E, HandledE>>(), queryStateTag,
globalStateRef, globalStateRef,
value => Ref.set(globalStateRef, value), value => Ref.set(globalStateRef, value),
)) ))
@@ -74,7 +74,7 @@ export const make = <EH, K extends readonly unknown[], A, E, HandledE, R>(
Effect.tap(() => Queue.shutdown(stateQueue)), Effect.tap(() => Queue.shutdown(stateQueue)),
Effect.provide(QueryState.layer( Effect.provide(QueryState.layer(
QueryState.makeTag<A, Exclude<E, HandledE>>(), queryStateTag,
stateRef, stateRef,
value => Queue.offer(stateQueue, value).pipe( value => Queue.offer(stateQueue, value).pipe(
Effect.andThen(Ref.set(stateRef, value)), Effect.andThen(Ref.set(stateRef, value)),

View File

@@ -2,6 +2,8 @@ import { BrowserStream } from "@effect/platform-browser"
import * as AsyncData from "@typed/async-data" import * as AsyncData from "@typed/async-data"
import { type Cause, type Context, Effect, Fiber, identity, Option, Ref, type Scope, Stream, SubscriptionRef } from "effect" import { type Cause, type Context, Effect, Fiber, identity, Option, Ref, type Scope, Stream, SubscriptionRef } from "effect"
import type * as QueryClient from "../QueryClient.js" import type * as QueryClient from "../QueryClient.js"
import * as QueryProgress from "../QueryProgress.js"
import * as QueryState from "./QueryState.js"
export interface QueryRunner<K extends readonly unknown[], A, E, R> { export interface QueryRunner<K extends readonly unknown[], A, E, R> {
@@ -43,6 +45,9 @@ export const make = <EH, K extends readonly unknown[], A, E, HandledE, R>(
const stateRef = yield* SubscriptionRef.make(AsyncData.noData<A, Exclude<E, HandledE>>()) const stateRef = yield* SubscriptionRef.make(AsyncData.noData<A, Exclude<E, HandledE>>())
const fiberRef = yield* SubscriptionRef.make(Option.none<Fiber.RuntimeFiber<void, Cause.NoSuchElementException>>()) const fiberRef = yield* SubscriptionRef.make(Option.none<Fiber.RuntimeFiber<void, Cause.NoSuchElementException>>())
const queryStateTag = QueryState.makeTag<A, Exclude<E, HandledE>>()
const queryStateLayer = QueryState.layer(queryStateTag, stateRef, value => Ref.set(stateRef, value))
const interrupt = fiberRef.pipe( const interrupt = fiberRef.pipe(
Effect.flatMap(Option.match({ Effect.flatMap(Option.match({
onSome: fiber => Ref.set(fiberRef, Option.none()).pipe( onSome: fiber => Ref.set(fiberRef, Option.none()).pipe(
@@ -64,27 +69,32 @@ export const make = <EH, K extends readonly unknown[], A, E, HandledE, R>(
})) }))
) )
const run = QueryClient.pipe( const run = Effect.all([
Effect.flatMap(client => client.ErrorHandler), queryStateTag,
Effect.flatMap(errorHandler => latestKeyRef.pipe( QueryClient.pipe(Effect.flatMap(client => client.ErrorHandler)),
]).pipe(
Effect.flatMap(([state, errorHandler]) => latestKeyRef.pipe(
Effect.flatMap(identity), Effect.flatMap(identity),
Effect.flatMap(key => query(key).pipe( Effect.flatMap(key => query(key).pipe(
errorHandler.handle, errorHandler.handle,
Effect.matchCauseEffect({ Effect.matchCauseEffect({
onSuccess: v => Ref.set(stateRef, AsyncData.success(v)), onSuccess: v => state.set(AsyncData.success(v)),
onFailure: c => Ref.set(stateRef, AsyncData.failure(c)), onFailure: c => state.set(AsyncData.failure(c)),
}), }),
)), )),
)), )),
Effect.provide(context), Effect.provide(context),
Effect.provide(QueryProgress.QueryProgress.Live),
) )
const forkFetch = interrupt.pipe( const forkFetch = queryStateTag.pipe(
Effect.andThen(Ref.set(stateRef, AsyncData.loading()).pipe( Effect.flatMap(state => interrupt.pipe(
Effect.andThen(state.set(AsyncData.loading()).pipe(
Effect.andThen(run), Effect.andThen(run),
Effect.fork, Effect.fork,
)), )),
)),
Effect.flatMap(fiber => Effect.flatMap(fiber =>
Ref.set(fiberRef, Option.some(fiber)).pipe( Ref.set(fiberRef, Option.some(fiber)).pipe(
@@ -94,10 +104,12 @@ export const make = <EH, K extends readonly unknown[], A, E, HandledE, R>(
), ),
Effect.forkDaemon, Effect.forkDaemon,
Effect.provide(queryStateLayer),
) )
const forkRefresh = interrupt.pipe( const forkRefresh = queryStateTag.pipe(
Effect.andThen(Ref.update(stateRef, previous => { Effect.flatMap(state => interrupt.pipe(
Effect.andThen(state.update(previous => {
if (AsyncData.isSuccess(previous) || AsyncData.isFailure(previous)) if (AsyncData.isSuccess(previous) || AsyncData.isFailure(previous))
return AsyncData.refreshing(previous) return AsyncData.refreshing(previous)
if (AsyncData.isRefreshing(previous)) if (AsyncData.isRefreshing(previous))
@@ -106,6 +118,7 @@ export const make = <EH, K extends readonly unknown[], A, E, HandledE, R>(
}).pipe( }).pipe(
Effect.andThen(run), Effect.andThen(run),
Effect.fork, Effect.fork,
))
)), )),
Effect.flatMap(fiber => Effect.flatMap(fiber =>
@@ -116,6 +129,7 @@ export const make = <EH, K extends readonly unknown[], A, E, HandledE, R>(
), ),
Effect.forkDaemon, Effect.forkDaemon,
Effect.provide(queryStateLayer),
) )
const fetchOnKeyChange = Effect.addFinalizer(() => interrupt).pipe( const fetchOnKeyChange = Effect.addFinalizer(() => interrupt).pipe(