Compare commits
7 Commits
c943d81702
...
e9e17ac211
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e9e17ac211 | ||
|
|
1f0ff725ff | ||
|
|
447d89982c | ||
|
|
778ee27795 | ||
|
|
077816efb6 | ||
|
|
e4bacd1ca7 | ||
|
|
0e2c0db28f |
@@ -5,7 +5,7 @@ import { Layer } from "effect"
|
||||
import { StrictMode } from "react"
|
||||
import { createRoot } from "react-dom/client"
|
||||
import { ReffuseRuntime } from "reffuse"
|
||||
import { AppQueryClientLive, AppQueryErrorHandlerLive } from "./query"
|
||||
import { AppQueryClient, AppQueryErrorHandler } from "./query"
|
||||
import { GlobalContext } from "./reffuse"
|
||||
import { routeTree } from "./routeTree.gen"
|
||||
|
||||
@@ -15,8 +15,8 @@ const layer = Layer.empty.pipe(
|
||||
Layer.provideMerge(Geolocation.layer),
|
||||
Layer.provideMerge(Permissions.layer),
|
||||
Layer.provideMerge(FetchHttpClient.layer),
|
||||
Layer.provideMerge(AppQueryClientLive),
|
||||
Layer.provideMerge(AppQueryErrorHandlerLive),
|
||||
Layer.provideMerge(AppQueryClient.Live),
|
||||
Layer.provideMerge(AppQueryErrorHandler.Live),
|
||||
)
|
||||
|
||||
const router = createRouter({ routeTree })
|
||||
|
||||
@@ -2,9 +2,8 @@ import { HttpClientError } from "@effect/platform"
|
||||
import { ErrorHandler, QueryClient } from "@reffuse/extension-query"
|
||||
|
||||
|
||||
export class AppQueryErrorHandler extends ErrorHandler.Tag("AppQueryErrorHandler")<AppQueryErrorHandler,
|
||||
export class AppQueryErrorHandler extends ErrorHandler.Service("AppQueryErrorHandler")<AppQueryErrorHandler,
|
||||
HttpClientError.HttpClientError
|
||||
>() {}
|
||||
export const AppQueryErrorHandlerLive = ErrorHandler.layer(AppQueryErrorHandler)
|
||||
|
||||
export const [AppQueryClient, AppQueryClientLive] = QueryClient.make({ ErrorHandler: AppQueryErrorHandler })
|
||||
export class AppQueryClient extends QueryClient.Service({ ErrorHandler: AppQueryErrorHandler })<AppQueryClient>() {}
|
||||
|
||||
@@ -2,7 +2,6 @@ import { HttpClient } from "@effect/platform"
|
||||
import { Clipboard, Geolocation, Permissions } from "@effect/platform-browser"
|
||||
import { LazyRefExtension } from "@reffuse/extension-lazyref"
|
||||
import { QueryExtension } from "@reffuse/extension-query"
|
||||
import { Context } from "effect"
|
||||
import { Reffuse, ReffuseContext } from "reffuse"
|
||||
import { AppQueryClient, AppQueryErrorHandler } from "./query"
|
||||
|
||||
@@ -12,7 +11,7 @@ export const GlobalContext = ReffuseContext.make<
|
||||
| Geolocation.Geolocation
|
||||
| Permissions.Permissions
|
||||
| HttpClient.HttpClient
|
||||
| Context.Tag.Service<typeof AppQueryClient>
|
||||
| AppQueryClient
|
||||
| AppQueryErrorHandler
|
||||
>()
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { type Cause, type Context, Effect, Layer, Queue, Stream } from "effect"
|
||||
import { type Cause, Context, Effect, Layer, Queue, Stream } from "effect"
|
||||
import type { Mutable } from "effect/Types"
|
||||
|
||||
|
||||
export interface ErrorHandler<E> {
|
||||
@@ -9,25 +10,28 @@ export interface ErrorHandler<E> {
|
||||
export type Error<T> = T extends ErrorHandler<infer E> ? E : never
|
||||
|
||||
|
||||
export const Tag = <const Id extends string>(id: Id) => <
|
||||
Self, E = never,
|
||||
>() => Effect.Tag(id)<Self, ErrorHandler<E>>()
|
||||
export interface ServiceResult<Self, Id extends string, E> extends Context.TagClass<Self, Id, ErrorHandler<E>> {
|
||||
readonly Live: Layer.Layer<Self>
|
||||
}
|
||||
|
||||
export const layer = <Self, Id extends string, E>(
|
||||
tag: Context.TagClass<Self, Id, ErrorHandler<E>>
|
||||
): Layer.Layer<Self> => Layer.effect(tag, Effect.gen(function*() {
|
||||
const queue = yield* Queue.unbounded<Cause.Cause<E>>()
|
||||
const errors = Stream.fromQueue(queue)
|
||||
export const Service = <const Id extends string>(id: Id) => (
|
||||
<Self, E = never>(): ServiceResult<Self, Id, E> => {
|
||||
const TagClass = Context.Tag(id)() as ServiceResult<Self, Id, E>
|
||||
(TagClass as Mutable<typeof TagClass>).Live = Layer.effect(TagClass, Effect.gen(function*() {
|
||||
const queue = yield* Queue.unbounded<Cause.Cause<E>>()
|
||||
const errors = Stream.fromQueue(queue)
|
||||
|
||||
const handle = <A, SelfE, R>(
|
||||
self: Effect.Effect<A, SelfE, R>
|
||||
) => Effect.tapErrorCause(self, cause =>
|
||||
Queue.offer(queue, cause as Cause.Cause<E>)
|
||||
) as Effect.Effect<A, Exclude<SelfE, E>, R>
|
||||
const handle = <A, SelfE, R>(
|
||||
self: Effect.Effect<A, SelfE, R>
|
||||
) => Effect.tapErrorCause(self, cause =>
|
||||
Queue.offer(queue, cause as Cause.Cause<E>)
|
||||
) as Effect.Effect<A, Exclude<SelfE, E>, R>
|
||||
|
||||
return { errors, handle }
|
||||
}))
|
||||
return { errors, handle }
|
||||
}))
|
||||
return TagClass
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
export class DefaultErrorHandler extends Tag("@reffuse/extension-query/DefaultErrorHandler")<DefaultErrorHandler>() {}
|
||||
export const DefaultErrorHandlerLive = layer(DefaultErrorHandler)
|
||||
export class DefaultErrorHandler extends Service("@reffuse/extension-query/DefaultErrorHandler")<DefaultErrorHandler>() {}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Context, Effect, Layer } from "effect"
|
||||
import { Context, Layer } from "effect"
|
||||
import type { Mutable } from "effect/Types"
|
||||
import * as ErrorHandler from "./ErrorHandler.js"
|
||||
|
||||
|
||||
@@ -6,42 +7,33 @@ export interface QueryClient<EH, HandledE> {
|
||||
readonly ErrorHandler: Context.Tag<EH, ErrorHandler.ErrorHandler<HandledE>>
|
||||
}
|
||||
|
||||
export type Tag<EH, HandledE> = Context.Tag<QueryClient<EH, HandledE>, QueryClient<EH, HandledE>>
|
||||
export const makeTag = <EH = never, HandledE = never>(): Tag<EH, HandledE> => Context.GenericTag("@reffuse/extension-query/QueryClient")
|
||||
|
||||
const id = "@reffuse/extension-query/QueryClient"
|
||||
|
||||
export type TagClassShape<EH, HandledE> = Context.TagClassShape<typeof id, QueryClient<EH, HandledE>>
|
||||
export type GenericTagClass<EH, HandledE> = Context.TagClass<TagClassShape<EH, HandledE>, typeof id, QueryClient<EH, HandledE>>
|
||||
export const makeGenericTagClass = <EH = never, HandledE = never>(): GenericTagClass<EH, HandledE> => Context.Tag(id)()
|
||||
|
||||
|
||||
export interface MakeProps<EH, HandledE> {
|
||||
export interface ServiceProps<EH, HandledE> {
|
||||
readonly ErrorHandler?: Context.Tag<EH, ErrorHandler.ErrorHandler<HandledE>>
|
||||
}
|
||||
|
||||
export type MakeResult<EH, HandledE> = [
|
||||
tag: Tag<EH, HandledE>,
|
||||
layer: Layer.Layer<
|
||||
| QueryClient<EH, HandledE>
|
||||
| (EH extends ErrorHandler.DefaultErrorHandler
|
||||
? ErrorHandler.DefaultErrorHandler
|
||||
: never)
|
||||
>,
|
||||
]
|
||||
export interface ServiceResult<Self, EH, HandledE> extends Context.TagClass<Self, typeof id, QueryClient<EH, HandledE>> {
|
||||
readonly Live: Layer.Layer<Self>
|
||||
}
|
||||
|
||||
export const make = <
|
||||
export const Service = <
|
||||
EH = ErrorHandler.DefaultErrorHandler,
|
||||
HandledE = never,
|
||||
HandledE = ErrorHandler.Error<Context.Tag.Service<ErrorHandler.DefaultErrorHandler>>,
|
||||
>(
|
||||
props?: MakeProps<EH, HandledE>
|
||||
): MakeResult<EH, HandledE> => [
|
||||
makeTag(),
|
||||
|
||||
Layer.empty.pipe(
|
||||
Layer.provideMerge(
|
||||
Layer.effect(makeTag<EH, HandledE>(), Effect.succeed({
|
||||
ErrorHandler: (props?.ErrorHandler ?? ErrorHandler.DefaultErrorHandler) as Context.Tag<EH, ErrorHandler.ErrorHandler<HandledE>>
|
||||
}))
|
||||
),
|
||||
|
||||
Layer.provideMerge((props?.ErrorHandler
|
||||
? Layer.empty
|
||||
: ErrorHandler.DefaultErrorHandlerLive
|
||||
) as Layer.Layer<ErrorHandler.DefaultErrorHandler>),
|
||||
),
|
||||
]
|
||||
props?: ServiceProps<EH, HandledE>
|
||||
) => (
|
||||
<Self>(): ServiceResult<Self, EH, HandledE> => {
|
||||
const TagClass = Context.Tag(id)() as ServiceResult<Self, EH, HandledE>
|
||||
(TagClass as Mutable<typeof TagClass>).Live = Layer.succeed(TagClass, {
|
||||
ErrorHandler: (props?.ErrorHandler ?? ErrorHandler.DefaultErrorHandler) as Context.Tag<EH, ErrorHandler.ErrorHandler<HandledE>>
|
||||
})
|
||||
return TagClass
|
||||
}
|
||||
)
|
||||
|
||||
@@ -34,11 +34,11 @@ export const QueryExtension = ReffuseExtension.make(() => ({
|
||||
QR extends R,
|
||||
R,
|
||||
>(
|
||||
this: ReffuseHelpers.ReffuseHelpers<R | QueryClient.QueryClient<EH, HandledE> | EH>,
|
||||
this: ReffuseHelpers.ReffuseHelpers<R | QueryClient.TagClassShape<EH, HandledE> | EH>,
|
||||
props: UseQueryProps<QK, QA, QE, QR>,
|
||||
): UseQueryResult<QK, QA, Exclude<QE, HandledE>> {
|
||||
const runner = this.useMemo(() => QueryRunner.make({
|
||||
QueryClient: QueryClient.makeTag<EH, HandledE>(),
|
||||
QueryClient: QueryClient.makeGenericTagClass<EH, HandledE>(),
|
||||
key: props.key,
|
||||
query: props.query,
|
||||
}), [props.key])
|
||||
|
||||
@@ -21,7 +21,7 @@ export interface QueryRunner<K extends readonly unknown[], A, E, R> {
|
||||
|
||||
|
||||
export interface MakeProps<EH, K extends readonly unknown[], A, E, HandledE, R> {
|
||||
readonly QueryClient: QueryClient.Tag<EH, HandledE>
|
||||
readonly QueryClient: QueryClient.GenericTagClass<EH, HandledE>
|
||||
readonly key: Stream.Stream<K>
|
||||
readonly query: (key: K) => Effect.Effect<A, E, R>
|
||||
}
|
||||
@@ -35,9 +35,9 @@ export const make = <EH, K extends readonly unknown[], A, E, HandledE, R>(
|
||||
): Effect.Effect<
|
||||
QueryRunner<K, A, Exclude<E, HandledE>, R>,
|
||||
never,
|
||||
R | QueryClient.QueryClient<EH, HandledE> | EH
|
||||
R | QueryClient.TagClassShape<EH, HandledE> | EH
|
||||
> => Effect.gen(function*() {
|
||||
const context = yield* Effect.context<R | QueryClient.QueryClient<EH, HandledE> | EH>()
|
||||
const context = yield* Effect.context<R | QueryClient.TagClassShape<EH, HandledE> | EH>()
|
||||
|
||||
const latestKeyRef = yield* SubscriptionRef.make(Option.none<K>())
|
||||
const stateRef = yield* SubscriptionRef.make(AsyncData.noData<A, Exclude<E, HandledE>>())
|
||||
|
||||
Reference in New Issue
Block a user