kitcn 0.21.0 → 0.22.1

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-47WTg13B.js";
2
+ import { r as AuthStore } from "../../auth-store-DHEk0ARa.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,5 +1,5 @@
1
1
  'use client';
2
- import { A as CRPCClientError, C as decodeJwtExp, D as readAuthSessionFallbackToken, E as readAuthSessionFallbackData, O as writeAuthSessionFallbackData, T as clearAuthSessionFallback, d as isSessionSyncGraceActive, g as useAuthValue, h as useAuthStore, j as defaultIsUnauthorized, n as AuthProvider, o as ConvexProviderWithAuth$1, s as FetchAccessTokenContext, t as AUTH_SESSION_SYNC_GRACE_MS } from "../../auth-store-BHk8eMnX.js";
2
+ import { A as CRPCClientError, C as decodeJwtExp, D as readAuthSessionFallbackToken, E as readAuthSessionFallbackData, O as writeAuthSessionFallbackData, T as clearAuthSessionFallback, d as isSessionSyncGraceActive, g as useAuthValue, h as useAuthStore, j as defaultIsUnauthorized, n as AuthProvider, o as ConvexProviderWithAuth$1, s as FetchAccessTokenContext, t as AUTH_SESSION_SYNC_GRACE_MS } from "../../auth-store-BnsWs1xd.js";
3
3
  import { useConvexAuth } from "convex/react";
4
4
  import { useCallback, useEffect, useMemo, useRef } from "react";
5
5
  import { jsx } from "react/jsx-runtime";
@@ -216,7 +216,8 @@ const { AuthProvider, useAuthStore, useAuthState, useAuthValue } = createAtomSto
216
216
  expiresAt: null,
217
217
  isLoading: true,
218
218
  isAuthenticated: false,
219
- sessionSyncGraceUntil: null
219
+ sessionSyncGraceUntil: null,
220
+ authEpoch: 0
220
221
  }, {
221
222
  name: "auth",
222
223
  suppressWarnings: true
@@ -49,6 +49,12 @@ type AuthStoreState = {
49
49
  isLoading: boolean; /** Auth state (synced from useConvexAuth for class methods) */
50
50
  isAuthenticated: boolean; /** Grace window for freshly seeded auth tokens while session sync catches up */
51
51
  sessionSyncGraceUntil: number | null;
52
+ /**
53
+ * Account generation, advanced on every identity transition. Client state
54
+ * that only makes sense inside one account's result set — paginated cursor
55
+ * chains — keys on it so it is rebuilt instead of reused across accounts.
56
+ */
57
+ authEpoch: number;
52
58
  };
53
59
  declare const AUTH_SESSION_SYNC_GRACE_MS = 10000;
54
60
  declare const isSessionSyncGraceActive: (sessionSyncGraceUntil: number | null) => boolean;
@@ -63,6 +69,7 @@ declare const AuthProvider: react.FC<jotai_x0.ProviderProps<{
63
69
  isLoading: boolean;
64
70
  isAuthenticated: boolean;
65
71
  sessionSyncGraceUntil: number | null;
72
+ authEpoch: number;
66
73
  }>>, useAuthStore: jotai_x0.UseStoreApi<AuthStoreState, object>, useAuthState: <K extends keyof AuthStoreState>(key: K, options?: string | jotai_x0.UseAtomOptions) => ({
67
74
  onMutationUnauthorized: jotai_x0.SimpleWritableAtom<() => void>;
68
75
  onQueryUnauthorized: jotai_x0.SimpleWritableAtom<(info: {
@@ -74,6 +81,7 @@ declare const AuthProvider: react.FC<jotai_x0.ProviderProps<{
74
81
  isLoading: jotai_x0.SimpleWritableAtom<boolean>;
75
82
  isAuthenticated: jotai_x0.SimpleWritableAtom<boolean>;
76
83
  sessionSyncGraceUntil: jotai_x0.SimpleWritableAtom<number | null>;
84
+ authEpoch: jotai_x0.SimpleWritableAtom<number>;
77
85
  } & 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 = (({
78
86
  onMutationUnauthorized: jotai_x0.SimpleWritableAtom<() => void>;
79
87
  onQueryUnauthorized: jotai_x0.SimpleWritableAtom<(info: {
@@ -85,6 +93,7 @@ declare const AuthProvider: react.FC<jotai_x0.ProviderProps<{
85
93
  isLoading: jotai_x0.SimpleWritableAtom<boolean>;
86
94
  isAuthenticated: jotai_x0.SimpleWritableAtom<boolean>;
87
95
  sessionSyncGraceUntil: jotai_x0.SimpleWritableAtom<number | null>;
96
+ authEpoch: jotai_x0.SimpleWritableAtom<number>;
88
97
  } & object)[K] extends jotai_vanilla0.Atom<infer V> ? V : never)>(key: K, options?: ({
89
98
  selector?: ((v: ({
90
99
  onMutationUnauthorized: jotai_x0.SimpleWritableAtom<() => void>;
@@ -97,6 +106,7 @@ declare const AuthProvider: react.FC<jotai_x0.ProviderProps<{
97
106
  isLoading: jotai_x0.SimpleWritableAtom<boolean>;
98
107
  isAuthenticated: jotai_x0.SimpleWritableAtom<boolean>;
99
108
  sessionSyncGraceUntil: jotai_x0.SimpleWritableAtom<number | null>;
109
+ authEpoch: jotai_x0.SimpleWritableAtom<number>;
100
110
  } & object)[K] extends jotai_vanilla0.Atom<infer V_1> ? V_1 : never, prevSelectorOutput?: S | undefined) => S) | undefined;
101
111
  equalityFn?: ((prev: S, next: S) => boolean) | undefined;
102
112
  } & jotai_x0.UseAtomOptions) | undefined, deps?: unknown[]) => S;
@@ -1,5 +1,5 @@
1
1
  'use client';
2
- import { A as decodeJwtExp, C as useAuthValue, D as useIsAuth, E as useFetchAccessToken, O as useMaybeAuth, S as useAuthStore, T as useConvexAuthRecovery, _ as Unauthenticated, a as Authenticated, b as useAuthGuard, c as ConvexAuthRecoveryError, d as ConvexAuthRecoveryStatus, f as ConvexProviderWithAuth, g as MaybeUnauthenticated, h as MaybeAuthenticated, i as AuthStoreState, k as useSafeConvexAuth, 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 isSessionSyncGraceActive, w as useConvexAuthBridge, x as useAuthState, y as useAuth } from "../auth-store-47WTg13B.js";
2
+ import { A as decodeJwtExp, C as useAuthValue, D as useIsAuth, E as useFetchAccessToken, O as useMaybeAuth, S as useAuthStore, T as useConvexAuthRecovery, _ as Unauthenticated, a as Authenticated, b as useAuthGuard, c as ConvexAuthRecoveryError, d as ConvexAuthRecoveryStatus, f as ConvexProviderWithAuth, g as MaybeUnauthenticated, h as MaybeAuthenticated, i as AuthStoreState, k as useSafeConvexAuth, 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 isSessionSyncGraceActive, w as useConvexAuthBridge, x as useAuthState, y as useAuth } from "../auth-store-DHEk0ARa.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";
@@ -235,7 +235,6 @@ declare class ConvexQueryClient {
235
235
  private cancelPendingUnsubscribe;
236
236
  /** Unsubscribe a live Convex watch (if present) and remove it from the subscription map. */
237
237
  private unsubscribeQueryByHash;
238
- private isAuthBoundQuery;
239
238
  private subscribeQuery;
240
239
  /** Update auth store (for HMR where jotai store may reset) */
241
240
  updateAuthStore(authStore?: AuthStore): void;
@@ -271,6 +270,12 @@ declare class ConvexQueryClient {
271
270
  * Call before logout to prevent UNAUTHORIZED errors during session invalidation.
272
271
  */
273
272
  unsubscribeAuthQueries(): void;
273
+ /**
274
+ * Advance the account generation published by the auth store.
275
+ * Client state that only makes sense inside one account's result set —
276
+ * paginated cursor chains — keys on it, so it is rebuilt instead of reused.
277
+ */
278
+ private bumpAuthEpoch;
274
279
  resetAuthQueries(): Promise<void>;
275
280
  /**
276
281
  * Batch update all subscriptions.
@@ -1,5 +1,5 @@
1
1
  'use client';
2
- import { A as CRPCClientError, C as decodeJwtExp, M as isCRPCClientError, O as writeAuthSessionFallbackData, S as useSafeConvexAuth, T as clearAuthSessionFallback, _ as useConvexAuthBridge, a as ConvexAuthRecoveryError, b as useIsAuth, c as MaybeAuthenticated, d as isSessionSyncGraceActive, f as useAuth, g as useAuthValue, h as useAuthStore, i as ConvexAuthBridge, j as defaultIsUnauthorized, k as writeAuthSessionFallbackToken, l as MaybeUnauthenticated, m as useAuthState, n as AuthProvider, o as ConvexProviderWithAuth, p as useAuthGuard, r as Authenticated, s as FetchAccessTokenContext, t as AUTH_SESSION_SYNC_GRACE_MS, u as Unauthenticated, v as useConvexAuthRecovery, w as decodeJwtIdentity, x as useMaybeAuth, y as useFetchAccessToken } from "../auth-store-BHk8eMnX.js";
2
+ import { A as CRPCClientError, C as decodeJwtExp, M as isCRPCClientError, O as writeAuthSessionFallbackData, S as useSafeConvexAuth, T as clearAuthSessionFallback, _ as useConvexAuthBridge, a as ConvexAuthRecoveryError, b as useIsAuth, c as MaybeAuthenticated, d as isSessionSyncGraceActive, f as useAuth, g as useAuthValue, h as useAuthStore, i as ConvexAuthBridge, j as defaultIsUnauthorized, k as writeAuthSessionFallbackToken, l as MaybeUnauthenticated, m as useAuthState, n as AuthProvider, o as ConvexProviderWithAuth, p as useAuthGuard, r as Authenticated, s as FetchAccessTokenContext, t as AUTH_SESSION_SYNC_GRACE_MS, u as Unauthenticated, v as useConvexAuthRecovery, w as decodeJwtIdentity, x as useMaybeAuth, y as useFetchAccessToken } from "../auth-store-BnsWs1xd.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";
@@ -1647,7 +1647,6 @@ function createAuthMutations(authClient) {
1647
1647
  });
1648
1648
  const useSignInSocialMutationOptions = ((options) => {
1649
1649
  const authStoreApi = useAuthStore();
1650
- const convexQueryClient = useConvexQueryClient();
1651
1650
  return {
1652
1651
  ...options,
1653
1652
  mutationFn: async (args) => {
@@ -1659,14 +1658,12 @@ function createAuthMutations(authClient) {
1659
1658
  await hydrateReturnedSession(authClient, res);
1660
1659
  await ensureAuth(authStoreApi);
1661
1660
  authStoreApi.set("isAuthenticated", true);
1662
- await convexQueryClient?.resetAuthQueries();
1663
1661
  return res;
1664
1662
  }
1665
1663
  };
1666
1664
  });
1667
1665
  const useSignInMutationOptions = ((options) => {
1668
1666
  const authStoreApi = useAuthStore();
1669
- const convexQueryClient = useConvexQueryClient();
1670
1667
  const { signInMethod = "email", ...mutationOptions } = options ?? {};
1671
1668
  return {
1672
1669
  ...mutationOptions,
@@ -1679,14 +1676,12 @@ function createAuthMutations(authClient) {
1679
1676
  await hydrateReturnedSession(authClient, res);
1680
1677
  await ensureAuth(authStoreApi);
1681
1678
  authStoreApi.set("isAuthenticated", true);
1682
- await convexQueryClient?.resetAuthQueries();
1683
1679
  return res;
1684
1680
  }
1685
1681
  };
1686
1682
  });
1687
1683
  const useSignUpMutationOptions = ((options) => {
1688
1684
  const authStoreApi = useAuthStore();
1689
- const convexQueryClient = useConvexQueryClient();
1690
1685
  return {
1691
1686
  ...options,
1692
1687
  mutationFn: async (args) => {
@@ -1698,7 +1693,6 @@ function createAuthMutations(authClient) {
1698
1693
  await hydrateReturnedSession(authClient, res);
1699
1694
  await ensureAuth(authStoreApi);
1700
1695
  authStoreApi.set("isAuthenticated", true);
1701
- await convexQueryClient?.resetAuthQueries();
1702
1696
  return res;
1703
1697
  }
1704
1698
  };
@@ -1711,6 +1705,81 @@ function createAuthMutations(authClient) {
1711
1705
  };
1712
1706
  }
1713
1707
 
1708
+ //#endregion
1709
+ //#region src/internal/auth-reset.ts
1710
+ /**
1711
+ * Erase the cached result of every auth-bound query.
1712
+ *
1713
+ * `queryClient.resetQueries()` is not enough. It restores each query's
1714
+ * `initialState`, and query-core derives that from `initialData` when the query
1715
+ * is built, never re-deriving it once real data lands. An auth-bound entry
1716
+ * therefore comes back holding the previous account's rows marked `success`,
1717
+ * and nothing corrects it: Convex query options set `staleTime: Infinity` with
1718
+ * every refetch trigger off, and `resetQueries` only refetches entries that are
1719
+ * currently active.
1720
+ *
1721
+ * Every entry is removed so query-core forgets both its current state and its
1722
+ * private `initialState`. Mounted observers are rebound with `initialData`
1723
+ * removed, creating a pristine replacement query that future public resets
1724
+ * cannot use to resurrect the previous account's rows.
1725
+ */
1726
+ async function clearAuthBoundQueries(cache, isAuthBound) {
1727
+ const authQueries = cache.getAll().filter((query) => isAuthBound(query));
1728
+ const restoreObservers = [];
1729
+ await Promise.all(authQueries.map((query) => query.cancel({ silent: true })));
1730
+ for (const query of authQueries) {
1731
+ const observers = [...query.observers];
1732
+ cache.remove(query);
1733
+ for (const observer of observers) {
1734
+ const previousOptions = observer.options;
1735
+ observer.setOptions({
1736
+ ...observer.options,
1737
+ enabled: false,
1738
+ initialData: void 0,
1739
+ placeholderData: void 0
1740
+ });
1741
+ const suspendedOptions = observer.options;
1742
+ restoreObservers.push(() => {
1743
+ const currentOptions = observer.options;
1744
+ observer.setOptions({
1745
+ ...currentOptions,
1746
+ enabled: observer.options === suspendedOptions ? previousOptions.enabled : currentOptions.enabled,
1747
+ initialData: void 0,
1748
+ placeholderData: void 0
1749
+ });
1750
+ });
1751
+ }
1752
+ }
1753
+ return () => {
1754
+ for (const restoreObserver of restoreObservers) restoreObserver();
1755
+ };
1756
+ }
1757
+
1758
+ //#endregion
1759
+ //#region src/internal/subscription-gate.ts
1760
+ /** Read kitcn's meta off a TanStack query. */
1761
+ function readConvexQueryMeta(query) {
1762
+ return query.meta;
1763
+ }
1764
+ /**
1765
+ * Auth-bound queries are cleared and resubscribed on an identity transition so
1766
+ * one account never renders another account's cached rows.
1767
+ */
1768
+ function isAuthBoundQuery(query) {
1769
+ const authType = readConvexQueryMeta(query)?.authType;
1770
+ return authType === "required" || authType === "optional";
1771
+ }
1772
+ /** Whether a Convex subscription may be opened for this query. */
1773
+ function canSubscribeQuery(query, opts) {
1774
+ if (opts.isSubscribed) return false;
1775
+ const meta = readConvexQueryMeta(query);
1776
+ if (meta?.subscribe === false) return false;
1777
+ if (query.getObserversCount() === 0) return false;
1778
+ if (query.isDisabled()) return false;
1779
+ if (opts.shouldSkipSubscription(meta?.authType)) return false;
1780
+ return true;
1781
+ }
1782
+
1714
1783
  //#endregion
1715
1784
  //#region src/react/client.ts
1716
1785
  /**
@@ -1882,17 +1951,11 @@ var ConvexQueryClient = class {
1882
1951
  sub.unsubscribe();
1883
1952
  delete this.subscriptions[queryHash];
1884
1953
  }
1885
- isAuthBoundQuery(query) {
1886
- const meta = query.meta;
1887
- return meta?.authType === "required" || meta?.authType === "optional";
1888
- }
1889
1954
  subscribeQuery(query) {
1890
- if (this.subscriptions[query.queryHash]) return;
1891
- const meta = query.meta;
1892
- if (meta?.subscribe === false) return;
1893
- if (query.getObserversCount() === 0) return;
1894
- if (query.isDisabled()) return;
1895
- if (this.shouldSkipSubscription(meta?.authType)) return;
1955
+ if (!canSubscribeQuery(query, {
1956
+ isSubscribed: !!this.subscriptions[query.queryHash],
1957
+ shouldSkipSubscription: (authType) => this.shouldSkipSubscription(authType)
1958
+ })) return;
1896
1959
  const [, funcName, args] = query.queryKey;
1897
1960
  const watch = this.convexClient.watchQuery(funcName, this.transformer.input.serialize(args));
1898
1961
  const unsubscribe = watch.onUpdate(() => {
@@ -1986,14 +2049,29 @@ var ConvexQueryClient = class {
1986
2049
  this.unsubscribeQueryByHash(queryHash);
1987
2050
  }
1988
2051
  }
2052
+ /**
2053
+ * Advance the account generation published by the auth store.
2054
+ * Client state that only makes sense inside one account's result set —
2055
+ * paginated cursor chains — keys on it, so it is rebuilt instead of reused.
2056
+ */
2057
+ bumpAuthEpoch() {
2058
+ if (!this.authStore) return;
2059
+ this.authStore.set("authEpoch", this.authStore.get("authEpoch") + 1);
2060
+ }
1989
2061
  async resetAuthQueries() {
1990
- const authQueries = this.queryClient.getQueryCache().getAll().filter((query) => this.isAuthBoundQuery(query));
1991
- for (const query of authQueries) {
2062
+ const queryCache = this.queryClient.getQueryCache();
2063
+ for (const query of queryCache.getAll()) {
2064
+ if (!isAuthBoundQuery(query)) continue;
1992
2065
  this.cancelPendingUnsubscribe(query.queryHash);
1993
2066
  this.unsubscribeQueryByHash(query.queryHash);
1994
2067
  }
1995
- await this.queryClient.resetQueries({ predicate: (query) => this.isAuthBoundQuery(query) });
1996
- for (const query of this.queryClient.getQueryCache().getAll()) if (this.isAuthBoundQuery(query)) this.subscribeQuery(query);
2068
+ this.bumpAuthEpoch();
2069
+ (await clearAuthBoundQueries(queryCache, (query) => isAuthBoundQuery(query)))();
2070
+ await this.queryClient.refetchQueries({
2071
+ predicate: (query) => isAuthBoundQuery(query),
2072
+ type: "active"
2073
+ });
2074
+ for (const query of queryCache.getAll()) if (isAuthBoundQuery(query)) this.subscribeQuery(query);
1997
2075
  }
1998
2076
  /**
1999
2077
  * Batch update all subscriptions.
@@ -2270,15 +2348,8 @@ const shouldSplitPaginationPage = (page, initialNumItems) => Boolean(page.splitC
2270
2348
  //#region src/react/use-infinite-query.ts
2271
2349
  /** biome-ignore-all lint/suspicious/noExplicitAny: Convex query/mutation type compatibility */
2272
2350
  const PAGINATION_KEY_PREFIX = "__pagination__";
2273
- const paginationIdStore = /* @__PURE__ */ new Map();
2274
2351
  let paginationIdCounter = 0;
2275
- const getOrCreatePaginationId = (storeKey) => {
2276
- const existing = paginationIdStore.get(storeKey);
2277
- if (existing !== void 0) return existing;
2278
- const newId = ++paginationIdCounter;
2279
- paginationIdStore.set(storeKey, newId);
2280
- return newId;
2281
- };
2352
+ const createPaginationId = () => ++paginationIdCounter;
2282
2353
  /** Build a unique key for recovery attempt detection */
2283
2354
  const buildRecoveryKey = (pageKeys, page0Cursor, page0UpdatedAt) => JSON.stringify({
2284
2355
  pageKeys,
@@ -2360,12 +2431,13 @@ const useStaleCursorRecovery = ({ argsObject, combined, limit, setState, state }
2360
2431
  * Use `useInfiniteQuery` for the public API with auth handling.
2361
2432
  */
2362
2433
  const useInfiniteQueryInternal = (query, args, options) => {
2363
- const { limit, enabled, placeholderData, ...forwardedOptions } = options;
2434
+ const { limit, authType, enabled, placeholderData, ...forwardedOptions } = options;
2364
2435
  const queryOptions = useStableIdentity(forwardedOptions);
2365
2436
  const { isLoading: isAuthLoading } = useSafeConvexAuth();
2366
2437
  const meta = useMeta();
2367
2438
  const queryClient = useQueryClient();
2368
- const prefetchedFirstPage = useMemo(() => {
2439
+ const authEpoch = useAuthValue("authEpoch");
2440
+ const skip = !useMemo(() => {
2369
2441
  const serverQueryKey = [
2370
2442
  "convexQuery",
2371
2443
  getFunctionName(query),
@@ -2381,8 +2453,7 @@ const useInfiniteQueryInternal = (query, args, options) => {
2381
2453
  JSON.stringify(args),
2382
2454
  limit,
2383
2455
  queryClient
2384
- ]);
2385
- const skip = !prefetchedFirstPage && (isAuthLoading || enabled === false);
2456
+ ]) && (isAuthLoading || enabled === false);
2386
2457
  const getPaginationState = useCallback((key) => {
2387
2458
  const queryKey = [PAGINATION_KEY_PREFIX, key];
2388
2459
  return queryClient.getQueryData(queryKey);
@@ -2394,10 +2465,16 @@ const useInfiniteQueryInternal = (query, args, options) => {
2394
2465
  const argsObject = useMemo(() => skip ? {} : args, [skip, JSON.stringify(args)]);
2395
2466
  const storeKey = useMemo(() => JSON.stringify({
2396
2467
  query: getFunctionName(query),
2397
- args: argsObject
2398
- }), [query, argsObject]);
2468
+ args: argsObject,
2469
+ ...authType ? { authEpoch } : {}
2470
+ }), [
2471
+ query,
2472
+ argsObject,
2473
+ authType,
2474
+ authEpoch
2475
+ ]);
2399
2476
  const createInitialState = useCallback(() => {
2400
- const id = getOrCreatePaginationId(storeKey);
2477
+ const id = createPaginationId();
2401
2478
  return {
2402
2479
  id,
2403
2480
  nextPageKey: 1,
@@ -2411,7 +2488,6 @@ const useInfiniteQueryInternal = (query, args, options) => {
2411
2488
  version: 0
2412
2489
  };
2413
2490
  }, [
2414
- storeKey,
2415
2491
  skip,
2416
2492
  argsObject,
2417
2493
  limit
@@ -2484,10 +2560,9 @@ const useInfiniteQueryInternal = (query, args, options) => {
2484
2560
  const pageArgs = state.queries[key]?.args;
2485
2561
  return {
2486
2562
  ...convexQuery(query, pageArgs ? (({ __paginationId, ...rest }) => rest)(pageArgs) : "skip", meta),
2487
- enabled: resolveEnabled(!skip && !!state.queries[key], enabled),
2563
+ enabled: resolveEnabled(!skip && !!state.queries[key] && (!authType || !isAuthLoading), enabled),
2488
2564
  structuralSharing: false,
2489
2565
  ...queryOptions ?? {},
2490
- ...index === 0 && prefetchedFirstPage ? { initialData: prefetchedFirstPage } : {},
2491
2566
  ...index === 0 && placeholderData ? { placeholderData: {
2492
2567
  page: placeholderData,
2493
2568
  isDone: false,
@@ -2502,8 +2577,9 @@ const useInfiniteQueryInternal = (query, args, options) => {
2502
2577
  enabled,
2503
2578
  meta,
2504
2579
  queryOptions,
2505
- prefetchedFirstPage,
2506
- placeholderData
2580
+ placeholderData,
2581
+ authType,
2582
+ isAuthLoading
2507
2583
  ]),
2508
2584
  combine: useCallback((results) => {
2509
2585
  const allItems = [];
@@ -2689,6 +2765,7 @@ function useInfiniteQuery(infiniteOptions) {
2689
2765
  ]);
2690
2766
  const enabled = useMemo(() => resolveEnabled(!shouldSkip, factoryEnabled), [shouldSkip, factoryEnabled]);
2691
2767
  const result = useInfiniteQueryInternal(query, args, {
2768
+ authType,
2692
2769
  limit,
2693
2770
  ...queryOptions,
2694
2771
  enabled
@@ -210,11 +210,15 @@ declare const FetchAccessTokenContext: solid_js0.Context<FetchAccessTokenFn | nu
210
210
  /** Get fetchAccessToken from context (available immediately, no race condition) */
211
211
  declare const useFetchAccessToken: () => FetchAccessTokenFn | null;
212
212
  type ConvexAuthResult = {
213
+ identity: unknown;
213
214
  isAuthenticated: boolean;
214
215
  isLoading: boolean;
215
216
  };
217
+ type ConvexAuthBridgeResult = ConvexAuthResult & {
218
+ authEpoch: number;
219
+ };
216
220
  /** Get auth from bridge context (null if no bridge configured) */
217
- declare const useConvexAuthBridge: () => ConvexAuthResult | null;
221
+ declare const useConvexAuthBridge: () => ConvexAuthBridgeResult | null;
218
222
  type AuthStoreState = {
219
223
  /** Callback when mutation/action called while unauthorized. Throws by default. */onMutationUnauthorized: () => void; /** Callback when query called while unauthorized. Noop by default. */
220
224
  onQueryUnauthorized: (info: {
@@ -225,6 +229,12 @@ type AuthStoreState = {
225
229
  expiresAt: number | null; /** Auth loading state (synced from useConvexAuth for class methods) */
226
230
  isLoading: boolean; /** Auth state (synced from useConvexAuth for class methods) */
227
231
  isAuthenticated: boolean;
232
+ /**
233
+ * Account generation, advanced on every identity transition. Client state
234
+ * that only makes sense inside one account's result set — paginated cursor
235
+ * chains — keys on it so it is rebuilt instead of reused across accounts.
236
+ */
237
+ authEpoch: number;
228
238
  };
229
239
  /** Decode JWT expiration (ms timestamp) from token */
230
240
  declare function decodeJwtExp(token: string): number | null;
@@ -258,6 +268,8 @@ declare function useSafeConvexAuth(): ConvexAuthResult;
258
268
  * @internal
259
269
  */
260
270
  declare function ConvexAuthBridge(props: ParentProps<{
271
+ authEpoch?: number;
272
+ identity?: unknown;
261
273
  isLoading: boolean;
262
274
  isAuthenticated: boolean;
263
275
  }>): JSX.Element;
@@ -369,6 +381,12 @@ declare class ConvexQueryClient {
369
381
  ssrQueryMode: 'consistent' | 'inconsistent';
370
382
  /** Auth store for checking auth state */
371
383
  private authStore?;
384
+ /** In-flight clear shared by overlapping account identity transitions. */
385
+ private authBarrierClear?;
386
+ /** Blocks auth-bound work created while Convex is changing identity. */
387
+ private authSettlementBarrier?;
388
+ /** Latest account transition allowed to restore and refetch observers. */
389
+ private authResetGeneration;
372
390
  /** Delay before unsubscribing when query has no observers */
373
391
  private unsubscribeDelay;
374
392
  /** Payload transformer used across request/response boundaries. */
@@ -381,6 +399,11 @@ declare class ConvexQueryClient {
381
399
  private cancelPendingUnsubscribe;
382
400
  /** Unsubscribe a live Convex subscription (if present) and remove it from the subscription map. */
383
401
  private unsubscribeQueryByHash;
402
+ /**
403
+ * Open a Convex subscription for a query, if the shared gate allows it.
404
+ * Single owner of the subscribe preconditions for every cache-event branch.
405
+ */
406
+ private subscribeQuery;
384
407
  /** Update auth store (for HMR where store may reset) */
385
408
  updateAuthStore(authStore?: AuthStore): void;
386
409
  /** Get current auth state from store */
@@ -390,6 +413,10 @@ declare class ConvexQueryClient {
390
413
  * Needed for useSuspenseQuery which ignores enabled: false.
391
414
  */
392
415
  private shouldSkipSubscription;
416
+ /** Hold new auth-bound requests until the latest Convex identity settles. */
417
+ private beginAuthSettlementBarrier;
418
+ /** Wait through overlapping barriers and stop canceled requests. */
419
+ private waitForAuthSettlement;
393
420
  /** Get QueryClient, throwing if not connected */
394
421
  get queryClient(): QueryClient;
395
422
  /**
@@ -414,6 +441,25 @@ declare class ConvexQueryClient {
414
441
  * Call before logout to prevent UNAUTHORIZED errors during session invalidation.
415
442
  */
416
443
  unsubscribeAuthQueries(): void;
444
+ /**
445
+ * Advance the account generation published by the auth store.
446
+ * Client state that only makes sense inside one account's result set —
447
+ * paginated cursor chains — keys on it, so it is rebuilt instead of reused.
448
+ */
449
+ private bumpAuthEpoch;
450
+ /** Drop auth-bound data without fetching while Convex changes identity. */
451
+ private clearAuthQueries;
452
+ /** Refetch and resubscribe auth-bound queries after Convex settles. */
453
+ private refetchAuthQueries;
454
+ /**
455
+ * Drop every auth-bound cache entry and resubscribe.
456
+ * Call after an identity transition when no separate settlement barrier owns
457
+ * the clear/refetch phases.
458
+ */
459
+ resetAuthQueries(options?: {
460
+ generation?: number;
461
+ refetch?: boolean;
462
+ }): Promise<number>;
417
463
  /**
418
464
  * Batch update all subscriptions.
419
465
  * Called internally when Convex client reconnects.
@@ -1271,6 +1317,7 @@ declare function ConvexProvider(props: ParentProps<{
1271
1317
  declare function ConvexProviderWithAuth(props: ParentProps<{
1272
1318
  client: ConvexClient;
1273
1319
  useAuth: () => {
1320
+ /** Stable account/session identity. Token refreshes must keep this value. */identity?: string | null;
1274
1321
  isLoading: boolean;
1275
1322
  isAuthenticated: boolean;
1276
1323
  fetchAccessToken: AuthTokenFetcher;
@@ -1477,7 +1524,9 @@ declare function useConvexInfiniteQueryOptions<T extends FunctionReference<'quer
1477
1524
  */
1478
1525
  declare function useConvexActionQueryOptions<Action extends FunctionReference<'action'>>(action: Action, args: FunctionArgs<Action> | SkipToken, options?: {
1479
1526
  skipUnauth?: boolean;
1480
- } & DistributiveOmit<SolidQueryOptions<FunctionReturnType<Action>, DefaultError>, ReservedQueryOptions>): ConvexActionOptions<Action>;
1527
+ } & DistributiveOmit<SolidQueryOptions<FunctionReturnType<Action>, DefaultError>, ReservedQueryOptions>): ConvexActionOptions<Action> & {
1528
+ meta: ConvexQueryMeta;
1529
+ };
1481
1530
  /**
1482
1531
  * Hook that returns mutation options for use with useMutation.
1483
1532
  * Wraps the Convex mutation with auth guard logic.
@@ -1,5 +1,5 @@
1
1
  import { getFunctionName } from "convex/server";
2
- import { Show, createComputed, createContext, createEffect, createMemo, createRenderEffect, createSignal, on, onCleanup, onMount, useContext } from "solid-js";
2
+ import { Show, batch, createComputed, createContext, createEffect, createMemo, createRenderEffect, createSignal, on, onCleanup, onMount, useContext } from "solid-js";
3
3
  import { createComponent, memo } from "solid-js/web";
4
4
  import { createStore } from "solid-js/store";
5
5
  import { notifyManager, skipToken, useQueryClient } from "@tanstack/solid-query";
@@ -78,7 +78,8 @@ const defaultState = {
78
78
  token: null,
79
79
  expiresAt: null,
80
80
  isLoading: true,
81
- isAuthenticated: false
81
+ isAuthenticated: false,
82
+ authEpoch: 0
82
83
  };
83
84
  const AuthStoreContext = createContext(null);
84
85
  function useAuthStore() {
@@ -91,7 +92,14 @@ function useAuthStore() {
91
92
  return ctx;
92
93
  }
93
94
  function useAuthValue(key) {
94
- return useAuthStore().get(key);
95
+ const store = useAuthStore();
96
+ const bridgeAuth = useConvexAuthBridge();
97
+ if (!store.store && bridgeAuth) {
98
+ if (key === "authEpoch") return bridgeAuth.authEpoch;
99
+ if (key === "isAuthenticated") return bridgeAuth.isAuthenticated;
100
+ if (key === "isLoading") return bridgeAuth.isLoading;
101
+ }
102
+ return store.get(key);
95
103
  }
96
104
  function AuthProvider(props) {
97
105
  const [state, setState] = createStore({
@@ -125,14 +133,17 @@ function useSafeConvexAuth() {
125
133
  const authStore = useAuthStore();
126
134
  const bridgeAuth = useConvexAuthBridge();
127
135
  return {
136
+ get identity() {
137
+ return bridgeAuth?.identity ?? null;
138
+ },
128
139
  get isAuthenticated() {
129
- if (authStore.store) return authStore.get("isAuthenticated");
130
140
  if (bridgeAuth !== null) return bridgeAuth.isAuthenticated;
141
+ if (authStore.store) return authStore.get("isAuthenticated");
131
142
  return false;
132
143
  },
133
144
  get isLoading() {
134
- if (authStore.store) return authStore.get("isLoading");
135
145
  if (bridgeAuth !== null) return bridgeAuth.isLoading;
146
+ if (authStore.store) return authStore.get("isLoading");
136
147
  return false;
137
148
  }
138
149
  };
@@ -144,6 +155,12 @@ function useSafeConvexAuth() {
144
155
  function ConvexAuthBridge(props) {
145
156
  return createComponent(ConvexAuthBridgeContext.Provider, {
146
157
  value: {
158
+ get authEpoch() {
159
+ return props.authEpoch ?? 0;
160
+ },
161
+ get identity() {
162
+ return props.identity ?? null;
163
+ },
147
164
  get isLoading() {
148
165
  return props.isLoading;
149
166
  },
@@ -991,6 +1008,19 @@ function convexInfiniteQueryOptions(funcRef, args, opts = {}, meta) {
991
1008
  /** Symbol key for attaching FunctionReference to options (non-serializable) */
992
1009
  const FUNC_REF_SYMBOL = Symbol.for("convex.funcRef");
993
1010
 
1011
+ //#endregion
1012
+ //#region src/internal/enabled.ts
1013
+ /**
1014
+ * Combine a computed gate with the caller's `enabled` option.
1015
+ * A predicate is preserved (never collapsed to a boolean) so TanStack Query
1016
+ * keeps evaluating it; `allowed: false` always wins.
1017
+ */
1018
+ function resolveEnabled(allowed, enabled) {
1019
+ if (!allowed) return false;
1020
+ if (typeof enabled === "function") return (query) => enabled(query) !== false;
1021
+ return enabled ?? true;
1022
+ }
1023
+
994
1024
  //#endregion
995
1025
  //#region src/solid/convex-solid.tsx
996
1026
  /** @jsxImportSource solid-js */
@@ -1018,25 +1048,52 @@ function ConvexProvider(props) {
1018
1048
  }
1019
1049
  function ConvexProviderWithAuth(props) {
1020
1050
  const client = props.client;
1051
+ const [authEpoch, setAuthEpoch] = createSignal(0);
1052
+ const [convexIdentity, setConvexIdentity] = createSignal(null);
1021
1053
  const [isConvexLoading, setIsConvexLoading] = createSignal(true);
1022
1054
  const [isConvexAuthenticated, setIsConvexAuthenticated] = createSignal(false);
1023
- createEffect(() => {
1024
- const auth = props.useAuth();
1025
- const loading = auth.isLoading;
1026
- const authenticated = auth.isAuthenticated;
1027
- if (loading) return;
1028
- if (!authenticated) {
1029
- client.clearAuth();
1055
+ const settleAuth = (nextIdentity, isAuthenticated) => {
1056
+ batch(() => {
1057
+ setConvexIdentity(nextIdentity);
1058
+ setAuthEpoch((epoch) => epoch + 1);
1059
+ setIsConvexAuthenticated(isAuthenticated);
1030
1060
  setIsConvexLoading(false);
1031
- setIsConvexAuthenticated(false);
1061
+ });
1062
+ };
1063
+ const authSnapshot = createMemo(() => props.useAuth(), void 0, { equals: false });
1064
+ const isAuthLoading = createMemo(() => authSnapshot().isLoading);
1065
+ const isAuthenticated = createMemo(() => authSnapshot().isAuthenticated);
1066
+ const fetchAccessToken = createMemo(() => authSnapshot().fetchAccessToken);
1067
+ const identity = createMemo(() => {
1068
+ const snapshot = authSnapshot();
1069
+ return snapshot.identity === void 0 ? Symbol("legacy-auth-transition") : snapshot.identity;
1070
+ });
1071
+ let authBindingGeneration = 0;
1072
+ createEffect(on([
1073
+ isAuthLoading,
1074
+ isAuthenticated,
1075
+ fetchAccessToken,
1076
+ identity
1077
+ ], () => {
1078
+ const generation = ++authBindingGeneration;
1079
+ if (isAuthLoading()) {
1080
+ setIsConvexLoading(true);
1032
1081
  return;
1033
1082
  }
1034
- client.setAuth(auth.fetchAccessToken, (isAuth) => {
1035
- setIsConvexLoading(false);
1036
- setIsConvexAuthenticated(isAuth);
1083
+ const nextIdentity = identity();
1084
+ setIsConvexLoading(true);
1085
+ if (!isAuthenticated()) {
1086
+ client.clearAuth();
1087
+ settleAuth(nextIdentity, false);
1088
+ return;
1089
+ }
1090
+ client.setAuth(fetchAccessToken(), (isAuth) => {
1091
+ if (generation !== authBindingGeneration) return;
1092
+ settleAuth(nextIdentity, isAuth);
1037
1093
  });
1038
- });
1094
+ }));
1039
1095
  onCleanup(() => {
1096
+ authBindingGeneration += 1;
1040
1097
  client.clearAuth();
1041
1098
  });
1042
1099
  return createComponent(ConvexContext.Provider, {
@@ -1045,6 +1102,12 @@ function ConvexProviderWithAuth(props) {
1045
1102
  },
1046
1103
  get children() {
1047
1104
  return createComponent(ConvexAuthBridge, {
1105
+ get authEpoch() {
1106
+ return authEpoch();
1107
+ },
1108
+ get identity() {
1109
+ return convexIdentity();
1110
+ },
1048
1111
  get isAuthenticated() {
1049
1112
  return isConvexAuthenticated();
1050
1113
  },
@@ -1110,14 +1173,15 @@ function useConvexQueryOptions(funcRef, args, options) {
1110
1173
  skipUnauth: options?.skipUnauth
1111
1174
  });
1112
1175
  const baseOptions = convexQuery(funcRef, isSkipped ? {} : args);
1113
- const { skipUnauth: _, subscribe, ...queryOptions } = options ?? {};
1176
+ const { enabled: userEnabled, skipUnauth, subscribe, ...queryOptions } = options ?? {};
1114
1177
  return {
1115
1178
  ...baseOptions,
1116
1179
  ...queryOptions,
1117
- enabled: isSkipped ? false : !authSkip.shouldSkip,
1180
+ enabled: resolveEnabled(!(isSkipped || authSkip.shouldSkip), userEnabled),
1118
1181
  meta: {
1119
1182
  ...baseOptions.meta,
1120
1183
  authType: authSkip.authType,
1184
+ skipUnauth,
1121
1185
  subscribe: subscribe !== false
1122
1186
  }
1123
1187
  };
@@ -1155,13 +1219,15 @@ function useConvexInfiniteQueryOptions(funcRef, args, opts) {
1155
1219
  enabled: isSkipped ? false : enabledOpt,
1156
1220
  skipUnauth: opts.skipUnauth
1157
1221
  });
1158
- const enabled = isSkipped || authSkip.shouldSkip ? false : enabledOpt;
1159
1222
  const baseOptions = convexInfiniteQueryOptions(funcRef, isSkipped ? {} : args, {
1160
1223
  ...opts,
1161
- enabled
1224
+ enabled: void 0
1162
1225
  }, meta);
1163
1226
  return {
1164
1227
  ...baseOptions,
1228
+ get enabled() {
1229
+ return resolveEnabled(!(isSkipped || authSkip.shouldSkip), opts.enabled);
1230
+ },
1165
1231
  meta: {
1166
1232
  ...baseOptions.meta,
1167
1233
  authType: authSkip.authType
@@ -1195,11 +1261,16 @@ function useConvexActionQueryOptions(action, args, options) {
1195
1261
  skipUnauth: options?.skipUnauth
1196
1262
  });
1197
1263
  const baseOptions = convexAction(action, isSkipped ? {} : args);
1198
- const { skipUnauth: _, ...queryOptions } = options ?? {};
1264
+ const { enabled: userEnabled, skipUnauth, ...queryOptions } = options ?? {};
1199
1265
  return {
1200
1266
  ...baseOptions,
1201
1267
  ...queryOptions,
1202
- enabled: isSkipped ? false : !authSkip.shouldSkip
1268
+ enabled: resolveEnabled(!(isSkipped || authSkip.shouldSkip), userEnabled),
1269
+ meta: {
1270
+ ...baseOptions.meta,
1271
+ authType: authSkip.authType,
1272
+ skipUnauth
1273
+ }
1203
1274
  };
1204
1275
  }
1205
1276
  /**
@@ -1528,7 +1599,39 @@ function createCRPCContext(options) {
1528
1599
  const HttpProxyContext = createContext(void 0);
1529
1600
  function CRPCProvider(props) {
1530
1601
  const authStore = useAuthStore();
1602
+ const bridgeAuth = useConvexAuthBridge();
1603
+ const safeAuth = useSafeConvexAuth();
1604
+ const auth = bridgeAuth ?? safeAuth;
1531
1605
  const fetchAccessToken = useFetchAccessToken();
1606
+ props.convexQueryClient.updateAuthStore(authStore.store ? authStore : void 0);
1607
+ let previousAuth;
1608
+ let authGeneration = 0;
1609
+ let transitionClear;
1610
+ createEffect(() => {
1611
+ const generation = ++authGeneration;
1612
+ const currentAuth = {
1613
+ identity: auth.identity,
1614
+ isAuthenticated: auth.isAuthenticated,
1615
+ isLoading: auth.isLoading
1616
+ };
1617
+ const previous = previousAuth;
1618
+ previousAuth = currentAuth;
1619
+ if (currentAuth.isLoading) {
1620
+ if (!previous?.isLoading) transitionClear = props.convexQueryClient.resetAuthQueries({ refetch: false });
1621
+ return;
1622
+ }
1623
+ if (previous?.isLoading) {
1624
+ const pendingClear = transitionClear;
1625
+ transitionClear = void 0;
1626
+ (async () => {
1627
+ const clientGeneration = await pendingClear;
1628
+ if (generation !== authGeneration) return;
1629
+ await props.convexQueryClient.resetAuthQueries({ generation: clientGeneration });
1630
+ })();
1631
+ return;
1632
+ }
1633
+ if (!previous || previous.identity !== currentAuth.identity || previous.isAuthenticated !== currentAuth.isAuthenticated) props.convexQueryClient.resetAuthQueries();
1634
+ });
1532
1635
  const proxy = createCRPCOptionsProxy(api, meta, options.transformer);
1533
1636
  const vanillaClient = createVanillaCRPCProxy(api, meta, props.convexClient, options.transformer);
1534
1637
  const httpProxy = (() => {
@@ -1770,6 +1873,56 @@ function createAuthMutations(authClient) {
1770
1873
  };
1771
1874
  }
1772
1875
 
1876
+ //#endregion
1877
+ //#region src/internal/auth-reset.ts
1878
+ /**
1879
+ * Erase the cached result of every auth-bound query.
1880
+ *
1881
+ * `queryClient.resetQueries()` is not enough. It restores each query's
1882
+ * `initialState`, and query-core derives that from `initialData` when the query
1883
+ * is built, never re-deriving it once real data lands. An auth-bound entry
1884
+ * therefore comes back holding the previous account's rows marked `success`,
1885
+ * and nothing corrects it: Convex query options set `staleTime: Infinity` with
1886
+ * every refetch trigger off, and `resetQueries` only refetches entries that are
1887
+ * currently active.
1888
+ *
1889
+ * Every entry is removed so query-core forgets both its current state and its
1890
+ * private `initialState`. Mounted observers are rebound with `initialData`
1891
+ * removed, creating a pristine replacement query that future public resets
1892
+ * cannot use to resurrect the previous account's rows.
1893
+ */
1894
+ async function clearAuthBoundQueries(cache, isAuthBound) {
1895
+ const authQueries = cache.getAll().filter((query) => isAuthBound(query));
1896
+ const restoreObservers = [];
1897
+ await Promise.all(authQueries.map((query) => query.cancel({ silent: true })));
1898
+ for (const query of authQueries) {
1899
+ const observers = [...query.observers];
1900
+ cache.remove(query);
1901
+ for (const observer of observers) {
1902
+ const previousOptions = observer.options;
1903
+ observer.setOptions({
1904
+ ...observer.options,
1905
+ enabled: false,
1906
+ initialData: void 0,
1907
+ placeholderData: void 0
1908
+ });
1909
+ const suspendedOptions = observer.options;
1910
+ restoreObservers.push(() => {
1911
+ const currentOptions = observer.options;
1912
+ observer.setOptions({
1913
+ ...currentOptions,
1914
+ enabled: observer.options === suspendedOptions ? previousOptions.enabled : currentOptions.enabled,
1915
+ initialData: void 0,
1916
+ placeholderData: void 0
1917
+ });
1918
+ });
1919
+ }
1920
+ }
1921
+ return () => {
1922
+ for (const restoreObserver of restoreObservers) restoreObserver();
1923
+ };
1924
+ }
1925
+
1773
1926
  //#endregion
1774
1927
  //#region src/internal/query-key.ts
1775
1928
  /**
@@ -1828,6 +1981,31 @@ function createHashFn(fallback = hashKey) {
1828
1981
  };
1829
1982
  }
1830
1983
 
1984
+ //#endregion
1985
+ //#region src/internal/subscription-gate.ts
1986
+ /** Read kitcn's meta off a TanStack query. */
1987
+ function readConvexQueryMeta(query) {
1988
+ return query.meta;
1989
+ }
1990
+ /**
1991
+ * Auth-bound queries are cleared and resubscribed on an identity transition so
1992
+ * one account never renders another account's cached rows.
1993
+ */
1994
+ function isAuthBoundQuery(query) {
1995
+ const authType = readConvexQueryMeta(query)?.authType;
1996
+ return authType === "required" || authType === "optional";
1997
+ }
1998
+ /** Whether a Convex subscription may be opened for this query. */
1999
+ function canSubscribeQuery(query, opts) {
2000
+ if (opts.isSubscribed) return false;
2001
+ const meta = readConvexQueryMeta(query);
2002
+ if (meta?.subscribe === false) return false;
2003
+ if (query.getObserversCount() === 0) return false;
2004
+ if (query.isDisabled()) return false;
2005
+ if (opts.shouldSkipSubscription(meta?.authType)) return false;
2006
+ return true;
2007
+ }
2008
+
1831
2009
  //#endregion
1832
2010
  //#region src/solid/client.ts
1833
2011
  /**
@@ -1920,6 +2098,12 @@ var ConvexQueryClient = class {
1920
2098
  ssrQueryMode;
1921
2099
  /** Auth store for checking auth state */
1922
2100
  authStore;
2101
+ /** In-flight clear shared by overlapping account identity transitions. */
2102
+ authBarrierClear;
2103
+ /** Blocks auth-bound work created while Convex is changing identity. */
2104
+ authSettlementBarrier;
2105
+ /** Latest account transition allowed to restore and refetch observers. */
2106
+ authResetGeneration = 0;
1923
2107
  /** Delay before unsubscribing when query has no observers */
1924
2108
  unsubscribeDelay;
1925
2109
  /** Payload transformer used across request/response boundaries. */
@@ -1947,6 +2131,18 @@ var ConvexQueryClient = class {
1947
2131
  sub.unsubscribe();
1948
2132
  delete this.subscriptions[queryHash];
1949
2133
  }
2134
+ /**
2135
+ * Open a Convex subscription for a query, if the shared gate allows it.
2136
+ * Single owner of the subscribe preconditions for every cache-event branch.
2137
+ */
2138
+ subscribeQuery(query) {
2139
+ if (!canSubscribeQuery(query, {
2140
+ isSubscribed: !!this.subscriptions[query.queryHash],
2141
+ shouldSkipSubscription: (authType) => this.shouldSkipSubscription(authType)
2142
+ })) return;
2143
+ const [, funcName, args] = query.queryKey;
2144
+ this.createSubscription(query.queryHash, funcName, args, query.queryKey);
2145
+ }
1950
2146
  /** Update auth store (for HMR where store may reset) */
1951
2147
  updateAuthStore(authStore) {
1952
2148
  this.authStore = authStore;
@@ -1966,12 +2162,30 @@ var ConvexQueryClient = class {
1966
2162
  * Needed for useSuspenseQuery which ignores enabled: false.
1967
2163
  */
1968
2164
  shouldSkipSubscription(authType) {
1969
- if (!authType || !this.authStore) return false;
2165
+ if (!authType) return false;
2166
+ if (this.authSettlementBarrier) return true;
2167
+ if (!this.authStore) return false;
1970
2168
  const authState = this.getAuthState();
1971
2169
  if (authState?.isLoading) return true;
1972
2170
  if (authType === "required" && !authState?.isAuthenticated) return true;
1973
2171
  return false;
1974
2172
  }
2173
+ /** Hold new auth-bound requests until the latest Convex identity settles. */
2174
+ beginAuthSettlementBarrier() {
2175
+ if (this.authSettlementBarrier) return;
2176
+ let resolve = () => {};
2177
+ this.authSettlementBarrier = {
2178
+ promise: new Promise((resolvePromise) => {
2179
+ resolve = resolvePromise;
2180
+ }),
2181
+ resolve
2182
+ };
2183
+ }
2184
+ /** Wait through overlapping barriers and stop canceled requests. */
2185
+ async waitForAuthSettlement(signal) {
2186
+ while (this.authSettlementBarrier) await this.authSettlementBarrier.promise;
2187
+ signal?.throwIfAborted();
2188
+ }
1975
2189
  /** Get QueryClient, throwing if not connected */
1976
2190
  get queryClient() {
1977
2191
  if (!this._queryClient) throw new Error("ConvexQueryClient not connected to TanStack QueryClient.");
@@ -2034,6 +2248,62 @@ var ConvexQueryClient = class {
2034
2248
  }
2035
2249
  }
2036
2250
  /**
2251
+ * Advance the account generation published by the auth store.
2252
+ * Client state that only makes sense inside one account's result set —
2253
+ * paginated cursor chains — keys on it, so it is rebuilt instead of reused.
2254
+ */
2255
+ bumpAuthEpoch() {
2256
+ if (!this.authStore) return;
2257
+ this.authStore.set("authEpoch", this.authStore.get("authEpoch") + 1);
2258
+ }
2259
+ /** Drop auth-bound data without fetching while Convex changes identity. */
2260
+ async clearAuthQueries() {
2261
+ const queryCache = this.queryClient.getQueryCache();
2262
+ for (const query of queryCache.getAll()) {
2263
+ if (!isAuthBoundQuery(query)) continue;
2264
+ this.cancelPendingUnsubscribe(query.queryHash);
2265
+ this.unsubscribeQueryByHash(query.queryHash);
2266
+ }
2267
+ this.bumpAuthEpoch();
2268
+ return clearAuthBoundQueries(queryCache, (query) => isAuthBoundQuery(query));
2269
+ }
2270
+ /** Refetch and resubscribe auth-bound queries after Convex settles. */
2271
+ async refetchAuthQueries(generation) {
2272
+ const queryCache = this.queryClient.getQueryCache();
2273
+ await this.queryClient.refetchQueries({
2274
+ predicate: (query) => isAuthBoundQuery(query),
2275
+ type: "active"
2276
+ });
2277
+ if (generation !== this.authResetGeneration) return;
2278
+ for (const query of queryCache.getAll()) if (isAuthBoundQuery(query)) this.subscribeQuery(query);
2279
+ }
2280
+ /**
2281
+ * Drop every auth-bound cache entry and resubscribe.
2282
+ * Call after an identity transition when no separate settlement barrier owns
2283
+ * the clear/refetch phases.
2284
+ */
2285
+ async resetAuthQueries(options = {}) {
2286
+ if (options.refetch === false) {
2287
+ const generation = ++this.authResetGeneration;
2288
+ this.beginAuthSettlementBarrier();
2289
+ this.authBarrierClear ??= this.clearAuthQueries();
2290
+ await this.authBarrierClear;
2291
+ return generation;
2292
+ }
2293
+ const generation = options.generation ?? ++this.authResetGeneration;
2294
+ if (generation !== this.authResetGeneration) return generation;
2295
+ this.authBarrierClear ??= this.clearAuthQueries();
2296
+ const restoreObservers = await this.authBarrierClear;
2297
+ if (generation !== this.authResetGeneration) return generation;
2298
+ this.authBarrierClear = void 0;
2299
+ const settlementBarrier = this.authSettlementBarrier;
2300
+ this.authSettlementBarrier = void 0;
2301
+ settlementBarrier?.resolve();
2302
+ restoreObservers();
2303
+ await this.refetchAuthQueries(generation);
2304
+ return generation;
2305
+ }
2306
+ /**
2037
2307
  * Batch update all subscriptions.
2038
2308
  * Called internally when Convex client reconnects.
2039
2309
  */
@@ -2107,26 +2377,13 @@ var ConvexQueryClient = class {
2107
2377
  this.cancelPendingUnsubscribe(event.query.queryHash);
2108
2378
  this.unsubscribeQueryByHash(event.query.queryHash);
2109
2379
  break;
2110
- case "added": {
2111
- const meta = event.query.meta;
2112
- if (meta?.subscribe === false) break;
2113
- const [, funcName, args] = event.query.queryKey;
2114
- if (event.query.getObserversCount() === 0) break;
2115
- if (this.shouldSkipSubscription(meta?.authType)) break;
2116
- this.createSubscription(event.query.queryHash, funcName, args, event.query.queryKey);
2380
+ case "added":
2381
+ this.subscribeQuery(event.query);
2117
2382
  break;
2118
- }
2119
- case "observerAdded": {
2383
+ case "observerAdded":
2120
2384
  this.cancelPendingUnsubscribe(event.query.queryHash);
2121
- if (this.subscriptions[event.query.queryHash]) break;
2122
- if (event.query.options.enabled === false) break;
2123
- const meta = event.query.meta;
2124
- if (meta?.subscribe === false) break;
2125
- const [, funcName, args] = event.query.queryKey;
2126
- if (this.shouldSkipSubscription(meta?.authType)) break;
2127
- this.createSubscription(event.query.queryHash, funcName, args, event.query.queryKey);
2385
+ this.subscribeQuery(event.query);
2128
2386
  break;
2129
- }
2130
2387
  case "observerRemoved":
2131
2388
  if (event.query.getObserversCount() === 0 && this.subscriptions[event.query.queryHash]) {
2132
2389
  const queryHash = event.query.queryHash;
@@ -2142,7 +2399,7 @@ var ConvexQueryClient = class {
2142
2399
  if (event.action.type === "setState" && event.action.setStateOptions?.meta === "set by ConvexQueryClient") break;
2143
2400
  break;
2144
2401
  case "observerOptionsUpdated": {
2145
- const isDisabled = event.query.options.enabled === false;
2402
+ const isDisabled = event.query.isDisabled();
2146
2403
  const isSubscribed = !!this.subscriptions[event.query.queryHash];
2147
2404
  if (isDisabled && isSubscribed) {
2148
2405
  this.cancelPendingUnsubscribe(event.query.queryHash);
@@ -2150,11 +2407,7 @@ var ConvexQueryClient = class {
2150
2407
  break;
2151
2408
  }
2152
2409
  if (isSubscribed || isDisabled) break;
2153
- const meta = event.query.meta;
2154
- if (meta?.subscribe === false) break;
2155
- const [, funcName, args] = event.query.queryKey;
2156
- if (this.shouldSkipSubscription(meta?.authType)) break;
2157
- this.createSubscription(event.query.queryHash, funcName, args, event.query.queryKey);
2410
+ this.subscribeQuery(event.query);
2158
2411
  break;
2159
2412
  }
2160
2413
  }
@@ -2197,6 +2450,7 @@ var ConvexQueryClient = class {
2197
2450
  return async (context) => {
2198
2451
  const { queryKey, meta: rawMeta } = context;
2199
2452
  const meta = rawMeta;
2453
+ if (!isServer && meta?.authType) await this.waitForAuthSettlement(context.signal);
2200
2454
  if (isConvexSkipped(queryKey)) throw new Error("Skipped query should not actually run, should { enabled: false }");
2201
2455
  if (isConvexQuery(queryKey)) {
2202
2456
  const [, funcName, args] = queryKey;
@@ -2268,6 +2522,38 @@ function throwBecauseNotConvexQuery(context) {
2268
2522
  throw new Error(`Query key is not for a Convex Query: ${context.queryKey}`);
2269
2523
  }
2270
2524
 
2525
+ //#endregion
2526
+ //#region src/internal/jwt.ts
2527
+ const VOLATILE_JWT_CLAIMS = new Set([
2528
+ "exp",
2529
+ "iat",
2530
+ "jti",
2531
+ "nbf"
2532
+ ]);
2533
+ const decodeJwtPayload = (token) => {
2534
+ try {
2535
+ const segment = token.split(".")[1];
2536
+ if (!segment) return null;
2537
+ const binary = atob(segment.replaceAll("-", "+").replaceAll("_", "/"));
2538
+ const payload = JSON.parse(new TextDecoder().decode(Uint8Array.from(binary, (char) => char.charCodeAt(0))));
2539
+ return typeof payload === "object" && payload !== null ? payload : null;
2540
+ } catch {
2541
+ return null;
2542
+ }
2543
+ };
2544
+ const stableStringify = (value) => {
2545
+ if (value === null || typeof value !== "object") return JSON.stringify(value);
2546
+ if (Array.isArray(value)) return `[${value.map(stableStringify).join(",")}]`;
2547
+ return `{${Object.entries(value).filter(([, claim]) => claim !== void 0).sort(([a], [b]) => a < b ? -1 : 1).map(([key, claim]) => `${JSON.stringify(key)}:${stableStringify(claim)}`).join(",")}}`;
2548
+ };
2549
+ const decodeJwtIdentity = (token) => {
2550
+ const payload = decodeJwtPayload(token);
2551
+ if (!payload) return null;
2552
+ const claims = {};
2553
+ for (const [key, claim] of Object.entries(payload)) if (!VOLATILE_JWT_CLAIMS.has(key)) claims[key] = claim;
2554
+ return stableStringify(claims);
2555
+ };
2556
+
2271
2557
  //#endregion
2272
2558
  //#region src/solid/convex-auth-provider.tsx
2273
2559
  /** @jsxImportSource solid-js */
@@ -2287,6 +2573,13 @@ const hasActiveSessionData = (session) => {
2287
2573
  if (!session || typeof session !== "object") return false;
2288
2574
  return Boolean(session.session);
2289
2575
  };
2576
+ const getSessionId = (sessionData) => {
2577
+ if (!sessionData || typeof sessionData !== "object") return;
2578
+ const session = sessionData.session;
2579
+ if (!session || typeof session !== "object") return;
2580
+ const id = session.id;
2581
+ return typeof id === "string" ? id : void 0;
2582
+ };
2290
2583
  /**
2291
2584
  * Unified auth provider for Convex + Better Auth (SolidJS).
2292
2585
  * Handles token sync and auth callbacks.
@@ -2336,21 +2629,40 @@ function ConvexAuthProviderInner(props) {
2336
2629
  const authStore = useAuthStore();
2337
2630
  const sessionAccessor = props.authClient.useSession();
2338
2631
  let pendingTokenPromise = null;
2632
+ let pendingTokenSessionId;
2633
+ let authIdentity = null;
2634
+ let identityClaims = null;
2635
+ let identityInitialized = false;
2636
+ let identitySessionId;
2637
+ let tokenSessionId;
2638
+ let tokenSessionInitialized = false;
2339
2639
  createEffect(() => {
2340
2640
  const sessionState = sessionAccessor();
2341
2641
  const session = sessionState.data;
2342
2642
  const isPending = sessionState.isPending;
2643
+ const sessionId = getSessionId(session);
2343
2644
  if (!hasActiveSessionData(session) && !isPending) {
2344
2645
  authStore.set("token", null);
2345
2646
  authStore.set("expiresAt", null);
2346
2647
  authStore.set("isAuthenticated", false);
2648
+ tokenSessionId = void 0;
2649
+ tokenSessionInitialized = false;
2650
+ } else if (hasActiveSessionData(session)) {
2651
+ if (!tokenSessionInitialized && authStore.get("token") !== null || tokenSessionInitialized && sessionId !== tokenSessionId) {
2652
+ authStore.set("token", null);
2653
+ authStore.set("expiresAt", null);
2654
+ }
2655
+ tokenSessionId = sessionId;
2656
+ tokenSessionInitialized = true;
2347
2657
  }
2348
2658
  });
2349
2659
  const fetchAccessToken = async ({ forceRefreshToken = false } = {}) => {
2350
2660
  const sessionState = sessionAccessor();
2351
2661
  const currentSession = sessionState.data;
2352
2662
  const currentIsPending = sessionState.isPending;
2353
- if (!hasActiveSessionData(currentSession)) {
2663
+ const hasSession = hasActiveSessionData(currentSession);
2664
+ const currentSessionId = getSessionId(currentSession);
2665
+ if (!hasSession) {
2354
2666
  if (!currentIsPending) {
2355
2667
  authStore.set("token", null);
2356
2668
  authStore.set("expiresAt", null);
@@ -2360,11 +2672,17 @@ function ConvexAuthProviderInner(props) {
2360
2672
  const cachedToken = authStore.get("token");
2361
2673
  const expiresAt = authStore.get("expiresAt");
2362
2674
  const timeRemaining = expiresAt ? expiresAt - Date.now() : 0;
2363
- if (!forceRefreshToken && cachedToken && expiresAt && timeRemaining >= 6e4) return cachedToken;
2364
- if (!forceRefreshToken && pendingTokenPromise) return pendingTokenPromise;
2675
+ if (!forceRefreshToken && cachedToken && expiresAt && currentSessionId === tokenSessionId && timeRemaining >= 6e4) return cachedToken;
2676
+ if (!forceRefreshToken && pendingTokenPromise && pendingTokenSessionId === currentSessionId) return pendingTokenPromise;
2365
2677
  const fetchOptions = { throw: false };
2366
- if (cachedToken && decodeJwtExp(cachedToken) === null) fetchOptions.headers = { Authorization: `Bearer ${cachedToken}` };
2367
- pendingTokenPromise = props.authClient.convex.token({ fetchOptions }).then((result) => {
2678
+ if (cachedToken && currentSessionId === tokenSessionId && decodeJwtExp(cachedToken) === null) fetchOptions.headers = { Authorization: `Bearer ${cachedToken}` };
2679
+ const sessionStillOwnsRequest = () => {
2680
+ const latestSession = sessionAccessor().data;
2681
+ return hasActiveSessionData(latestSession) && getSessionId(latestSession) === currentSessionId;
2682
+ };
2683
+ let tokenPromise;
2684
+ tokenPromise = props.authClient.convex.token({ fetchOptions }).then((result) => {
2685
+ if (!sessionStillOwnsRequest()) return null;
2368
2686
  const jwt = result.data?.token || null;
2369
2687
  if (jwt) {
2370
2688
  const exp = decodeJwtExp(jwt);
@@ -2376,21 +2694,47 @@ function ConvexAuthProviderInner(props) {
2376
2694
  authStore.set("expiresAt", null);
2377
2695
  return null;
2378
2696
  }).catch((error) => {
2697
+ if (!sessionStillOwnsRequest()) return null;
2379
2698
  authStore.set("token", null);
2380
2699
  authStore.set("expiresAt", null);
2381
2700
  console.error("[fetchAccessToken] error", error);
2382
2701
  return null;
2383
2702
  }).finally(() => {
2384
- pendingTokenPromise = null;
2703
+ if (pendingTokenPromise === tokenPromise) {
2704
+ pendingTokenPromise = null;
2705
+ pendingTokenSessionId = void 0;
2706
+ }
2385
2707
  });
2386
- return pendingTokenPromise;
2708
+ pendingTokenPromise = tokenPromise;
2709
+ pendingTokenSessionId = currentSessionId;
2710
+ return tokenPromise;
2387
2711
  };
2388
2712
  const useAuth = () => {
2389
2713
  const sessionState = sessionAccessor();
2390
2714
  const hasSession = hasActiveSessionData(sessionState.data);
2391
2715
  const sessionMissing = !hasSession && !sessionState.isPending;
2392
2716
  const token = authStore.get("token");
2717
+ const sessionId = getSessionId(sessionState.data);
2718
+ const claims = token && tokenSessionInitialized && sessionId === tokenSessionId ? decodeJwtIdentity(token) : null;
2719
+ const sessionChanged = identityInitialized && sessionId !== identitySessionId;
2720
+ if (!identityInitialized || sessionChanged) {
2721
+ identityInitialized = true;
2722
+ identitySessionId = sessionId;
2723
+ identityClaims = sessionChanged ? null : claims;
2724
+ authIdentity = !sessionChanged && claims ? JSON.stringify({
2725
+ claims,
2726
+ sessionId: sessionId ?? null
2727
+ }) : sessionId ?? null;
2728
+ } else if (claims && identityClaims === null) identityClaims = claims;
2729
+ else if (claims && claims !== identityClaims) {
2730
+ identityClaims = claims;
2731
+ authIdentity = JSON.stringify({
2732
+ claims,
2733
+ sessionId: sessionId ?? null
2734
+ });
2735
+ }
2393
2736
  return {
2737
+ identity: authIdentity,
2394
2738
  isLoading: sessionState.isPending && !token,
2395
2739
  isAuthenticated: sessionMissing ? false : hasSession || token !== null,
2396
2740
  fetchAccessToken
@@ -2543,15 +2887,8 @@ function createQueriesResults(queries) {
2543
2887
  //#endregion
2544
2888
  //#region src/solid/use-infinite-query.ts
2545
2889
  const PAGINATION_KEY_PREFIX = "__pagination__";
2546
- const paginationIdStore = /* @__PURE__ */ new Map();
2547
2890
  let paginationIdCounter = 0;
2548
- const getOrCreatePaginationId = (storeKey) => {
2549
- const existing = paginationIdStore.get(storeKey);
2550
- if (existing !== void 0) return existing;
2551
- const newId = ++paginationIdCounter;
2552
- paginationIdStore.set(storeKey, newId);
2553
- return newId;
2554
- };
2891
+ const createPaginationId = () => ++paginationIdCounter;
2555
2892
  /** Read the identity of a Convex document, tolerating `id` and `_id` shapes */
2556
2893
  const getItemId = (item) => {
2557
2894
  const doc = item;
@@ -2682,8 +3019,9 @@ const useStaleCursorRecovery = ({ argsObject, combined, limit, pageResults, setS
2682
3019
  * Use `useInfiniteQuery` for the public API with auth handling.
2683
3020
  */
2684
3021
  const useInfiniteQueryInternal = (query, args, options) => {
2685
- const { limit, enabled, placeholderData, ...queryOptions } = options;
3022
+ const { limit, authType, enabled, placeholderData, ...queryOptions } = options;
2686
3023
  const safeAuth = useSafeConvexAuth();
3024
+ const authEpoch = () => useAuthValue("authEpoch");
2687
3025
  const meta = useMeta();
2688
3026
  const queryClient = useQueryClient();
2689
3027
  const prefetchedFirstPage = createMemo(() => {
@@ -2698,7 +3036,7 @@ const useInfiniteQueryInternal = (query, args, options) => {
2698
3036
  ];
2699
3037
  return queryClient.getQueryData(serverQueryKey) ?? null;
2700
3038
  });
2701
- const skip = createMemo(() => !prefetchedFirstPage() && (safeAuth.isLoading || enabled === false));
3039
+ const skip = createMemo(() => !prefetchedFirstPage() && (safeAuth.isLoading || enabled?.() === false));
2702
3040
  const getPaginationState = (key) => {
2703
3041
  const queryKey = [PAGINATION_KEY_PREFIX, key];
2704
3042
  return queryClient.getQueryData(queryKey);
@@ -2710,10 +3048,11 @@ const useInfiniteQueryInternal = (query, args, options) => {
2710
3048
  const argsObject = createMemo(() => skip() ? {} : args);
2711
3049
  const storeKey = createMemo(() => JSON.stringify({
2712
3050
  query: getFunctionName(query),
2713
- args: argsObject()
3051
+ args: argsObject(),
3052
+ ...authType ? { authEpoch: authEpoch() } : {}
2714
3053
  }));
2715
3054
  const createInitialState = () => {
2716
- const id = getOrCreatePaginationId(storeKey());
3055
+ const id = createPaginationId();
2717
3056
  return {
2718
3057
  id,
2719
3058
  nextPageKey: 1,
@@ -2790,10 +3129,9 @@ const useInfiniteQueryInternal = (query, args, options) => {
2790
3129
  const pageArgs = state().queries[key]?.args;
2791
3130
  return {
2792
3131
  ...convexQuery(query, pageArgs ? (({ __paginationId, ...rest }) => rest)(pageArgs) : "skip", meta),
2793
- enabled: !skip() && !!state().queries[key],
3132
+ enabled: resolveEnabled(!skip() && !!state().queries[key] && (!authType || !safeAuth.isLoading), enabled?.()),
2794
3133
  structuralSharing: false,
2795
3134
  ...queryOptions ?? {},
2796
- ...index === 0 && prefetchedFirstPage() ? { initialData: prefetchedFirstPage() } : {},
2797
3135
  ...index === 0 && placeholderData ? { placeholderData: {
2798
3136
  page: placeholderData,
2799
3137
  isDone: false,
@@ -2941,34 +3279,36 @@ function useInfiniteQuery(infiniteOptions) {
2941
3279
  const query = infiniteOptions[FUNC_REF_SYMBOL];
2942
3280
  const onQueryUnauthorized = useAuthValue("onQueryUnauthorized");
2943
3281
  const safeAuth = useSafeConvexAuth();
2944
- const { queryKey: _queryKey, staleTime: _staleTime, refetchInterval: _refetchInterval, refetchOnMount: _refetchOnMount, refetchOnReconnect: _refetchOnReconnect, refetchOnWindowFocus: _refetchOnWindowFocus, enabled: factoryEnabled, meta, ...queryOptions } = infiniteOptions;
3282
+ const { queryKey: _queryKey, staleTime: _staleTime, refetchInterval: _refetchInterval, refetchOnMount: _refetchOnMount, refetchOnReconnect: _refetchOnReconnect, refetchOnWindowFocus: _refetchOnWindowFocus, enabled: _enabled, meta, ...queryOptions } = infiniteOptions;
2945
3283
  const { queryName, args, limit, authType, skipUnauth } = meta;
2946
3284
  const skipUnauthFinal = skipUnauth ?? false;
2947
- const isUnauthorized = authType === "required" && !safeAuth.isLoading && !safeAuth.isAuthenticated;
2948
- const shouldSkip = factoryEnabled === false || authType === "required" && safeAuth.isLoading || authType === "required" && !safeAuth.isAuthenticated;
3285
+ const factoryEnabled = () => infiniteOptions.enabled;
3286
+ const isUnauthorized = createMemo(() => authType === "required" && !safeAuth.isLoading && !safeAuth.isAuthenticated);
3287
+ const shouldSkip = createMemo(() => factoryEnabled() === false || authType === "required" && safeAuth.isLoading || authType === "required" && !safeAuth.isAuthenticated);
2949
3288
  const authError = createMemo(() => {
2950
- if (isUnauthorized && !skipUnauthFinal) return new CRPCClientError({
3289
+ if (isUnauthorized() && !skipUnauthFinal) return new CRPCClientError({
2951
3290
  code: "UNAUTHORIZED",
2952
3291
  functionName: queryName
2953
3292
  });
2954
3293
  return null;
2955
3294
  });
2956
3295
  createEffect(() => {
2957
- if (isUnauthorized && !skipUnauthFinal) onQueryUnauthorized({ queryName });
3296
+ if (isUnauthorized() && !skipUnauthFinal) onQueryUnauthorized({ queryName });
2958
3297
  });
2959
3298
  const result = useInfiniteQueryInternal(query, args, {
3299
+ authType,
2960
3300
  limit,
2961
3301
  ...queryOptions,
2962
- enabled: !shouldSkip
3302
+ enabled: () => resolveEnabled(!shouldSkip(), factoryEnabled())
2963
3303
  });
2964
3304
  const authLoadingApplies = authType === "optional" || authType === "required";
2965
- const isSkippedUnauth = isUnauthorized && skipUnauthFinal;
3305
+ const isSkippedUnauth = createMemo(() => isUnauthorized() && skipUnauthFinal);
2966
3306
  return {
2967
3307
  get data() {
2968
- return isSkippedUnauth ? [] : result.data;
3308
+ return isSkippedUnauth() ? [] : result.data;
2969
3309
  },
2970
3310
  get pages() {
2971
- return isSkippedUnauth ? [] : result.pages;
3311
+ return isSkippedUnauth() ? [] : result.pages;
2972
3312
  },
2973
3313
  get error() {
2974
3314
  return authError() ?? result.error;
@@ -2977,12 +3317,12 @@ function useInfiniteQuery(infiniteOptions) {
2977
3317
  return authError() ? true : result.isError;
2978
3318
  },
2979
3319
  get isPlaceholderData() {
2980
- return isSkippedUnauth ? false : result.isPlaceholderData;
3320
+ return isSkippedUnauth() ? false : result.isPlaceholderData;
2981
3321
  },
2982
3322
  get isLoading() {
2983
3323
  const ae = authError();
2984
3324
  const isClientError = isCRPCClientError(result.error);
2985
- return authLoadingApplies && safeAuth.isLoading || !isClientError && !ae && !isSkippedUnauth && result.isLoading;
3325
+ return authLoadingApplies && safeAuth.isLoading || !isClientError && !ae && !isSkippedUnauth() && result.isLoading;
2986
3326
  },
2987
3327
  get isFetching() {
2988
3328
  return result.isFetching;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kitcn",
3
- "version": "0.21.0",
3
+ "version": "0.22.1",
4
4
  "description": "kitcn - React Query integration and CLI tools for Convex",
5
5
  "keywords": [
6
6
  "convex",