kitcn 0.15.2 → 0.15.5
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 +1 -1
- package/dist/auth/client/index.d.ts +8 -2
- package/dist/auth/client/index.js +4 -2
- package/dist/auth/generated/index.d.ts +1 -1
- package/dist/auth/index.d.ts +1 -1
- package/dist/auth/start/index.d.ts +1 -15
- package/dist/auth/start/index.js +1 -124
- package/dist/auth/start/server/index.d.ts +17 -0
- package/dist/auth/start/server/index.js +126 -0
- package/dist/auth-store-B_ARzzEX.d.ts +156 -0
- package/dist/{backend-core-BYs_6mO4.mjs → backend-core-PsWKI66u.mjs} +46 -77
- package/dist/cli.mjs +1 -1
- package/dist/crpc/index.d.ts +1 -1
- package/dist/orm/index.d.ts +1 -1
- package/dist/plugins/index.d.ts +1 -1
- package/dist/ratelimit/index.d.ts +1 -1
- package/dist/react/index.d.ts +2 -152
- package/dist/react/index.js +4 -3
- package/dist/rsc/index.d.ts +1 -1
- package/dist/solid/index.js +1 -1
- package/dist/watcher.mjs +1 -1
- package/dist/{where-clause-compiler-DLiYI2EF.d.ts → where-clause-compiler-DcEhkJ12.d.ts} +8 -8
- package/package.json +7 -1
- package/skills/kitcn/references/features/auth.md +1 -0
- package/skills/kitcn/references/features/react.md +11 -16
- package/skills/kitcn/references/setup/index.md +1 -1
- package/skills/kitcn/references/setup/react.md +12 -21
- package/skills/kitcn/references/setup/start.md +1 -1
- /package/dist/{generated-contract-disabled-C_-KWRfT.d.ts → generated-contract-disabled-0xEF3NtW.d.ts} +0 -0
- /package/dist/{middleware-DrtexzF3.d.ts → middleware-Br5zubu7.d.ts} +0 -0
- /package/dist/{types-YHpe0rsb.d.ts → types-jNTcza_a.d.ts} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as ConvexNumberBuilderInitial, E as ConvexIdBuilderInitial, N as ConvexCustomBuilderInitial, dn as ConvexTableWithColumns, tr as ConvexTextBuilderInitial } from "../where-clause-compiler-
|
|
1
|
+
import { C as ConvexNumberBuilderInitial, E as ConvexIdBuilderInitial, N as ConvexCustomBuilderInitial, dn as ConvexTableWithColumns, tr as ConvexTextBuilderInitial } from "../where-clause-compiler-DcEhkJ12.js";
|
|
2
2
|
import * as convex_values0 from "convex/values";
|
|
3
3
|
import { GenericId, Infer, Value } from "convex/values";
|
|
4
4
|
import { DocumentByName, GenericDataModel, GenericDatabaseReader, GenericDatabaseWriter, TableNamesInDataModel } from "convex/server";
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
'use client';
|
|
2
|
+
import { r as AuthStore } from "../../auth-store-B_ARzzEX.js";
|
|
2
3
|
import { ConvexReactClient } from "convex/react";
|
|
3
4
|
import { ReactNode } from "react";
|
|
4
5
|
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
@@ -314,10 +315,14 @@ type AuthClientWithPlugins<Plugins extends PluginsWithCrossDomain | PluginsWitho
|
|
|
314
315
|
type AuthClient = AuthClientWithPlugins<PluginsWithCrossDomain> | AuthClientWithPlugins<PluginsWithoutCrossDomain>;
|
|
315
316
|
//#endregion
|
|
316
317
|
//#region src/auth-client/convex-auth-provider.d.ts
|
|
318
|
+
type ConvexAuthProviderQueryClient = {
|
|
319
|
+
updateAuthStore: (authStore?: AuthStore) => void;
|
|
320
|
+
};
|
|
317
321
|
type ConvexAuthProviderProps = {
|
|
318
322
|
children: ReactNode; /** Convex client instance */
|
|
319
323
|
client: ConvexReactClient; /** Better Auth client instance */
|
|
320
|
-
authClient: AuthClient; /**
|
|
324
|
+
authClient: AuthClient; /** Shared Convex query client to sync with auth state */
|
|
325
|
+
convexQueryClient?: ConvexAuthProviderQueryClient; /** Initial session token (from SSR) */
|
|
321
326
|
initialToken?: string; /** Callback when mutation called while unauthorized */
|
|
322
327
|
onMutationUnauthorized?: () => void; /** Callback when query called while unauthorized */
|
|
323
328
|
onQueryUnauthorized?: (info: {
|
|
@@ -336,10 +341,11 @@ declare function ConvexAuthProvider({
|
|
|
336
341
|
children,
|
|
337
342
|
client,
|
|
338
343
|
authClient,
|
|
344
|
+
convexQueryClient,
|
|
339
345
|
initialToken,
|
|
340
346
|
onMutationUnauthorized,
|
|
341
347
|
onQueryUnauthorized,
|
|
342
348
|
isUnauthorized
|
|
343
349
|
}: ConvexAuthProviderProps): react_jsx_runtime0.JSX.Element;
|
|
344
350
|
//#endregion
|
|
345
|
-
export { type AuthClient, type AuthClientWithPlugins, ConvexAuthProvider, ConvexAuthProviderProps, type PluginsWithCrossDomain, type PluginsWithoutCrossDomain, convexClient };
|
|
351
|
+
export { type AuthClient, type AuthClientWithPlugins, ConvexAuthProvider, ConvexAuthProviderProps, ConvexAuthProviderQueryClient, type PluginsWithCrossDomain, type PluginsWithoutCrossDomain, convexClient };
|
|
@@ -77,7 +77,7 @@ const clearSessionAtom = (authClient) => {
|
|
|
77
77
|
* Structure: AuthProvider wraps ConvexAuthProviderInner so that
|
|
78
78
|
* useAuthStore() is available when creating fetchAccessToken.
|
|
79
79
|
*/
|
|
80
|
-
function ConvexAuthProvider({ children, client, authClient, initialToken, onMutationUnauthorized, onQueryUnauthorized, isUnauthorized }) {
|
|
80
|
+
function ConvexAuthProvider({ children, client, authClient, convexQueryClient, initialToken, onMutationUnauthorized, onQueryUnauthorized, isUnauthorized }) {
|
|
81
81
|
useOTTHandler(authClient);
|
|
82
82
|
return /* @__PURE__ */ jsx(AuthProvider, {
|
|
83
83
|
initialValues: useMemo(() => ({
|
|
@@ -90,6 +90,7 @@ function ConvexAuthProvider({ children, client, authClient, initialToken, onMuta
|
|
|
90
90
|
children: /* @__PURE__ */ jsx(ConvexAuthProviderInner, {
|
|
91
91
|
authClient,
|
|
92
92
|
client,
|
|
93
|
+
convexQueryClient,
|
|
93
94
|
children
|
|
94
95
|
})
|
|
95
96
|
});
|
|
@@ -98,8 +99,9 @@ function ConvexAuthProvider({ children, client, authClient, initialToken, onMuta
|
|
|
98
99
|
* Inner provider that has access to AuthStore via useAuthStore().
|
|
99
100
|
* Creates fetchAccessToken and passes it through context (no race condition).
|
|
100
101
|
*/
|
|
101
|
-
function ConvexAuthProviderInner({ children, client, authClient }) {
|
|
102
|
+
function ConvexAuthProviderInner({ children, client, authClient, convexQueryClient }) {
|
|
102
103
|
const authStore = useAuthStore();
|
|
104
|
+
convexQueryClient?.updateAuthStore(authStore);
|
|
103
105
|
const { data: session, isPending } = authClient.useSession();
|
|
104
106
|
const sessionRef = useRef(session);
|
|
105
107
|
const isPendingRef = useRef(isPending);
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { S as defineAuth, _ as GenericAuthBeforeResult, b as GenericAuthTriggerHandlers, g as BetterAuthOptionsWithoutDatabase, i as getGeneratedAuthDisabledReason, n as GeneratedAuthDisabledReasonKind, r as createDisabledAuthRuntime, t as AuthRuntime, v as GenericAuthDefinition, x as GenericAuthTriggers, y as GenericAuthTriggerChange } from "../../generated-contract-disabled-
|
|
1
|
+
import { S as defineAuth, _ as GenericAuthBeforeResult, b as GenericAuthTriggerHandlers, g as BetterAuthOptionsWithoutDatabase, i as getGeneratedAuthDisabledReason, n as GeneratedAuthDisabledReasonKind, r as createDisabledAuthRuntime, t as AuthRuntime, v as GenericAuthDefinition, x as GenericAuthTriggers, y as GenericAuthTriggerChange } from "../../generated-contract-disabled-0xEF3NtW.js";
|
|
2
2
|
export { type AuthRuntime, BetterAuthOptionsWithoutDatabase, type GeneratedAuthDisabledReasonKind, GenericAuthBeforeResult, GenericAuthDefinition, GenericAuthTriggerChange, GenericAuthTriggerHandlers, GenericAuthTriggers, createDisabledAuthRuntime, defineAuth, getGeneratedAuthDisabledReason };
|
package/dist/auth/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { a as QueryCtxWithPreferredOrmQueryTable, n as LookupByIdResultByCtx, t as DocByCtx } from "../query-context-CNo9ffvI.js";
|
|
2
2
|
import { t as GetAuth } from "../types-BCl8gfGy.js";
|
|
3
3
|
import { t as GenericCtx } from "../context-utils-OMkMGhBk.js";
|
|
4
|
-
import { S as defineAuth, _ as GenericAuthBeforeResult, a as AuthFunctions, b as GenericAuthTriggerHandlers, c as createApi, d as deleteOneHandler, f as findManyHandler, g as BetterAuthOptionsWithoutDatabase, h as updateOneHandler, i as getGeneratedAuthDisabledReason, l as createHandler, m as updateManyHandler, n as GeneratedAuthDisabledReasonKind, o as Triggers, p as findOneHandler, r as createDisabledAuthRuntime, s as createClient, t as AuthRuntime, u as deleteManyHandler, v as GenericAuthDefinition, x as GenericAuthTriggers, y as GenericAuthTriggerChange } from "../generated-contract-disabled-
|
|
4
|
+
import { S as defineAuth, _ as GenericAuthBeforeResult, a as AuthFunctions, b as GenericAuthTriggerHandlers, c as createApi, d as deleteOneHandler, f as findManyHandler, g as BetterAuthOptionsWithoutDatabase, h as updateOneHandler, i as getGeneratedAuthDisabledReason, l as createHandler, m as updateManyHandler, n as GeneratedAuthDisabledReasonKind, o as Triggers, p as findOneHandler, r as createDisabledAuthRuntime, s as createClient, t as AuthRuntime, u as deleteManyHandler, v as GenericAuthDefinition, x as GenericAuthTriggers, y as GenericAuthTriggerChange } from "../generated-contract-disabled-0xEF3NtW.js";
|
|
5
5
|
import * as convex_values0 from "convex/values";
|
|
6
6
|
import { Infer } from "convex/values";
|
|
7
7
|
import { AuthConfig, DocumentByName, GenericDataModel, GenericMutationCtx, GenericQueryCtx, GenericSchema, PaginationOptions, PaginationResult, SchemaDefinition, TableNamesInDataModel } from "convex/server";
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
import { t as GetTokenOptions } from "../../token-B9Bjcqug.js";
|
|
2
|
-
import { FunctionReference, FunctionReturnType, OptionalRestArgs } from "convex/server";
|
|
3
|
-
|
|
4
1
|
//#region src/auth-start/index.d.ts
|
|
5
2
|
type MaybePromise<T> = Promise<T> | T;
|
|
6
3
|
type StartLoaderAuthClient = {
|
|
@@ -24,20 +21,9 @@ type StartLoaderAuthState = {
|
|
|
24
21
|
isAuthenticated: boolean;
|
|
25
22
|
token: null | string;
|
|
26
23
|
};
|
|
27
|
-
type ConvexBetterAuthReactStartOptions = Omit<GetTokenOptions, 'forceRefresh'> & {
|
|
28
|
-
convexSiteUrl: string;
|
|
29
|
-
convexUrl: string;
|
|
30
|
-
};
|
|
31
24
|
declare const syncConvexAuthForStartLoader: ({
|
|
32
25
|
convex,
|
|
33
26
|
getToken
|
|
34
27
|
}: SyncConvexAuthForStartLoaderOptions) => Promise<StartLoaderAuthState>;
|
|
35
|
-
declare const convexBetterAuthReactStart: (opts: ConvexBetterAuthReactStartOptions) => {
|
|
36
|
-
getToken: () => Promise<string | undefined>;
|
|
37
|
-
handler: (request: Request) => Promise<Response>;
|
|
38
|
-
fetchAuthQuery: <Query extends FunctionReference<"query">>(query: Query, ...args: OptionalRestArgs<Query>) => Promise<FunctionReturnType<Query>>;
|
|
39
|
-
fetchAuthMutation: <Mutation extends FunctionReference<"mutation">>(mutation: Mutation, ...args: OptionalRestArgs<Mutation>) => Promise<FunctionReturnType<Mutation>>;
|
|
40
|
-
fetchAuthAction: <Action extends FunctionReference<"action">>(action: Action, ...args: OptionalRestArgs<Action>) => Promise<FunctionReturnType<Action>>;
|
|
41
|
-
};
|
|
42
28
|
//#endregion
|
|
43
|
-
export { MaybePromise, StartLoaderAuthClient, StartLoaderAuthState, StartLoaderAuthTarget, StartLoaderConvexQueryClient, StartLoaderServerHttpClient, SyncConvexAuthForStartLoaderOptions,
|
|
29
|
+
export { MaybePromise, StartLoaderAuthClient, StartLoaderAuthState, StartLoaderAuthTarget, StartLoaderConvexQueryClient, StartLoaderServerHttpClient, SyncConvexAuthForStartLoaderOptions, syncConvexAuthForStartLoader };
|
package/dist/auth/start/index.js
CHANGED
|
@@ -1,13 +1,4 @@
|
|
|
1
|
-
import { t as getToken } from "../../token-oA2EMtPA.js";
|
|
2
|
-
import { stripIndent } from "common-tags";
|
|
3
|
-
import { ConvexHttpClient } from "convex/browser";
|
|
4
|
-
import React from "react";
|
|
5
|
-
|
|
6
1
|
//#region src/auth-start/index.ts
|
|
7
|
-
const fallbackCache = (fn) => fn;
|
|
8
|
-
const cache = React.cache ?? fallbackCache;
|
|
9
|
-
const TANSTACK_REACT_START_SERVER = "@tanstack/react-start/server";
|
|
10
|
-
const TRAILING_COLON_RE = /:$/;
|
|
11
2
|
const startLoaderAuthTokens = /* @__PURE__ */ new WeakMap();
|
|
12
3
|
const isStartLoaderConvexQueryClient = (target) => "convexClient" in target;
|
|
13
4
|
const syncConvexAuthForStartLoader = async ({ convex, getToken }) => {
|
|
@@ -34,120 +25,6 @@ const syncConvexAuthForStartLoader = async ({ convex, getToken }) => {
|
|
|
34
25
|
token
|
|
35
26
|
};
|
|
36
27
|
};
|
|
37
|
-
function setupClient(options) {
|
|
38
|
-
const client = new ConvexHttpClient(options.convexUrl);
|
|
39
|
-
if (options.token !== void 0) client.setAuth(options.token);
|
|
40
|
-
client.setFetchOptions?.({ cache: "no-store" });
|
|
41
|
-
return client;
|
|
42
|
-
}
|
|
43
|
-
const parseConvexSiteUrl = (url) => {
|
|
44
|
-
if (!url) throw new Error(stripIndent`
|
|
45
|
-
CONVEX_SITE_URL is not set.
|
|
46
|
-
This is automatically set in the Convex backend, but must be set in the TanStack Start environment.
|
|
47
|
-
For local development, this can be set in the .env.local file.
|
|
48
|
-
`);
|
|
49
|
-
if (url.endsWith(".convex.cloud")) throw new Error(stripIndent`
|
|
50
|
-
CONVEX_SITE_URL should be set to your Convex Site URL, which ends in .convex.site.
|
|
51
|
-
Currently set to ${url}.
|
|
52
|
-
`);
|
|
53
|
-
return url;
|
|
54
|
-
};
|
|
55
|
-
const appendSetCookieHeaders = (target, source) => {
|
|
56
|
-
const getSetCookie = source.getSetCookie;
|
|
57
|
-
if (typeof getSetCookie === "function") {
|
|
58
|
-
const values = getSetCookie.call(source);
|
|
59
|
-
for (const value of values) target.append("set-cookie", value);
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
62
|
-
const value = source.get("set-cookie");
|
|
63
|
-
if (value) target.append("set-cookie", value);
|
|
64
|
-
};
|
|
65
|
-
const cloneAuthHandlerResponse = (response) => {
|
|
66
|
-
const headers = new Headers();
|
|
67
|
-
for (const [key, value] of response.headers.entries()) {
|
|
68
|
-
if (key.toLowerCase() === "set-cookie") continue;
|
|
69
|
-
headers.append(key, value);
|
|
70
|
-
}
|
|
71
|
-
appendSetCookieHeaders(headers, response.headers);
|
|
72
|
-
return new Response(response.body, {
|
|
73
|
-
headers,
|
|
74
|
-
status: response.status,
|
|
75
|
-
statusText: response.statusText
|
|
76
|
-
});
|
|
77
|
-
};
|
|
78
|
-
const handler = (request, opts) => {
|
|
79
|
-
const requestUrl = new URL(request.url);
|
|
80
|
-
const nextUrl = `${opts.convexSiteUrl}${requestUrl.pathname}${requestUrl.search}`;
|
|
81
|
-
const headers = new Headers(request.headers);
|
|
82
|
-
const proto = requestUrl.protocol.replace(TRAILING_COLON_RE, "");
|
|
83
|
-
headers.set("accept-encoding", "application/json");
|
|
84
|
-
headers.set("host", new URL(opts.convexSiteUrl).host);
|
|
85
|
-
headers.set("x-forwarded-host", requestUrl.host);
|
|
86
|
-
headers.set("x-forwarded-proto", proto);
|
|
87
|
-
headers.set("x-better-auth-forwarded-host", requestUrl.host);
|
|
88
|
-
headers.set("x-better-auth-forwarded-proto", proto);
|
|
89
|
-
return fetch(nextUrl, {
|
|
90
|
-
body: request.method !== "GET" && request.method !== "HEAD" ? request.body : void 0,
|
|
91
|
-
duplex: "half",
|
|
92
|
-
headers,
|
|
93
|
-
method: request.method,
|
|
94
|
-
redirect: "manual"
|
|
95
|
-
});
|
|
96
|
-
};
|
|
97
|
-
const convexBetterAuthReactStart = (opts) => {
|
|
98
|
-
const siteUrl = parseConvexSiteUrl(opts.convexSiteUrl);
|
|
99
|
-
const cachedGetToken = cache(async (opts) => {
|
|
100
|
-
const { getRequestHeaders } = await import(TANSTACK_REACT_START_SERVER);
|
|
101
|
-
const headers = getRequestHeaders();
|
|
102
|
-
const mutableHeaders = new Headers(headers);
|
|
103
|
-
mutableHeaders.delete("content-length");
|
|
104
|
-
mutableHeaders.delete("transfer-encoding");
|
|
105
|
-
mutableHeaders.set("accept-encoding", "identity");
|
|
106
|
-
return getToken(siteUrl, mutableHeaders, opts);
|
|
107
|
-
});
|
|
108
|
-
const callWithToken = async (fn) => {
|
|
109
|
-
const token = await cachedGetToken(opts) ?? {};
|
|
110
|
-
try {
|
|
111
|
-
return await fn(token?.token);
|
|
112
|
-
} catch (error) {
|
|
113
|
-
if (!opts?.jwtCache?.enabled || token.isFresh || !opts.jwtCache?.isAuthError(error)) throw error;
|
|
114
|
-
return await fn((await cachedGetToken({
|
|
115
|
-
...opts,
|
|
116
|
-
forceRefresh: true
|
|
117
|
-
})).token);
|
|
118
|
-
}
|
|
119
|
-
};
|
|
120
|
-
return {
|
|
121
|
-
getToken: async () => {
|
|
122
|
-
return (await cachedGetToken(opts)).token;
|
|
123
|
-
},
|
|
124
|
-
handler: async (request) => cloneAuthHandlerResponse(await handler(request, opts)),
|
|
125
|
-
fetchAuthQuery: async (query, ...args) => {
|
|
126
|
-
return callWithToken((token) => {
|
|
127
|
-
return setupClient({
|
|
128
|
-
...opts,
|
|
129
|
-
token
|
|
130
|
-
}).query(query, ...args);
|
|
131
|
-
});
|
|
132
|
-
},
|
|
133
|
-
fetchAuthMutation: async (mutation, ...args) => {
|
|
134
|
-
return callWithToken((token) => {
|
|
135
|
-
return setupClient({
|
|
136
|
-
...opts,
|
|
137
|
-
token
|
|
138
|
-
}).mutation(mutation, ...args);
|
|
139
|
-
});
|
|
140
|
-
},
|
|
141
|
-
fetchAuthAction: async (action, ...args) => {
|
|
142
|
-
return callWithToken((token) => {
|
|
143
|
-
return setupClient({
|
|
144
|
-
...opts,
|
|
145
|
-
token
|
|
146
|
-
}).action(action, ...args);
|
|
147
|
-
});
|
|
148
|
-
}
|
|
149
|
-
};
|
|
150
|
-
};
|
|
151
28
|
|
|
152
29
|
//#endregion
|
|
153
|
-
export {
|
|
30
|
+
export { syncConvexAuthForStartLoader };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { t as GetTokenOptions } from "../../../token-B9Bjcqug.js";
|
|
2
|
+
import { FunctionReference, FunctionReturnType, OptionalRestArgs } from "convex/server";
|
|
3
|
+
|
|
4
|
+
//#region src/auth-start/server.d.ts
|
|
5
|
+
type ConvexBetterAuthReactStartOptions = Omit<GetTokenOptions, 'forceRefresh'> & {
|
|
6
|
+
convexSiteUrl: string;
|
|
7
|
+
convexUrl: string;
|
|
8
|
+
};
|
|
9
|
+
declare const convexBetterAuthReactStart: (opts: ConvexBetterAuthReactStartOptions) => {
|
|
10
|
+
getToken: () => Promise<string | undefined>;
|
|
11
|
+
handler: (request: Request) => Promise<Response>;
|
|
12
|
+
fetchAuthQuery: <Query extends FunctionReference<"query">>(query: Query, ...args: OptionalRestArgs<Query>) => Promise<FunctionReturnType<Query>>;
|
|
13
|
+
fetchAuthMutation: <Mutation extends FunctionReference<"mutation">>(mutation: Mutation, ...args: OptionalRestArgs<Mutation>) => Promise<FunctionReturnType<Mutation>>;
|
|
14
|
+
fetchAuthAction: <Action extends FunctionReference<"action">>(action: Action, ...args: OptionalRestArgs<Action>) => Promise<FunctionReturnType<Action>>;
|
|
15
|
+
};
|
|
16
|
+
//#endregion
|
|
17
|
+
export { convexBetterAuthReactStart };
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { t as getToken } from "../../../token-oA2EMtPA.js";
|
|
2
|
+
import { stripIndent } from "common-tags";
|
|
3
|
+
import { getRequestHeaders } from "@tanstack/react-start/server";
|
|
4
|
+
import { ConvexHttpClient } from "convex/browser";
|
|
5
|
+
import React from "react";
|
|
6
|
+
|
|
7
|
+
//#region src/auth-start/server.ts
|
|
8
|
+
const fallbackCache = (fn) => fn;
|
|
9
|
+
const cache = React.cache ?? fallbackCache;
|
|
10
|
+
const TRAILING_COLON_RE = /:$/;
|
|
11
|
+
function setupClient(options) {
|
|
12
|
+
const client = new ConvexHttpClient(options.convexUrl);
|
|
13
|
+
if (options.token !== void 0) client.setAuth(options.token);
|
|
14
|
+
client.setFetchOptions?.({ cache: "no-store" });
|
|
15
|
+
return client;
|
|
16
|
+
}
|
|
17
|
+
const parseConvexSiteUrl = (url) => {
|
|
18
|
+
if (!url) throw new Error(stripIndent`
|
|
19
|
+
CONVEX_SITE_URL is not set.
|
|
20
|
+
This is automatically set in the Convex backend, but must be set in the TanStack Start environment.
|
|
21
|
+
For local development, this can be set in the .env.local file.
|
|
22
|
+
`);
|
|
23
|
+
if (url.endsWith(".convex.cloud")) throw new Error(stripIndent`
|
|
24
|
+
CONVEX_SITE_URL should be set to your Convex Site URL, which ends in .convex.site.
|
|
25
|
+
Currently set to ${url}.
|
|
26
|
+
`);
|
|
27
|
+
return url;
|
|
28
|
+
};
|
|
29
|
+
const appendSetCookieHeaders = (target, source) => {
|
|
30
|
+
const getSetCookie = source.getSetCookie;
|
|
31
|
+
if (typeof getSetCookie === "function") {
|
|
32
|
+
const values = getSetCookie.call(source);
|
|
33
|
+
for (const value of values) target.append("set-cookie", value);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const value = source.get("set-cookie");
|
|
37
|
+
if (value) target.append("set-cookie", value);
|
|
38
|
+
};
|
|
39
|
+
const cloneAuthHandlerResponse = (response) => {
|
|
40
|
+
const headers = new Headers();
|
|
41
|
+
for (const [key, value] of response.headers.entries()) {
|
|
42
|
+
if (key.toLowerCase() === "set-cookie") continue;
|
|
43
|
+
headers.append(key, value);
|
|
44
|
+
}
|
|
45
|
+
appendSetCookieHeaders(headers, response.headers);
|
|
46
|
+
return new Response(response.body, {
|
|
47
|
+
headers,
|
|
48
|
+
status: response.status,
|
|
49
|
+
statusText: response.statusText
|
|
50
|
+
});
|
|
51
|
+
};
|
|
52
|
+
const handler = (request, opts) => {
|
|
53
|
+
const requestUrl = new URL(request.url);
|
|
54
|
+
const nextUrl = `${opts.convexSiteUrl}${requestUrl.pathname}${requestUrl.search}`;
|
|
55
|
+
const headers = new Headers(request.headers);
|
|
56
|
+
const proto = requestUrl.protocol.replace(TRAILING_COLON_RE, "");
|
|
57
|
+
headers.set("accept-encoding", "application/json");
|
|
58
|
+
headers.set("host", new URL(opts.convexSiteUrl).host);
|
|
59
|
+
headers.set("x-forwarded-host", requestUrl.host);
|
|
60
|
+
headers.set("x-forwarded-proto", proto);
|
|
61
|
+
headers.set("x-better-auth-forwarded-host", requestUrl.host);
|
|
62
|
+
headers.set("x-better-auth-forwarded-proto", proto);
|
|
63
|
+
return fetch(nextUrl, {
|
|
64
|
+
body: request.method !== "GET" && request.method !== "HEAD" ? request.body : void 0,
|
|
65
|
+
duplex: "half",
|
|
66
|
+
headers,
|
|
67
|
+
method: request.method,
|
|
68
|
+
redirect: "manual"
|
|
69
|
+
});
|
|
70
|
+
};
|
|
71
|
+
const convexBetterAuthReactStart = (opts) => {
|
|
72
|
+
const siteUrl = parseConvexSiteUrl(opts.convexSiteUrl);
|
|
73
|
+
const cachedGetToken = cache(async (opts) => {
|
|
74
|
+
const headers = getRequestHeaders();
|
|
75
|
+
const mutableHeaders = new Headers(headers);
|
|
76
|
+
mutableHeaders.delete("content-length");
|
|
77
|
+
mutableHeaders.delete("transfer-encoding");
|
|
78
|
+
mutableHeaders.set("accept-encoding", "identity");
|
|
79
|
+
return getToken(siteUrl, mutableHeaders, opts);
|
|
80
|
+
});
|
|
81
|
+
const callWithToken = async (fn) => {
|
|
82
|
+
const token = await cachedGetToken(opts) ?? {};
|
|
83
|
+
try {
|
|
84
|
+
return await fn(token?.token);
|
|
85
|
+
} catch (error) {
|
|
86
|
+
if (!opts?.jwtCache?.enabled || token.isFresh || !opts.jwtCache?.isAuthError(error)) throw error;
|
|
87
|
+
return await fn((await cachedGetToken({
|
|
88
|
+
...opts,
|
|
89
|
+
forceRefresh: true
|
|
90
|
+
})).token);
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
return {
|
|
94
|
+
getToken: async () => {
|
|
95
|
+
return (await cachedGetToken(opts)).token;
|
|
96
|
+
},
|
|
97
|
+
handler: async (request) => cloneAuthHandlerResponse(await handler(request, opts)),
|
|
98
|
+
fetchAuthQuery: async (query, ...args) => {
|
|
99
|
+
return callWithToken((token) => {
|
|
100
|
+
return setupClient({
|
|
101
|
+
...opts,
|
|
102
|
+
token
|
|
103
|
+
}).query(query, ...args);
|
|
104
|
+
});
|
|
105
|
+
},
|
|
106
|
+
fetchAuthMutation: async (mutation, ...args) => {
|
|
107
|
+
return callWithToken((token) => {
|
|
108
|
+
return setupClient({
|
|
109
|
+
...opts,
|
|
110
|
+
token
|
|
111
|
+
}).mutation(mutation, ...args);
|
|
112
|
+
});
|
|
113
|
+
},
|
|
114
|
+
fetchAuthAction: async (action, ...args) => {
|
|
115
|
+
return callWithToken((token) => {
|
|
116
|
+
return setupClient({
|
|
117
|
+
...opts,
|
|
118
|
+
token
|
|
119
|
+
}).action(action, ...args);
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
//#endregion
|
|
126
|
+
export { convexBetterAuthReactStart };
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { ConvexProviderWithAuth } from "convex/react";
|
|
3
|
+
import * as react from "react";
|
|
4
|
+
import * as jotai_x0 from "jotai-x";
|
|
5
|
+
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
6
|
+
import * as jotai_vanilla0 from "jotai/vanilla";
|
|
7
|
+
|
|
8
|
+
//#region src/react/auth-store.d.ts
|
|
9
|
+
type FetchAccessTokenFn = (args: {
|
|
10
|
+
forceRefreshToken: boolean;
|
|
11
|
+
}) => Promise<string | null>;
|
|
12
|
+
declare const FetchAccessTokenContext: react.Context<FetchAccessTokenFn | null>;
|
|
13
|
+
/** Get fetchAccessToken from context (available immediately, no race condition) */
|
|
14
|
+
declare const useFetchAccessToken: () => FetchAccessTokenFn | null;
|
|
15
|
+
type ConvexAuthResult = {
|
|
16
|
+
isAuthenticated: boolean;
|
|
17
|
+
isLoading: boolean;
|
|
18
|
+
};
|
|
19
|
+
/** Get auth from bridge context (null if no bridge configured) */
|
|
20
|
+
declare const useConvexAuthBridge: () => ConvexAuthResult | null;
|
|
21
|
+
type AuthStoreState = {
|
|
22
|
+
/** Callback when mutation/action called while unauthorized. Throws by default. */onMutationUnauthorized: () => void; /** Callback when query called while unauthorized. Noop by default. */
|
|
23
|
+
onQueryUnauthorized: (info: {
|
|
24
|
+
queryName: string;
|
|
25
|
+
}) => void; /** Custom function to detect UNAUTHORIZED errors. Default checks code or "auth" in message. */
|
|
26
|
+
isUnauthorized: (error: unknown) => boolean; /** Cached Convex JWT for HTTP requests */
|
|
27
|
+
token: string | null; /** JWT expiration timestamp (ms) */
|
|
28
|
+
expiresAt: number | null; /** Auth loading state (synced from useConvexAuth for class methods) */
|
|
29
|
+
isLoading: boolean; /** Auth state (synced from useConvexAuth for class methods) */
|
|
30
|
+
isAuthenticated: boolean; /** Grace window for freshly seeded auth tokens while session sync catches up */
|
|
31
|
+
sessionSyncGraceUntil: number | null;
|
|
32
|
+
};
|
|
33
|
+
declare const AUTH_SESSION_SYNC_GRACE_MS = 10000;
|
|
34
|
+
declare const isSessionSyncGraceActive: (sessionSyncGraceUntil: number | null) => boolean;
|
|
35
|
+
/** Decode JWT expiration (ms timestamp) from token */
|
|
36
|
+
declare function decodeJwtExp(token: string): number | null;
|
|
37
|
+
declare const AuthProvider: react.FC<jotai_x0.ProviderProps<{
|
|
38
|
+
onMutationUnauthorized: () => void;
|
|
39
|
+
onQueryUnauthorized: (info: {
|
|
40
|
+
queryName: string;
|
|
41
|
+
}) => void;
|
|
42
|
+
isUnauthorized: (error: unknown) => boolean;
|
|
43
|
+
token: string | null;
|
|
44
|
+
expiresAt: number | null;
|
|
45
|
+
isLoading: boolean;
|
|
46
|
+
isAuthenticated: boolean;
|
|
47
|
+
sessionSyncGraceUntil: number | null;
|
|
48
|
+
}>>, useAuthStore: jotai_x0.UseStoreApi<AuthStoreState, object>, useAuthState: <K extends keyof AuthStoreState>(key: K, options?: string | jotai_x0.UseAtomOptions) => ({
|
|
49
|
+
onMutationUnauthorized: jotai_x0.SimpleWritableAtom<() => void>;
|
|
50
|
+
onQueryUnauthorized: jotai_x0.SimpleWritableAtom<(info: {
|
|
51
|
+
queryName: string;
|
|
52
|
+
}) => void>;
|
|
53
|
+
isUnauthorized: jotai_x0.SimpleWritableAtom<(error: unknown) => boolean>;
|
|
54
|
+
token: jotai_x0.SimpleWritableAtom<string | null>;
|
|
55
|
+
expiresAt: jotai_x0.SimpleWritableAtom<number | null>;
|
|
56
|
+
isLoading: jotai_x0.SimpleWritableAtom<boolean>;
|
|
57
|
+
isAuthenticated: jotai_x0.SimpleWritableAtom<boolean>;
|
|
58
|
+
sessionSyncGraceUntil: jotai_x0.SimpleWritableAtom<number | null>;
|
|
59
|
+
} & object)[K] extends jotai_vanilla0.WritableAtom<infer V, infer A extends unknown[], infer R> ? [V, (...args: A) => R] : never, useAuthValue: <K extends keyof AuthStoreState, S = (({
|
|
60
|
+
onMutationUnauthorized: jotai_x0.SimpleWritableAtom<() => void>;
|
|
61
|
+
onQueryUnauthorized: jotai_x0.SimpleWritableAtom<(info: {
|
|
62
|
+
queryName: string;
|
|
63
|
+
}) => void>;
|
|
64
|
+
isUnauthorized: jotai_x0.SimpleWritableAtom<(error: unknown) => boolean>;
|
|
65
|
+
token: jotai_x0.SimpleWritableAtom<string | null>;
|
|
66
|
+
expiresAt: jotai_x0.SimpleWritableAtom<number | null>;
|
|
67
|
+
isLoading: jotai_x0.SimpleWritableAtom<boolean>;
|
|
68
|
+
isAuthenticated: jotai_x0.SimpleWritableAtom<boolean>;
|
|
69
|
+
sessionSyncGraceUntil: jotai_x0.SimpleWritableAtom<number | null>;
|
|
70
|
+
} & object)[K] extends jotai_vanilla0.Atom<infer V> ? V : never)>(key: K, options?: ({
|
|
71
|
+
selector?: ((v: ({
|
|
72
|
+
onMutationUnauthorized: jotai_x0.SimpleWritableAtom<() => void>;
|
|
73
|
+
onQueryUnauthorized: jotai_x0.SimpleWritableAtom<(info: {
|
|
74
|
+
queryName: string;
|
|
75
|
+
}) => void>;
|
|
76
|
+
isUnauthorized: jotai_x0.SimpleWritableAtom<(error: unknown) => boolean>;
|
|
77
|
+
token: jotai_x0.SimpleWritableAtom<string | null>;
|
|
78
|
+
expiresAt: jotai_x0.SimpleWritableAtom<number | null>;
|
|
79
|
+
isLoading: jotai_x0.SimpleWritableAtom<boolean>;
|
|
80
|
+
isAuthenticated: jotai_x0.SimpleWritableAtom<boolean>;
|
|
81
|
+
sessionSyncGraceUntil: jotai_x0.SimpleWritableAtom<number | null>;
|
|
82
|
+
} & object)[K] extends jotai_vanilla0.Atom<infer V_1> ? V_1 : never, prevSelectorOutput?: S | undefined) => S) | undefined;
|
|
83
|
+
equalityFn?: ((prev: S, next: S) => boolean) | undefined;
|
|
84
|
+
} & jotai_x0.UseAtomOptions) | undefined, deps?: unknown[]) => S;
|
|
85
|
+
type AuthStore = ReturnType<typeof useAuthStore>;
|
|
86
|
+
/**
|
|
87
|
+
* Safe wrapper around useConvexAuth that doesn't throw when used outside auth provider.
|
|
88
|
+
* Returns { isAuthenticated: false, isLoading: false } when no auth provider.
|
|
89
|
+
*
|
|
90
|
+
* Supports both:
|
|
91
|
+
* - better-auth users (via AuthProvider)
|
|
92
|
+
* - @convex-dev/auth users (via ConvexAuthBridge)
|
|
93
|
+
*/
|
|
94
|
+
declare function useSafeConvexAuth(): ConvexAuthResult;
|
|
95
|
+
/**
|
|
96
|
+
* Internal bridge component. Use `ConvexProviderWithAuth` instead.
|
|
97
|
+
* @internal
|
|
98
|
+
*/
|
|
99
|
+
declare function ConvexAuthBridge({
|
|
100
|
+
children
|
|
101
|
+
}: {
|
|
102
|
+
children: React.ReactNode;
|
|
103
|
+
}): react_jsx_runtime0.JSX.Element;
|
|
104
|
+
/**
|
|
105
|
+
* Convex provider with auth bridge for @convex-dev/auth users.
|
|
106
|
+
* Automatically wraps children with ConvexAuthBridge.
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* ```tsx
|
|
110
|
+
* import { ConvexProviderWithAuth } from 'kitcn/react';
|
|
111
|
+
*
|
|
112
|
+
* <ConvexProviderWithAuth client={convex} useAuth={useAuthFromConvexDev}>
|
|
113
|
+
* <App />
|
|
114
|
+
* </ConvexProviderWithAuth>
|
|
115
|
+
* ```
|
|
116
|
+
*/
|
|
117
|
+
declare function ConvexProviderWithAuth$1({
|
|
118
|
+
children,
|
|
119
|
+
...props
|
|
120
|
+
}: React.ComponentProps<typeof ConvexProviderWithAuth>): react_jsx_runtime0.JSX.Element;
|
|
121
|
+
declare const useAuth: () => {
|
|
122
|
+
hasSession: boolean;
|
|
123
|
+
isAuthenticated: boolean;
|
|
124
|
+
isLoading: boolean;
|
|
125
|
+
};
|
|
126
|
+
/** Check if user maybe has auth (optimistic, has token) */
|
|
127
|
+
declare const useMaybeAuth: () => boolean;
|
|
128
|
+
/** Check if user is authenticated (server-verified) */
|
|
129
|
+
declare const useIsAuth: () => boolean;
|
|
130
|
+
declare const useAuthGuard: () => (callback?: () => Promise<void> | void) => boolean | undefined;
|
|
131
|
+
/** Render children only when maybe has auth (optimistic) */
|
|
132
|
+
declare function MaybeAuthenticated({
|
|
133
|
+
children
|
|
134
|
+
}: {
|
|
135
|
+
children: React.ReactNode;
|
|
136
|
+
}): react.ReactNode;
|
|
137
|
+
/** Render children only when authenticated (server-verified) */
|
|
138
|
+
declare function Authenticated({
|
|
139
|
+
children
|
|
140
|
+
}: {
|
|
141
|
+
children: React.ReactNode;
|
|
142
|
+
}): react.ReactNode;
|
|
143
|
+
/** Render children only when maybe not auth (optimistic) */
|
|
144
|
+
declare function MaybeUnauthenticated({
|
|
145
|
+
children
|
|
146
|
+
}: {
|
|
147
|
+
children: React.ReactNode;
|
|
148
|
+
}): react.ReactNode;
|
|
149
|
+
/** Render children only when not authenticated (server-verified) */
|
|
150
|
+
declare function Unauthenticated({
|
|
151
|
+
children
|
|
152
|
+
}: {
|
|
153
|
+
children: React.ReactNode;
|
|
154
|
+
}): react.ReactNode;
|
|
155
|
+
//#endregion
|
|
156
|
+
export { useMaybeAuth as C, useIsAuth as S, useAuthState as _, Authenticated as a, useConvexAuthBridge as b, FetchAccessTokenContext as c, MaybeUnauthenticated as d, Unauthenticated as f, useAuthGuard as g, useAuth as h, AuthStoreState as i, FetchAccessTokenFn as l, isSessionSyncGraceActive as m, AuthProvider as n, ConvexAuthBridge as o, decodeJwtExp as p, AuthStore as r, ConvexProviderWithAuth$1 as s, AUTH_SESSION_SYNC_GRACE_MS as t, MaybeAuthenticated as u, useAuthStore as v, useSafeConvexAuth as w, useFetchAccessToken as x, useAuthValue as y };
|