diff --git a/packages/extension-query/src/QueryProgress.ts b/packages/extension-query/src/QueryProgress.ts index 53d5fee..665da94 100644 --- a/packages/extension-query/src/QueryProgress.ts +++ b/packages/extension-query/src/QueryProgress.ts @@ -1,7 +1,36 @@ -import type * as AsyncData from "@typed/async-data" -import { Effect, type Option } from "effect" +import * as AsyncData from "@typed/async-data" +import { Effect, flow, Layer, Match, Option } from "effect" +import * as QueryState from "./QueryState.js" export class QueryProgress extends Effect.Tag("@reffuse/extension-query/QueryProgress")) => Effect.Effect -}>() {} + readonly get: Effect.Effect, never, QueryState.QueryState> + + readonly update: ( + f: (previous: Option.Option) => AsyncData.Progress + ) => Effect.Effect> +}>() { + static readonly Live = Layer.sync(this, () => { + const queryStateTag = QueryState.makeTag() + + const get = queryStateTag.pipe( + Effect.flatMap(state => state.get), + Effect.map(flow(Match.value, + Match.tag("Loading", v => v.progress), + Match.tag("Refreshing", v => v.progress), + Match.orElse(() => Option.none()), + )), + ) + + const update = (f: (previous: Option.Option) => AsyncData.Progress) => get.pipe( + Effect.map(f), + Effect.flatMap(progress => queryStateTag.pipe( + Effect.flatMap(queryState => queryState.update(previous => + AsyncData.updateProgress(previous, progress) + )) + )), + ) + + return { get, update } + }) +} diff --git a/packages/extension-query/src/QueryState.ts b/packages/extension-query/src/QueryState.ts new file mode 100644 index 0000000..3fd2951 --- /dev/null +++ b/packages/extension-query/src/QueryState.ts @@ -0,0 +1,24 @@ +import * as AsyncData from "@typed/async-data" +import { Context, Effect, Layer } from "effect" + + +export interface QueryState { + readonly get: Effect.Effect> + readonly set: (value: AsyncData.AsyncData) => Effect.Effect + readonly update: (f: (previous: AsyncData.AsyncData) => AsyncData.AsyncData) => Effect.Effect +} + +export const makeTag = (): Context.Tag, QueryState> => Context.GenericTag("@reffuse/query-extension/QueryState") + +export const layer = ( + tag: Context.Tag, QueryState>, + get: Effect.Effect>, + set: (value: AsyncData.AsyncData) => Effect.Effect, +): Layer.Layer> => Layer.succeed(tag, { + get, + set, + update: f => get.pipe( + Effect.map(f), + Effect.flatMap(set), + ), +}) diff --git a/packages/extension-query/src/index.ts b/packages/extension-query/src/index.ts index e249d09..080c361 100644 --- a/packages/extension-query/src/index.ts +++ b/packages/extension-query/src/index.ts @@ -3,5 +3,7 @@ export * as MutationRunner from "./MutationRunner.js" export * as MutationService from "./MutationService.js" export * as QueryClient from "./QueryClient.js" export * from "./QueryExtension.js" +export * as QueryProgress from "./QueryProgress.js" export * as QueryRunner from "./QueryRunner.js" export * as QueryService from "./QueryService.js" +export * as QueryState from "./QueryState.js"