diff --git a/packages/example/src/query/services/Uuid4Query.ts b/packages/example/src/query/services/Uuid4Query.ts index ab9d4cf..08905a2 100644 --- a/packages/example/src/query/services/Uuid4Query.ts +++ b/packages/example/src/query/services/Uuid4Query.ts @@ -3,7 +3,7 @@ import { QueryService } from "@reffuse/extension-query" import { Console, Effect, ParseResult, Schema } from "effect" -export const Result = Schema.Tuple(Schema.String) +export const Result = Schema.Array(Schema.String) export class Uuid4Query extends QueryService.Tag("Uuid4Query") rootRoute, } as any) -const QueryRoute = QueryImport.update({ - id: '/query', - path: '/query', - getParentRoute: () => rootRoute, -} as any) - const PromiseRoute = PromiseImport.update({ id: '/promise', path: '/promise', @@ -71,10 +65,16 @@ const IndexRoute = IndexImport.update({ getParentRoute: () => rootRoute, } as any) +const QueryUsequeryRoute = QueryUsequeryImport.update({ + id: '/query/usequery', + path: '/query/usequery', + getParentRoute: () => rootRoute, +} as any) + const QueryServiceRoute = QueryServiceImport.update({ - id: '/service', - path: '/service', - getParentRoute: () => QueryRoute, + id: '/query/service', + path: '/query/service', + getParentRoute: () => rootRoute, } as any) // Populate the FileRoutesByPath interface @@ -116,13 +116,6 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof PromiseImport parentRoute: typeof rootRoute } - '/query': { - id: '/query' - path: '/query' - fullPath: '/query' - preLoaderRoute: typeof QueryImport - parentRoute: typeof rootRoute - } '/tests': { id: '/tests' path: '/tests' @@ -139,36 +132,33 @@ declare module '@tanstack/react-router' { } '/query/service': { id: '/query/service' - path: '/service' + path: '/query/service' fullPath: '/query/service' preLoaderRoute: typeof QueryServiceImport - parentRoute: typeof QueryImport + parentRoute: typeof rootRoute + } + '/query/usequery': { + id: '/query/usequery' + path: '/query/usequery' + fullPath: '/query/usequery' + preLoaderRoute: typeof QueryUsequeryImport + parentRoute: typeof rootRoute } } } // Create and export the route tree -interface QueryRouteChildren { - QueryServiceRoute: typeof QueryServiceRoute -} - -const QueryRouteChildren: QueryRouteChildren = { - QueryServiceRoute: QueryServiceRoute, -} - -const QueryRouteWithChildren = QueryRoute._addFileChildren(QueryRouteChildren) - export interface FileRoutesByFullPath { '/': typeof IndexRoute '/blank': typeof BlankRoute '/count': typeof CountRoute '/lazyref': typeof LazyrefRoute '/promise': typeof PromiseRoute - '/query': typeof QueryRouteWithChildren '/tests': typeof TestsRoute '/time': typeof TimeRoute '/query/service': typeof QueryServiceRoute + '/query/usequery': typeof QueryUsequeryRoute } export interface FileRoutesByTo { @@ -177,10 +167,10 @@ export interface FileRoutesByTo { '/count': typeof CountRoute '/lazyref': typeof LazyrefRoute '/promise': typeof PromiseRoute - '/query': typeof QueryRouteWithChildren '/tests': typeof TestsRoute '/time': typeof TimeRoute '/query/service': typeof QueryServiceRoute + '/query/usequery': typeof QueryUsequeryRoute } export interface FileRoutesById { @@ -190,10 +180,10 @@ export interface FileRoutesById { '/count': typeof CountRoute '/lazyref': typeof LazyrefRoute '/promise': typeof PromiseRoute - '/query': typeof QueryRouteWithChildren '/tests': typeof TestsRoute '/time': typeof TimeRoute '/query/service': typeof QueryServiceRoute + '/query/usequery': typeof QueryUsequeryRoute } export interface FileRouteTypes { @@ -204,10 +194,10 @@ export interface FileRouteTypes { | '/count' | '/lazyref' | '/promise' - | '/query' | '/tests' | '/time' | '/query/service' + | '/query/usequery' fileRoutesByTo: FileRoutesByTo to: | '/' @@ -215,10 +205,10 @@ export interface FileRouteTypes { | '/count' | '/lazyref' | '/promise' - | '/query' | '/tests' | '/time' | '/query/service' + | '/query/usequery' id: | '__root__' | '/' @@ -226,10 +216,10 @@ export interface FileRouteTypes { | '/count' | '/lazyref' | '/promise' - | '/query' | '/tests' | '/time' | '/query/service' + | '/query/usequery' fileRoutesById: FileRoutesById } @@ -239,9 +229,10 @@ export interface RootRouteChildren { CountRoute: typeof CountRoute LazyrefRoute: typeof LazyrefRoute PromiseRoute: typeof PromiseRoute - QueryRoute: typeof QueryRouteWithChildren TestsRoute: typeof TestsRoute TimeRoute: typeof TimeRoute + QueryServiceRoute: typeof QueryServiceRoute + QueryUsequeryRoute: typeof QueryUsequeryRoute } const rootRouteChildren: RootRouteChildren = { @@ -250,9 +241,10 @@ const rootRouteChildren: RootRouteChildren = { CountRoute: CountRoute, LazyrefRoute: LazyrefRoute, PromiseRoute: PromiseRoute, - QueryRoute: QueryRouteWithChildren, TestsRoute: TestsRoute, TimeRoute: TimeRoute, + QueryServiceRoute: QueryServiceRoute, + QueryUsequeryRoute: QueryUsequeryRoute, } export const routeTree = rootRoute @@ -270,9 +262,10 @@ export const routeTree = rootRoute "/count", "/lazyref", "/promise", - "/query", "/tests", - "/time" + "/time", + "/query/service", + "/query/usequery" ] }, "/": { @@ -290,12 +283,6 @@ export const routeTree = rootRoute "/promise": { "filePath": "promise.tsx" }, - "/query": { - "filePath": "query.tsx", - "children": [ - "/query/service" - ] - }, "/tests": { "filePath": "tests.tsx" }, @@ -303,8 +290,10 @@ export const routeTree = rootRoute "filePath": "time.tsx" }, "/query/service": { - "filePath": "query/service.tsx", - "parent": "/query" + "filePath": "query/service.tsx" + }, + "/query/usequery": { + "filePath": "query/usequery.tsx" } } } diff --git a/packages/example/src/routes/__root.tsx b/packages/example/src/routes/__root.tsx index a02f201..3253372 100644 --- a/packages/example/src/routes/__root.tsx +++ b/packages/example/src/routes/__root.tsx @@ -20,7 +20,7 @@ function Root() { Count Tests Promise - Query + Query Blank diff --git a/packages/example/src/routes/query/service.tsx b/packages/example/src/routes/query/service.tsx index 638dbe3..38a6b38 100644 --- a/packages/example/src/routes/query/service.tsx +++ b/packages/example/src/routes/query/service.tsx @@ -2,8 +2,9 @@ import { QueryContext } from "@/query/reffuse" import { Uuid4Query } from "@/query/services" import { Uuid4QueryService } from "@/query/views/Uuid4QueryService" import { R } from "@/reffuse" +import { HttpClient } from "@effect/platform" import { createFileRoute } from "@tanstack/react-router" -import { Layer } from "effect" +import { Console, Effect, Schema } from "effect" import { useMemo } from "react" @@ -12,12 +13,26 @@ export const Route = createFileRoute("/query/service")({ }) function RouteComponent() { - const context = R.useLayer() + // const context = R.useLayer() - const layer = useMemo(() => Layer.empty.pipe( - Layer.provideMerge(Uuid4Query.Uuid4QueryLive), - Layer.provide(context), - ), [context]) + // const layer = useMemo(() => Layer.empty.pipe( + // Layer.provideMerge(Uuid4Query.Uuid4QueryLive), + // Layer.provide(context), + // ), [context]) + + const query = R.useQuery({ + key: ["uuid4", 10], + query: () => Console.log(`Querying 10 IDs...`).pipe( + Effect.andThen(Effect.sleep("500 millis")), + Effect.andThen(HttpClient.get(`https://www.uuidtools.com/api/generate/v4/count/10`)), + HttpClient.withTracerPropagation(false), + Effect.flatMap(res => res.json), + Effect.flatMap(Schema.decodeUnknown(Uuid4Query.Result)), + Effect.scoped, + ), + }) + + const layer = useMemo(() => query.layer(Uuid4Query.Uuid4Query), [query]) return ( diff --git a/packages/example/src/routes/query.tsx b/packages/example/src/routes/query/usequery.tsx similarity index 97% rename from packages/example/src/routes/query.tsx rename to packages/example/src/routes/query/usequery.tsx index b63f0db..f2c58c8 100644 --- a/packages/example/src/routes/query.tsx +++ b/packages/example/src/routes/query/usequery.tsx @@ -7,7 +7,7 @@ import { Array, Console, Effect, flow, Option, Schema } from "effect" import { useState } from "react" -export const Route = createFileRoute("/query")({ +export const Route = createFileRoute("/query/usequery")({ component: RouteComponent }) @@ -20,6 +20,7 @@ function RouteComponent() { const [count, setCount] = useState(1) const query = R.useQuery({ + key: ["uuid4", count], query: () => Console.log(`Querying ${ count } IDs...`).pipe( Effect.andThen(Effect.sleep("500 millis")), Effect.andThen(HttpClient.get(`https://www.uuidtools.com/api/generate/v4/count/${ count }`)), @@ -28,7 +29,6 @@ function RouteComponent() { Effect.flatMap(Schema.decodeUnknown(Result)), Effect.scoped, ), - key: ["uuid4", count], }) const [state] = R.useRefState(query.state) diff --git a/packages/extension-query/src/QueryExtension.ts b/packages/extension-query/src/QueryExtension.ts index 526077a..443d95c 100644 --- a/packages/extension-query/src/QueryExtension.ts +++ b/packages/extension-query/src/QueryExtension.ts @@ -1,18 +1,22 @@ import * as AsyncData from "@typed/async-data" -import { Effect, ExecutionStrategy, Fiber, Ref, SubscriptionRef } from "effect" +import { Context, Effect, ExecutionStrategy, Fiber, Layer, Ref, SubscriptionRef } from "effect" import * as React from "react" import { ReffuseExtension, type ReffuseHelpers } from "reffuse" import * as QueryRunner from "./QueryRunner.js" +import * as QueryService from "./QueryService.js" export interface UseQueryProps { - readonly query: () => Effect.Effect readonly key: React.DependencyList + readonly query: () => Effect.Effect } export interface UseQueryResult { readonly state: SubscriptionRef.SubscriptionRef> readonly refresh: Effect.Effect> + readonly layer: ( + tag: Context.TagClass> + ) => Layer.Layer } @@ -35,6 +39,11 @@ export const QueryExtension = ReffuseExtension.make(() => ({ return React.useMemo(() => ({ state: runner.stateRef, refresh: runner.forkRefresh, + + layer: tag => Layer.succeed(tag, { + state: runner.stateRef, + refresh: runner.forkRefresh, + }), }), [runner]) } }))