@richie-rpc/react-query 1.0.4 → 1.0.6

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
@@ -55,7 +55,7 @@ Query hooks automatically fetch data when the component mounts:
55
55
  ```tsx
56
56
  function UserList() {
57
57
  const { data, isLoading, error, refetch } = hooks.listUsers.useQuery({
58
- query: { limit: "10", offset: "0" }
58
+ query: { limit: '10', offset: '0' },
59
59
  });
60
60
 
61
61
  if (isLoading) return <div>Loading...</div>;
@@ -63,7 +63,7 @@ function UserList() {
63
63
 
64
64
  return (
65
65
  <div>
66
- {data.data.users.map(user => (
66
+ {data.data.users.map((user) => (
67
67
  <div key={user.id}>{user.name}</div>
68
68
  ))}
69
69
  <button onClick={() => refetch()}>Refresh</button>
@@ -80,12 +80,12 @@ For React Suspense integration:
80
80
  function UserListSuspense() {
81
81
  // This will suspend the component until data is loaded
82
82
  const { data } = hooks.listUsers.useSuspenseQuery({
83
- query: { limit: "10" }
83
+ query: { limit: '10' },
84
84
  });
85
85
 
86
86
  return (
87
87
  <div>
88
- {data.data.users.map(user => (
88
+ {data.data.users.map((user) => (
89
89
  <div key={user.id}>{user.name}</div>
90
90
  ))}
91
91
  </div>
@@ -123,19 +123,16 @@ function CreateUserForm() {
123
123
  e.preventDefault();
124
124
  mutation.mutate({
125
125
  body: {
126
- name: "Alice",
127
- email: "alice@example.com",
126
+ name: 'Alice',
127
+ email: 'alice@example.com',
128
128
  age: 25,
129
- }
129
+ },
130
130
  });
131
131
  };
132
132
 
133
133
  return (
134
134
  <form onSubmit={handleSubmit}>
135
- <button
136
- type="submit"
137
- disabled={mutation.isPending}
138
- >
135
+ <button type="submit" disabled={mutation.isPending}>
139
136
  {mutation.isPending ? 'Creating...' : 'Create User'}
140
137
  </button>
141
138
  {mutation.error && <div>Error: {mutation.error.message}</div>}
@@ -151,6 +148,7 @@ function CreateUserForm() {
151
148
  Creates a typed hooks object from a client and contract.
152
149
 
153
150
  **Parameters:**
151
+
154
152
  - `client`: Client created with `createClient()`
155
153
  - `contract`: Your API contract definition
156
154
 
@@ -163,6 +161,7 @@ Creates a typed hooks object from a client and contract.
163
161
  Standard query hook for read operations.
164
162
 
165
163
  **Parameters:**
164
+
166
165
  - `options`: Request options (params, query, headers, body)
167
166
  - `queryOptions`: Optional TanStack Query options (staleTime, cacheTime, etc.)
168
167
 
@@ -173,6 +172,7 @@ Standard query hook for read operations.
173
172
  Suspense-enabled query hook.
174
173
 
175
174
  **Parameters:**
175
+
176
176
  - `options`: Request options (params, query, headers, body)
177
177
  - `queryOptions`: Optional TanStack Query options
178
178
 
@@ -185,6 +185,7 @@ Suspense-enabled query hook.
185
185
  Mutation hook for write operations.
186
186
 
187
187
  **Parameters:**
188
+
188
189
  - `mutationOptions`: Optional TanStack Query mutation options (onSuccess, onError, etc.)
189
190
 
190
191
  **Returns:** `UseMutationResult` with mutate, isPending, error, data, etc.
@@ -197,13 +198,13 @@ Pass TanStack Query options for fine-grained control:
197
198
 
198
199
  ```tsx
199
200
  const { data } = hooks.listUsers.useQuery(
200
- { query: { limit: "10" } },
201
+ { query: { limit: '10' } },
201
202
  {
202
203
  staleTime: 5 * 60 * 1000, // 5 minutes
203
204
  cacheTime: 10 * 60 * 1000, // 10 minutes
204
205
  refetchInterval: 30000, // Refetch every 30 seconds
205
206
  refetchOnWindowFocus: false,
206
- }
207
+ },
207
208
  );
208
209
  ```
209
210
 
@@ -216,24 +217,20 @@ import { useQueryClient } from '@tanstack/react-query';
216
217
 
217
218
  function DeleteUserButton({ userId }: { userId: string }) {
218
219
  const queryClient = useQueryClient();
219
-
220
+
220
221
  const mutation = hooks.deleteUser.useMutation({
221
222
  onSuccess: () => {
222
223
  // Invalidate all queries that start with 'listUsers'
223
224
  queryClient.invalidateQueries({ queryKey: ['listUsers'] });
224
-
225
+
225
226
  // Or invalidate specific query
226
- queryClient.invalidateQueries({
227
- queryKey: ['getUser', { params: { id: userId } }]
227
+ queryClient.invalidateQueries({
228
+ queryKey: ['getUser', { params: { id: userId } }],
228
229
  });
229
230
  },
230
231
  });
231
232
 
232
- return (
233
- <button onClick={() => mutation.mutate({ params: { id: userId } })}>
234
- Delete User
235
- </button>
236
- );
233
+ return <button onClick={() => mutation.mutate({ params: { id: userId } })}>Delete User</button>;
237
234
  }
238
235
  ```
239
236
 
@@ -253,7 +250,7 @@ const mutation = hooks.updateUser.useMutation({
253
250
  // Optimistically update
254
251
  queryClient.setQueryData(['getUser', { params: { id: userId } }], (old) => ({
255
252
  ...old,
256
- data: { ...old.data, ...variables.body }
253
+ data: { ...old.data, ...variables.body },
257
254
  }));
258
255
 
259
256
  return { previousUser };
@@ -261,10 +258,7 @@ const mutation = hooks.updateUser.useMutation({
261
258
  onError: (err, variables, context) => {
262
259
  // Rollback on error
263
260
  if (context?.previousUser) {
264
- queryClient.setQueryData(
265
- ['getUser', { params: { id: userId } }],
266
- context.previousUser
267
- );
261
+ queryClient.setQueryData(['getUser', { params: { id: userId } }], context.previousUser);
268
262
  }
269
263
  },
270
264
  onSettled: () => {
@@ -283,7 +277,7 @@ function UserPosts({ userId }: { userId: string | null }) {
283
277
  { params: { userId: userId! } },
284
278
  {
285
279
  enabled: !!userId, // Only fetch when userId is available
286
- }
280
+ },
287
281
  );
288
282
 
289
283
  // ...
@@ -332,10 +326,8 @@ Create a helper for consistent query keys:
332
326
 
333
327
  ```tsx
334
328
  const queryKeys = {
335
- listUsers: (query: { limit?: string; offset?: string }) =>
336
- ['listUsers', { query }] as const,
337
- getUser: (id: string) =>
338
- ['getUser', { params: { id } }] as const,
329
+ listUsers: (query: { limit?: string; offset?: string }) => ['listUsers', { query }] as const,
330
+ getUser: (id: string) => ['getUser', { params: { id } }] as const,
339
331
  };
340
332
 
341
333
  // Use in invalidation
@@ -357,4 +349,3 @@ See the `packages/demo` directory for complete working examples.
357
349
  ## License
358
350
 
359
351
  MIT
360
-
@@ -37,6 +37,20 @@ var import_react_query = require("@tanstack/react-query");
37
37
  function createHooks(client, contract) {
38
38
  const hooks = {};
39
39
  for (const [name, endpoint] of Object.entries(contract)) {
40
+ if (endpoint.type === "streaming") {
41
+ const streamMethod = client[name];
42
+ hooks[name] = {
43
+ stream: streamMethod
44
+ };
45
+ continue;
46
+ }
47
+ if (endpoint.type === "sse") {
48
+ const connectMethod = client[name];
49
+ hooks[name] = {
50
+ connect: connectMethod
51
+ };
52
+ continue;
53
+ }
40
54
  const method = endpoint.method;
41
55
  const clientMethod = client[name];
42
56
  if (method === "GET" || method === "HEAD") {
@@ -83,4 +97,4 @@ function createHooks(client, contract) {
83
97
  }
84
98
  })
85
99
 
86
- //# debugId=7B2442E74A7DC69E64756E2164756E21
100
+ //# debugId=47DF1EE9E6FD487A64756E2164756E21
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["../../index.ts"],
4
4
  "sourcesContent": [
5
- "import type {\n Client,\n ClientMethod,\n EndpointRequestOptions,\n EndpointResponse,\n} from '@richie-rpc/client';\nimport type { Contract, EndpointDefinition } from '@richie-rpc/core';\nimport {\n type UseMutationOptions,\n type UseMutationResult,\n type UseQueryOptions,\n type UseQueryResult,\n type UseSuspenseQueryOptions,\n type UseSuspenseQueryResult,\n useMutation,\n useQuery,\n useSuspenseQuery,\n} from '@tanstack/react-query';\n\n// HTTP methods that should use query hooks (read operations)\ntype QueryMethods = 'GET' | 'HEAD';\n\n// HTTP methods that should use mutation hooks (write operations)\ntype MutationMethods = 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS';\n\n/**\n * Hook wrapper for query endpoints (GET, HEAD)\n * Provides useQuery and useSuspenseQuery methods\n */\nexport type QueryHook<T extends EndpointDefinition> = {\n /**\n * Standard query hook that returns loading states\n */\n useQuery: (\n options: EndpointRequestOptions<T>,\n queryOptions?: Omit<UseQueryOptions<EndpointResponse<T>, Error>, 'queryKey' | 'queryFn'>,\n ) => UseQueryResult<EndpointResponse<T>, Error>;\n\n /**\n * Suspense-enabled query hook that throws promises for React Suspense\n */\n useSuspenseQuery: (\n options: EndpointRequestOptions<T>,\n queryOptions?: Omit<\n UseSuspenseQueryOptions<EndpointResponse<T>, Error>,\n 'queryKey' | 'queryFn'\n >,\n ) => UseSuspenseQueryResult<EndpointResponse<T>, Error>;\n};\n\n/**\n * Hook wrapper for mutation endpoints (POST, PUT, PATCH, DELETE)\n * Provides useMutation method\n */\nexport type MutationHook<T extends EndpointDefinition> = {\n /**\n * Mutation hook for write operations\n */\n useMutation: (\n mutationOptions?: Omit<\n UseMutationOptions<EndpointResponse<T>, Error, EndpointRequestOptions<T>>,\n 'mutationFn'\n >,\n ) => UseMutationResult<EndpointResponse<T>, Error, EndpointRequestOptions<T>>;\n};\n\n/**\n * Conditionally apply hook type based on HTTP method\n */\nexport type EndpointHook<T extends EndpointDefinition> = T['method'] extends QueryMethods\n ? QueryHook<T>\n : T['method'] extends MutationMethods\n ? MutationHook<T>\n : never;\n\n/**\n * Complete hooks object for a contract\n * Each endpoint gets appropriate hooks based on its HTTP method\n */\nexport type Hooks<T extends Contract> = {\n [K in keyof T]: EndpointHook<T[K]>;\n};\n\n/**\n * Create typed React hooks for all endpoints in a contract\n *\n * Query endpoints (GET, HEAD) get useQuery and useSuspenseQuery methods\n * Mutation endpoints (POST, PUT, PATCH, DELETE) get useMutation method\n *\n * @param client - The typed client created with createClient()\n * @param contract - The contract definition\n * @returns Hooks object with methods for each endpoint\n *\n * @example\n * ```tsx\n * const client = createClient(contract, { baseUrl: 'http://localhost:3000' });\n * const hooks = createHooks(client, contract);\n *\n * // In a component - Query\n * function UserList() {\n * const { data, isLoading } = hooks.listUsers.useQuery({\n * query: { limit: \"10\" }\n * });\n * // ...\n * }\n *\n * // In a component - Mutation\n * function CreateUser() {\n * const mutation = hooks.createUser.useMutation();\n * return (\n * <button onClick={() => mutation.mutate({\n * body: { name: \"Alice\", email: \"alice@example.com\" }\n * })}>\n * Create User\n * </button>\n * );\n * }\n * ```\n */\nexport function createHooks<T extends Contract>(client: Client<T>, contract: T): Hooks<T> {\n const hooks: Record<string, unknown> = {};\n\n for (const [name, endpoint] of Object.entries(contract)) {\n const method = endpoint.method;\n const clientMethod = client[name as keyof T] as unknown as ClientMethod<EndpointDefinition>;\n\n if (method === 'GET' || method === 'HEAD') {\n // Create query hooks for read operations\n hooks[name] = {\n useQuery: (\n options: EndpointRequestOptions<EndpointDefinition>,\n queryOptions?: Omit<\n UseQueryOptions<EndpointResponse<EndpointDefinition>, Error>,\n 'queryKey' | 'queryFn'\n >,\n ) => {\n return useQuery({\n queryKey: [\n name,\n options.params ?? null,\n options.query ?? null,\n options.headers ?? null,\n options.body ?? null,\n ],\n queryFn: () => clientMethod(options),\n ...queryOptions,\n });\n },\n useSuspenseQuery: (\n options: EndpointRequestOptions<EndpointDefinition>,\n queryOptions?: Omit<\n UseSuspenseQueryOptions<EndpointResponse<EndpointDefinition>, Error>,\n 'queryKey' | 'queryFn'\n >,\n ) => {\n return useSuspenseQuery({\n queryKey: [\n name,\n options.params ?? null,\n options.query ?? null,\n options.headers ?? null,\n options.body ?? null,\n ],\n queryFn: () => clientMethod(options),\n ...queryOptions,\n });\n },\n };\n } else {\n // Create mutation hooks for write operations\n hooks[name] = {\n useMutation: (\n mutationOptions?: Omit<\n UseMutationOptions<\n EndpointResponse<EndpointDefinition>,\n Error,\n EndpointRequestOptions<EndpointDefinition>\n >,\n 'mutationFn'\n >,\n ) => {\n return useMutation({\n mutationFn: (options: EndpointRequestOptions<EndpointDefinition>) =>\n clientMethod(options),\n ...mutationOptions,\n });\n },\n };\n }\n }\n\n return hooks as Hooks<T>;\n}\n"
5
+ "import type {\n Client,\n ClientMethod,\n EndpointRequestOptions,\n EndpointResponse,\n SSEClientMethod,\n StreamingClientMethod,\n} from '@richie-rpc/client';\nimport type {\n Contract,\n SSEEndpointDefinition,\n StandardEndpointDefinition,\n StreamingEndpointDefinition,\n} from '@richie-rpc/core';\nimport {\n type UseMutationOptions,\n type UseMutationResult,\n type UseQueryOptions,\n type UseQueryResult,\n type UseSuspenseQueryOptions,\n type UseSuspenseQueryResult,\n useMutation,\n useQuery,\n useSuspenseQuery,\n} from '@tanstack/react-query';\n\n// HTTP methods that should use query hooks (read operations)\ntype QueryMethods = 'GET' | 'HEAD';\n\n// HTTP methods that should use mutation hooks (write operations)\ntype MutationMethods = 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS';\n\n/**\n * Hook wrapper for query endpoints (GET, HEAD)\n * Provides useQuery and useSuspenseQuery methods\n */\nexport type QueryHook<T extends StandardEndpointDefinition> = {\n /**\n * Standard query hook that returns loading states\n */\n useQuery: (\n options: EndpointRequestOptions<T>,\n queryOptions?: Omit<UseQueryOptions<EndpointResponse<T>, Error>, 'queryKey' | 'queryFn'>,\n ) => UseQueryResult<EndpointResponse<T>, Error>;\n\n /**\n * Suspense-enabled query hook that throws promises for React Suspense\n */\n useSuspenseQuery: (\n options: EndpointRequestOptions<T>,\n queryOptions?: Omit<\n UseSuspenseQueryOptions<EndpointResponse<T>, Error>,\n 'queryKey' | 'queryFn'\n >,\n ) => UseSuspenseQueryResult<EndpointResponse<T>, Error>;\n};\n\n/**\n * Hook wrapper for mutation endpoints (POST, PUT, PATCH, DELETE)\n * Provides useMutation method\n */\nexport type MutationHook<T extends StandardEndpointDefinition> = {\n /**\n * Mutation hook for write operations\n */\n useMutation: (\n mutationOptions?: Omit<\n UseMutationOptions<EndpointResponse<T>, Error, EndpointRequestOptions<T>>,\n 'mutationFn'\n >,\n ) => UseMutationResult<EndpointResponse<T>, Error, EndpointRequestOptions<T>>;\n};\n\n/**\n * Conditionally apply hook type based on HTTP method\n */\nexport type EndpointHook<T extends StandardEndpointDefinition> = T['method'] extends QueryMethods\n ? QueryHook<T>\n : T['method'] extends MutationMethods\n ? MutationHook<T>\n : never;\n\n/**\n * Hook wrapper for streaming endpoints\n * Exposes the streaming client method directly since React Query\n * doesn't fit well with long-lived streaming connections\n */\nexport type StreamingHook<T extends StreamingEndpointDefinition> = {\n /**\n * Start a streaming request\n */\n stream: StreamingClientMethod<T>;\n};\n\n/**\n * Hook wrapper for SSE endpoints\n * Exposes the SSE client method directly since React Query\n * doesn't fit well with long-lived SSE connections\n */\nexport type SSEHook<T extends SSEEndpointDefinition> = {\n /**\n * Create an SSE connection\n */\n connect: SSEClientMethod<T>;\n};\n\n/**\n * Complete hooks object for a contract\n * Each endpoint gets appropriate hooks based on its type and HTTP method\n */\nexport type Hooks<T extends Contract> = {\n [K in keyof T]: T[K] extends StandardEndpointDefinition\n ? EndpointHook<T[K]>\n : T[K] extends StreamingEndpointDefinition\n ? StreamingHook<T[K]>\n : T[K] extends SSEEndpointDefinition\n ? SSEHook<T[K]>\n : never;\n};\n\n/**\n * Create typed React hooks for all endpoints in a contract\n *\n * Query endpoints (GET, HEAD) get useQuery and useSuspenseQuery methods\n * Mutation endpoints (POST, PUT, PATCH, DELETE) get useMutation method\n *\n * @param client - The typed client created with createClient()\n * @param contract - The contract definition\n * @returns Hooks object with methods for each endpoint\n *\n * @example\n * ```tsx\n * const client = createClient(contract, { baseUrl: 'http://localhost:3000' });\n * const hooks = createHooks(client, contract);\n *\n * // In a component - Query\n * function UserList() {\n * const { data, isLoading } = hooks.listUsers.useQuery({\n * query: { limit: \"10\" }\n * });\n * // ...\n * }\n *\n * // In a component - Mutation\n * function CreateUser() {\n * const mutation = hooks.createUser.useMutation();\n * return (\n * <button onClick={() => mutation.mutate({\n * body: { name: \"Alice\", email: \"alice@example.com\" }\n * })}>\n * Create User\n * </button>\n * );\n * }\n * ```\n */\nexport function createHooks<T extends Contract>(client: Client<T>, contract: T): Hooks<T> {\n const hooks: Record<string, unknown> = {};\n\n for (const [name, endpoint] of Object.entries(contract)) {\n // Handle streaming endpoints\n if (endpoint.type === 'streaming') {\n const streamMethod = client[\n name as keyof T\n ] as unknown as StreamingClientMethod<StreamingEndpointDefinition>;\n hooks[name] = {\n stream: streamMethod,\n };\n continue;\n }\n\n // Handle SSE endpoints\n if (endpoint.type === 'sse') {\n const connectMethod = client[\n name as keyof T\n ] as unknown as SSEClientMethod<SSEEndpointDefinition>;\n hooks[name] = {\n connect: connectMethod,\n };\n continue;\n }\n\n // Handle standard endpoints\n const method = endpoint.method;\n const clientMethod = client[\n name as keyof T\n ] as unknown as ClientMethod<StandardEndpointDefinition>;\n\n if (method === 'GET' || method === 'HEAD') {\n // Create query hooks for read operations\n hooks[name] = {\n useQuery: (\n options: EndpointRequestOptions<StandardEndpointDefinition>,\n queryOptions?: Omit<\n UseQueryOptions<EndpointResponse<StandardEndpointDefinition>, Error>,\n 'queryKey' | 'queryFn'\n >,\n ) => {\n return useQuery({\n queryKey: [\n name,\n options.params ?? null,\n options.query ?? null,\n options.headers ?? null,\n options.body ?? null,\n ],\n queryFn: () => clientMethod(options),\n ...queryOptions,\n });\n },\n useSuspenseQuery: (\n options: EndpointRequestOptions<StandardEndpointDefinition>,\n queryOptions?: Omit<\n UseSuspenseQueryOptions<EndpointResponse<StandardEndpointDefinition>, Error>,\n 'queryKey' | 'queryFn'\n >,\n ) => {\n return useSuspenseQuery({\n queryKey: [\n name,\n options.params ?? null,\n options.query ?? null,\n options.headers ?? null,\n options.body ?? null,\n ],\n queryFn: () => clientMethod(options),\n ...queryOptions,\n });\n },\n };\n } else {\n // Create mutation hooks for write operations\n hooks[name] = {\n useMutation: (\n mutationOptions?: Omit<\n UseMutationOptions<\n EndpointResponse<StandardEndpointDefinition>,\n Error,\n EndpointRequestOptions<StandardEndpointDefinition>\n >,\n 'mutationFn'\n >,\n ) => {\n return useMutation({\n mutationFn: (options: EndpointRequestOptions<StandardEndpointDefinition>) =>\n clientMethod(options),\n ...mutationOptions,\n });\n },\n };\n }\n }\n\n return hooks as Hooks<T>;\n}\n"
6
6
  ],
7
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiBO,IAVP;AAgHO,SAAS,WAA+B,CAAC,QAAmB,UAAuB;AAAA,EACxF,MAAM,QAAiC,CAAC;AAAA,EAExC,YAAY,MAAM,aAAa,OAAO,QAAQ,QAAQ,GAAG;AAAA,IACvD,MAAM,SAAS,SAAS;AAAA,IACxB,MAAM,eAAe,OAAO;AAAA,IAE5B,IAAI,WAAW,SAAS,WAAW,QAAQ;AAAA,MAEzC,MAAM,QAAQ;AAAA,QACZ,UAAU,CACR,SACA,iBAIG;AAAA,UACH,OAAO,4BAAS;AAAA,YACd,UAAU;AAAA,cACR;AAAA,cACA,QAAQ,UAAU;AAAA,cAClB,QAAQ,SAAS;AAAA,cACjB,QAAQ,WAAW;AAAA,cACnB,QAAQ,QAAQ;AAAA,YAClB;AAAA,YACA,SAAS,MAAM,aAAa,OAAO;AAAA,eAChC;AAAA,UACL,CAAC;AAAA;AAAA,QAEH,kBAAkB,CAChB,SACA,iBAIG;AAAA,UACH,OAAO,oCAAiB;AAAA,YACtB,UAAU;AAAA,cACR;AAAA,cACA,QAAQ,UAAU;AAAA,cAClB,QAAQ,SAAS;AAAA,cACjB,QAAQ,WAAW;AAAA,cACnB,QAAQ,QAAQ;AAAA,YAClB;AAAA,YACA,SAAS,MAAM,aAAa,OAAO;AAAA,eAChC;AAAA,UACL,CAAC;AAAA;AAAA,MAEL;AAAA,IACF,EAAO;AAAA,MAEL,MAAM,QAAQ;AAAA,QACZ,aAAa,CACX,oBAQG;AAAA,UACH,OAAO,+BAAY;AAAA,YACjB,YAAY,CAAC,YACX,aAAa,OAAO;AAAA,eACnB;AAAA,UACL,CAAC;AAAA;AAAA,MAEL;AAAA;AAAA,EAEJ;AAAA,EAEA,OAAO;AAAA;",
8
- "debugId": "7B2442E74A7DC69E64756E2164756E21",
7
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwBO,IAVP;AA8IO,SAAS,WAA+B,CAAC,QAAmB,UAAuB;AAAA,EACxF,MAAM,QAAiC,CAAC;AAAA,EAExC,YAAY,MAAM,aAAa,OAAO,QAAQ,QAAQ,GAAG;AAAA,IAEvD,IAAI,SAAS,SAAS,aAAa;AAAA,MACjC,MAAM,eAAe,OACnB;AAAA,MAEF,MAAM,QAAQ;AAAA,QACZ,QAAQ;AAAA,MACV;AAAA,MACA;AAAA,IACF;AAAA,IAGA,IAAI,SAAS,SAAS,OAAO;AAAA,MAC3B,MAAM,gBAAgB,OACpB;AAAA,MAEF,MAAM,QAAQ;AAAA,QACZ,SAAS;AAAA,MACX;AAAA,MACA;AAAA,IACF;AAAA,IAGA,MAAM,SAAS,SAAS;AAAA,IACxB,MAAM,eAAe,OACnB;AAAA,IAGF,IAAI,WAAW,SAAS,WAAW,QAAQ;AAAA,MAEzC,MAAM,QAAQ;AAAA,QACZ,UAAU,CACR,SACA,iBAIG;AAAA,UACH,OAAO,4BAAS;AAAA,YACd,UAAU;AAAA,cACR;AAAA,cACA,QAAQ,UAAU;AAAA,cAClB,QAAQ,SAAS;AAAA,cACjB,QAAQ,WAAW;AAAA,cACnB,QAAQ,QAAQ;AAAA,YAClB;AAAA,YACA,SAAS,MAAM,aAAa,OAAO;AAAA,eAChC;AAAA,UACL,CAAC;AAAA;AAAA,QAEH,kBAAkB,CAChB,SACA,iBAIG;AAAA,UACH,OAAO,oCAAiB;AAAA,YACtB,UAAU;AAAA,cACR;AAAA,cACA,QAAQ,UAAU;AAAA,cAClB,QAAQ,SAAS;AAAA,cACjB,QAAQ,WAAW;AAAA,cACnB,QAAQ,QAAQ;AAAA,YAClB;AAAA,YACA,SAAS,MAAM,aAAa,OAAO;AAAA,eAChC;AAAA,UACL,CAAC;AAAA;AAAA,MAEL;AAAA,IACF,EAAO;AAAA,MAEL,MAAM,QAAQ;AAAA,QACZ,aAAa,CACX,oBAQG;AAAA,UACH,OAAO,+BAAY;AAAA,YACjB,YAAY,CAAC,YACX,aAAa,OAAO;AAAA,eACnB;AAAA,UACL,CAAC;AAAA;AAAA,MAEL;AAAA;AAAA,EAEJ;AAAA,EAEA,OAAO;AAAA;",
8
+ "debugId": "47DF1EE9E6FD487A64756E2164756E21",
9
9
  "names": []
10
10
  }
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@richie-rpc/react-query",
3
- "version": "1.0.4",
3
+ "version": "1.0.6",
4
4
  "type": "commonjs"
5
5
  }
@@ -8,6 +8,20 @@ import {
8
8
  function createHooks(client, contract) {
9
9
  const hooks = {};
10
10
  for (const [name, endpoint] of Object.entries(contract)) {
11
+ if (endpoint.type === "streaming") {
12
+ const streamMethod = client[name];
13
+ hooks[name] = {
14
+ stream: streamMethod
15
+ };
16
+ continue;
17
+ }
18
+ if (endpoint.type === "sse") {
19
+ const connectMethod = client[name];
20
+ hooks[name] = {
21
+ connect: connectMethod
22
+ };
23
+ continue;
24
+ }
11
25
  const method = endpoint.method;
12
26
  const clientMethod = client[name];
13
27
  if (method === "GET" || method === "HEAD") {
@@ -56,4 +70,4 @@ export {
56
70
  createHooks
57
71
  };
58
72
 
59
- //# debugId=7FB1CC836CF104A564756E2164756E21
73
+ //# debugId=47BC57BE472723C264756E2164756E21
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["../../index.ts"],
4
4
  "sourcesContent": [
5
- "import type {\n Client,\n ClientMethod,\n EndpointRequestOptions,\n EndpointResponse,\n} from '@richie-rpc/client';\nimport type { Contract, EndpointDefinition } from '@richie-rpc/core';\nimport {\n type UseMutationOptions,\n type UseMutationResult,\n type UseQueryOptions,\n type UseQueryResult,\n type UseSuspenseQueryOptions,\n type UseSuspenseQueryResult,\n useMutation,\n useQuery,\n useSuspenseQuery,\n} from '@tanstack/react-query';\n\n// HTTP methods that should use query hooks (read operations)\ntype QueryMethods = 'GET' | 'HEAD';\n\n// HTTP methods that should use mutation hooks (write operations)\ntype MutationMethods = 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS';\n\n/**\n * Hook wrapper for query endpoints (GET, HEAD)\n * Provides useQuery and useSuspenseQuery methods\n */\nexport type QueryHook<T extends EndpointDefinition> = {\n /**\n * Standard query hook that returns loading states\n */\n useQuery: (\n options: EndpointRequestOptions<T>,\n queryOptions?: Omit<UseQueryOptions<EndpointResponse<T>, Error>, 'queryKey' | 'queryFn'>,\n ) => UseQueryResult<EndpointResponse<T>, Error>;\n\n /**\n * Suspense-enabled query hook that throws promises for React Suspense\n */\n useSuspenseQuery: (\n options: EndpointRequestOptions<T>,\n queryOptions?: Omit<\n UseSuspenseQueryOptions<EndpointResponse<T>, Error>,\n 'queryKey' | 'queryFn'\n >,\n ) => UseSuspenseQueryResult<EndpointResponse<T>, Error>;\n};\n\n/**\n * Hook wrapper for mutation endpoints (POST, PUT, PATCH, DELETE)\n * Provides useMutation method\n */\nexport type MutationHook<T extends EndpointDefinition> = {\n /**\n * Mutation hook for write operations\n */\n useMutation: (\n mutationOptions?: Omit<\n UseMutationOptions<EndpointResponse<T>, Error, EndpointRequestOptions<T>>,\n 'mutationFn'\n >,\n ) => UseMutationResult<EndpointResponse<T>, Error, EndpointRequestOptions<T>>;\n};\n\n/**\n * Conditionally apply hook type based on HTTP method\n */\nexport type EndpointHook<T extends EndpointDefinition> = T['method'] extends QueryMethods\n ? QueryHook<T>\n : T['method'] extends MutationMethods\n ? MutationHook<T>\n : never;\n\n/**\n * Complete hooks object for a contract\n * Each endpoint gets appropriate hooks based on its HTTP method\n */\nexport type Hooks<T extends Contract> = {\n [K in keyof T]: EndpointHook<T[K]>;\n};\n\n/**\n * Create typed React hooks for all endpoints in a contract\n *\n * Query endpoints (GET, HEAD) get useQuery and useSuspenseQuery methods\n * Mutation endpoints (POST, PUT, PATCH, DELETE) get useMutation method\n *\n * @param client - The typed client created with createClient()\n * @param contract - The contract definition\n * @returns Hooks object with methods for each endpoint\n *\n * @example\n * ```tsx\n * const client = createClient(contract, { baseUrl: 'http://localhost:3000' });\n * const hooks = createHooks(client, contract);\n *\n * // In a component - Query\n * function UserList() {\n * const { data, isLoading } = hooks.listUsers.useQuery({\n * query: { limit: \"10\" }\n * });\n * // ...\n * }\n *\n * // In a component - Mutation\n * function CreateUser() {\n * const mutation = hooks.createUser.useMutation();\n * return (\n * <button onClick={() => mutation.mutate({\n * body: { name: \"Alice\", email: \"alice@example.com\" }\n * })}>\n * Create User\n * </button>\n * );\n * }\n * ```\n */\nexport function createHooks<T extends Contract>(client: Client<T>, contract: T): Hooks<T> {\n const hooks: Record<string, unknown> = {};\n\n for (const [name, endpoint] of Object.entries(contract)) {\n const method = endpoint.method;\n const clientMethod = client[name as keyof T] as unknown as ClientMethod<EndpointDefinition>;\n\n if (method === 'GET' || method === 'HEAD') {\n // Create query hooks for read operations\n hooks[name] = {\n useQuery: (\n options: EndpointRequestOptions<EndpointDefinition>,\n queryOptions?: Omit<\n UseQueryOptions<EndpointResponse<EndpointDefinition>, Error>,\n 'queryKey' | 'queryFn'\n >,\n ) => {\n return useQuery({\n queryKey: [\n name,\n options.params ?? null,\n options.query ?? null,\n options.headers ?? null,\n options.body ?? null,\n ],\n queryFn: () => clientMethod(options),\n ...queryOptions,\n });\n },\n useSuspenseQuery: (\n options: EndpointRequestOptions<EndpointDefinition>,\n queryOptions?: Omit<\n UseSuspenseQueryOptions<EndpointResponse<EndpointDefinition>, Error>,\n 'queryKey' | 'queryFn'\n >,\n ) => {\n return useSuspenseQuery({\n queryKey: [\n name,\n options.params ?? null,\n options.query ?? null,\n options.headers ?? null,\n options.body ?? null,\n ],\n queryFn: () => clientMethod(options),\n ...queryOptions,\n });\n },\n };\n } else {\n // Create mutation hooks for write operations\n hooks[name] = {\n useMutation: (\n mutationOptions?: Omit<\n UseMutationOptions<\n EndpointResponse<EndpointDefinition>,\n Error,\n EndpointRequestOptions<EndpointDefinition>\n >,\n 'mutationFn'\n >,\n ) => {\n return useMutation({\n mutationFn: (options: EndpointRequestOptions<EndpointDefinition>) =>\n clientMethod(options),\n ...mutationOptions,\n });\n },\n };\n }\n }\n\n return hooks as Hooks<T>;\n}\n"
5
+ "import type {\n Client,\n ClientMethod,\n EndpointRequestOptions,\n EndpointResponse,\n SSEClientMethod,\n StreamingClientMethod,\n} from '@richie-rpc/client';\nimport type {\n Contract,\n SSEEndpointDefinition,\n StandardEndpointDefinition,\n StreamingEndpointDefinition,\n} from '@richie-rpc/core';\nimport {\n type UseMutationOptions,\n type UseMutationResult,\n type UseQueryOptions,\n type UseQueryResult,\n type UseSuspenseQueryOptions,\n type UseSuspenseQueryResult,\n useMutation,\n useQuery,\n useSuspenseQuery,\n} from '@tanstack/react-query';\n\n// HTTP methods that should use query hooks (read operations)\ntype QueryMethods = 'GET' | 'HEAD';\n\n// HTTP methods that should use mutation hooks (write operations)\ntype MutationMethods = 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS';\n\n/**\n * Hook wrapper for query endpoints (GET, HEAD)\n * Provides useQuery and useSuspenseQuery methods\n */\nexport type QueryHook<T extends StandardEndpointDefinition> = {\n /**\n * Standard query hook that returns loading states\n */\n useQuery: (\n options: EndpointRequestOptions<T>,\n queryOptions?: Omit<UseQueryOptions<EndpointResponse<T>, Error>, 'queryKey' | 'queryFn'>,\n ) => UseQueryResult<EndpointResponse<T>, Error>;\n\n /**\n * Suspense-enabled query hook that throws promises for React Suspense\n */\n useSuspenseQuery: (\n options: EndpointRequestOptions<T>,\n queryOptions?: Omit<\n UseSuspenseQueryOptions<EndpointResponse<T>, Error>,\n 'queryKey' | 'queryFn'\n >,\n ) => UseSuspenseQueryResult<EndpointResponse<T>, Error>;\n};\n\n/**\n * Hook wrapper for mutation endpoints (POST, PUT, PATCH, DELETE)\n * Provides useMutation method\n */\nexport type MutationHook<T extends StandardEndpointDefinition> = {\n /**\n * Mutation hook for write operations\n */\n useMutation: (\n mutationOptions?: Omit<\n UseMutationOptions<EndpointResponse<T>, Error, EndpointRequestOptions<T>>,\n 'mutationFn'\n >,\n ) => UseMutationResult<EndpointResponse<T>, Error, EndpointRequestOptions<T>>;\n};\n\n/**\n * Conditionally apply hook type based on HTTP method\n */\nexport type EndpointHook<T extends StandardEndpointDefinition> = T['method'] extends QueryMethods\n ? QueryHook<T>\n : T['method'] extends MutationMethods\n ? MutationHook<T>\n : never;\n\n/**\n * Hook wrapper for streaming endpoints\n * Exposes the streaming client method directly since React Query\n * doesn't fit well with long-lived streaming connections\n */\nexport type StreamingHook<T extends StreamingEndpointDefinition> = {\n /**\n * Start a streaming request\n */\n stream: StreamingClientMethod<T>;\n};\n\n/**\n * Hook wrapper for SSE endpoints\n * Exposes the SSE client method directly since React Query\n * doesn't fit well with long-lived SSE connections\n */\nexport type SSEHook<T extends SSEEndpointDefinition> = {\n /**\n * Create an SSE connection\n */\n connect: SSEClientMethod<T>;\n};\n\n/**\n * Complete hooks object for a contract\n * Each endpoint gets appropriate hooks based on its type and HTTP method\n */\nexport type Hooks<T extends Contract> = {\n [K in keyof T]: T[K] extends StandardEndpointDefinition\n ? EndpointHook<T[K]>\n : T[K] extends StreamingEndpointDefinition\n ? StreamingHook<T[K]>\n : T[K] extends SSEEndpointDefinition\n ? SSEHook<T[K]>\n : never;\n};\n\n/**\n * Create typed React hooks for all endpoints in a contract\n *\n * Query endpoints (GET, HEAD) get useQuery and useSuspenseQuery methods\n * Mutation endpoints (POST, PUT, PATCH, DELETE) get useMutation method\n *\n * @param client - The typed client created with createClient()\n * @param contract - The contract definition\n * @returns Hooks object with methods for each endpoint\n *\n * @example\n * ```tsx\n * const client = createClient(contract, { baseUrl: 'http://localhost:3000' });\n * const hooks = createHooks(client, contract);\n *\n * // In a component - Query\n * function UserList() {\n * const { data, isLoading } = hooks.listUsers.useQuery({\n * query: { limit: \"10\" }\n * });\n * // ...\n * }\n *\n * // In a component - Mutation\n * function CreateUser() {\n * const mutation = hooks.createUser.useMutation();\n * return (\n * <button onClick={() => mutation.mutate({\n * body: { name: \"Alice\", email: \"alice@example.com\" }\n * })}>\n * Create User\n * </button>\n * );\n * }\n * ```\n */\nexport function createHooks<T extends Contract>(client: Client<T>, contract: T): Hooks<T> {\n const hooks: Record<string, unknown> = {};\n\n for (const [name, endpoint] of Object.entries(contract)) {\n // Handle streaming endpoints\n if (endpoint.type === 'streaming') {\n const streamMethod = client[\n name as keyof T\n ] as unknown as StreamingClientMethod<StreamingEndpointDefinition>;\n hooks[name] = {\n stream: streamMethod,\n };\n continue;\n }\n\n // Handle SSE endpoints\n if (endpoint.type === 'sse') {\n const connectMethod = client[\n name as keyof T\n ] as unknown as SSEClientMethod<SSEEndpointDefinition>;\n hooks[name] = {\n connect: connectMethod,\n };\n continue;\n }\n\n // Handle standard endpoints\n const method = endpoint.method;\n const clientMethod = client[\n name as keyof T\n ] as unknown as ClientMethod<StandardEndpointDefinition>;\n\n if (method === 'GET' || method === 'HEAD') {\n // Create query hooks for read operations\n hooks[name] = {\n useQuery: (\n options: EndpointRequestOptions<StandardEndpointDefinition>,\n queryOptions?: Omit<\n UseQueryOptions<EndpointResponse<StandardEndpointDefinition>, Error>,\n 'queryKey' | 'queryFn'\n >,\n ) => {\n return useQuery({\n queryKey: [\n name,\n options.params ?? null,\n options.query ?? null,\n options.headers ?? null,\n options.body ?? null,\n ],\n queryFn: () => clientMethod(options),\n ...queryOptions,\n });\n },\n useSuspenseQuery: (\n options: EndpointRequestOptions<StandardEndpointDefinition>,\n queryOptions?: Omit<\n UseSuspenseQueryOptions<EndpointResponse<StandardEndpointDefinition>, Error>,\n 'queryKey' | 'queryFn'\n >,\n ) => {\n return useSuspenseQuery({\n queryKey: [\n name,\n options.params ?? null,\n options.query ?? null,\n options.headers ?? null,\n options.body ?? null,\n ],\n queryFn: () => clientMethod(options),\n ...queryOptions,\n });\n },\n };\n } else {\n // Create mutation hooks for write operations\n hooks[name] = {\n useMutation: (\n mutationOptions?: Omit<\n UseMutationOptions<\n EndpointResponse<StandardEndpointDefinition>,\n Error,\n EndpointRequestOptions<StandardEndpointDefinition>\n >,\n 'mutationFn'\n >,\n ) => {\n return useMutation({\n mutationFn: (options: EndpointRequestOptions<StandardEndpointDefinition>) =>\n clientMethod(options),\n ...mutationOptions,\n });\n },\n };\n }\n }\n\n return hooks as Hooks<T>;\n}\n"
6
6
  ],
7
- "mappings": ";;AAOA;AAAA;AAAA;AAAA;AAAA;AAgHO,SAAS,WAA+B,CAAC,QAAmB,UAAuB;AAAA,EACxF,MAAM,QAAiC,CAAC;AAAA,EAExC,YAAY,MAAM,aAAa,OAAO,QAAQ,QAAQ,GAAG;AAAA,IACvD,MAAM,SAAS,SAAS;AAAA,IACxB,MAAM,eAAe,OAAO;AAAA,IAE5B,IAAI,WAAW,SAAS,WAAW,QAAQ;AAAA,MAEzC,MAAM,QAAQ;AAAA,QACZ,UAAU,CACR,SACA,iBAIG;AAAA,UACH,OAAO,SAAS;AAAA,YACd,UAAU;AAAA,cACR;AAAA,cACA,QAAQ,UAAU;AAAA,cAClB,QAAQ,SAAS;AAAA,cACjB,QAAQ,WAAW;AAAA,cACnB,QAAQ,QAAQ;AAAA,YAClB;AAAA,YACA,SAAS,MAAM,aAAa,OAAO;AAAA,eAChC;AAAA,UACL,CAAC;AAAA;AAAA,QAEH,kBAAkB,CAChB,SACA,iBAIG;AAAA,UACH,OAAO,iBAAiB;AAAA,YACtB,UAAU;AAAA,cACR;AAAA,cACA,QAAQ,UAAU;AAAA,cAClB,QAAQ,SAAS;AAAA,cACjB,QAAQ,WAAW;AAAA,cACnB,QAAQ,QAAQ;AAAA,YAClB;AAAA,YACA,SAAS,MAAM,aAAa,OAAO;AAAA,eAChC;AAAA,UACL,CAAC;AAAA;AAAA,MAEL;AAAA,IACF,EAAO;AAAA,MAEL,MAAM,QAAQ;AAAA,QACZ,aAAa,CACX,oBAQG;AAAA,UACH,OAAO,YAAY;AAAA,YACjB,YAAY,CAAC,YACX,aAAa,OAAO;AAAA,eACnB;AAAA,UACL,CAAC;AAAA;AAAA,MAEL;AAAA;AAAA,EAEJ;AAAA,EAEA,OAAO;AAAA;",
8
- "debugId": "7FB1CC836CF104A564756E2164756E21",
7
+ "mappings": ";;AAcA;AAAA;AAAA;AAAA;AAAA;AA8IO,SAAS,WAA+B,CAAC,QAAmB,UAAuB;AAAA,EACxF,MAAM,QAAiC,CAAC;AAAA,EAExC,YAAY,MAAM,aAAa,OAAO,QAAQ,QAAQ,GAAG;AAAA,IAEvD,IAAI,SAAS,SAAS,aAAa;AAAA,MACjC,MAAM,eAAe,OACnB;AAAA,MAEF,MAAM,QAAQ;AAAA,QACZ,QAAQ;AAAA,MACV;AAAA,MACA;AAAA,IACF;AAAA,IAGA,IAAI,SAAS,SAAS,OAAO;AAAA,MAC3B,MAAM,gBAAgB,OACpB;AAAA,MAEF,MAAM,QAAQ;AAAA,QACZ,SAAS;AAAA,MACX;AAAA,MACA;AAAA,IACF;AAAA,IAGA,MAAM,SAAS,SAAS;AAAA,IACxB,MAAM,eAAe,OACnB;AAAA,IAGF,IAAI,WAAW,SAAS,WAAW,QAAQ;AAAA,MAEzC,MAAM,QAAQ;AAAA,QACZ,UAAU,CACR,SACA,iBAIG;AAAA,UACH,OAAO,SAAS;AAAA,YACd,UAAU;AAAA,cACR;AAAA,cACA,QAAQ,UAAU;AAAA,cAClB,QAAQ,SAAS;AAAA,cACjB,QAAQ,WAAW;AAAA,cACnB,QAAQ,QAAQ;AAAA,YAClB;AAAA,YACA,SAAS,MAAM,aAAa,OAAO;AAAA,eAChC;AAAA,UACL,CAAC;AAAA;AAAA,QAEH,kBAAkB,CAChB,SACA,iBAIG;AAAA,UACH,OAAO,iBAAiB;AAAA,YACtB,UAAU;AAAA,cACR;AAAA,cACA,QAAQ,UAAU;AAAA,cAClB,QAAQ,SAAS;AAAA,cACjB,QAAQ,WAAW;AAAA,cACnB,QAAQ,QAAQ;AAAA,YAClB;AAAA,YACA,SAAS,MAAM,aAAa,OAAO;AAAA,eAChC;AAAA,UACL,CAAC;AAAA;AAAA,MAEL;AAAA,IACF,EAAO;AAAA,MAEL,MAAM,QAAQ;AAAA,QACZ,aAAa,CACX,oBAQG;AAAA,UACH,OAAO,YAAY;AAAA,YACjB,YAAY,CAAC,YACX,aAAa,OAAO;AAAA,eACnB;AAAA,UACL,CAAC;AAAA;AAAA,MAEL;AAAA;AAAA,EAEJ;AAAA,EAEA,OAAO;AAAA;",
8
+ "debugId": "47BC57BE472723C264756E2164756E21",
9
9
  "names": []
10
10
  }
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@richie-rpc/react-query",
3
- "version": "1.0.4",
3
+ "version": "1.0.6",
4
4
  "type": "module"
5
5
  }
@@ -1,5 +1,5 @@
1
- import type { Client, EndpointRequestOptions, EndpointResponse } from '@richie-rpc/client';
2
- import type { Contract, EndpointDefinition } from '@richie-rpc/core';
1
+ import type { Client, EndpointRequestOptions, EndpointResponse, SSEClientMethod, StreamingClientMethod } from '@richie-rpc/client';
2
+ import type { Contract, SSEEndpointDefinition, StandardEndpointDefinition, StreamingEndpointDefinition } from '@richie-rpc/core';
3
3
  import { type UseMutationOptions, type UseMutationResult, type UseQueryOptions, type UseQueryResult, type UseSuspenseQueryOptions, type UseSuspenseQueryResult } from '@tanstack/react-query';
4
4
  type QueryMethods = 'GET' | 'HEAD';
5
5
  type MutationMethods = 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS';
@@ -7,7 +7,7 @@ type MutationMethods = 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS';
7
7
  * Hook wrapper for query endpoints (GET, HEAD)
8
8
  * Provides useQuery and useSuspenseQuery methods
9
9
  */
10
- export type QueryHook<T extends EndpointDefinition> = {
10
+ export type QueryHook<T extends StandardEndpointDefinition> = {
11
11
  /**
12
12
  * Standard query hook that returns loading states
13
13
  */
@@ -21,7 +21,7 @@ export type QueryHook<T extends EndpointDefinition> = {
21
21
  * Hook wrapper for mutation endpoints (POST, PUT, PATCH, DELETE)
22
22
  * Provides useMutation method
23
23
  */
24
- export type MutationHook<T extends EndpointDefinition> = {
24
+ export type MutationHook<T extends StandardEndpointDefinition> = {
25
25
  /**
26
26
  * Mutation hook for write operations
27
27
  */
@@ -30,13 +30,35 @@ export type MutationHook<T extends EndpointDefinition> = {
30
30
  /**
31
31
  * Conditionally apply hook type based on HTTP method
32
32
  */
33
- export type EndpointHook<T extends EndpointDefinition> = T['method'] extends QueryMethods ? QueryHook<T> : T['method'] extends MutationMethods ? MutationHook<T> : never;
33
+ export type EndpointHook<T extends StandardEndpointDefinition> = T['method'] extends QueryMethods ? QueryHook<T> : T['method'] extends MutationMethods ? MutationHook<T> : never;
34
+ /**
35
+ * Hook wrapper for streaming endpoints
36
+ * Exposes the streaming client method directly since React Query
37
+ * doesn't fit well with long-lived streaming connections
38
+ */
39
+ export type StreamingHook<T extends StreamingEndpointDefinition> = {
40
+ /**
41
+ * Start a streaming request
42
+ */
43
+ stream: StreamingClientMethod<T>;
44
+ };
45
+ /**
46
+ * Hook wrapper for SSE endpoints
47
+ * Exposes the SSE client method directly since React Query
48
+ * doesn't fit well with long-lived SSE connections
49
+ */
50
+ export type SSEHook<T extends SSEEndpointDefinition> = {
51
+ /**
52
+ * Create an SSE connection
53
+ */
54
+ connect: SSEClientMethod<T>;
55
+ };
34
56
  /**
35
57
  * Complete hooks object for a contract
36
- * Each endpoint gets appropriate hooks based on its HTTP method
58
+ * Each endpoint gets appropriate hooks based on its type and HTTP method
37
59
  */
38
60
  export type Hooks<T extends Contract> = {
39
- [K in keyof T]: EndpointHook<T[K]>;
61
+ [K in keyof T]: T[K] extends StandardEndpointDefinition ? EndpointHook<T[K]> : T[K] extends StreamingEndpointDefinition ? StreamingHook<T[K]> : T[K] extends SSEEndpointDefinition ? SSEHook<T[K]> : never;
40
62
  };
41
63
  /**
42
64
  * Create typed React hooks for all endpoints in a contract
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@richie-rpc/react-query",
3
- "version": "1.0.4",
3
+ "version": "1.0.6",
4
4
  "main": "./dist/cjs/index.cjs",
5
5
  "exports": {
6
6
  ".": {
@@ -10,8 +10,8 @@
10
10
  }
11
11
  },
12
12
  "peerDependencies": {
13
- "@richie-rpc/client": "^1.2.3",
14
- "@richie-rpc/core": "^1.2.2",
13
+ "@richie-rpc/client": "^1.2.5",
14
+ "@richie-rpc/core": "^1.2.4",
15
15
  "@tanstack/react-query": "^5.0.0",
16
16
  "react": "^18.0.0 || ^19.0.0",
17
17
  "typescript": "^5",