kitcn 0.20.0 → 0.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- import { C as ConvexNumberBuilderInitial, E as ConvexIdBuilderInitial, N as ConvexCustomBuilderInitial, dn as ConvexTableWithColumns, tr as ConvexTextBuilderInitial } from "../where-clause-compiler-BGBNBNit.js";
1
+ import { C as ConvexNumberBuilderInitial, E as ConvexIdBuilderInitial, N as ConvexCustomBuilderInitial, dn as ConvexTableWithColumns, tr as ConvexTextBuilderInitial } from "../where-clause-compiler-B_H3oio5.js";
2
2
  import * as convex_values0 from "convex/values";
3
3
  import { GenericId, Infer, Value } from "convex/values";
4
4
  import { DocumentByName, GenericDataModel, GenericDatabaseReader, GenericDatabaseWriter, TableNamesInDataModel } from "convex/server";
@@ -1,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";
@@ -24,28 +24,84 @@ const hasActiveSessionData = (session) => {
24
24
  if (!session || typeof session !== "object") return false;
25
25
  return Boolean(session.session);
26
26
  };
27
+ const getSessionId = (sessionData) => {
28
+ if (!sessionData || typeof sessionData !== "object") return;
29
+ const session = sessionData.session;
30
+ if (!session || typeof session !== "object") return;
31
+ const id = session.id;
32
+ return typeof id === "string" ? id : void 0;
33
+ };
34
+ const isSameSession = (left, right) => {
35
+ if (left === right) return true;
36
+ const leftId = getSessionId(left);
37
+ return leftId !== void 0 && leftId === getSessionId(right);
38
+ };
27
39
  const wait = (ms) => new Promise((resolve) => {
28
40
  setTimeout(resolve, ms);
29
41
  });
30
- const readAuthResultData = (result) => {
31
- if (!result || typeof result !== "object") return;
32
- return result.data;
42
+ const PERSISTED_TOKEN_RETRY_BASE_MS = 100;
43
+ const PERSISTED_TOKEN_RETRY_MAX_MS = 2e3;
44
+ const readAuthResult = (result) => {
45
+ if (!result || typeof result !== "object") return {
46
+ data: void 0,
47
+ errored: true
48
+ };
49
+ const { data, error } = result;
50
+ return {
51
+ data,
52
+ errored: Boolean(error)
53
+ };
33
54
  };
34
- const getSessionFromPersistedToken = async (authClient, token) => {
35
- await wait(250);
55
+ const fetchPersistedSession = async (authClient, token) => {
36
56
  const getSession = authClient.getSession;
37
- for (let attempt = 0; attempt < 10; attempt += 1) {
38
- const data = readAuthResultData(authClient.$fetch ? await authClient.$fetch("/get-session", {
57
+ try {
58
+ return await (authClient.$fetch ? authClient.$fetch("/get-session", {
39
59
  credentials: "omit",
40
60
  headers: { Authorization: `Bearer ${token}` }
41
- }) : await getSession?.({ fetchOptions: {
61
+ }) : getSession?.({ fetchOptions: {
42
62
  credentials: "omit",
43
63
  headers: { Authorization: `Bearer ${token}` }
44
64
  } }));
45
- if (data) return data;
46
- if (attempt < 9) await wait(100);
65
+ } catch (error) {
66
+ return {
67
+ data: void 0,
68
+ error
69
+ };
70
+ }
71
+ };
72
+ const fetchPersistedSessionBeforeDeadline = async (authClient, token, deadline) => {
73
+ const remaining = deadline - Date.now();
74
+ if (remaining <= 0) return { status: "deadline" };
75
+ let timeoutId;
76
+ const deadlineResult = new Promise((resolve) => {
77
+ timeoutId = setTimeout(() => resolve({ status: "deadline" }), remaining);
78
+ });
79
+ try {
80
+ return await Promise.race([fetchPersistedSession(authClient, token).then((result) => ({
81
+ result,
82
+ status: "result"
83
+ })), deadlineResult]);
84
+ } finally {
85
+ if (timeoutId !== void 0) clearTimeout(timeoutId);
86
+ }
87
+ };
88
+ const getSessionFromPersistedToken = async (authClient, token, { deadline, shouldStop }) => {
89
+ for (let attempt = 0;; attempt += 1) {
90
+ if (attempt > 0) {
91
+ const remaining = deadline - Date.now();
92
+ if (remaining <= 0) return { status: "unknown" };
93
+ await wait(Math.min(PERSISTED_TOKEN_RETRY_BASE_MS * 3 ** (attempt - 1), PERSISTED_TOKEN_RETRY_MAX_MS, remaining));
94
+ }
95
+ if (shouldStop()) return { status: "unknown" };
96
+ const request = await fetchPersistedSessionBeforeDeadline(authClient, token, deadline);
97
+ if (request.status === "deadline") return { status: "unknown" };
98
+ const { data, errored } = readAuthResult(request.result);
99
+ if (data) return {
100
+ data,
101
+ status: "session"
102
+ };
103
+ if (!errored) return { status: "none" };
47
104
  }
48
- return null;
49
105
  };
50
106
  const syncSessionAtom = (authClient, sessionData) => {
51
107
  const sessionAtom = authClient.$store?.atoms?.session;
@@ -107,6 +163,8 @@ function ConvexAuthProviderInner({ children, client, authClient, convexQueryClie
107
163
  const sessionRef = useRef(session);
108
164
  const isPendingRef = useRef(isPending);
109
165
  const pendingTokenRef = useRef(null);
166
+ const restoredTokenRef = useRef(null);
167
+ const isMountedRef = useRef(false);
110
168
  sessionRef.current = session;
111
169
  isPendingRef.current = isPending;
112
170
  const getCachedJwt = useCallback((minTimeRemainingMs = 0) => {
@@ -132,21 +190,41 @@ function ConvexAuthProviderInner({ children, client, authClient, convexQueryClie
132
190
  isPending,
133
191
  authStore
134
192
  ]);
193
+ useEffect(() => {
194
+ isMountedRef.current = true;
195
+ return () => {
196
+ isMountedRef.current = false;
197
+ };
198
+ }, []);
135
199
  useEffect(() => {
136
200
  if (hasActiveSessionData(session) || isPending || authStore.get("token")) return;
137
201
  const persistedToken = readAuthSessionFallbackToken();
202
+ if (!persistedToken || restoredTokenRef.current === persistedToken || typeof authClient.getSession !== "function" && typeof authClient.$fetch !== "function") return;
203
+ restoredTokenRef.current = persistedToken;
138
204
  const persistedSessionData = readAuthSessionFallbackData();
139
- if (!persistedToken || typeof authClient.getSession !== "function" && typeof authClient.$fetch !== "function") return;
140
- let cancelled = false;
205
+ const graceUntil = Date.now() + AUTH_SESSION_SYNC_GRACE_MS;
141
206
  authStore.set("token", persistedToken);
142
207
  authStore.set("expiresAt", decodeJwtExp(persistedToken));
143
- authStore.set("sessionSyncGraceUntil", Date.now() + AUTH_SESSION_SYNC_GRACE_MS);
208
+ authStore.set("sessionSyncGraceUntil", graceUntil);
144
209
  if (persistedSessionData) syncSessionAtom(authClient, persistedSessionData);
145
- getSessionFromPersistedToken(authClient, persistedToken).then((result) => {
146
- if (cancelled) return;
147
- if (result) {
148
- syncSessionAtom(authClient, result);
149
- writeAuthSessionFallbackData(result);
210
+ const ownsToken = () => authStore.get("token") === persistedToken;
211
+ const shouldStop = () => !isMountedRef.current || !ownsToken();
212
+ getSessionFromPersistedToken(authClient, persistedToken, {
213
+ deadline: graceUntil,
214
+ shouldStop
215
+ }).then((outcome) => {
216
+ const hasCompetingSession = hasActiveSessionData(sessionRef.current) && !isSameSession(sessionRef.current, persistedSessionData);
217
+ if (!isMountedRef.current || !ownsToken() || hasCompetingSession) return;
218
+ if (outcome.status === "session") {
219
+ syncSessionAtom(authClient, outcome.data);
220
+ writeAuthSessionFallbackData(outcome.data);
221
+ return;
222
+ }
223
+ if (outcome.status === "unknown") {
224
+ if (persistedSessionData) clearSessionAtom(authClient);
225
+ authStore.set("token", null);
226
+ authStore.set("expiresAt", null);
227
+ authStore.set("sessionSyncGraceUntil", null);
150
228
  return;
151
229
  }
152
230
  clearAuthSessionFallback();
@@ -154,17 +232,7 @@ function ConvexAuthProviderInner({ children, client, authClient, convexQueryClie
154
232
  authStore.set("token", null);
155
233
  authStore.set("expiresAt", null);
156
234
  authStore.set("sessionSyncGraceUntil", null);
157
- }).catch(() => {
158
- if (cancelled) return;
159
- clearAuthSessionFallback();
160
- clearSessionAtom(authClient);
161
- authStore.set("token", null);
162
- authStore.set("expiresAt", null);
163
- authStore.set("sessionSyncGraceUntil", null);
164
- });
165
- return () => {
166
- cancelled = true;
167
- };
235
+ }).catch(() => {});
168
236
  }, [
169
237
  session,
170
238
  isPending,
@@ -1,2 +1,2 @@
1
- import { S as defineAuth, _ as GenericAuthBeforeResult, b as GenericAuthTriggerHandlers, g as BetterAuthOptionsWithoutDatabase, i as getGeneratedAuthDisabledReason, n as GeneratedAuthDisabledReasonKind, r as createDisabledAuthRuntime, t as AuthRuntime, v as GenericAuthDefinition, x as GenericAuthTriggers, y as GenericAuthTriggerChange } from "../../generated-contract-disabled-BbPCefQM.js";
1
+ import { S as defineAuth, _ as GenericAuthBeforeResult, b as GenericAuthTriggerHandlers, g as BetterAuthOptionsWithoutDatabase, i as getGeneratedAuthDisabledReason, n as GeneratedAuthDisabledReasonKind, r as createDisabledAuthRuntime, t as AuthRuntime, v as GenericAuthDefinition, x as GenericAuthTriggers, y as GenericAuthTriggerChange } from "../../generated-contract-disabled-B-nmd7Ne.js";
2
2
  export { type AuthRuntime, BetterAuthOptionsWithoutDatabase, type GeneratedAuthDisabledReasonKind, GenericAuthBeforeResult, GenericAuthDefinition, GenericAuthTriggerChange, GenericAuthTriggerHandlers, GenericAuthTriggers, createDisabledAuthRuntime, defineAuth, getGeneratedAuthDisabledReason };
@@ -1,7 +1,7 @@
1
1
  import { a as QueryCtxWithPreferredOrmQueryTable, n as LookupByIdResultByCtx, t as DocByCtx } from "../query-context-CNo9ffvI.js";
2
2
  import { t as GetAuth } from "../types-BCl8gfGy.js";
3
3
  import { t as GenericCtx } from "../context-utils-BBUtBqjN.js";
4
- import { S as defineAuth, _ as GenericAuthBeforeResult, a as AuthFunctions, b as GenericAuthTriggerHandlers, c as createApi, d as deleteOneHandler, f as findManyHandler, g as BetterAuthOptionsWithoutDatabase, h as updateOneHandler, i as getGeneratedAuthDisabledReason, l as createHandler, m as updateManyHandler, n as GeneratedAuthDisabledReasonKind, o as Triggers, p as findOneHandler, r as createDisabledAuthRuntime, s as createClient, t as AuthRuntime, u as deleteManyHandler, v as GenericAuthDefinition, x as GenericAuthTriggers, y as GenericAuthTriggerChange } from "../generated-contract-disabled-BbPCefQM.js";
4
+ import { S as defineAuth, _ as GenericAuthBeforeResult, a as AuthFunctions, b as GenericAuthTriggerHandlers, c as createApi, d as deleteOneHandler, f as findManyHandler, g as BetterAuthOptionsWithoutDatabase, h as updateOneHandler, i as getGeneratedAuthDisabledReason, l as createHandler, m as updateManyHandler, n as GeneratedAuthDisabledReasonKind, o as Triggers, p as findOneHandler, r as createDisabledAuthRuntime, s as createClient, t as AuthRuntime, u as deleteManyHandler, v as GenericAuthDefinition, x as GenericAuthTriggers, y as GenericAuthTriggerChange } from "../generated-contract-disabled-B-nmd7Ne.js";
5
5
  import * as convex_values0 from "convex/values";
6
6
  import { Infer } from "convex/values";
7
7
  import { AuthConfig, DocumentByName, GenericDataModel, GenericMutationCtx, GenericQueryCtx, GenericSchema, PaginationOptions, PaginationResult, SchemaDefinition, TableNamesInDataModel } from "convex/server";
@@ -25,9 +25,11 @@ declare const handlePagination: (next: ({
25
25
  }) => Promise<SetOptional<PaginationResult<any>, "page"> & {
26
26
  count?: number;
27
27
  }>, {
28
+ countOnly,
28
29
  limit,
29
30
  numItems
30
31
  }?: {
32
+ countOnly?: boolean;
31
33
  limit?: number;
32
34
  numItems?: number;
33
35
  }) => Promise<{
@@ -66,7 +68,7 @@ declare const adapterConfig: {
66
68
  action: "create" | "update" | "findOne" | "findMany" | "updateMany" | "delete" | "deleteMany" | "consumeOne" | "incrementOne" | "count";
67
69
  model: string;
68
70
  schema: BetterAuthDBSchema;
69
- options: BetterAuthOptions;
71
+ options: better_auth0.BetterAuthOptions;
70
72
  }) => any;
71
73
  customTransformOutput: ({
72
74
  data,
@@ -78,7 +80,7 @@ declare const adapterConfig: {
78
80
  select: string[];
79
81
  model: string;
80
82
  schema: BetterAuthDBSchema;
81
- options: BetterAuthOptions;
83
+ options: better_auth0.BetterAuthOptions;
82
84
  }) => any;
83
85
  };
84
86
  declare const httpAdapter: <DataModel extends GenericDataModel, Schema extends SchemaDefinition<any, any>>(ctx: GenericCtx<DataModel>, {
@@ -89,16 +91,18 @@ declare const httpAdapter: <DataModel extends GenericDataModel, Schema extends S
89
91
  authFunctions: AuthFunctions;
90
92
  debugLogs?: DBAdapterDebugLogOption;
91
93
  schema?: Schema;
92
- }) => better_auth_adapters0.AdapterFactory<BetterAuthOptions>;
93
- declare const dbAdapter: <DataModel extends GenericDataModel, Schema extends SchemaDefinition<any, any>>(ctx: GenericCtx<DataModel>, getAuthOptions: (ctx: any) => BetterAuthOptions, {
94
+ }) => better_auth_adapters0.AdapterFactory<better_auth0.BetterAuthOptions>;
95
+ declare const dbAdapter: <DataModel extends GenericDataModel, Schema extends SchemaDefinition<any, any>>(ctx: GenericCtx<DataModel>, {
94
96
  authFunctions,
95
97
  debugLogs,
98
+ getBetterAuthSchema,
96
99
  schema
97
100
  }: {
98
- authFunctions: AuthFunctions;
101
+ authFunctions: AuthFunctions; /** Ctx-free Better Auth table schema, memoized by the caller. */
102
+ getBetterAuthSchema: () => BetterAuthDBSchema;
99
103
  schema: Schema;
100
104
  debugLogs?: DBAdapterDebugLogOption;
101
- }) => better_auth_adapters0.AdapterFactory<BetterAuthOptions>;
105
+ }) => better_auth_adapters0.AdapterFactory<better_auth0.BetterAuthOptions>;
102
106
  //#endregion
103
107
  //#region src/auth/adapter-utils.d.ts
104
108
  type AdapterPaginationOptions = PaginationOptions & {
@@ -109,30 +113,30 @@ declare const adapterWhereValidator: convex_values0.VObject<{
109
113
  mode?: "sensitive" | "insensitive" | undefined;
110
114
  connector?: "AND" | "OR" | undefined;
111
115
  operator?: "lt" | "lte" | "gt" | "gte" | "eq" | "in" | "not_in" | "ne" | "contains" | "starts_with" | "ends_with" | undefined;
112
- field: string;
113
116
  value: string | number | boolean | string[] | number[] | null;
117
+ field: string;
114
118
  }, {
115
119
  connector: convex_values0.VUnion<"AND" | "OR" | undefined, [convex_values0.VLiteral<"AND", "required">, convex_values0.VLiteral<"OR", "required">], "optional", never>;
116
120
  field: convex_values0.VString<string, "required">;
117
121
  mode: convex_values0.VUnion<"sensitive" | "insensitive" | undefined, [convex_values0.VLiteral<"sensitive", "required">, convex_values0.VLiteral<"insensitive", "required">], "optional", never>;
118
122
  operator: convex_values0.VUnion<"lt" | "lte" | "gt" | "gte" | "eq" | "in" | "not_in" | "ne" | "contains" | "starts_with" | "ends_with" | undefined, [convex_values0.VLiteral<"lt", "required">, convex_values0.VLiteral<"lte", "required">, convex_values0.VLiteral<"gt", "required">, convex_values0.VLiteral<"gte", "required">, convex_values0.VLiteral<"eq", "required">, convex_values0.VLiteral<"in", "required">, convex_values0.VLiteral<"not_in", "required">, convex_values0.VLiteral<"ne", "required">, convex_values0.VLiteral<"contains", "required">, convex_values0.VLiteral<"starts_with", "required">, convex_values0.VLiteral<"ends_with", "required">], "optional", never>;
119
123
  value: convex_values0.VUnion<string | number | boolean | string[] | number[] | null, [convex_values0.VString<string, "required">, convex_values0.VFloat64<number, "required">, convex_values0.VBoolean<boolean, "required">, convex_values0.VArray<string[], convex_values0.VString<string, "required">, "required">, convex_values0.VArray<number[], convex_values0.VFloat64<number, "required">, "required">, convex_values0.VNull<null, "required">], "required", never>;
120
- }, "required", "mode" | "connector" | "field" | "operator" | "value">;
124
+ }, "required", "mode" | "value" | "connector" | "field" | "operator">;
121
125
  declare const adapterArgsValidator: convex_values0.VObject<{
122
- limit?: number | undefined;
123
- offset?: number | undefined;
124
126
  select?: string[] | undefined;
125
- sortBy?: {
126
- field: string;
127
- direction: "asc" | "desc";
128
- } | undefined;
129
127
  where?: {
130
128
  mode?: "sensitive" | "insensitive" | undefined;
131
129
  connector?: "AND" | "OR" | undefined;
132
130
  operator?: "lt" | "lte" | "gt" | "gte" | "eq" | "in" | "not_in" | "ne" | "contains" | "starts_with" | "ends_with" | undefined;
133
- field: string;
134
131
  value: string | number | boolean | string[] | number[] | null;
132
+ field: string;
135
133
  }[] | undefined;
134
+ limit?: number | undefined;
135
+ offset?: number | undefined;
136
+ sortBy?: {
137
+ field: string;
138
+ direction: "asc" | "desc";
139
+ } | undefined;
136
140
  model: string;
137
141
  }, {
138
142
  limit: convex_values0.VFloat64<number | undefined, "optional">;
@@ -150,22 +154,22 @@ declare const adapterArgsValidator: convex_values0.VObject<{
150
154
  mode?: "sensitive" | "insensitive" | undefined;
151
155
  connector?: "AND" | "OR" | undefined;
152
156
  operator?: "lt" | "lte" | "gt" | "gte" | "eq" | "in" | "not_in" | "ne" | "contains" | "starts_with" | "ends_with" | undefined;
153
- field: string;
154
157
  value: string | number | boolean | string[] | number[] | null;
158
+ field: string;
155
159
  }[] | undefined, convex_values0.VObject<{
156
160
  mode?: "sensitive" | "insensitive" | undefined;
157
161
  connector?: "AND" | "OR" | undefined;
158
162
  operator?: "lt" | "lte" | "gt" | "gte" | "eq" | "in" | "not_in" | "ne" | "contains" | "starts_with" | "ends_with" | undefined;
159
- field: string;
160
163
  value: string | number | boolean | string[] | number[] | null;
164
+ field: string;
161
165
  }, {
162
166
  connector: convex_values0.VUnion<"AND" | "OR" | undefined, [convex_values0.VLiteral<"AND", "required">, convex_values0.VLiteral<"OR", "required">], "optional", never>;
163
167
  field: convex_values0.VString<string, "required">;
164
168
  mode: convex_values0.VUnion<"sensitive" | "insensitive" | undefined, [convex_values0.VLiteral<"sensitive", "required">, convex_values0.VLiteral<"insensitive", "required">], "optional", never>;
165
169
  operator: convex_values0.VUnion<"lt" | "lte" | "gt" | "gte" | "eq" | "in" | "not_in" | "ne" | "contains" | "starts_with" | "ends_with" | undefined, [convex_values0.VLiteral<"lt", "required">, convex_values0.VLiteral<"lte", "required">, convex_values0.VLiteral<"gt", "required">, convex_values0.VLiteral<"gte", "required">, convex_values0.VLiteral<"eq", "required">, convex_values0.VLiteral<"in", "required">, convex_values0.VLiteral<"not_in", "required">, convex_values0.VLiteral<"ne", "required">, convex_values0.VLiteral<"contains", "required">, convex_values0.VLiteral<"starts_with", "required">, convex_values0.VLiteral<"ends_with", "required">], "optional", never>;
166
170
  value: convex_values0.VUnion<string | number | boolean | string[] | number[] | null, [convex_values0.VString<string, "required">, convex_values0.VFloat64<number, "required">, convex_values0.VBoolean<boolean, "required">, convex_values0.VArray<string[], convex_values0.VString<string, "required">, "required">, convex_values0.VArray<number[], convex_values0.VFloat64<number, "required">, "required">, convex_values0.VNull<null, "required">], "required", never>;
167
- }, "required", "mode" | "connector" | "field" | "operator" | "value">, "optional">;
168
- }, "required", "limit" | "model" | "offset" | "select" | "sortBy" | "where" | "sortBy.field" | "sortBy.direction">;
171
+ }, "required", "mode" | "value" | "connector" | "field" | "operator">, "optional">;
172
+ }, "required", "model" | "select" | "where" | "limit" | "offset" | "sortBy" | "sortBy.field" | "sortBy.direction">;
169
173
  declare const hasUniqueFields: (betterAuthSchema: BetterAuthDBSchema, model: string, input: Record<string, any>) => boolean;
170
174
  declare const checkUniqueFields: <Schema extends SchemaDefinition<any, any>>(ctx: GenericQueryCtx<GenericDataModel>, schema: Schema, betterAuthSchema: BetterAuthDBSchema, table: string, input: Record<string, any>, doc?: Record<string, any>) => Promise<void>;
171
175
  declare const selectFields: <T extends TableNamesInDataModel<GenericDataModel>, D extends DocumentByName<GenericDataModel, T>>(doc: D | null, select?: string[]) => D | null;
@@ -4,12 +4,12 @@ import { i as defineAuth, n as createDisabledAuthRuntime, r as getGeneratedAuthD
4
4
  import { n as createGeneratedFunctionReference, o as isQueryCtx, s as isRunMutationCtx } from "../api-entry-N3nBOlI2.js";
5
5
  import { n as customCtx, r as customMutation } from "../customFunctions-DxEEO4Dq.js";
6
6
  import { o as mergedStream, s as stream, t as getByIdWithOrmQueryFallback, u as unsetToken, y as eq } from "../query-context-BzihIpnM.js";
7
- import { n as convex } from "../convex-plugin-BHVCqWTH.js";
7
+ import { n as convex } from "../convex-plugin-D8B0oCFq.js";
8
8
  import { v } from "convex/values";
9
9
  import { internalActionGeneric, internalMutationGeneric, internalQueryGeneric, paginationOptsValidator } from "convex/server";
10
10
  import { createAdapterFactory } from "better-auth/adapters";
11
- import { getAuthTables } from "better-auth/db";
12
11
  import { prop, sortBy } from "remeda";
12
+ import { getAuthTables } from "better-auth/db";
13
13
  import { stripIndent } from "common-tags";
14
14
  import { betterAuth } from "better-auth/minimal";
15
15
 
@@ -32,10 +32,34 @@ const adapterArgsValidator = v.object({
32
32
  })),
33
33
  where: v.optional(v.array(adapterWhereValidator))
34
34
  });
35
+ const schemaViewsCache = /* @__PURE__ */ new WeakMap();
36
+ const EMPTY_SCHEMA_VIEWS = {
37
+ modelNameToKey: /* @__PURE__ */ new Map(),
38
+ uniqueFields: /* @__PURE__ */ new Map()
39
+ };
40
+ const getSchemaViews = (betterAuthSchema) => {
41
+ if (!betterAuthSchema || typeof betterAuthSchema !== "object") return EMPTY_SCHEMA_VIEWS;
42
+ const cached = schemaViewsCache.get(betterAuthSchema);
43
+ if (cached) return cached;
44
+ const modelNameToKey = /* @__PURE__ */ new Map();
45
+ const uniqueFields = /* @__PURE__ */ new Map();
46
+ for (const [key, model] of Object.entries(betterAuthSchema)) {
47
+ if (model?.modelName && !modelNameToKey.has(model.modelName)) modelNameToKey.set(model.modelName, key);
48
+ const unique = /* @__PURE__ */ new Set();
49
+ for (const [field, attrs] of Object.entries(model?.fields ?? {})) if (attrs?.unique) unique.add(field);
50
+ uniqueFields.set(key, unique);
51
+ }
52
+ const views = {
53
+ modelNameToKey,
54
+ uniqueFields
55
+ };
56
+ schemaViewsCache.set(betterAuthSchema, views);
57
+ return views;
58
+ };
35
59
  const isUniqueField = (betterAuthSchema, model, field) => {
36
- const modelSchema = betterAuthSchema[Object.keys(betterAuthSchema).find((key) => betterAuthSchema[key].modelName === model) || model];
37
- if (!modelSchema?.fields) return false;
38
- return Object.entries(modelSchema.fields).filter(([, value]) => value.unique).map(([key]) => key).includes(field);
60
+ const { modelNameToKey, uniqueFields } = getSchemaViews(betterAuthSchema);
61
+ const betterAuthModel = modelNameToKey.get(model) ?? model;
62
+ return uniqueFields.get(betterAuthModel)?.has(field) ?? false;
39
63
  };
40
64
  const hasUniqueFields = (betterAuthSchema, model, input) => {
41
65
  for (const field of Object.keys(input)) if (isUniqueField(betterAuthSchema, model, field)) return true;
@@ -482,8 +506,25 @@ const findManyHandler = async (ctx, args, schema, betterAuthSchema) => toConvexS
482
506
  const updateOneHandler = async (ctx, args, schema, betterAuthSchema) => {
483
507
  const triggerCtx = args.triggerCtx ?? ctx;
484
508
  const tableTriggers = args.tableTriggers;
485
- const doc = await listOne(ctx, schema, betterAuthSchema, args.input);
509
+ const matches = [];
510
+ let cursor = null;
511
+ let isDone = false;
512
+ while (!isDone && matches.length < 2) {
513
+ const result = await paginate(ctx, schema, betterAuthSchema, {
514
+ ...args.input,
515
+ paginationOpts: {
516
+ cursor,
517
+ numItems: 2 - matches.length
518
+ }
519
+ });
520
+ matches.push(...result.page);
521
+ isDone = result.isDone;
522
+ if (!isDone && result.continueCursor === cursor) throw new Error("Pagination made no forward progress");
523
+ cursor = result.continueCursor;
524
+ }
525
+ const doc = matches[0];
486
526
  if (!doc) throw new Error(`Failed to update ${args.input.model}`);
527
+ if (matches.length > 1) throw new Error(`Multiple ${args.input.model} found matching criteria. Expected exactly 1.`);
487
528
  const normalizedDoc = withBothIdFields(doc);
488
529
  const update = stripUnsupportedAuthTimestamps(serializeDatesForConvex(await applyBeforeHook(args.input.model, "update", args.input.update, tableTriggers?.update?.before, triggerCtx)), schema, betterAuthSchema, args.input.model);
489
530
  await checkUniqueFields(ctx, schema, betterAuthSchema, args.input.model, update, normalizedDoc);
@@ -590,9 +631,10 @@ const deleteManyHandler = async (ctx, args, schema, betterAuthSchema) => {
590
631
  });
591
632
  };
592
633
  const createApi = (schema, getAuth, options) => {
593
- const { internalMutation, validateInput = false, context, triggers } = options ?? {};
634
+ const { internalMutation, validateInput = false, context, getBetterAuthSchema: injectedBetterAuthSchema, triggers } = options ?? {};
594
635
  let betterAuthSchema;
595
636
  const getBetterAuthSchema = () => {
637
+ if (injectedBetterAuthSchema) return injectedBetterAuthSchema();
596
638
  betterAuthSchema ??= getAuthTables(getAuth({}).options);
597
639
  return betterAuthSchema;
598
640
  };
@@ -749,7 +791,7 @@ const createApi = (schema, getAuth, options) => {
749
791
  //#endregion
750
792
  //#region src/auth/adapter.ts
751
793
  let didWarnExperimentalJoinsUnsupported = false;
752
- const handlePagination = async (next, { limit, numItems } = {}) => {
794
+ const handlePagination = async (next, { countOnly, limit, numItems } = {}) => {
753
795
  const state = {
754
796
  count: 0,
755
797
  cursor: null,
@@ -759,6 +801,11 @@ const handlePagination = async (next, { limit, numItems } = {}) => {
759
801
  const onResult = (result) => {
760
802
  state.cursor = result.continueCursor;
761
803
  if (result.page) {
804
+ if (countOnly) {
805
+ state.count += result.page.length;
806
+ state.isDone = limit && state.count >= limit || result.isDone;
807
+ return;
808
+ }
762
809
  state.docs.push(...result.page);
763
810
  state.isDone = limit && state.docs.length >= limit || result.isDone;
764
811
  return;
@@ -772,9 +819,10 @@ const handlePagination = async (next, { limit, numItems } = {}) => {
772
819
  };
773
820
  do {
774
821
  const cursorBeforePage = state.cursor;
822
+ const consumed = countOnly ? state.count : state.docs.length;
775
823
  const result = await next({ paginationOpts: {
776
824
  cursor: state.cursor,
777
- numItems: Math.min(numItems ?? 200, limit === void 0 ? Number.POSITIVE_INFINITY : limit - state.docs.length, 200)
825
+ numItems: Math.min(numItems ?? 200, limit === void 0 ? Number.POSITIVE_INFINITY : limit - consumed, 200)
778
826
  } });
779
827
  onResult(result);
780
828
  const advanced = state.cursor !== cursorBeforePage;
@@ -901,7 +949,7 @@ const httpAdapter = (ctx, { authFunctions, debugLogs, schema }) => {
901
949
  ...data,
902
950
  paginationOpts,
903
951
  where: parseWhere(data.where)
904
- }))).docs.length;
952
+ }), { countOnly: true })).count;
905
953
  },
906
954
  create: async ({ data, model, select }) => {
907
955
  if (!("runMutation" in ctx)) throw new Error("ctx is not a mutation ctx");
@@ -990,20 +1038,11 @@ const httpAdapter = (ctx, { authFunctions, debugLogs, schema }) => {
990
1038
  update: async (data) => {
991
1039
  if (!("runMutation" in ctx)) throw new Error("ctx is not a mutation ctx");
992
1040
  if (!data.where?.length) return null;
993
- if (data.where.every((w) => (w.operator === "eq" || w.operator === void 0) && w.connector !== "OR")) {
994
- const countResult = await handlePagination(async ({ paginationOpts }) => await ctx.runQuery(authFunctions.findMany, {
995
- model: data.model,
996
- paginationOpts,
997
- where: parseWhere(data.where)
998
- }), { limit: 2 });
999
- if (countResult.docs.length === 0) throw new Error(`No ${data.model} found matching criteria`);
1000
- if (countResult.docs.length > 1) throw new Error(`Multiple ${data.model} found matching criteria. Expected exactly 1.`);
1001
- return await ctx.runMutation(authFunctions.updateOne, { input: {
1002
- model: data.model,
1003
- update: data.update,
1004
- where: parseWhere(data.where)
1005
- } });
1006
- }
1041
+ if (data.where.every((w) => (w.operator === "eq" || w.operator === void 0) && w.connector !== "OR")) return await ctx.runMutation(authFunctions.updateOne, { input: {
1042
+ model: data.model,
1043
+ update: data.update,
1044
+ where: parseWhere(data.where)
1045
+ } });
1007
1046
  throw new Error("where clause not supported");
1008
1047
  },
1009
1048
  updateMany: async (data) => {
@@ -1039,8 +1078,8 @@ const httpAdapter = (ctx, { authFunctions, debugLogs, schema }) => {
1039
1078
  }
1040
1079
  });
1041
1080
  };
1042
- const dbAdapter = (ctx, getAuthOptions, { authFunctions, debugLogs, schema }) => {
1043
- const betterAuthSchema = getAuthTables(getAuthOptions({}));
1081
+ const dbAdapter = (ctx, { authFunctions, debugLogs, getBetterAuthSchema, schema }) => {
1082
+ const betterAuthSchema = getBetterAuthSchema();
1044
1083
  return createAdapterFactory({
1045
1084
  config: {
1046
1085
  ...adapterConfig,
@@ -1079,7 +1118,7 @@ const dbAdapter = (ctx, getAuthOptions, { authFunctions, debugLogs, schema }) =>
1079
1118
  ...data,
1080
1119
  paginationOpts,
1081
1120
  where: parseWhere(data.where)
1082
- }, schema, betterAuthSchema))).docs.length;
1121
+ }, schema, betterAuthSchema), { countOnly: true })).count;
1083
1122
  },
1084
1123
  create: async ({ data, model, select }) => {
1085
1124
  if (!("runMutation" in ctx)) throw new Error("ctx is not a mutation ctx");
@@ -1167,13 +1206,6 @@ const dbAdapter = (ctx, getAuthOptions, { authFunctions, debugLogs, schema }) =>
1167
1206
  update: async (data) => {
1168
1207
  if (!data.where?.length) return null;
1169
1208
  if (data.where.every((w) => (w.operator === "eq" || w.operator === void 0) && w.connector !== "OR")) {
1170
- const countResult = await handlePagination(async ({ paginationOpts }) => await findManyHandler(ctx, {
1171
- model: data.model,
1172
- paginationOpts,
1173
- where: parseWhere(data.where)
1174
- }, schema, betterAuthSchema), { limit: 2 });
1175
- if (countResult.docs.length === 0) throw new Error(`No ${data.model} found matching criteria`);
1176
- if (countResult.docs.length > 1) throw new Error(`Multiple ${data.model} found matching criteria. Expected exactly 1.`);
1177
1209
  if (!("runMutation" in ctx)) throw new Error("ctx is not a mutation ctx");
1178
1210
  return await ctx.runMutation(authFunctions.updateOne, { input: {
1179
1211
  model: data.model,
@@ -1222,7 +1254,7 @@ const dbAdapter = (ctx, getAuthOptions, { authFunctions, debugLogs, schema }) =>
1222
1254
  const createClient = (config) => ({
1223
1255
  authFunctions: config.authFunctions,
1224
1256
  triggers: config.triggers,
1225
- adapter: (ctx, getAuthOptions) => isQueryCtx(ctx) ? dbAdapter(ctx, getAuthOptions, config) : httpAdapter(ctx, config)
1257
+ adapter: (ctx) => isQueryCtx(ctx) ? dbAdapter(ctx, config) : httpAdapter(ctx, config)
1226
1258
  });
1227
1259
 
1228
1260
  //#endregion
@@ -1333,17 +1365,23 @@ const createAuthRuntime = (config) => {
1333
1365
  const authDefinition = resolveGeneratedAuthDefinition(config.auth, getInvalidAuthDefinitionExportReason());
1334
1366
  const authFunctions = resolveAuthFunctions(config.internal, config.moduleName);
1335
1367
  const resolveRuntimeTriggers = (ctx) => authDefinition(ctx).triggers;
1368
+ let betterAuthSchema;
1369
+ const getBetterAuthSchema = () => {
1370
+ betterAuthSchema ??= getAuthTables(withoutTriggers(authDefinition({})));
1371
+ return betterAuthSchema;
1372
+ };
1336
1373
  const authClient = createClient({
1337
1374
  authFunctions,
1375
+ getBetterAuthSchema,
1338
1376
  schema: config.schema,
1339
1377
  ...config.context ? { context: config.context } : {},
1340
1378
  triggers: resolveRuntimeTriggers
1341
1379
  });
1342
- const adapterGetAuthOptions = ((ctx) => withoutTriggers(authDefinition(ctx)));
1343
- const resolveAuthOptions = (ctx) => withDatabase(withAuthDefaults(withoutTriggers(authDefinition(ctx))), ctx, (_ctx) => authClient.adapter(_ctx, adapterGetAuthOptions));
1380
+ const resolveAuthOptions = (ctx) => withDatabase(withAuthDefaults(withoutTriggers(authDefinition(ctx))), ctx, (_ctx) => authClient.adapter(_ctx));
1344
1381
  const getAuth = (ctx) => betterAuth(resolveAuthOptions(ctx));
1345
1382
  const decoratedAuthApi = decorateAuthRuntimeProcedures(createApi(config.schema, getAuth, {
1346
1383
  ...config.context ? { context: config.context } : {},
1384
+ getBetterAuthSchema,
1347
1385
  triggers: resolveRuntimeTriggers
1348
1386
  }));
1349
1387
  let staticAuth;
@@ -1,4 +1,4 @@
1
- import { t as getToken } from "../../token-oA2EMtPA.js";
1
+ import { t as getToken } from "../../token-xlpENMVn.js";
2
2
  import { n as defaultIsUnauthorized } from "../../error-Bvo7YEhk.js";
3
3
  import { t as createCallerFactory } from "../../caller-factory-DHywSoGZ.js";
4
4
 
@@ -1,4 +1,4 @@
1
- import { t as getToken } from "../../../token-oA2EMtPA.js";
1
+ import { t as getToken } from "../../../token-xlpENMVn.js";
2
2
  import { stripIndent } from "common-tags";
3
3
  import { getRequestHeaders } from "@tanstack/react-start/server";
4
4
  import { ConvexHttpClient } from "convex/browser";
@@ -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;