@tiesen/effect-tanstack-query 0.0.5 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -14,14 +14,17 @@ A lightweight, type-safe bridge between **Effect HTTP API clients** and **TanSta
14
14
  Install using your preferred package manager:
15
15
 
16
16
  ```bash
17
+ # Using npm
18
+ npm install @tiesen/effect-tanstack-query
19
+
20
+ # Using yarn
21
+ yarn add @tiesen/effect-tanstack-query
22
+
17
23
  # Using bun
18
- bun add effect-tanstack-query
24
+ bun add @tiesen/effect-tanstack-query
19
25
 
20
26
  # Using pnpm
21
- pnpm add effect-tanstack-query
22
-
23
- # Using npm
24
- npm install effect-tanstack-query`
27
+ pnpm add @tiesen/effect-tanstack-query
25
28
  ```
26
29
 
27
30
  ## Quick Start
@@ -89,7 +92,7 @@ class ApiClient extends Context.Service<
89
92
 
90
93
  ```ts
91
94
  import { ManagedRuntime } from 'effect'
92
- import { createTanstackQueryOptionsProxy } from 'effect-tanstack-query'
95
+ import { createTanstackQueryOptionsProxy } from '@tiesen/effect-tanstack-query'
93
96
 
94
97
  const runtime = ManagedRuntime.make(ApiClient.live)
95
98
  const api = createTanstackQueryOptionsProxy(ApiClient, runtime)
package/dist/index.d.mts CHANGED
@@ -1,38 +1,10 @@
1
+ import { r as TanstackQueryOptionsProxy } from "./types-BGHsAv5y.mjs";
1
2
  import { Service } from "effect/Context";
2
3
  import { ManagedRuntime } from "effect/ManagedRuntime";
3
- import { DefinedInitialDataOptions, MutationOptions } from "@tanstack/react-query";
4
- import { Schema } from "effect/Schema";
5
- import { Client } from "effect/unstable/httpapi/HttpApiClient";
6
- import { HttpApiEndpoint } from "effect/unstable/httpapi/HttpApiEndpoint";
7
- //#region src/types.d.ts
8
- type TanstackQueryOptionsProxy<T> = T extends Client.Method<HttpApiEndpoint<infer _Key, infer Method, infer _Path, infer Params, infer Query, infer Payload, infer Headers, infer Success, infer Error>, infer _Error, infer _Requires> ? {
9
- queryOptions: Method extends 'GET' ? <TQuery = DefinedInitialDataOptions<UnwrapCodec<Success>, UnwrapCodec<Error>>>(input: MakeOptionalInput<([Params] extends [never] ? {} : {
10
- params: UnwrapCodec<Params>;
11
- }) & ([Query] extends [never] ? {} : {
12
- query: UnwrapCodec<Query>;
13
- }) & ([Headers] extends [never] ? {} : {
14
- headers: UnwrapCodec<Headers>;
15
- })>, options?: Omit<TQuery, 'queryKey' | 'queryFn'>) => TQuery : never;
16
- mutationOptions: Method extends 'GET' ? never : <TMutation = MutationOptions<UnwrapCodec<Success>, UnwrapCodec<Error>, UnwrapCodec<Payload>>>(input: MakeOptionalInput<([Params] extends [never] ? {} : {
17
- params: UnwrapCodec<Params>;
18
- }) & ([Headers] extends [never] ? {} : {
19
- headers: UnwrapCodec<Headers>;
20
- })>, options?: Omit<TMutation, 'mutationKey' | 'mutationFn'>) => TMutation;
21
- getQueryKey: Method extends 'GET' ? (input?: Partial<MakeOptionalInput<([Params] extends [never] ? {} : {
22
- params: UnwrapCodec<Params>;
23
- }) & ([Query] extends [never] ? {} : {
24
- query: UnwrapCodec<Query>;
25
- }) & ([Headers] extends [never] ? {} : {
26
- headers: UnwrapCodec<Headers>;
27
- })>>) => readonly unknown[] : never;
28
- } : T extends object ? { readonly [K in keyof T]: TanstackQueryOptionsProxy<T[K]>; } : T;
29
- type UnwrapCodec<T> = T extends Schema<unknown> ? Schema.Type<T> : T extends object ? { [K in keyof T]: UnwrapCodec<T[K]>; } : T;
30
- type MakeOptionalInput<T> = keyof T extends never ? void | undefined : T;
31
- //#endregion
32
4
  //#region src/index.d.ts
33
5
  /**
34
6
  * Creates a type-safe proxy that bridges Effect `HttpApiClient` endpoints
35
- * with TanStack Query options (`queryOptions`, `mutationOptions`, and `getQueryKey`).
7
+ * with TanStack Query options (`queryOptions`, `subscriptionOptions`, `mutationOptions`, and `getQueryKey`).
36
8
  *
37
9
  * @param tag - The Effect `Service` tag used to locate the client implementation within the Context.
38
10
  * @param runtime - The Effect `ManagedRuntime` used to execute effects as promises.
@@ -42,13 +14,14 @@ type MakeOptionalInput<T> = keyof T extends never ? void | undefined : T;
42
14
  * @example
43
15
  * ```ts
44
16
  * class ApiGroup extends HttpApiGroup.make('ApiGroup')
45
- * .add(HttpApiEndpoint.get('hello', '/hello', { success: Schema.String, query: Schema.Struct({ name: Schema.String }) }))
46
- * .add(HttpApiEndpoint.post('bye', '/bye', { success: Schema.String, payload: Schema.Struct({ name: Schema.String }) })) {}
17
+ * .add(HttpApiEndpoint.get('hello', '/hello', { success: Schema.String, query: Schema.Struct({ name: Schema.String }) }))
18
+ * .add(HttpApiEndpoint.post('bye', '/bye', { success: Schema.String, payload: Schema.Struct({ name: Schema.String }) }))
19
+ * .add(HttpApiEndpoint.get('stream', '/stream', { success: HttpApiSchema.StreamSse({ data: Schema.String }) })) {}
47
20
  *
48
21
  * class Api extends HttpApi.make('Api').add(ApiGroup) {}
49
22
  *
50
23
  * class ApiClient extends Context.Service<ApiClient, HttpApiClient.ForApi<typeof Api>>()('ApiClient') {
51
- * public static live = Layer.effect(this, HttpApiClient.make(Api)).pipe(Layer.provide(FetchHttpClient.layer))
24
+ * public static live = Layer.effect(this, HttpApiClient.make(Api)).pipe(Layer.provide(FetchHttpClient.layer))
52
25
  * }
53
26
  *
54
27
  * const runtime = ManagedRuntime.make(ApiClient.live)
@@ -56,11 +29,16 @@ type MakeOptionalInput<T> = keyof T extends never ? void | undefined : T;
56
29
  *
57
30
  * // Example usage in a React component with TanStack Query
58
31
  * const { data } = useQuery(api.hello.queryOptions({ query: { name: 'World' } }))
59
- * // ^? const data: string = "Hello, World!"
32
+ * ^? const data: string = "Hello, World!"
60
33
  *
61
34
  * const { mutate, data } = useMutation(api.bye.mutationOptions())
62
- * // ^? const data: string = "Goodbye, World!"
35
+ * ^? const data: string = "Goodbye, World!"
63
36
  * mutate({ name: 'World' })
37
+ *
38
+ * useSubscription(api.stream.subscriptionOptions({
39
+ * onData: (data) => console.log(data),
40
+ * ^? const data: string = "data: keep-alive\n\n"
41
+ * }))
64
42
  * ```
65
43
  */
66
44
  declare function createTanstackQueryOptionsProxy<TServiceTag, TService>(tag: Service<TServiceTag, TService>, runtime: ManagedRuntime<TServiceTag, never>): TanstackQueryOptionsProxy<TService>;
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import*as e from"effect/Effect";function t(t,n){let r=new Map,i=a=>{let o=a.join(`.`);if(r.has(o))return r.get(o);let s=new Proxy(()=>{},{get(e,t){if(typeof t!=`symbol`&&t!==`then`)return i([...a,String(t)])},apply(r,i,o){let s=a.at(-1),c=a.slice(0,-1),[l,u]=o,d=(r,i)=>n.runPromise(e.gen(function*(){let e=yield*t;for(let t of c)e=e[t];return yield*e(r)}),{signal:i}),f=(e,t)=>[{type:e},...c,...t?[t]:[]];if(s===`queryOptions`)return{...u,queryKey:f(`query`,l),queryFn:({signal:e})=>d(l,e)};if(s===`getQueryKey`)return f(`query`,l);if(s===`mutationOptions`)return{...u,mutationKey:f(`mutation`,l),mutationFn:e=>d({payload:e})}}});return r.set(o,s),s};return i([])}export{t as createTanstackQueryOptionsProxy};
1
+ import*as e from"effect/Effect";import*as t from"effect/Stream";function n(n,r){let i=new Map,a=o=>{let s=o.join(`.`);if(i.has(s))return i.get(s);let c=new Proxy(()=>{},{get(e,t){if(typeof t!=`symbol`&&t!==`then`)return a([...o,String(t)])},apply(i,a,s){let c=o.at(-1),l=o.slice(0,-1),[u,d]=s,f=e.fn(function*(e){let t=yield*n;for(let e of l)t=t[e];return yield*t(e)}),p=(e,t)=>r.runPromise(f(e),{signal:t}),m=(e,t)=>[{type:e},...l,...t?[t]:[]];if(c===`queryOptions`)return{...d,queryKey:m(`query`,u),queryFn:({signal:e})=>p(u,e)};if(c===`getQueryKey`)return m(`query`,u);if(c===`subscriptionOptions`){let n=t.unwrap(f({...u,responseMode:`response-only`}).pipe(e.map(e=>e.stream.pipe(t.decodeText())))),i=d;return{...d,subcriptionKey:m(`subscription`,u),subscriptionFn:({signal:a}={})=>{let o=r.runFork(n.pipe(t.tap(t=>e.sync(()=>i.onData(t))),t.runDrain)),s=()=>o.interruptUnsafe(o.id);return a&&(a.aborted?s():a.addEventListener(`abort`,s,{once:!0})),o.addObserver(e=>{e._tag===`Failure`&&i.onError?.(e.cause)}),s}}}if(c===`mutationOptions`)return{...d,mutationKey:m(`mutation`,u),mutationFn:e=>p({payload:e})}}});return i.set(s,c),c};return a([])}export{n as createTanstackQueryOptionsProxy};
@@ -0,0 +1,7 @@
1
+ import { n as SubscriptionReturns, t as SubscriptionOptions } from "./types-BGHsAv5y.mjs";
2
+ //#region src/react.d.ts
3
+ declare function useSubscription<TData, TError>({ enabled, ...subscriptionOptions }: SubscriptionOptions<TData, TError> & {
4
+ enabled?: boolean;
5
+ }): SubscriptionReturns;
6
+ //#endregion
7
+ export { type SubscriptionOptions, type SubscriptionReturns, useSubscription };
package/dist/react.mjs ADDED
@@ -0,0 +1 @@
1
+ import*as e from"react";function t({enabled:t=!0,...n}){let[r,i]=e.useState(`disconnected`),[a,o]=e.useState(0),s=e.useCallback(()=>{o(e=>e+1)},[]);return e.useEffect(()=>{if(!t){i(`disconnected`);return}i(`connecting`);let e=new AbortController,r=n.subscriptionFn({signal:e.signal});return i(`connected`),()=>{e.abort(),r(),i(`disconnected`)}},[t,n.subscriptionFn,a]),e.useMemo(()=>({status:r,reconnect:s}),[r,s])}export{t as useSubscription};
@@ -0,0 +1,54 @@
1
+ import { DefinedInitialDataOptions, MutationOptions } from "@tanstack/react-query";
2
+ import { Schema } from "effect/Schema";
3
+ import { Client } from "effect/unstable/httpapi/HttpApiClient";
4
+ import { HttpApiEndpoint } from "effect/unstable/httpapi/HttpApiEndpoint";
5
+ import { SseEventFromData, StreamSse } from "effect/unstable/httpapi/HttpApiSchema";
6
+ //#region src/types.d.ts
7
+ type TanstackQueryOptionsProxy<T> = T extends Client.Method<HttpApiEndpoint<infer _Key, infer Method, infer _Path, infer Params, infer Query, infer Payload, infer Headers, infer Success, infer Error>, infer _Error, infer _Requires> ? {
8
+ queryOptions: Method extends 'GET' ? <TQuery = DefinedInitialDataOptions<UnwrapCodec<Success>, UnwrapCodec<Error>>>(input: MakeOptionalInput<([Params] extends [never] ? {} : {
9
+ params: UnwrapCodec<Params>;
10
+ }) & ([Query] extends [never] ? {} : {
11
+ query: UnwrapCodec<Query>;
12
+ }) & ([Headers] extends [never] ? {} : {
13
+ headers: UnwrapCodec<Headers>;
14
+ })>, options?: Omit<TQuery, 'queryKey' | 'queryFn'>) => TQuery : never;
15
+ subscriptionOptions: Success extends StreamSse<SseEventFromData<infer StreamSuccess>, infer StreamError, infer _StreamValue> ? (input: MakeOptionalInput<([Params] extends [never] ? {} : {
16
+ params: UnwrapCodec<Params>;
17
+ }) & ([Query] extends [never] ? {} : {
18
+ query: UnwrapCodec<Query>;
19
+ }) & ([Headers] extends [never] ? {} : {
20
+ headers: UnwrapCodec<Headers>;
21
+ })>, options?: {
22
+ onData: (data: StreamSuccess) => void;
23
+ onError?: (error: StreamError) => void;
24
+ }) => SubscriptionOptions<StreamSuccess, StreamError> : never;
25
+ mutationOptions: Method extends 'GET' ? never : <TMutation = MutationOptions<UnwrapCodec<Success>, UnwrapCodec<Error>, UnwrapCodec<Payload>>>(input: MakeOptionalInput<([Params] extends [never] ? {} : {
26
+ params: UnwrapCodec<Params>;
27
+ }) & ([Headers] extends [never] ? {} : {
28
+ headers: UnwrapCodec<Headers>;
29
+ })>, options?: Omit<TMutation, 'mutationKey' | 'mutationFn'>) => TMutation;
30
+ getQueryKey: Method extends 'GET' ? (input?: Partial<MakeOptionalInput<([Params] extends [never] ? {} : {
31
+ params: UnwrapCodec<Params>;
32
+ }) & ([Query] extends [never] ? {} : {
33
+ query: UnwrapCodec<Query>;
34
+ }) & ([Headers] extends [never] ? {} : {
35
+ headers: UnwrapCodec<Headers>;
36
+ })>>) => readonly unknown[] : never;
37
+ } : T extends object ? { readonly [K in keyof T]: TanstackQueryOptionsProxy<T[K]>; } : T;
38
+ type UnsubscribeFn = () => void;
39
+ interface SubscriptionOptions<TData, TError> {
40
+ subcriptionKey: readonly unknown[];
41
+ subscriptionFn: (options: {
42
+ signal?: AbortSignal;
43
+ }) => UnsubscribeFn;
44
+ onData: (data: TData) => void;
45
+ onError?: (error: TError) => void;
46
+ }
47
+ interface SubscriptionReturns {
48
+ status: 'connecting' | 'connected' | 'disconnected' | 'error';
49
+ reconnect: () => void;
50
+ }
51
+ type UnwrapCodec<T> = T extends Schema<unknown> ? Schema.Type<T> : T extends object ? { [K in keyof T]: UnwrapCodec<T[K]>; } : T;
52
+ type MakeOptionalInput<T> = keyof T extends never ? void | undefined : T;
53
+ //#endregion
54
+ export { SubscriptionReturns as n, TanstackQueryOptionsProxy as r, SubscriptionOptions as t };
package/package.json CHANGED
@@ -1,13 +1,29 @@
1
1
  {
2
2
  "name": "@tiesen/effect-tanstack-query",
3
- "version": "0.0.5",
3
+ "version": "0.0.7",
4
4
  "private": false,
5
+ "description": " A lightweight, type-safe bridge between Effect HTTP API clients and TanStack Query.",
5
6
  "keywords": [
6
7
  "effect",
7
- "tanstack-intent",
8
- "typesafe"
8
+ "effect-ts",
9
+ "http-api",
10
+ "http-client",
11
+ "proxy",
12
+ "react-query",
13
+ "tanstack",
14
+ "tanstack-query",
15
+ "type-safe",
16
+ "typescript"
9
17
  ],
18
+ "bugs": {
19
+ "url": "https://github.com/tiesen243/effect-tanstack-query/issues"
20
+ },
10
21
  "license": "MIT",
22
+ "author": {
23
+ "name": "Tiesen",
24
+ "email": "tiesen243@tiesen.id.vn",
25
+ "url": "tiesen.id.vn"
26
+ },
11
27
  "repository": {
12
28
  "type": "git",
13
29
  "url": "git+https://github.com/tiesen243/effect-tanstack-query.git"
@@ -18,8 +34,12 @@
18
34
  "type": "module",
19
35
  "exports": {
20
36
  ".": {
21
- "import": "./dist/index.mjs",
22
- "types": "./dist/index.d.mts"
37
+ "types": "./dist/index.d.mts",
38
+ "default": "./dist/index.mjs"
39
+ },
40
+ "./react": {
41
+ "types": "./dist/react.d.mts",
42
+ "default": "./dist/react.mjs"
23
43
  }
24
44
  },
25
45
  "publishConfig": {
@@ -35,6 +55,7 @@
35
55
  "typecheck": "tsc --noEmit"
36
56
  },
37
57
  "devDependencies": {
58
+ "@types/react": "^19.2.18",
38
59
  "oxfmt": "^0.61.0",
39
60
  "oxlint": "^1.76.0",
40
61
  "tegami": "^1.2.7",
@@ -42,9 +63,11 @@
42
63
  "typescript": "^7.0.2"
43
64
  },
44
65
  "peerDependencies": {
45
- "@tanstack/react-query": ">=^5.100.0",
46
- "effect": ">=^4.0.0-beta.100 || >=^4.0.0"
66
+ "@tanstack/react-query": ">=5.100.0",
67
+ "effect": ">=4.0.0-beta.100 || >=4.0.0",
68
+ "react": ">=19.2.8"
47
69
  },
70
+ "packageManager": "bun@1.3.0",
48
71
  "patchedDependencies": {
49
72
  "tegami@1.2.7": "patches/tegami@1.2.7.patch"
50
73
  }