@convex-dev/better-auth 0.7.0-alpha.12 → 0.7.0-alpha.3

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 (108) hide show
  1. package/dist/commonjs/client/adapter.d.ts +1 -10
  2. package/dist/commonjs/client/adapter.d.ts.map +1 -1
  3. package/dist/commonjs/client/adapter.js +192 -183
  4. package/dist/commonjs/client/adapter.js.map +1 -1
  5. package/dist/commonjs/client/index.d.ts +179 -238
  6. package/dist/commonjs/client/index.d.ts.map +1 -1
  7. package/dist/commonjs/client/index.js +67 -60
  8. package/dist/commonjs/client/index.js.map +1 -1
  9. package/dist/commonjs/component/lib.d.ts +548 -218
  10. package/dist/commonjs/component/lib.d.ts.map +1 -1
  11. package/dist/commonjs/component/lib.js +286 -315
  12. package/dist/commonjs/component/lib.js.map +1 -1
  13. package/dist/commonjs/component/schema.d.ts +28 -90
  14. package/dist/commonjs/component/schema.d.ts.map +1 -1
  15. package/dist/commonjs/component/schema.js +18 -76
  16. package/dist/commonjs/component/schema.js.map +1 -1
  17. package/dist/commonjs/component/util.d.ts +86 -148
  18. package/dist/commonjs/component/util.d.ts.map +1 -1
  19. package/dist/commonjs/nextjs/index.d.ts.map +1 -1
  20. package/dist/commonjs/nextjs/index.js +0 -3
  21. package/dist/commonjs/nextjs/index.js.map +1 -1
  22. package/dist/commonjs/plugins/convex/index.d.ts +11 -14
  23. package/dist/commonjs/plugins/convex/index.d.ts.map +1 -1
  24. package/dist/commonjs/plugins/convex/index.js +4 -10
  25. package/dist/commonjs/plugins/convex/index.js.map +1 -1
  26. package/dist/commonjs/plugins/cross-domain/client.d.ts +1 -1
  27. package/dist/commonjs/plugins/cross-domain/index.d.ts +3 -5
  28. package/dist/commonjs/plugins/cross-domain/index.d.ts.map +1 -1
  29. package/dist/commonjs/plugins/cross-domain/index.js +5 -19
  30. package/dist/commonjs/plugins/cross-domain/index.js.map +1 -1
  31. package/dist/commonjs/react/client.d.ts +1 -1
  32. package/dist/commonjs/react/client.d.ts.map +1 -1
  33. package/dist/commonjs/react/client.js +9 -3
  34. package/dist/commonjs/react/client.js.map +1 -1
  35. package/dist/commonjs/react-start/index.d.ts +3 -37
  36. package/dist/commonjs/react-start/index.d.ts.map +1 -1
  37. package/dist/commonjs/react-start/index.js +4 -20
  38. package/dist/commonjs/react-start/index.js.map +1 -1
  39. package/dist/esm/client/adapter.d.ts +1 -10
  40. package/dist/esm/client/adapter.d.ts.map +1 -1
  41. package/dist/esm/client/adapter.js +192 -183
  42. package/dist/esm/client/adapter.js.map +1 -1
  43. package/dist/esm/client/index.d.ts +179 -238
  44. package/dist/esm/client/index.d.ts.map +1 -1
  45. package/dist/esm/client/index.js +67 -60
  46. package/dist/esm/client/index.js.map +1 -1
  47. package/dist/esm/component/lib.d.ts +548 -218
  48. package/dist/esm/component/lib.d.ts.map +1 -1
  49. package/dist/esm/component/lib.js +286 -315
  50. package/dist/esm/component/lib.js.map +1 -1
  51. package/dist/esm/component/schema.d.ts +28 -90
  52. package/dist/esm/component/schema.d.ts.map +1 -1
  53. package/dist/esm/component/schema.js +18 -76
  54. package/dist/esm/component/schema.js.map +1 -1
  55. package/dist/esm/component/util.d.ts +86 -148
  56. package/dist/esm/component/util.d.ts.map +1 -1
  57. package/dist/esm/nextjs/index.d.ts.map +1 -1
  58. package/dist/esm/nextjs/index.js +0 -3
  59. package/dist/esm/nextjs/index.js.map +1 -1
  60. package/dist/esm/plugins/convex/index.d.ts +11 -14
  61. package/dist/esm/plugins/convex/index.d.ts.map +1 -1
  62. package/dist/esm/plugins/convex/index.js +4 -10
  63. package/dist/esm/plugins/convex/index.js.map +1 -1
  64. package/dist/esm/plugins/cross-domain/client.d.ts +1 -1
  65. package/dist/esm/plugins/cross-domain/index.d.ts +3 -5
  66. package/dist/esm/plugins/cross-domain/index.d.ts.map +1 -1
  67. package/dist/esm/plugins/cross-domain/index.js +5 -19
  68. package/dist/esm/plugins/cross-domain/index.js.map +1 -1
  69. package/dist/esm/react/client.d.ts +1 -1
  70. package/dist/esm/react/client.d.ts.map +1 -1
  71. package/dist/esm/react/client.js +9 -3
  72. package/dist/esm/react/client.js.map +1 -1
  73. package/dist/esm/react-start/index.d.ts +3 -37
  74. package/dist/esm/react-start/index.d.ts.map +1 -1
  75. package/dist/esm/react-start/index.js +4 -20
  76. package/dist/esm/react-start/index.js.map +1 -1
  77. package/package.json +5 -20
  78. package/src/client/adapter.ts +195 -191
  79. package/src/client/cors.ts +425 -0
  80. package/src/client/index.ts +80 -61
  81. package/src/component/_generated/api.d.ts +149 -605
  82. package/src/component/lib.ts +335 -444
  83. package/src/component/schema.ts +19 -81
  84. package/src/nextjs/index.ts +0 -3
  85. package/src/plugins/convex/index.ts +4 -12
  86. package/src/plugins/cross-domain/index.ts +5 -19
  87. package/src/react/client.tsx +11 -5
  88. package/src/react-start/index.ts +6 -33
  89. package/dist/commonjs/component/adapterTest.d.ts +0 -19
  90. package/dist/commonjs/component/adapterTest.d.ts.map +0 -1
  91. package/dist/commonjs/component/adapterTest.js +0 -82
  92. package/dist/commonjs/component/adapterTest.js.map +0 -1
  93. package/dist/commonjs/utils/index.d.ts +0 -2
  94. package/dist/commonjs/utils/index.d.ts.map +0 -1
  95. package/dist/commonjs/utils/index.js +0 -8
  96. package/dist/commonjs/utils/index.js.map +0 -1
  97. package/dist/esm/component/adapterTest.d.ts +0 -19
  98. package/dist/esm/component/adapterTest.d.ts.map +0 -1
  99. package/dist/esm/component/adapterTest.js +0 -82
  100. package/dist/esm/component/adapterTest.js.map +0 -1
  101. package/dist/esm/utils/index.d.ts +0 -2
  102. package/dist/esm/utils/index.d.ts.map +0 -1
  103. package/dist/esm/utils/index.js +0 -8
  104. package/dist/esm/utils/index.js.map +0 -1
  105. package/src/client/adapter.test.ts +0 -144
  106. package/src/component/adapterTest.ts +0 -141
  107. package/src/react-start/vite-env.d.ts +0 -2
  108. /package/src/{utils/index.ts → util.ts} +0 -0
@@ -1,139 +1,34 @@
1
1
  import { BetterAuth } from "./index";
2
- import {
3
- AdapterDebugLogs,
4
- CleanedWhere,
5
- createAdapter,
6
- } from "better-auth/adapters";
2
+ import { transformInput } from "../component/lib";
3
+ import { createAdapter } from "better-auth/adapters";
7
4
  import {
8
5
  GenericActionCtx,
9
6
  GenericMutationCtx,
10
7
  GenericQueryCtx,
11
- PaginationOptions,
12
- PaginationResult,
13
8
  } from "convex/server";
14
- import { SetOptional } from "type-fest";
15
-
16
- const paginate = 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
- if (result.count) {
51
- state.count += result.count;
52
- state.isDone = (limit && state.count >= limit) || result.isDone;
53
- return;
54
- }
55
- state.isDone = result.isDone;
56
- };
57
-
58
- do {
59
- const result = await next({
60
- paginationOpts: {
61
- numItems: Math.min(numItems ?? 200, limit ?? 200, 200),
62
- cursor: state.cursor,
63
- },
64
- });
65
- onResult(result);
66
- } while (!state.isDone);
67
- return state;
68
- };
69
-
70
- type ConvexCleanedWhere = CleanedWhere & {
71
- value: string | number | boolean | string[] | number[] | null;
72
- };
73
-
74
- const parseWhere = (where?: CleanedWhere[]): ConvexCleanedWhere[] => {
75
- return where?.map((where) => {
76
- if (where.value instanceof Date) {
77
- return {
78
- ...where,
79
- value: where.value.getTime(),
80
- };
81
- }
82
- return where;
83
- }) as ConvexCleanedWhere[];
84
- };
85
9
 
86
- type GenericCtx =
87
- | GenericQueryCtx<any>
88
- | GenericMutationCtx<any>
89
- | GenericActionCtx<any>;
90
-
91
- interface ConvexAdapterConfig {
92
- /**
93
- * Helps you debug issues with the adapter.
94
- */
95
- debugLogs?: AdapterDebugLogs;
96
- }
97
- export const convexAdapter = (
98
- ctx: GenericCtx,
99
- component: BetterAuth,
100
- config: ConvexAdapterConfig = {}
101
- ) => {
102
- const { debugLogs } = config;
103
- return createAdapter({
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({
104
20
  config: {
105
21
  adapterId: "convex",
106
22
  adapterName: "Convex Adapter",
107
- debugLogs: component.config.verbose ?? debugLogs ?? false,
23
+ debugLogs: component.config.verbose ?? false,
108
24
  disableIdGeneration: true,
109
- supportsNumericIds: false,
110
- usePlural: false,
111
- mapKeysTransformOutput: {
112
- _id: "id",
113
- },
114
- customTransformInput: ({ data, fieldAttributes, field }) => {
115
- if (data && fieldAttributes.type === "date") {
116
- const result = data.getTime();
117
- console.log("transformed input", field, result);
118
- return result;
119
- }
120
- return data;
121
- },
122
- customTransformOutput: ({ data, fieldAttributes, field }) => {
123
- if (data && fieldAttributes.type === "date") {
124
- const result = new Date(data);
125
- console.log("transformed output", field, result);
126
- return result;
127
- }
128
- return data;
129
- },
130
25
  },
131
26
  adapter: ({ schema }) => {
132
27
  return {
133
28
  id: "convex",
134
29
  create: async ({ model, data, select }): Promise<any> => {
135
30
  if (!("runMutation" in ctx)) {
136
- throw new Error("ctx is not a mutation ctx");
31
+ throw new Error("ctx is not an action ctx");
137
32
  }
138
33
  if (select) {
139
34
  throw new Error("select is not supported");
@@ -144,114 +39,223 @@ export const convexAdapter = (
144
39
  : model === "session"
145
40
  ? component.config.authFunctions.createSession
146
41
  : component.component.lib.create;
147
- return await ctx.runMutation(createFn, {
148
- input: { model, data },
42
+ return ctx.runMutation(createFn, {
43
+ input: { table: model, ...transformInput(model, data) },
149
44
  });
150
45
  },
151
- findOne: async (data): Promise<any> => {
152
- return await ctx.runQuery(component.component.lib.findOne, {
153
- ...data,
154
- where: parseWhere(data.where),
155
- });
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,
70
+ }
71
+ );
72
+ }
73
+ throw new Error("where clause not supported");
156
74
  },
157
- findMany: async (data): Promise<any[]> => {
158
- if (data.offset) {
75
+ findMany: async ({
76
+ model,
77
+ where,
78
+ sortBy,
79
+ offset,
80
+ limit,
81
+ }): Promise<any[]> => {
82
+ if (offset) {
159
83
  throw new Error("offset not supported");
160
84
  }
161
- if (data.where?.length === 1 && data.where[0].operator === "in") {
162
- return ctx.runQuery(component.component.lib.getIn, {
163
- ...data,
164
- where: parseWhere(data.where),
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
+ );
108
+ }
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
+ });
114
+ }
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,
165
119
  });
166
120
  }
167
- const result = await paginate(
168
- async ({ paginationOpts }) => {
169
- return await ctx.runQuery(component.component.lib.findMany, {
170
- ...data,
171
- where: parseWhere(data.where),
172
- paginationOpts,
173
- });
174
- },
175
- { limit: data.limit }
176
- );
177
- return result.docs;
121
+ throw new Error("where clause not supported");
178
122
  },
179
- count: async () => {
123
+ count: async ({ where }) => {
180
124
  throw new Error("count not implemented");
125
+ // return 0;
181
126
  },
182
- update: async (data): Promise<any> => {
127
+ update: async ({ model, where, update }): Promise<any> => {
183
128
  if (!("runMutation" in ctx)) {
184
- throw new Error("ctx is not a mutation ctx");
129
+ throw new Error("ctx is not an action ctx");
185
130
  }
186
- if (data.where?.length === 1 && data.where[0].operator === "eq") {
131
+ if (where?.length === 1 && where[0].operator === "eq") {
132
+ const { value, field } = where[0];
187
133
  const updateFn =
188
- data.model === "user"
134
+ model === "user"
189
135
  ? component.config.authFunctions.updateUser
190
- : component.component.lib.updateOne;
136
+ : component.component.lib.update;
191
137
  return ctx.runMutation(updateFn, {
192
138
  input: {
193
- model: data.model,
194
- where: parseWhere(data.where),
195
- update: data.update as any,
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),
196
145
  },
197
146
  });
198
147
  }
199
148
  throw new Error("where clause not supported");
200
149
  },
201
- delete: async (data) => {
150
+ delete: async ({ model, where }) => {
202
151
  if (!("runMutation" in ctx)) {
203
- throw new Error("ctx is not a mutation ctx");
152
+ throw new Error("ctx is not an action ctx");
204
153
  }
205
- const deleteFn =
206
- data.model === "user"
207
- ? component.config.authFunctions.deleteUser
208
- : component.component.lib.deleteOne;
209
- await ctx.runMutation(deleteFn, {
210
- model: data.model,
211
- where: parseWhere(data.where),
212
- });
213
- return;
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
214
169
  },
215
- deleteMany: async (data) => {
216
- if (!("runMutation" in ctx)) {
217
- throw new Error("ctx is not a mutation ctx");
170
+ deleteMany: async ({ model, where }) => {
171
+ if (!("runAction" in ctx)) {
172
+ throw new Error("ctx is not an action ctx");
218
173
  }
219
174
  if (
220
- data.model === "session" &&
221
- data.where?.length === 1 &&
222
- data.where[0].operator === "in"
175
+ model === "verification" &&
176
+ where?.length === 1 &&
177
+ where[0].operator === "lt" &&
178
+ where[0].field === "expiresAt"
223
179
  ) {
224
- return ctx.runMutation(component.component.lib.deleteIn, {
225
- input: {
226
- table: data.model,
227
- field: data.where[0].field as any,
228
- values: data.where[0].value as string[],
229
- },
230
- });
180
+ return ctx.runAction(
181
+ component.component.lib.deleteOldVerifications,
182
+ {
183
+ currentTimestamp: Date.now(),
184
+ }
185
+ );
231
186
  }
232
- const result = await paginate(async ({ paginationOpts }) => {
233
- return await ctx.runMutation(component.component.lib.deleteMany, {
234
- ...data,
235
- where: parseWhere(data.where),
236
- paginationOpts,
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,
237
191
  });
238
- });
239
- return result.count;
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;
240
213
  },
241
- updateMany: async (data) => {
214
+ updateMany: async ({ model, where, update }) => {
242
215
  if (!("runMutation" in ctx)) {
243
216
  throw new Error("ctx is not an action ctx");
244
217
  }
245
- const result = await paginate(async ({ paginationOpts }) => {
246
- return await ctx.runMutation(component.component.lib.updateMany, {
247
- ...data,
248
- where: parseWhere(data.where),
249
- paginationOpts,
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),
250
227
  });
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);
251
255
  });
252
- return result.count;
256
+ return res[0] || null;
257
+ */
253
258
  },
254
259
  };
255
260
  },
256
261
  });
257
- };