kitcn 0.15.15 → 0.15.17

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.
@@ -1,5 +1,5 @@
1
1
  'use client';
2
- import { r as AuthStore } from "../../auth-store-B_ARzzEX.js";
2
+ import { r as AuthStore } from "../../auth-store-GDNKweSK.js";
3
3
  import { ConvexReactClient } from "convex/react";
4
4
  import { ReactNode } from "react";
5
5
  import * as react_jsx_runtime0 from "react/jsx-runtime";
@@ -1,6 +1,6 @@
1
1
  'use client';
2
- import { C as readAuthSessionFallbackData, D as CRPCClientError, O as defaultIsUnauthorized, S as clearAuthSessionFallback, T as writeAuthSessionFallbackData, d as isSessionSyncGraceActive, g as useAuthValue, h as useAuthStore, n as AuthProvider, o as FetchAccessTokenContext, t as AUTH_SESSION_SYNC_GRACE_MS, u as decodeJwtExp, w as readAuthSessionFallbackToken } from "../../auth-store-CwGbvP_s.js";
3
- import { ConvexProviderWithAuth, useConvexAuth } from "convex/react";
2
+ import { A as defaultIsUnauthorized, D as writeAuthSessionFallbackData, E as readAuthSessionFallbackToken, T as readAuthSessionFallbackData, _ as useAuthValue, d as decodeJwtExp, f as isSessionSyncGraceActive, g as useAuthStore, k as CRPCClientError, n as AuthProvider, o as ConvexProviderWithAuth$1, s as FetchAccessTokenContext, t as AUTH_SESSION_SYNC_GRACE_MS, w as clearAuthSessionFallback } from "../../auth-store-ssZDPa37.js";
3
+ import { useConvexAuth } from "convex/react";
4
4
  import { useCallback, useEffect, useMemo, useRef } from "react";
5
5
  import { jsx } from "react/jsx-runtime";
6
6
 
@@ -272,7 +272,7 @@ function ConvexAuthProviderInner({ children, client, authClient, convexQueryClie
272
272
  }, [fetchAccessToken, authStore]);
273
273
  return /* @__PURE__ */ jsx(FetchAccessTokenContext.Provider, {
274
274
  value: fetchAccessToken,
275
- children: /* @__PURE__ */ jsx(ConvexProviderWithAuth, {
275
+ children: /* @__PURE__ */ jsx(ConvexProviderWithAuth$1, {
276
276
  client,
277
277
  useAuth,
278
278
  children: /* @__PURE__ */ jsx(AuthStateSync, { children })
@@ -18,6 +18,23 @@ type ConvexAuthResult = {
18
18
  };
19
19
  /** Get auth from bridge context (null if no bridge configured) */
20
20
  declare const useConvexAuthBridge: () => ConvexAuthResult | null;
21
+ type ConvexAuthRecoveryStatus = 'idle' | 'recovering' | 'failed';
22
+ type ConvexAuthRecoveryErrorCode = 'AUTH_PROVIDER_LOADING' | 'AUTH_PROVIDER_UNAUTHENTICATED' | 'AUTH_RECOVERY_CANCELLED' | 'AUTH_RECOVERY_FAILED' | 'AUTH_RECOVERY_TIMEOUT';
23
+ declare class ConvexAuthRecoveryError extends Error {
24
+ readonly code: ConvexAuthRecoveryErrorCode;
25
+ constructor(code: ConvexAuthRecoveryErrorCode, message: string);
26
+ }
27
+ type ConvexAuthRecoveryOptions = {
28
+ /** Maximum time to wait for Convex backend confirmation. Defaults to 10s. */timeoutMs?: number;
29
+ };
30
+ type ConvexAuthRecovery = {
31
+ error: ConvexAuthRecoveryError | null;
32
+ recover: (options?: ConvexAuthRecoveryOptions) => Promise<void>;
33
+ status: ConvexAuthRecoveryStatus;
34
+ };
35
+ /** Imperatively rebind Convex auth and wait for backend confirmation. */
36
+ declare function useConvexAuthRecovery(): ConvexAuthRecovery;
37
+ type ConvexProviderWithAuthProps = React.ComponentProps<typeof ConvexProviderWithAuth>;
21
38
  type AuthStoreState = {
22
39
  /** Callback when mutation/action called while unauthorized. Throws by default. */onMutationUnauthorized: () => void; /** Callback when query called while unauthorized. Noop by default. */
23
40
  onQueryUnauthorized: (info: {
@@ -116,8 +133,9 @@ declare function ConvexAuthBridge({
116
133
  */
117
134
  declare function ConvexProviderWithAuth$1({
118
135
  children,
119
- ...props
120
- }: React.ComponentProps<typeof ConvexProviderWithAuth>): react_jsx_runtime0.JSX.Element;
136
+ client,
137
+ useAuth
138
+ }: ConvexProviderWithAuthProps): react_jsx_runtime0.JSX.Element;
121
139
  declare const useAuth: () => {
122
140
  hasSession: boolean;
123
141
  isAuthenticated: boolean;
@@ -153,4 +171,4 @@ declare function Unauthenticated({
153
171
  children: React.ReactNode;
154
172
  }): react.ReactNode;
155
173
  //#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 };
174
+ export { useSafeConvexAuth as A, useAuthStore as C, useFetchAccessToken as D, useConvexAuthRecovery as E, useIsAuth as O, useAuthState as S, useConvexAuthBridge as T, Unauthenticated as _, Authenticated as a, useAuth as b, ConvexAuthRecoveryError as c, ConvexAuthRecoveryStatus as d, ConvexProviderWithAuth$1 as f, MaybeUnauthenticated as g, MaybeAuthenticated as h, AuthStoreState as i, useMaybeAuth as k, ConvexAuthRecoveryErrorCode as l, FetchAccessTokenFn as m, AuthProvider as n, ConvexAuthBridge as o, FetchAccessTokenContext as p, AuthStore as r, ConvexAuthRecovery as s, AUTH_SESSION_SYNC_GRACE_MS as t, ConvexAuthRecoveryOptions as u, decodeJwtExp as v, useAuthValue as w, useAuthGuard as x, isSessionSyncGraceActive as y };
@@ -1,8 +1,8 @@
1
1
  'use client';
2
2
  import { ConvexProviderWithAuth, useConvexAuth } from "convex/react";
3
- import { createContext, useContext } from "react";
3
+ import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
4
4
  import { createAtomStore } from "jotai-x";
5
- import { jsx } from "react/jsx-runtime";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
6
 
7
7
  //#region src/crpc/error.ts
8
8
  /**
@@ -102,6 +102,69 @@ const useFetchAccessToken = () => useContext(FetchAccessTokenContext);
102
102
  const ConvexAuthBridgeContext = createContext(null);
103
103
  /** Get auth from bridge context (null if no bridge configured) */
104
104
  const useConvexAuthBridge = () => useContext(ConvexAuthBridgeContext);
105
+ var ConvexAuthRecoveryError = class extends Error {
106
+ code;
107
+ constructor(code, message) {
108
+ super(message);
109
+ this.name = "ConvexAuthRecoveryError";
110
+ this.code = code;
111
+ }
112
+ };
113
+ const ConvexAuthRecoveryContext = createContext(null);
114
+ /** Imperatively rebind Convex auth and wait for backend confirmation. */
115
+ function useConvexAuthRecovery() {
116
+ const recovery = useContext(ConvexAuthRecoveryContext);
117
+ if (!recovery) throw new Error("useConvexAuthRecovery must be used inside ConvexProviderWithAuth");
118
+ return recovery;
119
+ }
120
+ const AUTH_RECOVERY_TIMEOUT_MS = 1e4;
121
+ function ConvexAuthRecoverySync({ authProviderAuthenticated, authProviderLoading, onChange }) {
122
+ const auth = useConvexAuth();
123
+ useEffect(() => {
124
+ onChange({
125
+ authProviderAuthenticated,
126
+ authProviderLoading,
127
+ isAuthenticated: auth.isAuthenticated,
128
+ isLoading: auth.isLoading
129
+ });
130
+ }, [
131
+ auth.isAuthenticated,
132
+ auth.isLoading,
133
+ authProviderAuthenticated,
134
+ authProviderLoading,
135
+ onChange
136
+ ]);
137
+ return null;
138
+ }
139
+ function ConvexAuthBinding({ bindingVersion, children, client, onAuthSnapshot, onBindingFetch, useAuth }) {
140
+ const { fetchAccessToken: fetchAccessTokenFromAuth, isAuthenticated, isLoading } = useAuth();
141
+ const fetchAccessToken = useCallback((args) => {
142
+ onBindingFetch(bindingVersion);
143
+ return fetchAccessTokenFromAuth(args);
144
+ }, [
145
+ bindingVersion,
146
+ fetchAccessTokenFromAuth,
147
+ onBindingFetch
148
+ ]);
149
+ const boundAuth = useMemo(() => ({
150
+ fetchAccessToken,
151
+ isAuthenticated,
152
+ isLoading
153
+ }), [
154
+ fetchAccessToken,
155
+ isAuthenticated,
156
+ isLoading
157
+ ]);
158
+ return /* @__PURE__ */ jsxs(ConvexProviderWithAuth, {
159
+ client,
160
+ useAuth: useCallback(() => boundAuth, [boundAuth]),
161
+ children: [/* @__PURE__ */ jsx(ConvexAuthRecoverySync, {
162
+ authProviderAuthenticated: isAuthenticated,
163
+ authProviderLoading: isLoading,
164
+ onChange: onAuthSnapshot
165
+ }), /* @__PURE__ */ jsx(ConvexAuthBridge, { children })]
166
+ });
167
+ }
105
168
  const AUTH_SESSION_SYNC_GRACE_MS = 1e4;
106
169
  const isSessionSyncGraceActive = (sessionSyncGraceUntil) => typeof sessionSyncGraceUntil === "number" && sessionSyncGraceUntil > Date.now();
107
170
  /** Decode JWT expiration (ms timestamp) from token */
@@ -176,10 +239,123 @@ function ConvexAuthBridge({ children }) {
176
239
  * </ConvexProviderWithAuth>
177
240
  * ```
178
241
  */
179
- function ConvexProviderWithAuth$1({ children, ...props }) {
180
- return /* @__PURE__ */ jsx(ConvexProviderWithAuth, {
181
- ...props,
182
- children: /* @__PURE__ */ jsx(ConvexAuthBridge, { children })
242
+ function ConvexProviderWithAuth$1({ children, client, useAuth }) {
243
+ const [bindingVersion, setBindingVersion] = useState(0);
244
+ const [error, setError] = useState(null);
245
+ const [status, setStatus] = useState("idle");
246
+ const bindingVersionRef = useRef(0);
247
+ const pendingRef = useRef(null);
248
+ const authSnapshotRef = useRef({
249
+ authProviderAuthenticated: false,
250
+ authProviderLoading: true,
251
+ isAuthenticated: false,
252
+ isLoading: true
253
+ });
254
+ const settleRecovery = useCallback((recoveryError) => {
255
+ const pending = pendingRef.current;
256
+ if (!pending) return;
257
+ clearTimeout(pending.timeoutId);
258
+ pendingRef.current = null;
259
+ if (recoveryError) {
260
+ setError(recoveryError);
261
+ setStatus("failed");
262
+ pending.reject(recoveryError);
263
+ return;
264
+ }
265
+ setError(null);
266
+ setStatus("idle");
267
+ pending.resolve();
268
+ }, []);
269
+ const onAuthSnapshot = useCallback((snapshot) => {
270
+ authSnapshotRef.current = snapshot;
271
+ const pending = pendingRef.current;
272
+ if (!pending) return;
273
+ if (snapshot.authProviderLoading) {
274
+ settleRecovery(new ConvexAuthRecoveryError("AUTH_PROVIDER_LOADING", "Cannot recover Convex auth while the auth provider is loading"));
275
+ return;
276
+ }
277
+ if (!snapshot.authProviderAuthenticated) {
278
+ settleRecovery(new ConvexAuthRecoveryError("AUTH_PROVIDER_UNAUTHENTICATED", "Cannot recover Convex auth without an authenticated provider session"));
279
+ return;
280
+ }
281
+ if (!pending.isBound || snapshot.isLoading) return;
282
+ if (snapshot.isAuthenticated) {
283
+ settleRecovery(null);
284
+ return;
285
+ }
286
+ settleRecovery(new ConvexAuthRecoveryError("AUTH_RECOVERY_FAILED", "Convex rejected the recovered authentication binding"));
287
+ }, [settleRecovery]);
288
+ const onBindingFetch = useCallback((activeBindingVersion) => {
289
+ const pending = pendingRef.current;
290
+ if (pending?.bindingVersion === activeBindingVersion) pending.isBound = true;
291
+ }, []);
292
+ const recover = useCallback((options = {}) => {
293
+ const pending = pendingRef.current;
294
+ if (pending) return pending.promise;
295
+ const authSnapshot = authSnapshotRef.current;
296
+ if (authSnapshot.authProviderLoading) {
297
+ const recoveryError = new ConvexAuthRecoveryError("AUTH_PROVIDER_LOADING", "Cannot recover Convex auth while the auth provider is loading");
298
+ setError(recoveryError);
299
+ setStatus("failed");
300
+ return Promise.reject(recoveryError);
301
+ }
302
+ if (!authSnapshot.authProviderAuthenticated) {
303
+ const recoveryError = new ConvexAuthRecoveryError("AUTH_PROVIDER_UNAUTHENTICATED", "Cannot recover Convex auth without an authenticated provider session");
304
+ setError(recoveryError);
305
+ setStatus("failed");
306
+ return Promise.reject(recoveryError);
307
+ }
308
+ let resolve;
309
+ let reject;
310
+ const promise = new Promise((resolvePromise, rejectPromise) => {
311
+ resolve = resolvePromise;
312
+ reject = rejectPromise;
313
+ });
314
+ const timeoutMs = options.timeoutMs ?? AUTH_RECOVERY_TIMEOUT_MS;
315
+ const nextBindingVersion = bindingVersionRef.current + 1;
316
+ const timeoutId = setTimeout(() => {
317
+ settleRecovery(new ConvexAuthRecoveryError("AUTH_RECOVERY_TIMEOUT", `Convex auth recovery timed out after ${timeoutMs}ms`));
318
+ }, timeoutMs);
319
+ pendingRef.current = {
320
+ bindingVersion: nextBindingVersion,
321
+ isBound: false,
322
+ promise,
323
+ reject,
324
+ resolve,
325
+ timeoutId
326
+ };
327
+ bindingVersionRef.current = nextBindingVersion;
328
+ setError(null);
329
+ setStatus("recovering");
330
+ setBindingVersion(nextBindingVersion);
331
+ return promise;
332
+ }, [settleRecovery]);
333
+ useEffect(() => () => {
334
+ const pending = pendingRef.current;
335
+ if (!pending) return;
336
+ clearTimeout(pending.timeoutId);
337
+ pendingRef.current = null;
338
+ pending.reject(new ConvexAuthRecoveryError("AUTH_RECOVERY_CANCELLED", "Convex auth recovery was cancelled because the provider unmounted"));
339
+ }, []);
340
+ const recovery = useMemo(() => ({
341
+ error,
342
+ recover,
343
+ status
344
+ }), [
345
+ error,
346
+ recover,
347
+ status
348
+ ]);
349
+ return /* @__PURE__ */ jsx(ConvexAuthRecoveryContext.Provider, {
350
+ value: recovery,
351
+ children: /* @__PURE__ */ jsx(ConvexAuthBinding, {
352
+ bindingVersion,
353
+ client,
354
+ onAuthSnapshot,
355
+ onBindingFetch,
356
+ useAuth,
357
+ children
358
+ })
183
359
  });
184
360
  }
185
361
  const useAuth = () => {
@@ -251,4 +427,4 @@ function Unauthenticated({ children }) {
251
427
  }
252
428
 
253
429
  //#endregion
254
- export { readAuthSessionFallbackData as C, CRPCClientError as D, writeAuthSessionFallbackToken as E, defaultIsUnauthorized as O, clearAuthSessionFallback as S, writeAuthSessionFallbackData as T, useConvexAuthBridge as _, ConvexProviderWithAuth$1 as a, useMaybeAuth as b, MaybeUnauthenticated as c, isSessionSyncGraceActive as d, useAuth as f, useAuthValue as g, useAuthStore as h, ConvexAuthBridge as i, isCRPCClientError as k, Unauthenticated as l, useAuthState as m, AuthProvider as n, FetchAccessTokenContext as o, useAuthGuard as p, Authenticated as r, MaybeAuthenticated as s, AUTH_SESSION_SYNC_GRACE_MS as t, decodeJwtExp as u, useFetchAccessToken as v, readAuthSessionFallbackToken as w, useSafeConvexAuth as x, useIsAuth as y };
430
+ export { defaultIsUnauthorized as A, useSafeConvexAuth as C, writeAuthSessionFallbackData as D, readAuthSessionFallbackToken as E, writeAuthSessionFallbackToken as O, useMaybeAuth as S, readAuthSessionFallbackData as T, useAuthValue as _, ConvexAuthRecoveryError as a, useFetchAccessToken as b, MaybeAuthenticated as c, decodeJwtExp as d, isSessionSyncGraceActive as f, useAuthStore as g, useAuthState as h, ConvexAuthBridge as i, isCRPCClientError as j, CRPCClientError as k, MaybeUnauthenticated as l, useAuthGuard as m, AuthProvider as n, ConvexProviderWithAuth$1 as o, useAuth as p, Authenticated as r, FetchAccessTokenContext as s, AUTH_SESSION_SYNC_GRACE_MS as t, Unauthenticated as u, useConvexAuthBridge as v, clearAuthSessionFallback as w, useIsAuth as x, useConvexAuthRecovery as y };
@@ -1,5 +1,5 @@
1
1
  'use client';
2
- import { C as useMaybeAuth, S as useIsAuth, _ as useAuthState, a as Authenticated, b as useConvexAuthBridge, c as FetchAccessTokenContext, d as MaybeUnauthenticated, f as Unauthenticated, g as useAuthGuard, h as useAuth, i as AuthStoreState, l as FetchAccessTokenFn, m as isSessionSyncGraceActive, n as AuthProvider, o as ConvexAuthBridge, p as decodeJwtExp, r as AuthStore, s as ConvexProviderWithAuth, t as AUTH_SESSION_SYNC_GRACE_MS, u as MaybeAuthenticated, v as useAuthStore, w as useSafeConvexAuth, x as useFetchAccessToken, y as useAuthValue } from "../auth-store-B_ARzzEX.js";
2
+ import { A as useSafeConvexAuth, C as useAuthStore, D as useFetchAccessToken, E as useConvexAuthRecovery, O as useIsAuth, S as useAuthState, T as useConvexAuthBridge, _ as Unauthenticated, a as Authenticated, b as useAuth, c as ConvexAuthRecoveryError, d as ConvexAuthRecoveryStatus, f as ConvexProviderWithAuth, g as MaybeUnauthenticated, h as MaybeAuthenticated, i as AuthStoreState, k as useMaybeAuth, l as ConvexAuthRecoveryErrorCode, m as FetchAccessTokenFn, n as AuthProvider, o as ConvexAuthBridge, p as FetchAccessTokenContext, r as AuthStore, s as ConvexAuthRecovery, t as AUTH_SESSION_SYNC_GRACE_MS, u as ConvexAuthRecoveryOptions, v as decodeJwtExp, w as useAuthValue, x as useAuthGuard, y as isSessionSyncGraceActive } from "../auth-store-GDNKweSK.js";
3
3
  import { ConvexProvider, ConvexReactClient, ConvexReactClient as ConvexReactClient$1, ConvexReactClientOptions, Watch, WatchQueryOptions, useConvex } from "convex/react";
4
4
  import { ReactNode } from "react";
5
5
  import * as react_jsx_runtime0 from "react/jsx-runtime";
@@ -1143,4 +1143,4 @@ declare function useUploadMutationOptions<TGenerateUrlMutation extends FunctionR
1143
1143
  */
1144
1144
  declare function createVanillaCRPCProxy<TApi extends Record<string, unknown>>(api: TApi, meta: CallerMeta, convexClient: ConvexReactClient$1, transformer?: DataTransformerOptions): VanillaCRPCClient<TApi>;
1145
1145
  //#endregion
1146
- export { AUTH_SESSION_SYNC_GRACE_MS, AuthMutationError, AuthProvider, AuthStore, AuthStoreState, Authenticated, CRPCHttpOptions, ConvexAuthBridge, ConvexProvider, ConvexProviderWithAuth, ConvexQueryClient, ConvexQueryClientOptions, ConvexQueryClientSingletonOptions, ConvexReactClient, CreateCRPCContextOptions, FetchAccessTokenContext, FetchAccessTokenFn, HttpCRPCClient, HttpCRPCClientFromRouter, type HttpClientOptions, type HttpFormValue, type HttpInputArgs, HttpMutationKey, HttpProxyOptions, HttpQueryKey, HttpRouteInfo, HttpRouteMap, MaybeAuthenticated, MaybeUnauthenticated, PaginationState, PaginationStatus, Unauthenticated, UseInfiniteQueryResult, VanillaHttpCRPCClient, VanillaHttpCRPCClientFromRouter, createAuthMutations, createCRPCContext, createCRPCOptionsProxy, createHttpProxy, createVanillaCRPCProxy, decodeJwtExp, getConvexQueryClientSingleton, getQueryClientSingleton, isAuthMutationError, isSessionSyncGraceActive, useAuth, useAuthGuard, useAuthState, useAuthStore, useAuthValue, useConvex, useConvexActionOptions, useConvexActionQueryOptions, useSafeConvexAuth as useConvexAuth, useSafeConvexAuth, useConvexAuthBridge, useConvexInfiniteQueryOptions, useConvexMutationOptions, useConvexQueryClient, useConvexQueryOptions, useFetchAccessToken, useFnMeta, useInfiniteQuery, useIsAuth, useMaybeAuth, useMeta, useUploadMutationOptions };
1146
+ export { AUTH_SESSION_SYNC_GRACE_MS, AuthMutationError, AuthProvider, AuthStore, AuthStoreState, Authenticated, CRPCHttpOptions, ConvexAuthBridge, ConvexAuthRecovery, ConvexAuthRecoveryError, ConvexAuthRecoveryErrorCode, ConvexAuthRecoveryOptions, ConvexAuthRecoveryStatus, ConvexProvider, ConvexProviderWithAuth, ConvexQueryClient, ConvexQueryClientOptions, ConvexQueryClientSingletonOptions, ConvexReactClient, CreateCRPCContextOptions, FetchAccessTokenContext, FetchAccessTokenFn, HttpCRPCClient, HttpCRPCClientFromRouter, type HttpClientOptions, type HttpFormValue, type HttpInputArgs, HttpMutationKey, HttpProxyOptions, HttpQueryKey, HttpRouteInfo, HttpRouteMap, MaybeAuthenticated, MaybeUnauthenticated, PaginationState, PaginationStatus, Unauthenticated, UseInfiniteQueryResult, VanillaHttpCRPCClient, VanillaHttpCRPCClientFromRouter, createAuthMutations, createCRPCContext, createCRPCOptionsProxy, createHttpProxy, createVanillaCRPCProxy, decodeJwtExp, getConvexQueryClientSingleton, getQueryClientSingleton, isAuthMutationError, isSessionSyncGraceActive, useAuth, useAuthGuard, useAuthState, useAuthStore, useAuthValue, useConvex, useConvexActionOptions, useConvexActionQueryOptions, useSafeConvexAuth as useConvexAuth, useSafeConvexAuth, useConvexAuthBridge, useConvexAuthRecovery, useConvexInfiniteQueryOptions, useConvexMutationOptions, useConvexQueryClient, useConvexQueryOptions, useFetchAccessToken, useFnMeta, useInfiniteQuery, useIsAuth, useMaybeAuth, useMeta, useUploadMutationOptions };
@@ -1,5 +1,5 @@
1
1
  'use client';
2
- import { D as CRPCClientError, E as writeAuthSessionFallbackToken, O as defaultIsUnauthorized, S as clearAuthSessionFallback, T as writeAuthSessionFallbackData, _ as useConvexAuthBridge, a as ConvexProviderWithAuth, b as useMaybeAuth, c as MaybeUnauthenticated, d as isSessionSyncGraceActive, f as useAuth, g as useAuthValue, h as useAuthStore, i as ConvexAuthBridge, k as isCRPCClientError, l as Unauthenticated, m as useAuthState, n as AuthProvider, o as FetchAccessTokenContext, p as useAuthGuard, r as Authenticated, s as MaybeAuthenticated, t as AUTH_SESSION_SYNC_GRACE_MS, u as decodeJwtExp, v as useFetchAccessToken, x as useSafeConvexAuth, y as useIsAuth } from "../auth-store-CwGbvP_s.js";
2
+ import { A as defaultIsUnauthorized, C as useSafeConvexAuth, D as writeAuthSessionFallbackData, O as writeAuthSessionFallbackToken, S as useMaybeAuth, _ as useAuthValue, a as ConvexAuthRecoveryError, b as useFetchAccessToken, c as MaybeAuthenticated, d as decodeJwtExp, f as isSessionSyncGraceActive, g as useAuthStore, h as useAuthState, i as ConvexAuthBridge, j as isCRPCClientError, k as CRPCClientError, l as MaybeUnauthenticated, m as useAuthGuard, n as AuthProvider, o as ConvexProviderWithAuth, p as useAuth, r as Authenticated, s as FetchAccessTokenContext, t as AUTH_SESSION_SYNC_GRACE_MS, u as Unauthenticated, v as useConvexAuthBridge, w as clearAuthSessionFallback, x as useIsAuth, y as useConvexAuthRecovery } from "../auth-store-ssZDPa37.js";
3
3
  import { ConvexProvider, ConvexReactClient, ConvexReactClient as ConvexReactClient$1, useAction, useConvex, useMutation } from "convex/react";
4
4
  import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
5
5
  import { jsx } from "react/jsx-runtime";
@@ -2159,6 +2159,10 @@ const getConvexQueryClientSingleton = ({ authStore, convex, queryClient, symbolK
2159
2159
  return client;
2160
2160
  };
2161
2161
 
2162
+ //#endregion
2163
+ //#region src/internal/pagination.ts
2164
+ const shouldSplitPaginationPage = (page, initialNumItems) => Boolean(page.splitCursor) && (page.pageStatus === "SplitRecommended" || page.pageStatus === "SplitRequired" || initialNumItems !== void 0 && page.page.length > initialNumItems * 2);
2165
+
2162
2166
  //#endregion
2163
2167
  //#region src/react/use-infinite-query.ts
2164
2168
  /** biome-ignore-all lint/suspicious/noExplicitAny: Convex query/mutation type compatibility */
@@ -2453,7 +2457,7 @@ const useInfiniteQueryInternal = (query, args, options) => {
2453
2457
  const page = pageQuery.data;
2454
2458
  const pageKey = state.pageKeys[i];
2455
2459
  const pageState = state.queries[pageKey];
2456
- if (page.splitCursor && pageState && !pageState.endCursor) {
2460
+ if (shouldSplitPaginationPage(page, limit) && pageState && !pageState.endCursor) {
2457
2461
  setState((prev) => {
2458
2462
  const currentPageState = prev.queries[pageKey];
2459
2463
  if (!currentPageState || currentPageState.endCursor) return prev;
@@ -2491,6 +2495,7 @@ const useInfiniteQueryInternal = (query, args, options) => {
2491
2495
  state.pageKeys,
2492
2496
  state.queries,
2493
2497
  argsObject,
2498
+ limit,
2494
2499
  setState
2495
2500
  ]);
2496
2501
  const loadMore = useCallback((pageLimit) => {
@@ -2592,4 +2597,4 @@ function useInfiniteQuery(infiniteOptions) {
2592
2597
  }
2593
2598
 
2594
2599
  //#endregion
2595
- export { AUTH_SESSION_SYNC_GRACE_MS, AuthMutationError, AuthProvider, Authenticated, ConvexAuthBridge, ConvexProvider, ConvexProviderWithAuth, ConvexQueryClient, ConvexReactClient, FetchAccessTokenContext, MaybeAuthenticated, MaybeUnauthenticated, Unauthenticated, createAuthMutations, createCRPCContext, createCRPCOptionsProxy, createHttpProxy, createVanillaCRPCProxy, decodeJwtExp, getConvexQueryClientSingleton, getQueryClientSingleton, isAuthMutationError, isSessionSyncGraceActive, useAuth, useAuthGuard, useAuthState, useAuthStore, useAuthValue, useConvex, useConvexActionOptions, useConvexActionQueryOptions, useSafeConvexAuth as useConvexAuth, useSafeConvexAuth, useConvexAuthBridge, useConvexInfiniteQueryOptions, useConvexMutationOptions, useConvexQueryClient, useConvexQueryOptions, useFetchAccessToken, useFnMeta, useInfiniteQuery, useIsAuth, useMaybeAuth, useMeta, useUploadMutationOptions };
2600
+ export { AUTH_SESSION_SYNC_GRACE_MS, AuthMutationError, AuthProvider, Authenticated, ConvexAuthBridge, ConvexAuthRecoveryError, ConvexProvider, ConvexProviderWithAuth, ConvexQueryClient, ConvexReactClient, FetchAccessTokenContext, MaybeAuthenticated, MaybeUnauthenticated, Unauthenticated, createAuthMutations, createCRPCContext, createCRPCOptionsProxy, createHttpProxy, createVanillaCRPCProxy, decodeJwtExp, getConvexQueryClientSingleton, getQueryClientSingleton, isAuthMutationError, isSessionSyncGraceActive, useAuth, useAuthGuard, useAuthState, useAuthStore, useAuthValue, useConvex, useConvexActionOptions, useConvexActionQueryOptions, useSafeConvexAuth as useConvexAuth, useSafeConvexAuth, useConvexAuthBridge, useConvexAuthRecovery, useConvexInfiniteQueryOptions, useConvexMutationOptions, useConvexQueryClient, useConvexQueryOptions, useFetchAccessToken, useFnMeta, useInfiniteQuery, useIsAuth, useMaybeAuth, useMeta, useUploadMutationOptions };
@@ -2486,6 +2486,10 @@ const getConvexQueryClientSingleton = ({ authStore, convex, queryClient, symbolK
2486
2486
  return client;
2487
2487
  };
2488
2488
 
2489
+ //#endregion
2490
+ //#region src/internal/pagination.ts
2491
+ const shouldSplitPaginationPage = (page, initialNumItems) => Boolean(page.splitCursor) && (page.pageStatus === "SplitRecommended" || page.pageStatus === "SplitRequired" || initialNumItems !== void 0 && page.page.length > initialNumItems * 2);
2492
+
2489
2493
  //#endregion
2490
2494
  //#region src/solid/use-infinite-query.ts
2491
2495
  const PAGINATION_KEY_PREFIX = "__pagination__";
@@ -2757,7 +2761,7 @@ const useInfiniteQueryInternal = (query, args, options) => {
2757
2761
  const page = pageQuery.data;
2758
2762
  const pageKey = state().pageKeys[i];
2759
2763
  const pageState = state().queries[pageKey];
2760
- if (page.splitCursor && pageState && !pageState.endCursor) {
2764
+ if (shouldSplitPaginationPage(page, limit) && pageState && !pageState.endCursor) {
2761
2765
  setState((prev) => {
2762
2766
  const currentPageState = prev.queries[pageKey];
2763
2767
  if (!currentPageState || currentPageState.endCursor) return prev;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kitcn",
3
- "version": "0.15.15",
3
+ "version": "0.15.17",
4
4
  "description": "kitcn - React Query integration and CLI tools for Convex",
5
5
  "keywords": [
6
6
  "convex",
@@ -358,6 +358,7 @@ All from `kitcn/react`:
358
358
  | `useMaybeAuth()` | `boolean` | Has token (optimistic, may not be verified) |
359
359
  | `useIsAuth()` | `boolean` | Server-verified authentication |
360
360
  | `useAuthGuard()` | `() => boolean` | Guard mutations, returns true if blocked |
361
+ | `useConvexAuthRecovery()` | `{ recover, status, error }` | Rebind Convex auth after a transient token failure |
361
362
 
362
363
  ### useAuthGuard
363
364
 
@@ -409,6 +410,28 @@ import { ConvexProviderWithAuth } from 'kitcn/react';
409
410
  <ConvexProviderWithAuth client={convex} useAuth={useAuthFromConvexDev}>
410
411
  ```
411
412
 
413
+ ### Convex Auth Recovery
414
+
415
+ Use recovery only when the outer auth provider remains authenticated but
416
+ Convex entered an unauthenticated state after a transient token refresh
417
+ failure:
418
+
419
+ ```tsx
420
+ import { useConvexAuthRecovery } from 'kitcn/react';
421
+
422
+ const { error, recover, status } = useConvexAuthRecovery();
423
+ await recover();
424
+ ```
425
+
426
+ `recover()` replaces the provider-owned auth binding and resolves after Convex
427
+ confirms authentication. Concurrent calls share one promise. The default
428
+ timeout is 10 seconds; override it with `recover({ timeoutMs })`.
429
+
430
+ Failures are `ConvexAuthRecoveryError` values with code
431
+ `AUTH_PROVIDER_LOADING`, `AUTH_PROVIDER_UNAUTHENTICATED`,
432
+ `AUTH_RECOVERY_CANCELLED`, `AUTH_RECOVERY_FAILED`, or
433
+ `AUTH_RECOVERY_TIMEOUT`. Never recover an intentional sign-out.
434
+
412
435
  ---
413
436
 
414
437
  ## Auth Triggers