better-convex 0.9.2 → 0.10.0

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.
@@ -4,9 +4,10 @@ import { c } from "react/compiler-runtime";
4
4
  import { ConvexProvider, ConvexReactClient, ConvexReactClient as ConvexReactClient$1, useAction, useConvex, useMutation } from "convex/react";
5
5
  import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
6
6
  import { jsx } from "react/jsx-runtime";
7
- import { hashKey, notifyManager, skipToken, useQueries, useQueryClient } from "@tanstack/react-query";
7
+ import { notifyManager, skipToken, useQueries, useQueryClient } from "@tanstack/react-query";
8
8
  import { getFunctionName } from "convex/server";
9
9
  import { ConvexHttpClient } from "convex/browser";
10
+ import { hashKey } from "@tanstack/query-core";
10
11
  import { convexToJson } from "convex/values";
11
12
 
12
13
  //#region src/shared/meta-utils.ts
@@ -140,6 +141,114 @@ var HttpClientError = class extends Error {
140
141
  }
141
142
  };
142
143
 
144
+ //#endregion
145
+ //#region src/crpc/http-client.ts
146
+ /**
147
+ * HTTP Client Helpers
148
+ *
149
+ * Framework-agnostic utilities for executing HTTP requests
150
+ * against Convex HTTP endpoints.
151
+ */
152
+ /** Reserved keys that are not part of JSON body */
153
+ const RESERVED_KEYS = new Set([
154
+ "params",
155
+ "searchParams",
156
+ "form",
157
+ "fetch",
158
+ "init",
159
+ "headers"
160
+ ]);
161
+ /**
162
+ * Replace URL path parameters with actual values.
163
+ * e.g., '/users/:id' with { id: '123' } -> '/users/123'
164
+ */
165
+ function replaceUrlParam(url, params) {
166
+ return url.replace(/:(\w+)/g, (_, key) => {
167
+ const value = params[key];
168
+ return value !== void 0 ? encodeURIComponent(value) : `:${key}`;
169
+ });
170
+ }
171
+ /**
172
+ * Build URLSearchParams from query object.
173
+ * Handles array values as multiple params with same key (like Hono).
174
+ */
175
+ function buildSearchParams(query) {
176
+ const params = new URLSearchParams();
177
+ for (const [key, value] of Object.entries(query)) if (Array.isArray(value)) for (const v of value) params.append(key, v);
178
+ else if (value !== void 0 && value !== null) params.append(key, value);
179
+ return params;
180
+ }
181
+ /**
182
+ * Hono-style HTTP request executor.
183
+ * Processes args in the same way as Hono's ClientRequestImpl.fetch().
184
+ */
185
+ async function executeHttpRequest(opts) {
186
+ const { method, path } = opts.route;
187
+ const args = opts.args ?? {};
188
+ let rBody;
189
+ let cType;
190
+ if (args.form) {
191
+ const form = new FormData();
192
+ for (const [k, v] of Object.entries(args.form)) if (Array.isArray(v)) for (const v2 of v) form.append(k, v2);
193
+ else form.append(k, v);
194
+ rBody = form;
195
+ } else {
196
+ const jsonBody = {};
197
+ for (const [key, value] of Object.entries(args)) if (!RESERVED_KEYS.has(key) && value !== void 0) jsonBody[key] = value;
198
+ if (Object.keys(jsonBody).length > 0) {
199
+ rBody = JSON.stringify(opts.transformer.input.serialize(jsonBody));
200
+ cType = "application/json";
201
+ }
202
+ }
203
+ const argsClientOpts = {};
204
+ if (args.fetch) argsClientOpts.fetch = args.fetch;
205
+ if (args.init) argsClientOpts.init = args.init;
206
+ if (args.headers) argsClientOpts.headers = args.headers;
207
+ const mergedClientOpts = {
208
+ ...opts.clientOpts,
209
+ ...argsClientOpts
210
+ };
211
+ const resolvedBaseHeaders = typeof opts.baseHeaders === "function" ? await opts.baseHeaders() : opts.baseHeaders;
212
+ const headerValues = { ...typeof mergedClientOpts.headers === "function" ? await mergedClientOpts.headers() : mergedClientOpts.headers };
213
+ if (cType) headerValues["Content-Type"] = cType;
214
+ const finalHeaders = {};
215
+ if (resolvedBaseHeaders) {
216
+ for (const [key, value] of Object.entries(resolvedBaseHeaders)) if (value !== void 0) finalHeaders[key] = value;
217
+ }
218
+ Object.assign(finalHeaders, headerValues);
219
+ let url = opts.convexSiteUrl + path;
220
+ if (args.params) url = opts.convexSiteUrl + replaceUrlParam(path, args.params);
221
+ if (args.searchParams) {
222
+ const queryString = buildSearchParams(args.searchParams).toString();
223
+ if (queryString) url = `${url}?${queryString}`;
224
+ }
225
+ const methodUpperCase = method.toUpperCase();
226
+ const setBody = !(methodUpperCase === "GET" || methodUpperCase === "HEAD");
227
+ const response = await (mergedClientOpts.fetch ?? opts.baseFetch ?? globalThis.fetch)(url, {
228
+ body: setBody ? rBody : void 0,
229
+ method: methodUpperCase,
230
+ headers: finalHeaders,
231
+ ...mergedClientOpts.init
232
+ });
233
+ if (!response.ok) {
234
+ const errorData = await response.json().catch(() => ({ error: {
235
+ code: "UNKNOWN",
236
+ message: response.statusText
237
+ } }));
238
+ const errorCode = errorData?.error?.code || "UNKNOWN";
239
+ const errorMessage = errorData?.error?.message || response.statusText;
240
+ throw new HttpClientError({
241
+ code: errorCode,
242
+ status: response.status,
243
+ procedureName: opts.procedureName,
244
+ message: errorMessage
245
+ });
246
+ }
247
+ if (response.headers.get("content-length") === "0" || response.status === 204) return;
248
+ if ((response.headers.get("content-type") || "").includes("application/json")) return opts.transformer.output.deserialize(await response.json());
249
+ return response.text();
250
+ }
251
+
143
252
  //#endregion
144
253
  //#region src/crpc/transformer.ts
145
254
  const isPlainObject = (value) => {
@@ -313,105 +422,6 @@ const getTransformer = (transformer) => {
313
422
 
314
423
  //#endregion
315
424
  //#region src/react/http-proxy.ts
316
- /** Reserved keys that are not part of JSON body */
317
- const RESERVED_KEYS = new Set([
318
- "params",
319
- "searchParams",
320
- "form",
321
- "fetch",
322
- "init",
323
- "headers"
324
- ]);
325
- /**
326
- * Replace URL path parameters with actual values.
327
- * e.g., '/users/:id' with { id: '123' } -> '/users/123'
328
- */
329
- function replaceUrlParam(url, params) {
330
- return url.replace(/:(\w+)/g, (_, key) => {
331
- const value = params[key];
332
- return value !== void 0 ? encodeURIComponent(value) : `:${key}`;
333
- });
334
- }
335
- /**
336
- * Build URLSearchParams from query object.
337
- * Handles array values as multiple params with same key (like Hono).
338
- */
339
- function buildSearchParams(query) {
340
- const params = new URLSearchParams();
341
- for (const [key, value] of Object.entries(query)) if (Array.isArray(value)) for (const v of value) params.append(key, v);
342
- else if (value !== void 0 && value !== null) params.append(key, value);
343
- return params;
344
- }
345
- /**
346
- * Hono-style HTTP request executor.
347
- * Processes args in the same way as Hono's ClientRequestImpl.fetch().
348
- */
349
- async function executeHttpRequest(opts) {
350
- const { method, path } = opts.route;
351
- const args = opts.args ?? {};
352
- let rBody;
353
- let cType;
354
- if (args.form) {
355
- const form = new FormData();
356
- for (const [k, v] of Object.entries(args.form)) if (Array.isArray(v)) for (const v2 of v) form.append(k, v2);
357
- else form.append(k, v);
358
- rBody = form;
359
- } else {
360
- const jsonBody = {};
361
- for (const [key, value] of Object.entries(args)) if (!RESERVED_KEYS.has(key) && value !== void 0) jsonBody[key] = value;
362
- if (Object.keys(jsonBody).length > 0) {
363
- rBody = JSON.stringify(opts.transformer.input.serialize(jsonBody));
364
- cType = "application/json";
365
- }
366
- }
367
- const argsClientOpts = {};
368
- if (args.fetch) argsClientOpts.fetch = args.fetch;
369
- if (args.init) argsClientOpts.init = args.init;
370
- if (args.headers) argsClientOpts.headers = args.headers;
371
- const mergedClientOpts = {
372
- ...opts.clientOpts,
373
- ...argsClientOpts
374
- };
375
- const resolvedBaseHeaders = typeof opts.baseHeaders === "function" ? await opts.baseHeaders() : opts.baseHeaders;
376
- const headerValues = { ...typeof mergedClientOpts.headers === "function" ? await mergedClientOpts.headers() : mergedClientOpts.headers };
377
- if (cType) headerValues["Content-Type"] = cType;
378
- const finalHeaders = {};
379
- if (resolvedBaseHeaders) {
380
- for (const [key, value] of Object.entries(resolvedBaseHeaders)) if (value !== void 0) finalHeaders[key] = value;
381
- }
382
- Object.assign(finalHeaders, headerValues);
383
- let url = opts.convexSiteUrl + path;
384
- if (args.params) url = opts.convexSiteUrl + replaceUrlParam(path, args.params);
385
- if (args.searchParams) {
386
- const queryString = buildSearchParams(args.searchParams).toString();
387
- if (queryString) url = `${url}?${queryString}`;
388
- }
389
- const methodUpperCase = method.toUpperCase();
390
- const setBody = !(methodUpperCase === "GET" || methodUpperCase === "HEAD");
391
- const response = await (mergedClientOpts.fetch ?? opts.baseFetch ?? globalThis.fetch)(url, {
392
- body: setBody ? rBody : void 0,
393
- method: methodUpperCase,
394
- headers: finalHeaders,
395
- ...mergedClientOpts.init
396
- });
397
- if (!response.ok) {
398
- const errorData = await response.json().catch(() => ({ error: {
399
- code: "UNKNOWN",
400
- message: response.statusText
401
- } }));
402
- const errorCode = errorData?.error?.code || "UNKNOWN";
403
- const errorMessage = errorData?.error?.message || response.statusText;
404
- throw new HttpClientError({
405
- code: errorCode,
406
- status: response.status,
407
- procedureName: opts.procedureName,
408
- message: errorMessage
409
- });
410
- }
411
- if (response.headers.get("content-length") === "0" || response.status === 204) return;
412
- if ((response.headers.get("content-type") || "").includes("application/json")) return opts.transformer.output.deserialize(await response.json());
413
- return response.text();
414
- }
415
425
  /**
416
426
  * Create a recursive proxy for HTTP routes with TanStack Query integration.
417
427
  *
@@ -1637,7 +1647,12 @@ function createCRPCContext(options) {
1637
1647
  }
1638
1648
 
1639
1649
  //#endregion
1640
- //#region src/react/auth-mutations.ts
1650
+ //#region src/crpc/auth-error.ts
1651
+ /**
1652
+ * Auth Mutation Error
1653
+ *
1654
+ * Framework-agnostic error class for Better Auth mutations.
1655
+ */
1641
1656
  /**
1642
1657
  * Error thrown when a Better Auth mutation fails.
1643
1658
  * Contains the original error details from Better Auth.
@@ -1663,6 +1678,9 @@ var AuthMutationError = class extends Error {
1663
1678
  function isAuthMutationError(error) {
1664
1679
  return error instanceof AuthMutationError;
1665
1680
  }
1681
+
1682
+ //#endregion
1683
+ //#region src/react/auth-mutations.ts
1666
1684
  /** Poll until token is null (max 5s) */
1667
1685
  const waitForTokenClear = async (store, timeout = 5e3) => {
1668
1686
  const start = Date.now();
@@ -1,29 +1,106 @@
1
- import { o as Simplify, r as DistributiveOmit } from "../types-BTb_4BaU.js";
1
+ import { n as DeepPartial, o as Simplify, r as DistributiveOmit } from "../types-BTb_4BaU.js";
2
2
  import { C as HttpProcedure, G as DataTransformerOptions, V as UnsetMarker, d as CRPCHttpRouter, p as HttpRouterRecord } from "../http-types-BK7FuIcR.js";
3
- import { n as CRPCClient } from "../types-f53SgpBL.js";
4
- import { DefaultError, QueryFilters, UseMutationOptions, UseQueryOptions } from "@tanstack/react-query";
3
+ import { A as HttpInputArgs, C as ReservedMutationOptions$1, S as ReservedInfiniteQueryOptions, T as StaticQueryOptsParam, _ as IsPaginated, b as PaginatedFnMeta, c as ConvexMutationKey, d as ConvexQueryMeta, f as EmptyObject, g as InfiniteQueryInput, l as ConvexQueryHookOptions, m as FUNC_REF_SYMBOL, o as ConvexActionKey, p as ExtractPaginatedItem, s as ConvexInfiniteQueryMeta, u as ConvexQueryKey, w as ReservedQueryOptions$1, y as MutationVariables } from "../types-7bF_8IjP.js";
4
+ import { FunctionArgs, FunctionReference, FunctionReturnType } from "convex/server";
5
5
  import { z } from "zod";
6
+ import { DefaultError, QueryFilters, SkipToken, UseMutationOptions, UseQueryOptions } from "@tanstack/react-query";
6
7
 
7
- //#region src/react/http-proxy.d.ts
8
- /** Form value types (matches Hono's FormValue) */
9
- type HttpFormValue = string | Blob;
10
- /**
11
- * Hybrid input args: JSON body fields at root, explicit params/searchParams/form.
12
- * - JSON body: spread at root level (tRPC-style)
13
- * - Path params: { params: { id: '123' } }
14
- * - Query params: { searchParams: { limit: '10' } }
15
- * - Form data: { form: { file: blob } } - typed via .form() builder
16
- * - Client options: { headers, fetch, init } - for per-call customization
17
- */
18
- type HttpInputArgs = {
19
- /** Path parameters (e.g., :id in /users/:id) */params?: Record<string, string>; /** Query string parameters */
20
- searchParams?: Record<string, string | string[]>; /** Form data body (Content-Type: multipart/form-data) - typed via .form() builder */
21
- form?: Record<string, HttpFormValue | HttpFormValue[]>; /** Custom fetch function (per-call override) */
22
- fetch?: typeof fetch; /** Standard RequestInit (per-call override) */
23
- init?: RequestInit; /** Additional headers (per-call override) */
24
- headers?: Record<string, string> | (() => Record<string, string> | Promise<Record<string, string>>); /** Any other properties are JSON body fields */
25
- [key: string]: unknown;
8
+ //#region src/react/crpc-types.d.ts
9
+ /** Options returned by `convexQuery` factory */
10
+ type ConvexQueryOptions<T extends FunctionReference<'query'>> = Pick<UseQueryOptions<FunctionReturnType<T>, Error, FunctionReturnType<T>, ConvexQueryKey<T>>, 'queryKey' | 'staleTime' | 'enabled'>;
11
+ /** Options returned by `convexAction` factory */
12
+ type ConvexActionOptions<T extends FunctionReference<'action'>> = Pick<UseQueryOptions<FunctionReturnType<T>, Error, FunctionReturnType<T>, ConvexActionKey<T>>, 'queryKey' | 'staleTime' | 'enabled'>;
13
+ /** Query options parameter type */
14
+ type QueryOptsParam<T extends FunctionReference<'query'>> = Simplify<ConvexQueryHookOptions & DistributiveOmit<UseQueryOptions<FunctionReturnType<T>, DefaultError>, ReservedQueryOptions$1>>;
15
+ /** Query options return type */
16
+ type QueryOptsReturn<T extends FunctionReference<'query'>> = ConvexQueryOptions<T> & {
17
+ meta: ConvexQueryMeta;
18
+ };
19
+ /** Action query options parameter type (actions don't support subscriptions) */
20
+ type ActionQueryOptsParam<T extends FunctionReference<'action'>> = DistributiveOmit<UseQueryOptions<FunctionReturnType<T>, DefaultError>, ReservedQueryOptions$1>;
21
+ /** Action query options return type */
22
+ type ActionQueryOptsReturn<T extends FunctionReference<'action'>> = ConvexActionOptions<T>;
23
+ /**
24
+ * Decorated query procedure with queryOptions, queryKey, and queryFilter methods.
25
+ * Args are optional when the function has no required parameters.
26
+ * Supports skipToken for type-safe conditional queries.
27
+ */
28
+ type DecorateQuery<T extends FunctionReference<'query'>> = {
29
+ queryOptions: keyof FunctionArgs<T> extends never ? (args?: EmptyObject | SkipToken, opts?: QueryOptsParam<T>) => QueryOptsReturn<T> : EmptyObject extends FunctionArgs<T> ? (args?: FunctionArgs<T> | SkipToken, opts?: QueryOptsParam<T>) => QueryOptsReturn<T> : (args: FunctionArgs<T> | SkipToken, opts?: QueryOptsParam<T>) => QueryOptsReturn<T>; /** Static (non-hook) query options for event handlers and prefetching */
30
+ staticQueryOptions: keyof FunctionArgs<T> extends never ? (args?: EmptyObject | SkipToken, opts?: StaticQueryOptsParam) => ConvexQueryOptions<T> & {
31
+ meta: ConvexQueryMeta;
32
+ } : EmptyObject extends FunctionArgs<T> ? (args?: FunctionArgs<T> | SkipToken, opts?: StaticQueryOptsParam) => ConvexQueryOptions<T> & {
33
+ meta: ConvexQueryMeta;
34
+ } : (args: FunctionArgs<T> | SkipToken, opts?: StaticQueryOptsParam) => ConvexQueryOptions<T> & {
35
+ meta: ConvexQueryMeta;
36
+ }; /** Get query key for QueryClient methods (setQueryData, getQueryData, etc.) */
37
+ queryKey: (args?: DeepPartial<FunctionArgs<T>>) => ConvexQueryKey<T>; /** Get query filter for QueryClient methods (invalidateQueries, removeQueries, etc.) */
38
+ queryFilter: (args?: DeepPartial<FunctionArgs<T>>, filters?: DistributiveOmit<QueryFilters, 'queryKey'>) => QueryFilters;
39
+ };
40
+ /** Options for infinite query - extends TanStack Query options */
41
+ type InfiniteQueryOptsParam<T extends FunctionReference<'query'> = FunctionReference<'query'>> = {
42
+ /** Items per page. Optional - server uses .paginated() default if not provided. */limit?: number; /** Skip query silently when unauthenticated */
43
+ skipUnauth?: boolean; /** Placeholder data shown while loading (item array, not pagination result) */
44
+ placeholderData?: ExtractPaginatedItem<FunctionReturnType<T>>[];
45
+ } & DistributiveOmit<UseQueryOptions<FunctionReturnType<T>, DefaultError>, ReservedInfiniteQueryOptions>;
46
+ /** Return type of infiniteQueryOptions - compatible with TanStack prefetch */
47
+ type ConvexInfiniteQueryOptions<T extends FunctionReference<'query'>> = Pick<UseQueryOptions<FunctionReturnType<T>, Error, FunctionReturnType<T>, ConvexQueryKey<T>>, 'queryKey' | 'staleTime' | 'enabled'> & {
48
+ meta: ConvexInfiniteQueryMeta;
49
+ refetchInterval: false;
50
+ refetchOnMount: false;
51
+ refetchOnReconnect: false;
52
+ refetchOnWindowFocus: false; /** Placeholder data shown while loading (item array, not pagination result) */
53
+ placeholderData?: ExtractPaginatedItem<FunctionReturnType<T>>[];
54
+ } & DistributiveOmit<UseQueryOptions<FunctionReturnType<T>, DefaultError>, ReservedInfiniteQueryOptions>;
55
+ /** Infinite query options with attached function reference (client-only) */
56
+ type ConvexInfiniteQueryOptionsWithRef<T extends FunctionReference<'query'>> = ConvexInfiniteQueryOptions<T> & {
57
+ [FUNC_REF_SYMBOL]: T;
58
+ };
59
+ /** Infinite query options return type */
60
+ type InfiniteQueryOptsReturn<T extends FunctionReference<'query'>> = ConvexInfiniteQueryOptionsWithRef<T>;
61
+ /**
62
+ * Decorated infinite query procedure.
63
+ * Only available on queries that have cursor/limit in their input (paginated).
64
+ * Supports skipToken for conditional queries.
65
+ * Args are optional when the function has no required parameters (besides cursor/limit).
66
+ */
67
+ type DecorateInfiniteQuery<T extends FunctionReference<'query'>> = {
68
+ /** Create infinite query options for useInfiniteQuery and prefetch */infiniteQueryOptions: keyof InfiniteQueryInput<FunctionArgs<T>> extends never ? (args?: EmptyObject | SkipToken, opts?: InfiniteQueryOptsParam<T>) => InfiniteQueryOptsReturn<T> : EmptyObject extends InfiniteQueryInput<FunctionArgs<T>> ? (args?: InfiniteQueryInput<FunctionArgs<T>> | SkipToken, opts?: InfiniteQueryOptsParam<T>) => InfiniteQueryOptsReturn<T> : (args: InfiniteQueryInput<FunctionArgs<T>> | SkipToken, opts?: InfiniteQueryOptsParam<T>) => InfiniteQueryOptsReturn<T>; /** Get query key for infinite query (QueryClient methods like setQueryData, getQueryData) */
69
+ infiniteQueryKey: (args?: DeepPartial<InfiniteQueryInput<FunctionArgs<T>>>) => ConvexQueryKey<T>; /** Function metadata from server (auth, limit, rateLimit, role, type) */
70
+ meta: PaginatedFnMeta;
71
+ };
72
+ /**
73
+ * Decorated mutation procedure with mutationOptions and mutationKey methods.
74
+ */
75
+ type DecorateMutation<T extends FunctionReference<'mutation'>> = {
76
+ mutationOptions: (opts?: DistributiveOmit<UseMutationOptions<FunctionReturnType<T>, DefaultError, MutationVariables<T>>, ReservedMutationOptions$1>) => UseMutationOptions<FunctionReturnType<T>, DefaultError, MutationVariables<T>>; /** Get mutation key for QueryClient methods */
77
+ mutationKey: () => ConvexMutationKey;
78
+ };
79
+ /**
80
+ * Decorated action procedure with queryOptions, mutationOptions, and key methods.
81
+ * Actions can be used as one-shot queries (no subscription) or as mutations.
82
+ * Supports skipToken for conditional queries.
83
+ */
84
+ type DecorateAction<T extends FunctionReference<'action'>> = {
85
+ /** Use action as a one-shot query (no WebSocket subscription) */queryOptions: keyof FunctionArgs<T> extends never ? (args?: EmptyObject | SkipToken, opts?: ActionQueryOptsParam<T>) => ActionQueryOptsReturn<T> : EmptyObject extends FunctionArgs<T> ? (args?: FunctionArgs<T> | SkipToken, opts?: ActionQueryOptsParam<T>) => ActionQueryOptsReturn<T> : (args: FunctionArgs<T> | SkipToken, opts?: ActionQueryOptsParam<T>) => ActionQueryOptsReturn<T>; /** Static (non-hook) action query options for event handlers and prefetching */
86
+ staticQueryOptions: keyof FunctionArgs<T> extends never ? (args?: EmptyObject | SkipToken, opts?: StaticQueryOptsParam) => ConvexActionOptions<T> & {
87
+ meta: ConvexQueryMeta;
88
+ } : EmptyObject extends FunctionArgs<T> ? (args?: FunctionArgs<T> | SkipToken, opts?: StaticQueryOptsParam) => ConvexActionOptions<T> & {
89
+ meta: ConvexQueryMeta;
90
+ } : (args: FunctionArgs<T> | SkipToken, opts?: StaticQueryOptsParam) => ConvexActionOptions<T> & {
91
+ meta: ConvexQueryMeta;
92
+ }; /** Use action as a mutation */
93
+ mutationOptions: (opts?: DistributiveOmit<UseMutationOptions<FunctionReturnType<T>, DefaultError, MutationVariables<T>>, ReservedMutationOptions$1>) => UseMutationOptions<FunctionReturnType<T>, DefaultError, MutationVariables<T>>; /** Get mutation key for QueryClient methods */
94
+ mutationKey: () => ConvexMutationKey; /** Get query key for QueryClient methods */
95
+ queryKey: (args?: DeepPartial<FunctionArgs<T>>) => ConvexActionKey<T>; /** Get query filter for QueryClient methods */
96
+ queryFilter: (args?: DeepPartial<FunctionArgs<T>>, filters?: DistributiveOmit<QueryFilters, 'queryKey'>) => QueryFilters;
26
97
  };
98
+ /**
99
+ * Recursively decorates all procedures in a Convex API object.
100
+ */
101
+ type CRPCClient<TApi> = { [K in keyof TApi as K extends string ? K extends `_${string}` ? never : K : K]: TApi[K] extends FunctionReference<'query'> ? IsPaginated<FunctionArgs<TApi[K]>> extends true ? DecorateQuery<TApi[K]> & DecorateInfiniteQuery<TApi[K]> : DecorateQuery<TApi[K]> : TApi[K] extends FunctionReference<'mutation'> ? DecorateMutation<TApi[K]> : TApi[K] extends FunctionReference<'action'> ? DecorateAction<TApi[K]> : TApi[K] extends Record<string, unknown> ? CRPCClient<TApi[K]> : never };
102
+ //#endregion
103
+ //#region src/react/http-proxy.d.ts
27
104
  /** Infer schema type or return empty object if UnsetMarker */
28
105
  type InferSchemaOrEmpty<T> = T extends UnsetMarker ? object : T extends z.ZodTypeAny ? z.infer<T> : object;
29
106
  /** Infer merged input from HttpProcedure (flat - used internally) */
package/dist/rsc/index.js CHANGED
@@ -5,7 +5,7 @@ import { n as convexInfiniteQueryOptions, r as convexQuery } from "../query-opti
5
5
  import { convexToJson } from "convex/values";
6
6
  import { getFunctionName } from "convex/server";
7
7
  import { fetchAction, fetchQuery } from "convex/nextjs";
8
- import { hashKey } from "@tanstack/react-query";
8
+ import { hashKey } from "@tanstack/query-core";
9
9
 
10
10
  //#region src/rsc/http-server.ts
11
11
  /**