better-convex 0.6.4 → 0.7.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.
- package/dist/aggregate/index.d.ts +388 -0
- package/dist/aggregate/index.js +37 -0
- package/dist/{auth-client → auth/client}/index.js +1 -1
- package/dist/auth/http/index.d.ts +63 -0
- package/dist/auth/http/index.js +429 -0
- package/dist/auth/index.d.ts +18991 -175
- package/dist/auth/index.js +373 -686
- package/dist/{auth-nextjs → auth/nextjs}/index.d.ts +3 -5
- package/dist/{auth-nextjs → auth/nextjs}/index.js +3 -5
- package/dist/{caller-factory-B1FvYSKr.js → caller-factory-Dmgv8MLS.js} +15 -12
- package/dist/cli.mjs +2601 -13
- package/dist/codegen-Cz1idI3-.mjs +969 -0
- package/dist/{create-schema-orm-DplxTtYj.js → create-schema-orm-69VF4CFV.js} +4 -3
- package/dist/crpc/index.d.ts +2 -2
- package/dist/crpc/index.js +3 -3
- package/dist/{http-types-BRLY10NX.d.ts → http-types-BCf2wCgp.d.ts} +25 -25
- package/dist/meta-utils-DDVYp9Xf.js +117 -0
- package/dist/orm/index.d.ts +4 -3012
- package/dist/orm/index.js +9631 -2
- package/dist/{index-BQkhP2ny.d.ts → procedure-caller-CcjtUFvL.d.ts} +211 -74
- package/dist/query-context-BDSis9rT.js +1518 -0
- package/dist/query-context-DGExXZIV.d.ts +42 -0
- package/dist/react/index.d.ts +31 -35
- package/dist/react/index.js +145 -58
- package/dist/rsc/index.d.ts +4 -7
- package/dist/rsc/index.js +14 -10
- package/dist/runtime-B9xQFY8W.js +2280 -0
- package/dist/server/index.d.ts +3 -4
- package/dist/server/index.js +384 -10
- package/dist/{types-o-5rYcTr.d.ts → types-CIBGEYXq.d.ts} +4 -3
- package/dist/types-DgwvxKbT.d.ts +4 -0
- package/dist/watcher.mjs +8 -8
- package/dist/where-clause-compiler-CRP-i1Qa.d.ts +3463 -0
- package/package.json +14 -10
- package/dist/codegen-DkpPBVPn.mjs +0 -189
- package/dist/context-utils-DSuX99Da.d.ts +0 -17
- package/dist/meta-utils-DCpLSBWB.js +0 -41
- package/dist/orm-BKc-pwj_.js +0 -8821
- /package/dist/{auth-client → auth/client}/index.d.ts +0 -0
- /package/dist/{auth-config → auth/config}/index.d.ts +0 -0
- /package/dist/{auth-config → auth/config}/index.js +0 -0
- /package/dist/{create-schema-DhWXOhnU.js → create-schema-BdZOL6ns.js} +0 -0
- /package/dist/{customFunctions-C1okqCzL.js → customFunctions-CZnCwoR3.js} +0 -0
- /package/dist/{error-BZUhlhYz.js → error-Be4OcwwD.js} +0 -0
- /package/dist/{query-options-BL1Q0X7q.js → query-options-B0c1b6pZ.js} +0 -0
- /package/dist/{transformer-CTNSPjwp.js → transformer-Dh0w2py0.js} +0 -0
- /package/dist/{types-jftzhhuc.d.ts → types-DwGkkq2s.d.ts} +0 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { DocumentByName, GenericQueryCtx, TableNamesInDataModel } from "convex/server";
|
|
2
|
+
|
|
3
|
+
//#region src/orm/query-context.d.ts
|
|
4
|
+
type InferCtxDataModel<TCtx extends GenericQueryCtx<any>> = TCtx extends GenericQueryCtx<infer DataModel> ? DataModel : never;
|
|
5
|
+
type DocByCtx<TCtx extends GenericQueryCtx<any>, TableName extends TableNamesInDataModel<InferCtxDataModel<TCtx>>> = DocumentByName<InferCtxDataModel<TCtx>, TableName>;
|
|
6
|
+
type QueryCtxWithOptionalOrmQueryTable<TCtx extends GenericQueryCtx<any>, TableName extends TableNamesInDataModel<InferCtxDataModel<TCtx>>> = TCtx & {
|
|
7
|
+
orm?: {
|
|
8
|
+
query?: { [K in TableName]?: {
|
|
9
|
+
findFirst?: (...args: any[]) => unknown;
|
|
10
|
+
} };
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
type QueryCtxWithOrmQueryTable<TCtx extends GenericQueryCtx<any>, TableName extends TableNamesInDataModel<InferCtxDataModel<TCtx>>> = TCtx & {
|
|
14
|
+
orm: {
|
|
15
|
+
query: { [K in TableName]-?: {
|
|
16
|
+
findFirst: (...args: any[]) => unknown;
|
|
17
|
+
} };
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
type OrmQueryByCtx<TCtx extends GenericQueryCtx<any>> = TCtx extends {
|
|
21
|
+
orm: {
|
|
22
|
+
query: infer TQuery;
|
|
23
|
+
};
|
|
24
|
+
} ? TQuery : never;
|
|
25
|
+
type OrmQueryEntryByCtx<TCtx extends GenericQueryCtx<any>, TableName extends TableNamesInDataModel<InferCtxDataModel<TCtx>>> = TableName extends keyof OrmQueryByCtx<TCtx> ? NonNullable<OrmQueryByCtx<TCtx>[TableName]> : never;
|
|
26
|
+
type HasOrmFindFirstByCtx<TCtx extends GenericQueryCtx<any>, TableName extends TableNamesInDataModel<InferCtxDataModel<TCtx>>> = [OrmQueryEntryByCtx<TCtx, TableName>] extends [never] ? false : OrmQueryEntryByCtx<TCtx, TableName> extends {
|
|
27
|
+
findFirst: (...args: any[]) => unknown;
|
|
28
|
+
} ? true : false;
|
|
29
|
+
type QueryCtxWithPreferredOrmQueryTable<TCtx extends GenericQueryCtx<any>, TableName extends TableNamesInDataModel<InferCtxDataModel<TCtx>>> = TCtx extends {
|
|
30
|
+
orm: unknown;
|
|
31
|
+
} ? HasOrmFindFirstByCtx<TCtx, TableName> extends true ? TCtx : never : TCtx;
|
|
32
|
+
type OrmQueryRowByCtx<TCtx extends GenericQueryCtx<any>, TableName extends TableNamesInDataModel<InferCtxDataModel<TCtx>>> = OrmQueryEntryByCtx<TCtx, TableName> extends {
|
|
33
|
+
_: {
|
|
34
|
+
baseResult: infer TResult;
|
|
35
|
+
};
|
|
36
|
+
} ? TResult : never;
|
|
37
|
+
type LookupByIdResultByCtx<TCtx extends GenericQueryCtx<any>, TableName extends TableNamesInDataModel<InferCtxDataModel<TCtx>>> = (TCtx extends {
|
|
38
|
+
orm: unknown;
|
|
39
|
+
} ? OrmQueryRowByCtx<TCtx, TableName> : DocByCtx<TCtx, TableName>) | null;
|
|
40
|
+
declare function getByIdWithOrmQueryFallback<TCtx extends GenericQueryCtx<any>, TableName extends TableNamesInDataModel<InferCtxDataModel<TCtx>>>(ctx: QueryCtxWithPreferredOrmQueryTable<TCtx, TableName>, tableName: TableName, id: DocByCtx<TCtx, TableName>['_id']): Promise<LookupByIdResultByCtx<TCtx, TableName>>;
|
|
41
|
+
//#endregion
|
|
42
|
+
export { QueryCtxWithPreferredOrmQueryTable as a, QueryCtxWithOrmQueryTable as i, LookupByIdResultByCtx as n, getByIdWithOrmQueryFallback as o, QueryCtxWithOptionalOrmQueryTable as r, DocByCtx as t };
|
package/dist/react/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { ConvexProvider, ConvexProviderWithAuth as ConvexProviderWithAuth$1, ConvexReactClient, ConvexReactClient as ConvexReactClient$1, ConvexReactClientOptions, Watch, WatchQueryOptions, useConvex } from "convex/react";
|
|
3
|
-
import * as
|
|
3
|
+
import * as react from "react";
|
|
4
4
|
import { ReactNode } from "react";
|
|
5
5
|
import * as jotai_x0 from "jotai-x";
|
|
6
6
|
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
@@ -80,7 +80,7 @@ declare function createAuthMutations<T extends AuthClient>(authClient: T): AuthM
|
|
|
80
80
|
type FetchAccessTokenFn = (args: {
|
|
81
81
|
forceRefreshToken: boolean;
|
|
82
82
|
}) => Promise<string | null>;
|
|
83
|
-
declare const FetchAccessTokenContext:
|
|
83
|
+
declare const FetchAccessTokenContext: react.Context<FetchAccessTokenFn | null>;
|
|
84
84
|
/** Get fetchAccessToken from context (available immediately, no race condition) */
|
|
85
85
|
declare const useFetchAccessToken: () => FetchAccessTokenFn | null;
|
|
86
86
|
type ConvexAuthResult = {
|
|
@@ -102,7 +102,7 @@ type AuthStoreState = {
|
|
|
102
102
|
};
|
|
103
103
|
/** Decode JWT expiration (ms timestamp) from token */
|
|
104
104
|
declare function decodeJwtExp(token: string): number | null;
|
|
105
|
-
declare const AuthProvider:
|
|
105
|
+
declare const AuthProvider: react.FC<jotai_x0.ProviderProps<{
|
|
106
106
|
onMutationUnauthorized: () => void;
|
|
107
107
|
onQueryUnauthorized: (info: {
|
|
108
108
|
queryName: string;
|
|
@@ -197,33 +197,33 @@ declare function MaybeAuthenticated({
|
|
|
197
197
|
children
|
|
198
198
|
}: {
|
|
199
199
|
children: React.ReactNode;
|
|
200
|
-
}):
|
|
200
|
+
}): react.ReactNode;
|
|
201
201
|
/** Render children only when authenticated (server-verified) */
|
|
202
202
|
declare function Authenticated({
|
|
203
203
|
children
|
|
204
204
|
}: {
|
|
205
205
|
children: React.ReactNode;
|
|
206
|
-
}):
|
|
206
|
+
}): react.ReactNode;
|
|
207
207
|
/** Render children only when maybe not auth (optimistic) */
|
|
208
208
|
declare function MaybeUnauthenticated({
|
|
209
209
|
children
|
|
210
210
|
}: {
|
|
211
211
|
children: React.ReactNode;
|
|
212
|
-
}):
|
|
212
|
+
}): react.ReactNode;
|
|
213
213
|
/** Render children only when not authenticated (server-verified) */
|
|
214
214
|
declare function Unauthenticated({
|
|
215
215
|
children
|
|
216
216
|
}: {
|
|
217
217
|
children: React.ReactNode;
|
|
218
|
-
}):
|
|
218
|
+
}): react.ReactNode;
|
|
219
219
|
//#endregion
|
|
220
220
|
//#region src/crpc/transformer.d.ts
|
|
221
221
|
/**
|
|
222
222
|
* Generic transformer contract (mirrors tRPC shape).
|
|
223
223
|
*/
|
|
224
224
|
interface DataTransformer {
|
|
225
|
-
serialize(object: any): any;
|
|
226
225
|
deserialize(object: any): any;
|
|
226
|
+
serialize(object: any): any;
|
|
227
227
|
}
|
|
228
228
|
/**
|
|
229
229
|
* Separate input/output transformers.
|
|
@@ -241,15 +241,17 @@ type DataTransformerOptions = CombinedDataTransformer | DataTransformer;
|
|
|
241
241
|
interface ConvexQueryClientOptions extends ConvexReactClientOptions {
|
|
242
242
|
/** Auth store for checking auth state in queryFn */
|
|
243
243
|
authStore?: AuthStore;
|
|
244
|
-
/** TanStack QueryClient. Can also be set later via .connect(queryClient) */
|
|
245
|
-
queryClient?: QueryClient;
|
|
246
|
-
/** Custom fetch for SSR. Avoid bundling on client. */
|
|
247
|
-
serverFetch?: typeof globalThis.fetch;
|
|
248
244
|
/**
|
|
249
245
|
* Opt out of consistent SSR queries for faster performance.
|
|
250
246
|
* Trade-off: queries may return results from different timestamps.
|
|
251
247
|
*/
|
|
252
248
|
dangerouslyUseInconsistentQueriesDuringSSR?: boolean;
|
|
249
|
+
/** TanStack QueryClient. Can also be set later via .connect(queryClient) */
|
|
250
|
+
queryClient?: QueryClient;
|
|
251
|
+
/** Custom fetch for SSR. Avoid bundling on client. */
|
|
252
|
+
serverFetch?: typeof globalThis.fetch;
|
|
253
|
+
/** Optional payload transformer (always composed with built-in Date support). */
|
|
254
|
+
transformer?: DataTransformerOptions;
|
|
253
255
|
/**
|
|
254
256
|
* Delay in ms before unsubscribing when a query has no observers.
|
|
255
257
|
* Prevents wasteful unsubscribe/subscribe cycles from React StrictMode
|
|
@@ -257,8 +259,6 @@ interface ConvexQueryClientOptions extends ConvexReactClientOptions {
|
|
|
257
259
|
* @default 3000
|
|
258
260
|
*/
|
|
259
261
|
unsubscribeDelay?: number;
|
|
260
|
-
/** Optional payload transformer (always composed with built-in Date support). */
|
|
261
|
-
transformer?: DataTransformerOptions;
|
|
262
262
|
}
|
|
263
263
|
/**
|
|
264
264
|
* Bridges TanStack Query with Convex real-time subscriptions.
|
|
@@ -466,8 +466,8 @@ type UnsetMarker = {
|
|
|
466
466
|
//#region src/server/http-types.d.ts
|
|
467
467
|
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
468
468
|
interface HttpRouteDefinition<TMethod extends HttpMethod = HttpMethod> {
|
|
469
|
-
path: string;
|
|
470
469
|
method: TMethod;
|
|
470
|
+
path: string;
|
|
471
471
|
pathParamNames: string[];
|
|
472
472
|
usePathPrefix: boolean;
|
|
473
473
|
}
|
|
@@ -497,11 +497,11 @@ interface HttpRouterRecord {
|
|
|
497
497
|
* Router definition - stores both flat procedures and hierarchical record
|
|
498
498
|
*/
|
|
499
499
|
interface HttpRouterDef<TRecord extends HttpRouterRecord> {
|
|
500
|
-
router: true;
|
|
501
500
|
/** Flat map with dot-notation keys (e.g., "todos.get") for lookup */
|
|
502
501
|
procedures: Record<string, HttpProcedure>;
|
|
503
502
|
/** Hierarchical structure for type inference */
|
|
504
503
|
record: TRecord;
|
|
504
|
+
router: true;
|
|
505
505
|
}
|
|
506
506
|
/**
|
|
507
507
|
* HTTP Router - like tRPC's BuiltRouter
|
|
@@ -541,6 +541,7 @@ type FnMeta$1 = {
|
|
|
541
541
|
rateLimit?: string;
|
|
542
542
|
type?: 'query' | 'mutation' | 'action';
|
|
543
543
|
limit?: number;
|
|
544
|
+
[key: string]: unknown;
|
|
544
545
|
};
|
|
545
546
|
/** Metadata for paginated functions (limit is required) */
|
|
546
547
|
type PaginatedFnMeta = Omit<FnMeta$1, 'limit'> & {
|
|
@@ -708,7 +709,7 @@ type VanillaAction<T extends FunctionReference<'action'>> = {
|
|
|
708
709
|
* await client.user.update.mutate({ id, name: 'test' });
|
|
709
710
|
* ```
|
|
710
711
|
*/
|
|
711
|
-
type VanillaCRPCClient<TApi> = { [K in keyof TApi]: TApi[K] extends FunctionReference<'query'> ? VanillaQuery<TApi[K]> : TApi[K] extends FunctionReference<'mutation'> ? VanillaMutation<TApi[K]> : TApi[K] extends FunctionReference<'action'> ? VanillaAction<TApi[K]> : TApi[K] extends Record<string, unknown> ? VanillaCRPCClient<TApi[K]> : never };
|
|
712
|
+
type VanillaCRPCClient<TApi> = { [K in keyof TApi as K extends string ? K extends `_${string}` ? never : K : K]: TApi[K] extends FunctionReference<'query'> ? VanillaQuery<TApi[K]> : TApi[K] extends FunctionReference<'mutation'> ? VanillaMutation<TApi[K]> : TApi[K] extends FunctionReference<'action'> ? VanillaAction<TApi[K]> : TApi[K] extends Record<string, unknown> ? VanillaCRPCClient<TApi[K]> : never };
|
|
712
713
|
/**
|
|
713
714
|
* Recursively decorates all procedures in a Convex API object.
|
|
714
715
|
*
|
|
@@ -728,7 +729,7 @@ type VanillaCRPCClient<TApi> = { [K in keyof TApi]: TApi[K] extends FunctionRefe
|
|
|
728
729
|
*/
|
|
729
730
|
/** Check if a type has cursor key (pagination detection) */
|
|
730
731
|
type IsPaginated<T> = 'cursor' extends keyof T ? true : false;
|
|
731
|
-
type CRPCClient<TApi> = { [K in keyof TApi]: 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 };
|
|
732
|
+
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 };
|
|
732
733
|
//#endregion
|
|
733
734
|
//#region src/react/http-proxy.d.ts
|
|
734
735
|
type HttpRouteInfo = {
|
|
@@ -865,8 +866,8 @@ type HttpCRPCClientFromRouter<TRouter extends CRPCHttpRouter<any>> = HttpCRPCCli
|
|
|
865
866
|
interface HttpProxyOptions<TRoutes extends HttpRouteMap> {
|
|
866
867
|
/** Base URL for the Convex HTTP API (e.g., https://your-site.convex.site) */
|
|
867
868
|
convexSiteUrl: string;
|
|
868
|
-
/**
|
|
869
|
-
|
|
869
|
+
/** Custom fetch function (defaults to global fetch) */
|
|
870
|
+
fetch?: typeof fetch;
|
|
870
871
|
/** Default headers or async function returning headers (for auth tokens) */
|
|
871
872
|
headers?: {
|
|
872
873
|
[key: string]: string | undefined;
|
|
@@ -875,10 +876,10 @@ interface HttpProxyOptions<TRoutes extends HttpRouteMap> {
|
|
|
875
876
|
} | Promise<{
|
|
876
877
|
[key: string]: string | undefined;
|
|
877
878
|
}>);
|
|
878
|
-
/** Custom fetch function (defaults to global fetch) */
|
|
879
|
-
fetch?: typeof fetch;
|
|
880
879
|
/** Error handler called on HTTP errors */
|
|
881
880
|
onError?: (error: HttpClientError) => void;
|
|
881
|
+
/** Runtime route definitions (from codegen httpRoutes) */
|
|
882
|
+
routes: TRoutes;
|
|
882
883
|
/** Optional payload transformer (always composed with built-in Date support). */
|
|
883
884
|
transformer?: DataTransformerOptions;
|
|
884
885
|
}
|
|
@@ -930,8 +931,7 @@ type CRPCHttpOptions = {
|
|
|
930
931
|
onError?: (error: HttpClientError) => void;
|
|
931
932
|
};
|
|
932
933
|
type CreateCRPCContextOptions<TApi> = {
|
|
933
|
-
api: TApi;
|
|
934
|
-
meta: Meta; /** Optional payload transformer (always composed with built-in Date support). */
|
|
934
|
+
api: TApi; /** Optional payload transformer (always composed with built-in Date support). */
|
|
935
935
|
transformer?: DataTransformerOptions;
|
|
936
936
|
} & Partial<CRPCHttpOptions>;
|
|
937
937
|
/**
|
|
@@ -944,23 +944,18 @@ type ExtractHttpRouter<TApi> = TApi extends {
|
|
|
944
944
|
/**
|
|
945
945
|
* Create CRPC context, provider, and hooks for a Convex API.
|
|
946
946
|
*
|
|
947
|
-
* @param options - Configuration object containing api
|
|
947
|
+
* @param options - Configuration object containing api and optional HTTP settings
|
|
948
948
|
* @returns Object with CRPCProvider, useCRPC, and useCRPCClient
|
|
949
949
|
*
|
|
950
950
|
* @example
|
|
951
951
|
* ```tsx
|
|
952
952
|
* // lib/crpc.ts
|
|
953
953
|
* import { api } from '@convex/api';
|
|
954
|
-
* import { meta } from '@convex/meta';
|
|
955
954
|
* import { createCRPCContext } from 'better-convex/react';
|
|
956
955
|
*
|
|
957
|
-
* //
|
|
958
|
-
* export const { useCRPC } = createCRPCContext({
|
|
959
|
-
*
|
|
960
|
-
* // With HTTP endpoints (Api = Api & { http?: typeof appRouter })
|
|
961
|
-
* export const { useCRPC } = createCRPCContext<Api>({
|
|
956
|
+
* // Works for both regular Convex functions and generated HTTP router types
|
|
957
|
+
* export const { useCRPC } = createCRPCContext({
|
|
962
958
|
* api,
|
|
963
|
-
* meta,
|
|
964
959
|
* convexSiteUrl: process.env.NEXT_PUBLIC_CONVEX_SITE_URL!,
|
|
965
960
|
* });
|
|
966
961
|
*
|
|
@@ -1000,7 +995,7 @@ type FnMeta = {
|
|
|
1000
995
|
};
|
|
1001
996
|
/** Metadata for all functions in a module */
|
|
1002
997
|
type ModuleMeta = Record<string, FnMeta>;
|
|
1003
|
-
/** Metadata for all modules - from generated `@convex/
|
|
998
|
+
/** Metadata for all modules - from generated `@convex/api` */
|
|
1004
999
|
type CallerMeta = Record<string, ModuleMeta>;
|
|
1005
1000
|
//#endregion
|
|
1006
1001
|
//#region src/react/proxy.d.ts
|
|
@@ -1017,9 +1012,10 @@ type CallerMeta = Record<string, ModuleMeta>;
|
|
|
1017
1012
|
* @example
|
|
1018
1013
|
* ```tsx
|
|
1019
1014
|
* import { api } from '@convex/api';
|
|
1020
|
-
* import { meta } from '@convex/meta';
|
|
1021
1015
|
*
|
|
1022
|
-
*
|
|
1016
|
+
* // Usually you should use createCRPCContext({ api }) instead.
|
|
1017
|
+
* // createCRPCOptionsProxy is a low-level helper.
|
|
1018
|
+
* const crpc = createCRPCOptionsProxy(api, {} as any);
|
|
1023
1019
|
*
|
|
1024
1020
|
* function MyComponent() {
|
|
1025
1021
|
* const { data } = useQuery(crpc.user.get.queryOptions({ id }));
|
package/dist/react/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import { S as isCRPCClientError, _ as useIsAuth, a as FetchAccessTokenContext, b as CRPCClientError, c as Unauthenticated, d as useAuthGuard, f as useAuthState, g as useFetchAccessToken, h as useConvexAuthBridge, i as ConvexProviderWithAuth, l as decodeJwtExp, m as useAuthValue, n as Authenticated, o as MaybeAuthenticated, p as useAuthStore, r as ConvexAuthBridge, s as MaybeUnauthenticated, t as AuthProvider, u as useAuth, v as useMaybeAuth, y as useSafeConvexAuth } from "../auth-store-DHapqI5u.js";
|
|
2
|
+
import { S as isCRPCClientError, _ as useIsAuth, a as FetchAccessTokenContext, b as CRPCClientError, c as Unauthenticated, d as useAuthGuard, f as useAuthState, g as useFetchAccessToken, h as useConvexAuthBridge, i as ConvexProviderWithAuth, l as decodeJwtExp, m as useAuthValue, n as Authenticated, o as MaybeAuthenticated, p as useAuthStore, r as ConvexAuthBridge, s as MaybeUnauthenticated, t as AuthProvider, u as useAuth, v as useMaybeAuth, x as defaultIsUnauthorized, y as useSafeConvexAuth } from "../auth-store-DHapqI5u.js";
|
|
3
3
|
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";
|
|
@@ -9,6 +9,122 @@ import { getFunctionName } from "convex/server";
|
|
|
9
9
|
import { ConvexHttpClient } from "convex/browser";
|
|
10
10
|
import { convexToJson } from "convex/values";
|
|
11
11
|
|
|
12
|
+
//#region src/shared/meta-utils.ts
|
|
13
|
+
const metaCache = /* @__PURE__ */ new WeakMap();
|
|
14
|
+
const nonMetaLeafKeys = new Set(["functionRef", "ref"]);
|
|
15
|
+
function isRecord(value) {
|
|
16
|
+
return typeof value === "object" && value !== null;
|
|
17
|
+
}
|
|
18
|
+
function isFunctionType(value) {
|
|
19
|
+
return value === "query" || value === "mutation" || value === "action";
|
|
20
|
+
}
|
|
21
|
+
function isMetaScalar(value) {
|
|
22
|
+
return typeof value === "string" || typeof value === "number" || typeof value === "boolean";
|
|
23
|
+
}
|
|
24
|
+
function extractLeafMeta(value) {
|
|
25
|
+
const type = value.type;
|
|
26
|
+
if (!isFunctionType(type)) return;
|
|
27
|
+
const result = { type };
|
|
28
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
29
|
+
if (key === "type" || nonMetaLeafKeys.has(key) || key.startsWith("_")) continue;
|
|
30
|
+
if (entry === void 0) continue;
|
|
31
|
+
if (isMetaScalar(entry)) result[key] = entry;
|
|
32
|
+
}
|
|
33
|
+
return result;
|
|
34
|
+
}
|
|
35
|
+
function getHttpRoutes(api) {
|
|
36
|
+
const routes = api._http;
|
|
37
|
+
if (!isRecord(routes)) return;
|
|
38
|
+
const normalized = {};
|
|
39
|
+
for (const [routeKey, routeValue] of Object.entries(routes)) {
|
|
40
|
+
if (!isRecord(routeValue)) continue;
|
|
41
|
+
const routePath = routeValue.path;
|
|
42
|
+
const routeMethod = routeValue.method;
|
|
43
|
+
if (typeof routePath === "string" && typeof routeMethod === "string") normalized[routeKey] = {
|
|
44
|
+
path: routePath,
|
|
45
|
+
method: routeMethod
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
return normalized;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Build a metadata index from merged API leaves.
|
|
52
|
+
* Supports both generated `api` objects and plain metadata fixtures.
|
|
53
|
+
*/
|
|
54
|
+
function buildMetaIndex(api) {
|
|
55
|
+
const cached = metaCache.get(api);
|
|
56
|
+
if (cached) return cached;
|
|
57
|
+
const meta = {};
|
|
58
|
+
const httpRoutes = getHttpRoutes(api);
|
|
59
|
+
if (httpRoutes) meta._http = httpRoutes;
|
|
60
|
+
const walk = (node, path) => {
|
|
61
|
+
for (const [key, value] of Object.entries(node)) {
|
|
62
|
+
if (key.startsWith("_")) continue;
|
|
63
|
+
if (!isRecord(value)) continue;
|
|
64
|
+
const leafMeta = extractLeafMeta(value);
|
|
65
|
+
if (leafMeta) {
|
|
66
|
+
if (path.length === 0) continue;
|
|
67
|
+
const namespace = path.join("/");
|
|
68
|
+
meta[namespace] ??= {};
|
|
69
|
+
meta[namespace][key] = leafMeta;
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
walk(value, [...path, key]);
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
walk(api, []);
|
|
76
|
+
metaCache.set(api, meta);
|
|
77
|
+
return meta;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Get a function reference from the API object by traversing the path.
|
|
81
|
+
*/
|
|
82
|
+
function getFuncRef(api, path) {
|
|
83
|
+
let current = api;
|
|
84
|
+
for (const key of path) if (current && typeof current === "object") {
|
|
85
|
+
const next = current[key];
|
|
86
|
+
if (next === void 0) throw new Error(`Invalid path: ${path.join(".")}`);
|
|
87
|
+
current = next;
|
|
88
|
+
} else throw new Error(`Invalid path: ${path.join(".")}`);
|
|
89
|
+
if (current && typeof current === "object") {
|
|
90
|
+
const maybeFunctionRef = current.functionRef;
|
|
91
|
+
if (maybeFunctionRef && typeof maybeFunctionRef === "object") return maybeFunctionRef;
|
|
92
|
+
}
|
|
93
|
+
if (!current || typeof current !== "object") throw new Error(`Invalid function reference at path: ${path.join(".")}`);
|
|
94
|
+
return current;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Get function type from meta using path.
|
|
98
|
+
* Supports nested paths like ['items', 'queries', 'list'] → namespace='items/queries', fn='list'
|
|
99
|
+
*
|
|
100
|
+
* @param path - Path segments like ['todos', 'create'] or ['items', 'queries', 'list']
|
|
101
|
+
* @param meta - The meta object from codegen
|
|
102
|
+
* @returns Function type or 'query' as default
|
|
103
|
+
*/
|
|
104
|
+
function getFunctionType(path, source) {
|
|
105
|
+
if (path.length < 2) return "query";
|
|
106
|
+
const meta = buildMetaIndex(source);
|
|
107
|
+
const fnName = path.at(-1);
|
|
108
|
+
const fnType = meta[path.slice(0, -1).join("/")]?.[fnName]?.type;
|
|
109
|
+
if (fnType === "query" || fnType === "mutation" || fnType === "action") return fnType;
|
|
110
|
+
return "query";
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Get function metadata from meta using path.
|
|
114
|
+
* Supports nested paths like ['items', 'queries', 'list'] → namespace='items/queries', fn='list'
|
|
115
|
+
*
|
|
116
|
+
* @param path - Path segments like ['todos', 'create'] or ['items', 'queries', 'list']
|
|
117
|
+
* @param meta - The meta object from codegen
|
|
118
|
+
* @returns Function metadata or undefined
|
|
119
|
+
*/
|
|
120
|
+
function getFunctionMeta(path, source) {
|
|
121
|
+
if (path.length < 2) return;
|
|
122
|
+
const meta = buildMetaIndex(source);
|
|
123
|
+
const fnName = path.at(-1);
|
|
124
|
+
return meta[path.slice(0, -1).join("/")]?.[fnName];
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
//#endregion
|
|
12
128
|
//#region src/crpc/http-types.ts
|
|
13
129
|
/** HTTP client error */
|
|
14
130
|
var HttpClientError = class extends Error {
|
|
@@ -578,46 +694,6 @@ function convexInfiniteQueryOptions(funcRef, args, opts = {}, meta) {
|
|
|
578
694
|
/** Symbol key for attaching FunctionReference to options (non-serializable) */
|
|
579
695
|
const FUNC_REF_SYMBOL = Symbol.for("convex.funcRef");
|
|
580
696
|
|
|
581
|
-
//#endregion
|
|
582
|
-
//#region src/shared/meta-utils.ts
|
|
583
|
-
/**
|
|
584
|
-
* Get a function reference from the API object by traversing the path.
|
|
585
|
-
*/
|
|
586
|
-
function getFuncRef(api, path) {
|
|
587
|
-
let current = api;
|
|
588
|
-
for (const key of path) if (current && typeof current === "object") current = current[key];
|
|
589
|
-
else throw new Error(`Invalid path: ${path.join(".")}`);
|
|
590
|
-
return current;
|
|
591
|
-
}
|
|
592
|
-
/**
|
|
593
|
-
* Get function type from meta using path.
|
|
594
|
-
* Supports nested paths like ['items', 'queries', 'list'] → namespace='items/queries', fn='list'
|
|
595
|
-
*
|
|
596
|
-
* @param path - Path segments like ['todos', 'create'] or ['items', 'queries', 'list']
|
|
597
|
-
* @param meta - The meta object from codegen
|
|
598
|
-
* @returns Function type or 'query' as default
|
|
599
|
-
*/
|
|
600
|
-
function getFunctionType(path, meta) {
|
|
601
|
-
if (path.length < 2) return "query";
|
|
602
|
-
const fnName = path.at(-1);
|
|
603
|
-
const fnType = meta[path.slice(0, -1).join("/")]?.[fnName]?.type;
|
|
604
|
-
if (fnType === "query" || fnType === "mutation" || fnType === "action") return fnType;
|
|
605
|
-
return "query";
|
|
606
|
-
}
|
|
607
|
-
/**
|
|
608
|
-
* Get function metadata from meta using path.
|
|
609
|
-
* Supports nested paths like ['items', 'queries', 'list'] → namespace='items/queries', fn='list'
|
|
610
|
-
*
|
|
611
|
-
* @param path - Path segments like ['todos', 'create'] or ['items', 'queries', 'list']
|
|
612
|
-
* @param meta - The meta object from codegen
|
|
613
|
-
* @returns Function metadata or undefined
|
|
614
|
-
*/
|
|
615
|
-
function getFunctionMeta(path, meta) {
|
|
616
|
-
if (path.length < 2) return;
|
|
617
|
-
const fnName = path.at(-1);
|
|
618
|
-
return meta[path.slice(0, -1).join("/")]?.[fnName];
|
|
619
|
-
}
|
|
620
|
-
|
|
621
697
|
//#endregion
|
|
622
698
|
//#region src/internal/auth.ts
|
|
623
699
|
/** Get auth type from meta for a function */
|
|
@@ -1221,9 +1297,10 @@ function createRecursiveProxy(api, path, meta, transformer) {
|
|
|
1221
1297
|
* @example
|
|
1222
1298
|
* ```tsx
|
|
1223
1299
|
* import { api } from '@convex/api';
|
|
1224
|
-
* import { meta } from '@convex/meta';
|
|
1225
1300
|
*
|
|
1226
|
-
*
|
|
1301
|
+
* // Usually you should use createCRPCContext({ api }) instead.
|
|
1302
|
+
* // createCRPCOptionsProxy is a low-level helper.
|
|
1303
|
+
* const crpc = createCRPCOptionsProxy(api, {} as any);
|
|
1227
1304
|
*
|
|
1228
1305
|
* function MyComponent() {
|
|
1229
1306
|
* const { data } = useQuery(crpc.user.get.queryOptions({ id }));
|
|
@@ -1325,23 +1402,18 @@ function useFnMeta() {
|
|
|
1325
1402
|
/**
|
|
1326
1403
|
* Create CRPC context, provider, and hooks for a Convex API.
|
|
1327
1404
|
*
|
|
1328
|
-
* @param options - Configuration object containing api
|
|
1405
|
+
* @param options - Configuration object containing api and optional HTTP settings
|
|
1329
1406
|
* @returns Object with CRPCProvider, useCRPC, and useCRPCClient
|
|
1330
1407
|
*
|
|
1331
1408
|
* @example
|
|
1332
1409
|
* ```tsx
|
|
1333
1410
|
* // lib/crpc.ts
|
|
1334
1411
|
* import { api } from '@convex/api';
|
|
1335
|
-
* import { meta } from '@convex/meta';
|
|
1336
1412
|
* import { createCRPCContext } from 'better-convex/react';
|
|
1337
1413
|
*
|
|
1338
|
-
* //
|
|
1339
|
-
* export const { useCRPC } = createCRPCContext({
|
|
1340
|
-
*
|
|
1341
|
-
* // With HTTP endpoints (Api = Api & { http?: typeof appRouter })
|
|
1342
|
-
* export const { useCRPC } = createCRPCContext<Api>({
|
|
1414
|
+
* // Works for both regular Convex functions and generated HTTP router types
|
|
1415
|
+
* export const { useCRPC } = createCRPCContext({
|
|
1343
1416
|
* api,
|
|
1344
|
-
* meta,
|
|
1345
1417
|
* convexSiteUrl: process.env.NEXT_PUBLIC_CONVEX_SITE_URL!,
|
|
1346
1418
|
* });
|
|
1347
1419
|
*
|
|
@@ -1356,7 +1428,8 @@ function useFnMeta() {
|
|
|
1356
1428
|
* ```
|
|
1357
1429
|
*/
|
|
1358
1430
|
function createCRPCContext(options) {
|
|
1359
|
-
const { api,
|
|
1431
|
+
const { api, ...httpOptions } = options;
|
|
1432
|
+
const meta = buildMetaIndex(api);
|
|
1360
1433
|
const CRPCProxyContext = createContext(null);
|
|
1361
1434
|
const VanillaClientContext = createContext(null);
|
|
1362
1435
|
const HttpProxyContext = createContext(void 0);
|
|
@@ -2171,9 +2244,11 @@ var ConvexQueryClient = class {
|
|
|
2171
2244
|
if (isConvexQuery(queryKey)) {
|
|
2172
2245
|
const [, funcName, args] = queryKey;
|
|
2173
2246
|
const wireArgs = this.transformer.input.serialize(args);
|
|
2247
|
+
const skipUnauth = meta?.skipUnauth ?? false;
|
|
2174
2248
|
if (meta?.authType === "required" && !isServer && this.authStore) {
|
|
2175
2249
|
const authState = this.getAuthState();
|
|
2176
2250
|
if (authState && !authState.isLoading && !authState.isAuthenticated) {
|
|
2251
|
+
if (skipUnauth) return null;
|
|
2177
2252
|
authState.onUnauthorized({ queryName: funcName });
|
|
2178
2253
|
throw new CRPCClientError({
|
|
2179
2254
|
code: "UNAUTHORIZED",
|
|
@@ -2181,18 +2256,25 @@ var ConvexQueryClient = class {
|
|
|
2181
2256
|
});
|
|
2182
2257
|
}
|
|
2183
2258
|
}
|
|
2184
|
-
|
|
2185
|
-
if (
|
|
2186
|
-
|
|
2259
|
+
try {
|
|
2260
|
+
if (isServer) {
|
|
2261
|
+
if (this.ssrQueryMode === "consistent") return this.transformer.output.deserialize(await this.serverHttpClient.consistentQuery(funcName, wireArgs));
|
|
2262
|
+
return this.transformer.output.deserialize(await this.serverHttpClient.query(funcName, wireArgs));
|
|
2263
|
+
}
|
|
2264
|
+
return this.transformer.output.deserialize(await this.convexClient.query(funcName, wireArgs));
|
|
2265
|
+
} catch (error) {
|
|
2266
|
+
if (skipUnauth && defaultIsUnauthorized(error)) return null;
|
|
2267
|
+
throw error;
|
|
2187
2268
|
}
|
|
2188
|
-
return this.transformer.output.deserialize(await this.convexClient.query(funcName, wireArgs));
|
|
2189
2269
|
}
|
|
2190
2270
|
if (isConvexAction(queryKey)) {
|
|
2191
2271
|
const [, funcName, args] = queryKey;
|
|
2192
2272
|
const wireArgs = this.transformer.input.serialize(args);
|
|
2273
|
+
const skipUnauth = meta?.skipUnauth ?? false;
|
|
2193
2274
|
if (meta?.authType === "required" && !isServer && this.authStore) {
|
|
2194
2275
|
const authState = this.getAuthState();
|
|
2195
2276
|
if (authState && !authState.isLoading && !authState.isAuthenticated) {
|
|
2277
|
+
if (skipUnauth) return null;
|
|
2196
2278
|
authState.onUnauthorized({ queryName: funcName });
|
|
2197
2279
|
throw new CRPCClientError({
|
|
2198
2280
|
code: "UNAUTHORIZED",
|
|
@@ -2200,8 +2282,13 @@ var ConvexQueryClient = class {
|
|
|
2200
2282
|
});
|
|
2201
2283
|
}
|
|
2202
2284
|
}
|
|
2203
|
-
|
|
2204
|
-
|
|
2285
|
+
try {
|
|
2286
|
+
if (isServer) return this.transformer.output.deserialize(await this.serverHttpClient.action(funcName, wireArgs));
|
|
2287
|
+
return this.transformer.output.deserialize(await this.convexClient.action(funcName, wireArgs));
|
|
2288
|
+
} catch (error) {
|
|
2289
|
+
if (skipUnauth && defaultIsUnauthorized(error)) return null;
|
|
2290
|
+
throw error;
|
|
2291
|
+
}
|
|
2205
2292
|
}
|
|
2206
2293
|
return otherFetch(context);
|
|
2207
2294
|
};
|
package/dist/rsc/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { o as Simplify, r as DistributiveOmit } from "../types-DwGkkq2s.js";
|
|
2
|
+
import { C as HttpProcedure, G as DataTransformerOptions, V as UnsetMarker, d as CRPCHttpRouter, p as HttpRouterRecord } from "../http-types-BCf2wCgp.js";
|
|
3
|
+
import { n as CRPCClient } from "../types-CIBGEYXq.js";
|
|
4
4
|
import { DefaultError, QueryFilters, UseMutationOptions, UseQueryOptions } from "@tanstack/react-query";
|
|
5
5
|
import { z } from "zod";
|
|
6
6
|
|
|
@@ -110,7 +110,6 @@ type HttpCRPCClientFromRouter<TRouter extends CRPCHttpRouter<any>> = HttpCRPCCli
|
|
|
110
110
|
//#region src/rsc/proxy-server.d.ts
|
|
111
111
|
type CreateServerCRPCProxyOptions<TApi> = {
|
|
112
112
|
api: TApi;
|
|
113
|
-
meta: Meta;
|
|
114
113
|
};
|
|
115
114
|
/**
|
|
116
115
|
* Extract HTTP router from TApi['http'] if present (optional).
|
|
@@ -137,11 +136,9 @@ type ServerCRPCClient<TApi extends Record<string, unknown>> = ExtractHttpRouter<
|
|
|
137
136
|
* ```tsx
|
|
138
137
|
* // src/lib/convex/rsc.tsx
|
|
139
138
|
* import { api } from '@convex/api';
|
|
140
|
-
* import { meta } from '@convex/meta';
|
|
141
|
-
* import type { Api } from '@convex/types';
|
|
142
139
|
*
|
|
143
140
|
* // Proxy just builds query options - no auth config here
|
|
144
|
-
* export const crpc = createServerCRPCProxy
|
|
141
|
+
* export const crpc = createServerCRPCProxy({ api });
|
|
145
142
|
*
|
|
146
143
|
* // Auth + execution config in QueryClient
|
|
147
144
|
* const queryClient = new QueryClient({
|
package/dist/rsc/index.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { n as getFunctionMeta, t as
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { n as defaultIsUnauthorized } from "../error-Be4OcwwD.js";
|
|
2
|
+
import { n as getFuncRef, r as getFunctionMeta, t as buildMetaIndex } from "../meta-utils-DDVYp9Xf.js";
|
|
3
|
+
import { i as decodeWire, s as getTransformer } from "../transformer-Dh0w2py0.js";
|
|
4
|
+
import { n as convexInfiniteQueryOptions, r as convexQuery } from "../query-options-B0c1b6pZ.js";
|
|
5
5
|
import { convexToJson } from "convex/values";
|
|
6
|
+
import { getFunctionName } from "convex/server";
|
|
6
7
|
import { fetchAction, fetchQuery } from "convex/nextjs";
|
|
7
8
|
import { hashKey } from "@tanstack/react-query";
|
|
8
9
|
|
|
@@ -105,11 +106,9 @@ function createRecursiveProxy(api, path, meta) {
|
|
|
105
106
|
* ```tsx
|
|
106
107
|
* // src/lib/convex/rsc.tsx
|
|
107
108
|
* import { api } from '@convex/api';
|
|
108
|
-
* import { meta } from '@convex/meta';
|
|
109
|
-
* import type { Api } from '@convex/types';
|
|
110
109
|
*
|
|
111
110
|
* // Proxy just builds query options - no auth config here
|
|
112
|
-
* export const crpc = createServerCRPCProxy
|
|
111
|
+
* export const crpc = createServerCRPCProxy({ api });
|
|
113
112
|
*
|
|
114
113
|
* // Auth + execution config in QueryClient
|
|
115
114
|
* const queryClient = new QueryClient({
|
|
@@ -125,8 +124,8 @@ function createRecursiveProxy(api, path, meta) {
|
|
|
125
124
|
* ```
|
|
126
125
|
*/
|
|
127
126
|
function createServerCRPCProxy(options) {
|
|
128
|
-
const { api
|
|
129
|
-
return createRecursiveProxy(api, [],
|
|
127
|
+
const { api } = options;
|
|
128
|
+
return createRecursiveProxy(api, [], buildMetaIndex(api));
|
|
130
129
|
}
|
|
131
130
|
|
|
132
131
|
//#endregion
|
|
@@ -219,7 +218,12 @@ function getServerQueryClientOptions({ getToken, convexSiteUrl, transformer: tra
|
|
|
219
218
|
const authRequired = queryMeta?.authType === "required";
|
|
220
219
|
if (!token && (skipUnauth || authRequired)) return null;
|
|
221
220
|
const opts = token ? { token } : void 0;
|
|
222
|
-
|
|
221
|
+
try {
|
|
222
|
+
return transformer.output.deserialize(type === "convexQuery" ? await fetchQuery(funcRef, wireArgs, opts) : await fetchAction(funcRef, wireArgs, opts));
|
|
223
|
+
} catch (error) {
|
|
224
|
+
if ((skipUnauth || authRequired) && defaultIsUnauthorized(error)) return null;
|
|
225
|
+
throw error;
|
|
226
|
+
}
|
|
223
227
|
},
|
|
224
228
|
queryKeyHashFn: createHashFn()
|
|
225
229
|
} };
|