@convex-dev/better-auth 0.7.0-alpha.9 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. package/dist/commonjs/client/adapter.d.ts +10 -1
  2. package/dist/commonjs/client/adapter.d.ts.map +1 -1
  3. package/dist/commonjs/client/adapter.js +190 -192
  4. package/dist/commonjs/client/adapter.js.map +1 -1
  5. package/dist/commonjs/client/index.d.ts +283 -179
  6. package/dist/commonjs/client/index.d.ts.map +1 -1
  7. package/dist/commonjs/client/index.js +46 -58
  8. package/dist/commonjs/client/index.js.map +1 -1
  9. package/dist/commonjs/component/adapterTest.d.ts +19 -0
  10. package/dist/commonjs/component/adapterTest.d.ts.map +1 -0
  11. package/dist/commonjs/component/adapterTest.js +82 -0
  12. package/dist/commonjs/component/adapterTest.js.map +1 -0
  13. package/dist/commonjs/component/lib.d.ts +308 -536
  14. package/dist/commonjs/component/lib.d.ts.map +1 -1
  15. package/dist/commonjs/component/lib.js +469 -292
  16. package/dist/commonjs/component/lib.js.map +1 -1
  17. package/dist/commonjs/component/schema.d.ts +465 -26
  18. package/dist/commonjs/component/schema.d.ts.map +1 -1
  19. package/dist/commonjs/component/schema.js +334 -18
  20. package/dist/commonjs/component/schema.js.map +1 -1
  21. package/dist/commonjs/component/util.d.ts +944 -68
  22. package/dist/commonjs/component/util.d.ts.map +1 -1
  23. package/dist/commonjs/nextjs/index.d.ts.map +1 -1
  24. package/dist/commonjs/nextjs/index.js +3 -9
  25. package/dist/commonjs/nextjs/index.js.map +1 -1
  26. package/dist/commonjs/plugins/convex/index.d.ts +14 -11
  27. package/dist/commonjs/plugins/convex/index.d.ts.map +1 -1
  28. package/dist/commonjs/plugins/convex/index.js +3 -2
  29. package/dist/commonjs/plugins/convex/index.js.map +1 -1
  30. package/dist/commonjs/plugins/cross-domain/client.d.ts +1 -1
  31. package/dist/commonjs/plugins/cross-domain/index.d.ts +5 -3
  32. package/dist/commonjs/plugins/cross-domain/index.d.ts.map +1 -1
  33. package/dist/commonjs/plugins/cross-domain/index.js +19 -5
  34. package/dist/commonjs/plugins/cross-domain/index.js.map +1 -1
  35. package/dist/commonjs/react/client.d.ts +1 -1
  36. package/dist/commonjs/react/client.d.ts.map +1 -1
  37. package/dist/commonjs/react/client.js +3 -9
  38. package/dist/commonjs/react/client.js.map +1 -1
  39. package/dist/commonjs/react-start/index.d.ts +4 -4
  40. package/dist/commonjs/react-start/index.d.ts.map +1 -1
  41. package/dist/commonjs/react-start/index.js +3 -0
  42. package/dist/commonjs/react-start/index.js.map +1 -1
  43. package/dist/commonjs/utils/index.d.ts +2 -0
  44. package/dist/commonjs/utils/index.d.ts.map +1 -0
  45. package/dist/commonjs/utils/index.js +8 -0
  46. package/dist/commonjs/utils/index.js.map +1 -0
  47. package/dist/esm/client/adapter.d.ts +10 -1
  48. package/dist/esm/client/adapter.d.ts.map +1 -1
  49. package/dist/esm/client/adapter.js +190 -192
  50. package/dist/esm/client/adapter.js.map +1 -1
  51. package/dist/esm/client/index.d.ts +283 -179
  52. package/dist/esm/client/index.d.ts.map +1 -1
  53. package/dist/esm/client/index.js +46 -58
  54. package/dist/esm/client/index.js.map +1 -1
  55. package/dist/esm/component/adapterTest.d.ts +19 -0
  56. package/dist/esm/component/adapterTest.d.ts.map +1 -0
  57. package/dist/esm/component/adapterTest.js +82 -0
  58. package/dist/esm/component/adapterTest.js.map +1 -0
  59. package/dist/esm/component/lib.d.ts +308 -536
  60. package/dist/esm/component/lib.d.ts.map +1 -1
  61. package/dist/esm/component/lib.js +469 -292
  62. package/dist/esm/component/lib.js.map +1 -1
  63. package/dist/esm/component/schema.d.ts +465 -26
  64. package/dist/esm/component/schema.d.ts.map +1 -1
  65. package/dist/esm/component/schema.js +334 -18
  66. package/dist/esm/component/schema.js.map +1 -1
  67. package/dist/esm/component/util.d.ts +944 -68
  68. package/dist/esm/component/util.d.ts.map +1 -1
  69. package/dist/esm/nextjs/index.d.ts.map +1 -1
  70. package/dist/esm/nextjs/index.js +3 -9
  71. package/dist/esm/nextjs/index.js.map +1 -1
  72. package/dist/esm/plugins/convex/index.d.ts +14 -11
  73. package/dist/esm/plugins/convex/index.d.ts.map +1 -1
  74. package/dist/esm/plugins/convex/index.js +3 -2
  75. package/dist/esm/plugins/convex/index.js.map +1 -1
  76. package/dist/esm/plugins/cross-domain/client.d.ts +1 -1
  77. package/dist/esm/plugins/cross-domain/index.d.ts +5 -3
  78. package/dist/esm/plugins/cross-domain/index.d.ts.map +1 -1
  79. package/dist/esm/plugins/cross-domain/index.js +19 -5
  80. package/dist/esm/plugins/cross-domain/index.js.map +1 -1
  81. package/dist/esm/react/client.d.ts +1 -1
  82. package/dist/esm/react/client.d.ts.map +1 -1
  83. package/dist/esm/react/client.js +3 -9
  84. package/dist/esm/react/client.js.map +1 -1
  85. package/dist/esm/react-start/index.d.ts +4 -4
  86. package/dist/esm/react-start/index.d.ts.map +1 -1
  87. package/dist/esm/react-start/index.js +3 -0
  88. package/dist/esm/react-start/index.js.map +1 -1
  89. package/dist/esm/utils/index.d.ts +2 -0
  90. package/dist/esm/utils/index.d.ts.map +1 -0
  91. package/dist/esm/utils/index.js +8 -0
  92. package/dist/esm/utils/index.js.map +1 -0
  93. package/package.json +24 -7
  94. package/src/client/adapter.test.ts +378 -0
  95. package/src/client/adapter.ts +206 -198
  96. package/src/client/index.ts +46 -71
  97. package/src/component/_generated/api.d.ts +2189 -171
  98. package/src/component/adapterTest.ts +141 -0
  99. package/src/component/lib.ts +648 -342
  100. package/src/component/schema.ts +349 -18
  101. package/src/nextjs/index.ts +3 -14
  102. package/src/plugins/convex/index.ts +5 -2
  103. package/src/plugins/cross-domain/index.ts +19 -5
  104. package/src/react/client.tsx +5 -11
  105. package/src/react-start/index.ts +4 -1
  106. package/src/client/cors.ts +0 -425
  107. /package/src/{util.ts → utils/index.ts} +0 -0
@@ -1,34 +1,140 @@
1
1
  import { BetterAuth } from "./index";
2
- import { transformInput } from "../component/lib";
3
- import { createAdapter } from "better-auth/adapters";
2
+ import {
3
+ AdapterDebugLogs,
4
+ CleanedWhere,
5
+ createAdapter,
6
+ } from "better-auth/adapters";
4
7
  import {
5
8
  GenericActionCtx,
6
9
  GenericMutationCtx,
7
10
  GenericQueryCtx,
11
+ PaginationOptions,
12
+ PaginationResult,
8
13
  } from "convex/server";
14
+ import { SetOptional } from "type-fest";
15
+
16
+ const handlePagination = async (
17
+ next: ({
18
+ paginationOpts,
19
+ }: {
20
+ paginationOpts: PaginationOptions;
21
+ }) => Promise<
22
+ SetOptional<PaginationResult<any>, "page"> & { count?: number }
23
+ >,
24
+ { limit, numItems }: { limit?: number; numItems?: number } = {}
25
+ ) => {
26
+ const state: {
27
+ isDone: boolean;
28
+ cursor: string | null;
29
+ docs: any[];
30
+ count: number;
31
+ } = {
32
+ isDone: false,
33
+ cursor: null,
34
+ docs: [],
35
+ count: 0,
36
+ };
37
+ const onResult = (
38
+ result: SetOptional<PaginationResult<any>, "page"> & { count?: number }
39
+ ) => {
40
+ state.cursor =
41
+ result.pageStatus === "SplitRecommended" ||
42
+ result.pageStatus === "SplitRequired"
43
+ ? result.splitCursor ?? result.continueCursor
44
+ : result.continueCursor;
45
+ if (result.page) {
46
+ state.docs.push(...result.page);
47
+ state.isDone = (limit && state.docs.length >= limit) || result.isDone;
48
+ return;
49
+ }
50
+ // Update and delete only return a count
51
+ if (result.count) {
52
+ state.count += result.count;
53
+ state.isDone = (limit && state.count >= limit) || result.isDone;
54
+ return;
55
+ }
56
+ state.isDone = result.isDone;
57
+ };
58
+
59
+ do {
60
+ const result = await next({
61
+ paginationOpts: {
62
+ numItems: Math.min(
63
+ numItems ?? 200,
64
+ (limit ?? 200) - state.docs.length,
65
+ 200
66
+ ),
67
+ cursor: state.cursor,
68
+ },
69
+ });
70
+ onResult(result);
71
+ } while (!state.isDone);
72
+ return state;
73
+ };
9
74
 
10
- export const convexAdapter = <
11
- Ctx extends
12
- | GenericQueryCtx<any>
13
- | GenericMutationCtx<any>
14
- | GenericActionCtx<any>,
15
- >(
16
- ctx: Ctx,
17
- component: BetterAuth
18
- ) =>
19
- createAdapter({
75
+ type ConvexCleanedWhere = CleanedWhere & {
76
+ value: string | number | boolean | string[] | number[] | null;
77
+ };
78
+
79
+ const parseWhere = (where?: CleanedWhere[]): ConvexCleanedWhere[] => {
80
+ return where?.map((where) => {
81
+ if (where.value instanceof Date) {
82
+ return {
83
+ ...where,
84
+ value: where.value.getTime(),
85
+ };
86
+ }
87
+ return where;
88
+ }) as ConvexCleanedWhere[];
89
+ };
90
+
91
+ type GenericCtx =
92
+ | GenericQueryCtx<any>
93
+ | GenericMutationCtx<any>
94
+ | GenericActionCtx<any>;
95
+
96
+ interface ConvexAdapterConfig {
97
+ /**
98
+ * Helps you debug issues with the adapter.
99
+ */
100
+ debugLogs?: AdapterDebugLogs;
101
+ }
102
+ export const convexAdapter = (
103
+ ctx: GenericCtx,
104
+ component: BetterAuth,
105
+ config: ConvexAdapterConfig = {}
106
+ ) => {
107
+ const { debugLogs } = config;
108
+ return createAdapter({
20
109
  config: {
21
110
  adapterId: "convex",
22
111
  adapterName: "Convex Adapter",
23
- debugLogs: component.config.verbose ?? false,
112
+ debugLogs: component.config.verbose ?? debugLogs ?? false,
24
113
  disableIdGeneration: true,
114
+ supportsNumericIds: false,
115
+ usePlural: false,
116
+ mapKeysTransformOutput: {
117
+ _id: "id",
118
+ },
119
+ customTransformInput: ({ data, fieldAttributes }) => {
120
+ if (data && fieldAttributes.type === "date") {
121
+ return data.getTime();
122
+ }
123
+ return data;
124
+ },
125
+ customTransformOutput: ({ data, fieldAttributes }) => {
126
+ if (data && fieldAttributes.type === "date") {
127
+ return new Date(data);
128
+ }
129
+ return data;
130
+ },
25
131
  },
26
- adapter: ({ schema }) => {
132
+ adapter: () => {
27
133
  return {
28
134
  id: "convex",
29
135
  create: async ({ model, data, select }): Promise<any> => {
30
136
  if (!("runMutation" in ctx)) {
31
- throw new Error("ctx is not an action ctx");
137
+ throw new Error("ctx is not a mutation ctx");
32
138
  }
33
139
  if (select) {
34
140
  throw new Error("select is not supported");
@@ -39,223 +145,125 @@ export const convexAdapter = <
39
145
  : model === "session"
40
146
  ? component.config.authFunctions.createSession
41
147
  : component.component.lib.create;
42
- return ctx.runMutation(createFn, {
43
- input: { table: model, ...transformInput(model, data) },
148
+ return await ctx.runMutation(createFn, {
149
+ input: { model, data },
44
150
  });
45
151
  },
46
- findOne: async ({ model, where }): Promise<any> => {
47
- if (where.length === 1 && where[0].operator === "eq") {
48
- const { value, field } = where[0];
49
- const result = await ctx.runQuery(component.component.lib.getBy, {
50
- table: model,
51
- field,
52
- unique:
53
- field === "id" ? true : schema[model].fields[field].unique,
54
- value: value instanceof Date ? value.getTime() : value,
55
- });
56
- return result;
57
- }
58
- if (
59
- model === "account" &&
60
- where.length === 2 &&
61
- where[0].field === "accountId" &&
62
- where[1].field === "providerId" &&
63
- where[0].connector === "AND"
64
- ) {
65
- return ctx.runQuery(
66
- component.component.lib.getAccountByAccountIdAndProviderId,
67
- {
68
- accountId: where[0].value as string,
69
- providerId: where[1].value as string,
152
+ findOne: async (data): Promise<any> => {
153
+ if (data.where?.every((w) => w.connector === "OR")) {
154
+ for (const w of data.where) {
155
+ const result = await ctx.runQuery(
156
+ component.component.lib.findOne,
157
+ {
158
+ ...data,
159
+ where: parseWhere([w]),
160
+ }
161
+ );
162
+ if (result) {
163
+ return result;
70
164
  }
71
- );
165
+ }
72
166
  }
73
- throw new Error("where clause not supported");
167
+ return await ctx.runQuery(component.component.lib.findOne, {
168
+ ...data,
169
+ where: parseWhere(data.where),
170
+ });
74
171
  },
75
- findMany: async ({
76
- model,
77
- where,
78
- sortBy,
79
- offset,
80
- limit,
81
- }): Promise<any[]> => {
82
- if (offset) {
172
+ findMany: async (data): Promise<any[]> => {
173
+ if (data.offset) {
83
174
  throw new Error("offset not supported");
84
175
  }
85
- if (
86
- model === "jwks" &&
87
- !where &&
88
- (!sortBy ||
89
- (sortBy?.field === "createdAt" && sortBy?.direction === "desc"))
90
- ) {
91
- return ctx.runQuery(component.component.lib.getJwks, { limit });
92
- }
93
- if (
94
- where?.length !== 1 ||
95
- (where[0].operator && where[0].operator !== "eq")
96
- ) {
97
- throw new Error("where clause not supported");
98
- }
99
- if (model === "verification" && where[0].field === "identifier") {
100
- return ctx.runQuery(
101
- component.component.lib.listVerificationsByIdentifier,
102
- {
103
- identifier: where[0].value as string,
104
- sortBy,
105
- limit,
106
- }
107
- );
176
+ if (data.where?.some((w) => w.connector === "OR")) {
177
+ throw new Error("OR connector not supported in findMany");
108
178
  }
109
- if (model === "account" && where[0].field === "userId" && !sortBy) {
110
- return ctx.runQuery(component.component.lib.getAccountsByUserId, {
111
- userId: where[0].value as any,
112
- limit,
113
- });
179
+ const result = await handlePagination(
180
+ async ({ paginationOpts }) => {
181
+ return await ctx.runQuery(component.component.lib.findMany, {
182
+ ...data,
183
+ where: parseWhere(data.where),
184
+ paginationOpts,
185
+ });
186
+ },
187
+ { limit: data.limit }
188
+ );
189
+ return result.docs;
190
+ },
191
+ count: async (data) => {
192
+ // Yes, count is just findMany returning a number.
193
+ if (data.where?.some((w) => w.connector === "OR")) {
194
+ throw new Error("OR connector not supported in findMany");
114
195
  }
115
- if (model === "session" && where[0].field === "userId" && !sortBy) {
116
- return ctx.runQuery(component.component.lib.getSessionsByUserId, {
117
- userId: where[0].value as any,
118
- limit,
196
+ const result = await handlePagination(async ({ paginationOpts }) => {
197
+ return await ctx.runQuery(component.component.lib.findMany, {
198
+ ...data,
199
+ where: parseWhere(data.where),
200
+ paginationOpts,
119
201
  });
120
- }
121
- throw new Error("where clause not supported");
122
- },
123
- count: async ({ where }) => {
124
- throw new Error("count not implemented");
125
- // return 0;
202
+ });
203
+ return result.docs?.length ?? 0;
126
204
  },
127
- update: async ({ model, where, update }): Promise<any> => {
205
+ update: async (data): Promise<any> => {
128
206
  if (!("runMutation" in ctx)) {
129
- throw new Error("ctx is not an action ctx");
207
+ throw new Error("ctx is not a mutation ctx");
130
208
  }
131
- if (where?.length === 1 && where[0].operator === "eq") {
132
- const { value, field } = where[0];
209
+ if (data.where?.length === 1 && data.where[0].operator === "eq") {
133
210
  const updateFn =
134
- model === "user"
211
+ data.model === "user"
135
212
  ? component.config.authFunctions.updateUser
136
- : component.component.lib.update;
213
+ : component.component.lib.updateOne;
137
214
  return ctx.runMutation(updateFn, {
138
215
  input: {
139
- table: model as any,
140
- where: {
141
- field,
142
- value: value instanceof Date ? value.getTime() : value,
143
- },
144
- value: transformInput(model, update as any),
216
+ model: data.model,
217
+ where: parseWhere(data.where),
218
+ update: data.update as any,
145
219
  },
146
220
  });
147
221
  }
148
222
  throw new Error("where clause not supported");
149
223
  },
150
- delete: async ({ model, where }) => {
224
+ delete: async (data) => {
151
225
  if (!("runMutation" in ctx)) {
152
- throw new Error("ctx is not an action ctx");
226
+ throw new Error("ctx is not a mutation ctx");
153
227
  }
154
- if (where?.length === 1 && where[0].operator === "eq") {
155
- const { field, value } = where[0];
156
- const deleteFn =
157
- model === "user"
158
- ? component.config.authFunctions.deleteUser
159
- : component.component.lib.deleteBy;
160
- await ctx.runMutation(deleteFn, {
161
- table: model,
162
- field,
163
- value: value instanceof Date ? value.getTime() : value,
164
- });
165
- return;
166
- }
167
- throw new Error("where clause not supported");
168
- // return null
228
+ const deleteFn =
229
+ data.model === "user"
230
+ ? component.config.authFunctions.deleteUser
231
+ : component.component.lib.deleteOne;
232
+ await ctx.runMutation(deleteFn, {
233
+ model: data.model,
234
+ where: parseWhere(data.where),
235
+ });
236
+ return;
169
237
  },
170
- deleteMany: async ({ model, where }) => {
171
- if (!("runAction" in ctx)) {
172
- throw new Error("ctx is not an action ctx");
173
- }
174
- if (
175
- model === "verification" &&
176
- where?.length === 1 &&
177
- where[0].operator === "lt" &&
178
- where[0].field === "expiresAt"
179
- ) {
180
- return ctx.runAction(
181
- component.component.lib.deleteOldVerifications,
182
- {
183
- currentTimestamp: Date.now(),
184
- }
185
- );
238
+ deleteMany: async (data) => {
239
+ if (!("runMutation" in ctx)) {
240
+ throw new Error("ctx is not a mutation ctx");
186
241
  }
187
- if (where?.length === 1 && where[0].field === "userId") {
188
- return ctx.runAction(component.component.lib.deleteAllForUser, {
189
- table: model,
190
- userId: where[0].value as any,
242
+ const result = await handlePagination(async ({ paginationOpts }) => {
243
+ return await ctx.runMutation(component.component.lib.deleteMany, {
244
+ ...data,
245
+ where: parseWhere(data.where),
246
+ paginationOpts,
191
247
  });
192
- }
193
- if (
194
- model === "session" &&
195
- where?.length === 2 &&
196
- where[0].operator === "eq" &&
197
- where[0].connector === "AND" &&
198
- where[0].field === "userId" &&
199
- where[1].operator === "lte" &&
200
- where[1].field === "expiresAt" &&
201
- typeof where[1].value === "number"
202
- ) {
203
- return ctx.runMutation(
204
- component.component.lib.deleteExpiredSessions,
205
- {
206
- userId: where[0].value as string,
207
- expiresAt: where[1].value as number,
208
- }
209
- );
210
- }
211
- throw new Error("where clause not supported");
212
- // return count;
248
+ });
249
+ return result.count;
213
250
  },
214
- updateMany: async ({ model, where, update }) => {
251
+ updateMany: async (data) => {
215
252
  if (!("runMutation" in ctx)) {
216
253
  throw new Error("ctx is not an action ctx");
217
254
  }
218
- if (
219
- model === "twoFactor" &&
220
- where?.length === 1 &&
221
- where[0].operator === "eq" &&
222
- where[0].field === "userId"
223
- ) {
224
- return ctx.runMutation(component.component.lib.updateTwoFactor, {
225
- userId: where[0].value as string,
226
- update: transformInput(model, update as any),
255
+ const result = await handlePagination(async ({ paginationOpts }) => {
256
+ return await ctx.runMutation(component.component.lib.updateMany, {
257
+ input: {
258
+ ...data,
259
+ where: parseWhere(data.where),
260
+ paginationOpts,
261
+ },
227
262
  });
228
- }
229
- if (
230
- model === "account" &&
231
- where?.length === 2 &&
232
- where[0].operator === "eq" &&
233
- where[0].connector === "AND" &&
234
- where[0].field === "userId" &&
235
- where[1].operator === "eq" &&
236
- where[1].field === "providerId"
237
- ) {
238
- return ctx.runMutation(
239
- component.component.lib.updateUserProviderAccounts,
240
- {
241
- userId: where[0].value as string,
242
- providerId: where[1].value as string,
243
- update: transformInput(model, update as any),
244
- }
245
- );
246
- }
247
- throw new Error("updateMany not implemented");
248
- //return 0;
249
- /*
250
- const { model, where, update } = data;
251
- const table = db[model];
252
- const res = convertWhereClause(where, table, model);
253
- res.forEach((record) => {
254
- Object.assign(record, update);
255
263
  });
256
- return res[0] || null;
257
- */
264
+ return result.count;
258
265
  },
259
266
  };
260
267
  },
261
268
  });
269
+ };
@@ -16,33 +16,36 @@ import { type GenericId, Infer, v } from "convex/values";
16
16
  import type { api } from "../component/_generated/api";
17
17
  import schema from "../component/schema";
18
18
  import { convexAdapter } from "./adapter";
19
- import corsRouter from "./cors";
20
- import { getByArgsValidator, updateArgsInputValidator } from "../component/lib";
21
19
  import { betterAuth } from "better-auth";
22
20
  import { omit } from "convex-helpers";
23
21
  import { createCookieGetter } from "better-auth/cookies";
24
22
  import { fetchQuery } from "convex/nextjs";
25
23
  import { JWT_COOKIE_NAME } from "../plugins/convex";
26
- import { requireEnv } from "../util";
24
+ import { requireEnv } from "../utils";
25
+ import { partial } from "convex-helpers/validators";
26
+ import { adapterArgsValidator, adapterWhereValidator } from "../component/lib";
27
+ import { corsRouter } from "convex-helpers/server/cors";
27
28
  export { convexAdapter };
28
29
 
29
30
  const createUserFields = omit(schema.tables.user.validator.fields, ["userId"]);
30
31
  const createUserValidator = v.object(createUserFields);
31
32
  const createUserArgsValidator = v.object({
32
33
  input: v.object({
33
- ...createUserFields,
34
- table: v.literal("user"),
34
+ model: v.literal("user"),
35
+ data: v.object(createUserFields),
35
36
  }),
36
37
  });
37
38
  const updateUserArgsValidator = v.object({
38
- input: updateArgsInputValidator("user"),
39
+ input: v.object({
40
+ model: v.literal("user"),
41
+ where: v.optional(v.array(adapterWhereValidator)),
42
+ update: v.object(partial(createUserFields)),
43
+ }),
39
44
  });
40
- const deleteUserArgsValidator = v.object(getByArgsValidator);
41
-
42
45
  const createSessionArgsValidator = v.object({
43
46
  input: v.object({
44
- table: v.literal("session"),
45
- ...schema.tables.session.validator.fields,
47
+ model: v.literal("session"),
48
+ data: v.object(schema.tables.session.validator.fields),
46
49
  }),
47
50
  });
48
51
 
@@ -61,7 +64,7 @@ export type AuthFunctions = {
61
64
  deleteUser: FunctionReference<
62
65
  "mutation",
63
66
  "internal",
64
- Infer<typeof deleteUserArgsValidator>
67
+ Infer<typeof adapterArgsValidator>
65
68
  >;
66
69
  updateUser: FunctionReference<
67
70
  "mutation",
@@ -128,10 +131,14 @@ export class BetterAuth<UserId extends string = string> {
128
131
  if (!identity) {
129
132
  return null;
130
133
  }
131
- const doc = await ctx.runQuery(this.component.lib.getBy, {
132
- table: "user",
133
- field: "userId",
134
- value: identity.subject,
134
+ const doc = await ctx.runQuery(this.component.lib.findOne, {
135
+ model: "user",
136
+ where: [
137
+ {
138
+ field: "userId",
139
+ value: identity.subject,
140
+ },
141
+ ],
135
142
  });
136
143
  if (!doc) {
137
144
  return null;
@@ -182,35 +189,38 @@ export class BetterAuth<UserId extends string = string> {
182
189
  createUser: internalMutationGeneric({
183
190
  args: createUserArgsValidator,
184
191
  handler: async (ctx, args) => {
185
- const userId = await opts.onCreateUser(ctx, args.input);
186
- const input = { ...args.input, table: "user", userId };
192
+ const userId = await opts.onCreateUser(ctx, args.input.data);
187
193
  return ctx.runMutation(this.component.lib.create, {
188
- input,
194
+ input: {
195
+ ...args.input,
196
+ data: { ...args.input.data, userId },
197
+ },
189
198
  });
190
199
  },
191
200
  }),
192
201
  deleteUser: internalMutationGeneric({
193
- args: deleteUserArgsValidator,
202
+ args: adapterArgsValidator,
194
203
  handler: async (ctx, args) => {
195
- const doc = await ctx.runMutation(this.component.lib.deleteBy, args);
196
- if (opts.onDeleteUser) {
204
+ const doc = await ctx.runMutation(this.component.lib.deleteOne, args);
205
+ if (doc && opts.onDeleteUser) {
197
206
  await opts.onDeleteUser(ctx, doc.userId as UserId);
198
207
  }
208
+ return doc;
199
209
  },
200
210
  }),
201
211
  updateUser: internalMutationGeneric({
202
212
  args: updateUserArgsValidator,
203
213
  handler: async (ctx, args) => {
204
214
  const updatedUser = await ctx.runMutation(
205
- this.component.lib.update,
206
- args
215
+ this.component.lib.updateOne,
216
+ { input: args.input }
207
217
  );
208
218
  // Type narrowing
209
219
  if (!("emailVerified" in updatedUser)) {
210
220
  throw new Error("invalid user");
211
221
  }
212
222
  if (opts.onUpdateUser) {
213
- await opts.onUpdateUser(ctx, omit(updatedUser, ["id"]));
223
+ await opts.onUpdateUser(ctx, omit(updatedUser, ["_id"]));
214
224
  }
215
225
  return updatedUser;
216
226
  },
@@ -218,14 +228,9 @@ export class BetterAuth<UserId extends string = string> {
218
228
  createSession: internalMutationGeneric({
219
229
  args: createSessionArgsValidator,
220
230
  handler: async (ctx, args) => {
221
- const session = await ctx.runMutation(
222
- this.component.lib.create,
223
- args
224
- );
225
- // Type narrowing
226
- if (!("ipAddress" in session)) {
227
- throw new Error("invalid session");
228
- }
231
+ const session = await ctx.runMutation(this.component.lib.create, {
232
+ input: args.input,
233
+ });
229
234
  await opts.onCreateSession?.(ctx, session);
230
235
  return session;
231
236
  },
@@ -283,50 +288,20 @@ export class BetterAuth<UserId extends string = string> {
283
288
 
284
289
  return;
285
290
  }
286
-
287
- const trustedOrigins = [
288
- ...(Array.isArray(betterAuthOptions.trustedOrigins)
289
- ? betterAuthOptions.trustedOrigins
290
- : [betterAuthOptions.trustedOrigins]),
291
- betterAuthOptions.baseURL!,
292
- ];
293
- // The crossDomain plugin adds siteUrl to trustedOrigins
294
- const trustedOriginsFromPlugins =
295
- betterAuthOptions.plugins?.reduce((acc, plugin) => {
296
- if (plugin.options?.trustedOrigins) {
297
- acc.push(...plugin.options.trustedOrigins);
298
- }
299
- return acc;
300
- }, [] as string[]) ?? [];
301
-
302
- // Reuse trustedOrigins as default for allowedOrigins
303
- const allowedOrigins = async (request: Request) => {
304
- return (
305
- await Promise.all(
306
- [...trustedOrigins, ...trustedOriginsFromPlugins].map(
307
- async (origin) => {
308
- if (!origin) {
309
- return [];
310
- }
311
- if (typeof origin === "function") {
312
- return origin(request);
313
- }
314
- return [origin];
315
- }
316
- )
317
- )
318
- )
319
- .flat()
320
- .map((origin) =>
291
+ const cors = corsRouter(http, {
292
+ allowedOrigins: async (request) => {
293
+ const trustedOriginsOption =
294
+ (await createAuth({} as any).$context).options.trustedOrigins ?? [];
295
+ const trustedOrigins = Array.isArray(trustedOriginsOption)
296
+ ? trustedOriginsOption
297
+ : await trustedOriginsOption(request);
298
+ return trustedOrigins.map((origin) =>
321
299
  // Strip trailing wildcards, unsupported for allowedOrigins
322
300
  origin.endsWith("*") && origin.length > 1
323
301
  ? origin.slice(0, -1)
324
302
  : origin
325
303
  );
326
- };
327
-
328
- const cors = corsRouter(http, {
329
- allowedOrigins,
304
+ },
330
305
  allowCredentials: true,
331
306
  allowedHeaders: ["Content-Type", "Better-Auth-Cookie"],
332
307
  exposedHeaders: ["Set-Better-Auth-Cookie"],