diff --git a/packages/extension-query/src/internal/MutationRunner.ts b/packages/extension-query/src/MutationRunner.ts similarity index 68% rename from packages/extension-query/src/internal/MutationRunner.ts rename to packages/extension-query/src/MutationRunner.ts index 5e53dc8..d25bcea 100644 --- a/packages/extension-query/src/internal/MutationRunner.ts +++ b/packages/extension-query/src/MutationRunner.ts @@ -1,12 +1,11 @@ import * as AsyncData from "@typed/async-data" -import { type Context, Effect, type Fiber, Queue, Ref, Stream, SubscriptionRef } from "effect" -import type * as QueryClient from "../QueryClient.js" -import * as QueryProgress from "../QueryProgress.js" -import * as QueryState from "./QueryState.js" +import { Effect, type Fiber, Queue, Ref, Stream, SubscriptionRef } from "effect" +import type * as QueryClient from "./QueryClient.js" +import * as QueryProgress from "./QueryProgress.js" +import { QueryState } from "./internal/index.js" -export interface MutationRunner { - readonly context: Context.Context +export interface MutationRunner { readonly stateRef: SubscriptionRef.SubscriptionRef> readonly mutate: (...key: K) => Effect.Effect | AsyncData.Failure> @@ -17,6 +16,11 @@ export interface MutationRunner { } +export const Tag = (id: Id) => < + Self, K extends readonly unknown[], A, E = never, +>() => Effect.Tag(id)>() + + export interface MakeProps { readonly QueryClient: QueryClient.GenericTagClass readonly mutation: (key: K) => Effect.Effect @@ -28,7 +32,7 @@ export const make = mutation, }: MakeProps ): Effect.Effect< - MutationRunner, R>, + MutationRunner>, never, R | QueryClient.TagClassShape > => Effect.gen(function*() { @@ -37,20 +41,13 @@ export const make = const queryStateTag = QueryState.makeTag>() - const run = (key: K) => Effect.Do.pipe( - Effect.bind("state", () => queryStateTag), - Effect.bind("client", () => QueryClient), - - Effect.flatMap(({ state, client }) => state.set(AsyncData.loading()).pipe( + const run = (key: K) => Effect.all([QueryClient, queryStateTag]).pipe( + Effect.flatMap(([client, state]) => state.set(AsyncData.loading()).pipe( Effect.andThen(mutation(key)), client.errorHandler.handle, Effect.matchCauseEffect({ - onSuccess: v => Effect.succeed(AsyncData.success(v)).pipe( - Effect.tap(state.set) - ), - onFailure: c => Effect.succeed(AsyncData.failure(c)).pipe( - Effect.tap(state.set) - ), + onSuccess: v => Effect.tap(Effect.succeed(AsyncData.success(v)), state.set), + onFailure: c => Effect.tap(Effect.succeed(AsyncData.failure(c)), state.set), }), )), @@ -64,11 +61,11 @@ export const make = value => Ref.set(globalStateRef, value), )) - const forkMutate = (...key: K) => Effect.Do.pipe( - Effect.bind("stateRef", () => Ref.make(AsyncData.noData>())), - Effect.bind("stateQueue", () => Queue.unbounded>>()), - - Effect.flatMap(({ stateRef, stateQueue }) => + const forkMutate = (...key: K) => Effect.all([ + Ref.make(AsyncData.noData>()), + Queue.unbounded>>(), + ]).pipe( + Effect.flatMap(([stateRef, stateQueue]) => Effect.addFinalizer(() => Queue.shutdown(stateQueue)).pipe( Effect.andThen(run(key)), Effect.scoped, diff --git a/packages/extension-query/src/MutationService.ts b/packages/extension-query/src/MutationService.ts deleted file mode 100644 index bdfb30a..0000000 --- a/packages/extension-query/src/MutationService.ts +++ /dev/null @@ -1,16 +0,0 @@ -import type * as AsyncData from "@typed/async-data" -import { Effect, type Fiber, type Stream, type SubscriptionRef } from "effect" - - -export interface MutationService { - readonly state: SubscriptionRef.SubscriptionRef> - readonly mutate: (...key: K) => Effect.Effect | AsyncData.Failure> - readonly forkMutate: (...key: K) => Effect.Effect | AsyncData.Failure>, - state: Stream.Stream>, - ]> -} - -export const Tag = (id: Id) => < - Self, K extends readonly unknown[], A, E = never, ->() => Effect.Tag(id)>() diff --git a/packages/extension-query/src/QueryExtension.ts b/packages/extension-query/src/QueryExtension.ts index 58e5f05..43de83a 100644 --- a/packages/extension-query/src/QueryExtension.ts +++ b/packages/extension-query/src/QueryExtension.ts @@ -1,9 +1,6 @@ -import type * as AsyncData from "@typed/async-data" -import { type Context, Effect, type Fiber, Layer, type Stream, type SubscriptionRef } from "effect" -import * as React from "react" +import { type Effect, type Stream } from "effect" import { ReffuseExtension, type ReffuseNamespace } from "reffuse" -import { MutationRunner } from "./internal/index.js" -import type * as MutationService from "./MutationService.js" +import * as MutationRunner from "./MutationRunner.js" import * as QueryClient from "./QueryClient.js" import type * as QueryProgress from "./QueryProgress.js" import * as QueryRunner from "./QueryRunner.js" @@ -15,25 +12,10 @@ export interface UseQueryProps { readonly options?: QueryRunner.RunOptions } - export interface UseMutationProps { readonly mutation: (key: K) => Effect.Effect } -export interface UseMutationResult { - readonly state: SubscriptionRef.SubscriptionRef> - - readonly mutate: (...key: K) => Effect.Effect | AsyncData.Failure> - readonly forkMutate: (...key: K) => Effect.Effect | AsyncData.Failure>, - state: Stream.Stream>, - ]> - - readonly layer: ( - tag: Context.TagClass> - ) => Layer.Layer -} - export const QueryExtension = ReffuseExtension.make(() => ({ useQuery< @@ -70,23 +52,10 @@ export const QueryExtension = ReffuseExtension.make(() => ({ >( this: ReffuseNamespace.ReffuseNamespace>, props: UseMutationProps, - ): UseMutationResult> { - const runner = this.useMemo(() => MutationRunner.make({ + ): MutationRunner.MutationRunner> { + return this.useMemo(() => MutationRunner.make({ QueryClient: QueryClient.makeGenericTagClass(), mutation: props.mutation, }), []) - - return React.useMemo(() => ({ - state: runner.stateRef, - - mutate: runner.mutate, - forkMutate: runner.forkMutate, - - layer: tag => Layer.succeed(tag, { - state: runner.stateRef, - mutate: runner.mutate, - forkMutate: runner.forkMutate, - }), - }), [runner]) }, })) diff --git a/packages/extension-query/src/index.ts b/packages/extension-query/src/index.ts index b86b17b..71e9d7a 100644 --- a/packages/extension-query/src/index.ts +++ b/packages/extension-query/src/index.ts @@ -1,4 +1,4 @@ -export * as MutationService from "./MutationService.js" +export * as MutationRunner from "./MutationRunner.js" export * as QueryClient from "./QueryClient.js" export * as QueryErrorHandler from "./QueryErrorHandler.js" export * from "./QueryExtension.js" diff --git a/packages/extension-query/src/internal/index.ts b/packages/extension-query/src/internal/index.ts index 4f4784e..d062e02 100644 --- a/packages/extension-query/src/internal/index.ts +++ b/packages/extension-query/src/internal/index.ts @@ -1,2 +1 @@ -export * as MutationRunner from "./MutationRunner.js" export * as QueryState from "./QueryState.js"