@convex-dev/better-auth 0.10.13 → 0.11.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 (185) hide show
  1. package/dist/auth-options.d.ts.map +1 -1
  2. package/dist/auth-options.js +0 -2
  3. package/dist/auth-options.js.map +1 -1
  4. package/dist/client/adapter-utils.d.ts +10 -10
  5. package/dist/client/adapter-utils.d.ts.map +1 -1
  6. package/dist/client/adapter-utils.js +41 -32
  7. package/dist/client/adapter-utils.js.map +1 -1
  8. package/dist/client/adapter.d.ts +1 -1
  9. package/dist/client/adapter.d.ts.map +1 -1
  10. package/dist/client/adapter.js +113 -7
  11. package/dist/client/adapter.js.map +1 -1
  12. package/dist/client/create-api.d.ts +8 -7
  13. package/dist/client/create-api.d.ts.map +1 -1
  14. package/dist/client/create-api.js +1 -0
  15. package/dist/client/create-api.js.map +1 -1
  16. package/dist/client/create-client.d.ts +1 -1
  17. package/dist/client/create-client.d.ts.map +1 -1
  18. package/dist/client/create-client.js +8 -7
  19. package/dist/client/create-client.js.map +1 -1
  20. package/dist/client/create-schema.d.ts +0 -1
  21. package/dist/client/create-schema.d.ts.map +1 -1
  22. package/dist/client/create-schema.js +0 -1
  23. package/dist/client/create-schema.js.map +1 -1
  24. package/dist/component/_generated/api.d.ts +12 -0
  25. package/dist/component/_generated/api.d.ts.map +1 -1
  26. package/dist/component/_generated/api.js.map +1 -1
  27. package/dist/component/_generated/component.d.ts +7407 -92
  28. package/dist/component/_generated/component.d.ts.map +1 -1
  29. package/dist/component/adapter.d.ts +8 -7
  30. package/dist/component/adapter.d.ts.map +1 -1
  31. package/dist/component/adapterTest.d.ts +1 -7
  32. package/dist/component/adapterTest.d.ts.map +1 -1
  33. package/dist/component/adapterTest.js +193 -390
  34. package/dist/component/adapterTest.js.map +1 -1
  35. package/dist/component/schema.d.ts +35 -74
  36. package/dist/component/schema.d.ts.map +1 -1
  37. package/dist/component/schema.js +16 -21
  38. package/dist/component/schema.js.map +1 -1
  39. package/dist/component/testProfiles/adapterAdditionalFields.d.ts +131 -0
  40. package/dist/component/testProfiles/adapterAdditionalFields.d.ts.map +1 -0
  41. package/dist/component/testProfiles/adapterAdditionalFields.js +5 -0
  42. package/dist/component/testProfiles/adapterAdditionalFields.js.map +1 -0
  43. package/dist/component/testProfiles/adapterOrganizationJoins.d.ts +131 -0
  44. package/dist/component/testProfiles/adapterOrganizationJoins.d.ts.map +1 -0
  45. package/dist/component/testProfiles/adapterOrganizationJoins.js +5 -0
  46. package/dist/component/testProfiles/adapterOrganizationJoins.js.map +1 -0
  47. package/dist/component/testProfiles/adapterPluginTable.d.ts +131 -0
  48. package/dist/component/testProfiles/adapterPluginTable.d.ts.map +1 -0
  49. package/dist/component/testProfiles/adapterPluginTable.js +5 -0
  50. package/dist/component/testProfiles/adapterPluginTable.js.map +1 -0
  51. package/dist/component/testProfiles/adapterRenameField.d.ts +131 -0
  52. package/dist/component/testProfiles/adapterRenameField.d.ts.map +1 -0
  53. package/dist/component/testProfiles/adapterRenameField.js +5 -0
  54. package/dist/component/testProfiles/adapterRenameField.js.map +1 -0
  55. package/dist/component/testProfiles/adapterRenameUserCustom.d.ts +131 -0
  56. package/dist/component/testProfiles/adapterRenameUserCustom.d.ts.map +1 -0
  57. package/dist/component/testProfiles/adapterRenameUserCustom.js +5 -0
  58. package/dist/component/testProfiles/adapterRenameUserCustom.js.map +1 -0
  59. package/dist/component/testProfiles/adapterRenameUserTable.d.ts +131 -0
  60. package/dist/component/testProfiles/adapterRenameUserTable.d.ts.map +1 -0
  61. package/dist/component/testProfiles/adapterRenameUserTable.js +5 -0
  62. package/dist/component/testProfiles/adapterRenameUserTable.js.map +1 -0
  63. package/dist/component/testProfiles/auth-options.profile-additional-fields.d.ts +3 -0
  64. package/dist/component/testProfiles/auth-options.profile-additional-fields.d.ts.map +1 -0
  65. package/dist/component/testProfiles/auth-options.profile-additional-fields.js +38 -0
  66. package/dist/component/testProfiles/auth-options.profile-additional-fields.js.map +1 -0
  67. package/dist/component/testProfiles/auth-options.profile-plugin-table.d.ts +3 -0
  68. package/dist/component/testProfiles/auth-options.profile-plugin-table.d.ts.map +1 -0
  69. package/dist/component/testProfiles/auth-options.profile-plugin-table.js +92 -0
  70. package/dist/component/testProfiles/auth-options.profile-plugin-table.js.map +1 -0
  71. package/dist/component/testProfiles/auth-options.profile-rename-joins.d.ts +6 -0
  72. package/dist/component/testProfiles/auth-options.profile-rename-joins.d.ts.map +1 -0
  73. package/dist/component/testProfiles/auth-options.profile-rename-joins.js +49 -0
  74. package/dist/component/testProfiles/auth-options.profile-rename-joins.js.map +1 -0
  75. package/dist/component/testProfiles/schema.profile-additional-fields.d.ts +227 -0
  76. package/dist/component/testProfiles/schema.profile-additional-fields.d.ts.map +1 -0
  77. package/dist/component/testProfiles/schema.profile-additional-fields.js +37 -0
  78. package/dist/component/testProfiles/schema.profile-additional-fields.js.map +1 -0
  79. package/dist/component/testProfiles/schema.profile-plugin-table.d.ts +450 -0
  80. package/dist/component/testProfiles/schema.profile-plugin-table.d.ts.map +1 -0
  81. package/dist/component/testProfiles/schema.profile-plugin-table.js +116 -0
  82. package/dist/component/testProfiles/schema.profile-plugin-table.js.map +1 -0
  83. package/dist/nextjs/index.d.ts.map +1 -1
  84. package/dist/nextjs/index.js +1 -0
  85. package/dist/nextjs/index.js.map +1 -1
  86. package/dist/plugins/convex/index.d.ts +131 -12
  87. package/dist/plugins/convex/index.d.ts.map +1 -1
  88. package/dist/plugins/convex/index.js +12 -5
  89. package/dist/plugins/convex/index.js.map +1 -1
  90. package/dist/plugins/cross-domain/client.d.ts +1 -1
  91. package/dist/plugins/cross-domain/index.d.ts +126 -1
  92. package/dist/plugins/cross-domain/index.d.ts.map +1 -1
  93. package/dist/plugins/cross-domain/index.js +10 -15
  94. package/dist/plugins/cross-domain/index.js.map +1 -1
  95. package/dist/react-start/index.d.ts.map +1 -1
  96. package/dist/react-start/index.js +1 -0
  97. package/dist/react-start/index.js.map +1 -1
  98. package/dist/test/adapter-factory/auth-flow.d.ts +42 -0
  99. package/dist/test/adapter-factory/auth-flow.d.ts.map +1 -0
  100. package/dist/test/adapter-factory/auth-flow.js +145 -0
  101. package/dist/test/adapter-factory/auth-flow.js.map +1 -0
  102. package/dist/test/adapter-factory/basic.d.ts +190 -0
  103. package/dist/test/adapter-factory/basic.d.ts.map +1 -0
  104. package/dist/test/adapter-factory/basic.js +2713 -0
  105. package/dist/test/adapter-factory/basic.js.map +1 -0
  106. package/dist/test/adapter-factory/convex-custom.d.ts +18 -0
  107. package/dist/test/adapter-factory/convex-custom.d.ts.map +1 -0
  108. package/dist/test/adapter-factory/convex-custom.js +610 -0
  109. package/dist/test/adapter-factory/convex-custom.js.map +1 -0
  110. package/dist/test/adapter-factory/index.d.ts +11 -0
  111. package/dist/test/adapter-factory/index.d.ts.map +1 -0
  112. package/dist/test/adapter-factory/index.js +11 -0
  113. package/dist/test/adapter-factory/index.js.map +1 -0
  114. package/dist/test/adapter-factory/joins.d.ts +18 -0
  115. package/dist/test/adapter-factory/joins.d.ts.map +1 -0
  116. package/dist/test/adapter-factory/joins.js +22 -0
  117. package/dist/test/adapter-factory/joins.js.map +1 -0
  118. package/dist/test/adapter-factory/number-id.d.ts +18 -0
  119. package/dist/test/adapter-factory/number-id.d.ts.map +1 -0
  120. package/dist/test/adapter-factory/number-id.js +36 -0
  121. package/dist/test/adapter-factory/number-id.js.map +1 -0
  122. package/dist/test/adapter-factory/profile-additional-fields.d.ts +71 -0
  123. package/dist/test/adapter-factory/profile-additional-fields.d.ts.map +1 -0
  124. package/dist/test/adapter-factory/profile-additional-fields.js +44 -0
  125. package/dist/test/adapter-factory/profile-additional-fields.js.map +1 -0
  126. package/dist/test/adapter-factory/profile-plugin-table.d.ts +19 -0
  127. package/dist/test/adapter-factory/profile-plugin-table.d.ts.map +1 -0
  128. package/dist/test/adapter-factory/profile-plugin-table.js +25 -0
  129. package/dist/test/adapter-factory/profile-plugin-table.js.map +1 -0
  130. package/dist/test/adapter-factory/profile-rename-joins.d.ts +73 -0
  131. package/dist/test/adapter-factory/profile-rename-joins.d.ts.map +1 -0
  132. package/dist/test/adapter-factory/profile-rename-joins.js +34 -0
  133. package/dist/test/adapter-factory/profile-rename-joins.js.map +1 -0
  134. package/dist/test/adapter-factory/transactions.d.ts +21 -0
  135. package/dist/test/adapter-factory/transactions.d.ts.map +1 -0
  136. package/dist/test/adapter-factory/transactions.js +28 -0
  137. package/dist/test/adapter-factory/transactions.js.map +1 -0
  138. package/dist/test/adapter-factory/uuid.d.ts +18 -0
  139. package/dist/test/adapter-factory/uuid.d.ts.map +1 -0
  140. package/dist/test/adapter-factory/uuid.js +58 -0
  141. package/dist/test/adapter-factory/uuid.js.map +1 -0
  142. package/dist/utils/index.d.ts +18 -3
  143. package/dist/utils/index.d.ts.map +1 -1
  144. package/dist/utils/index.js.map +1 -1
  145. package/package.json +8 -4
  146. package/src/auth-options.ts +0 -2
  147. package/src/client/adapter-utils.ts +80 -73
  148. package/src/client/adapter.test.ts +2 -74
  149. package/src/client/adapter.ts +142 -7
  150. package/src/client/create-api.ts +1 -0
  151. package/src/client/create-client.ts +14 -6
  152. package/src/client/create-schema.ts +0 -1
  153. package/src/component/_generated/api.ts +12 -0
  154. package/src/component/_generated/component.ts +19454 -215
  155. package/src/component/adapterTest.ts +250 -466
  156. package/src/component/schema.ts +21 -26
  157. package/src/component/testProfiles/adapterAdditionalFields.ts +13 -0
  158. package/src/component/testProfiles/adapterOrganizationJoins.ts +13 -0
  159. package/src/component/testProfiles/adapterPluginTable.ts +13 -0
  160. package/src/component/testProfiles/adapterRenameField.ts +13 -0
  161. package/src/component/testProfiles/adapterRenameUserCustom.ts +13 -0
  162. package/src/component/testProfiles/adapterRenameUserTable.ts +13 -0
  163. package/src/component/testProfiles/auth-options.profile-additional-fields.ts +39 -0
  164. package/src/component/testProfiles/auth-options.profile-plugin-table.ts +93 -0
  165. package/src/component/testProfiles/auth-options.profile-rename-joins.ts +54 -0
  166. package/src/component/testProfiles/schema.profile-additional-fields.ts +39 -0
  167. package/src/component/testProfiles/schema.profile-plugin-table.ts +130 -0
  168. package/src/nextjs/index.ts +1 -0
  169. package/src/plugins/convex/index.test.ts +55 -0
  170. package/src/plugins/convex/index.ts +26 -11
  171. package/src/plugins/cross-domain/index.test.ts +67 -0
  172. package/src/plugins/cross-domain/index.ts +10 -21
  173. package/src/react-start/index.ts +1 -0
  174. package/src/test/adapter-factory/auth-flow.ts +170 -0
  175. package/src/test/adapter-factory/basic.ts +3190 -0
  176. package/src/test/adapter-factory/convex-custom.ts +706 -0
  177. package/src/test/adapter-factory/index.ts +10 -0
  178. package/src/test/adapter-factory/joins.ts +28 -0
  179. package/src/test/adapter-factory/number-id.ts +45 -0
  180. package/src/test/adapter-factory/profile-additional-fields.ts +84 -0
  181. package/src/test/adapter-factory/profile-plugin-table.ts +37 -0
  182. package/src/test/adapter-factory/profile-rename-joins.ts +67 -0
  183. package/src/test/adapter-factory/transactions.ts +38 -0
  184. package/src/test/adapter-factory/uuid.ts +67 -0
  185. package/src/utils/index.ts +25 -3
@@ -1,505 +1,289 @@
1
1
  import { createClient } from "../client/index.js";
2
- import type { GenericCtx } from "../client/index.js";
3
- import { api } from "./_generated/api.js";
2
+ import { internal } from "./_generated/api.js";
4
3
  import { action } from "./_generated/server.js";
5
4
  import type { GenericActionCtx } from "convex/server";
6
5
  import type { DataModel } from "./_generated/dataModel.js";
7
- import type { BetterAuthOptions } from "better-auth";
8
6
  import type { EmptyObject } from "convex-helpers";
7
+ import type { BetterAuthOptions } from "better-auth";
8
+ import type { ComponentApi } from "./_generated/component.js";
9
+
10
+ // Tests need to run inside of a Convex function to use the Convex adapter.
11
+ // Test dependencies are dynamically imported to keep them out of the
12
+ // production bundle. convex-test runs in the vitest process, so vitest
13
+ // globals are available through dynamic imports.
14
+
15
+ const NORMAL_DISABLED_TESTS = [
16
+ "create - should apply default values to fields",
17
+ "create - should return null for nullable foreign keys",
18
+ "create - should support arrays",
19
+ "create - should support json",
20
+ "create - should use generateId if provided",
21
+ "findMany - should be able to perform a complex limited join",
22
+ "findMany - should find many models with limit and offset",
23
+ "findMany - should find many models with offset",
24
+ "findMany - should find many models with sortBy and limit and offset",
25
+ "findMany - should find many models with sortBy and limit and offset and where",
26
+ "findMany - should find many models with sortBy and offset",
27
+ "findMany - should find many with both one-to-one and one-to-many joins",
28
+ "findMany - should find many with join and offset",
29
+ "findMany - should find many with join, where, limit, and offset",
30
+ "findMany - should find many with one-to-one join",
31
+ "findMany - should handle mixed joins correctly when some are missing",
32
+ "findMany - should return empty array when base records don't exist with joins",
33
+ "findMany - should return null for one-to-one join when joined records don't exist",
34
+ "findMany - should select fields with one-to-one join",
35
+ "findOne - backwards join with modified field name (session base, users-table join)",
36
+ "findOne - multiple joins should return result even when some joined tables have no matching rows",
37
+ "findOne - should find a model with modified field name",
38
+ "findOne - should find a model with modified model name",
39
+ "findOne - should join a model with modified field name",
40
+ "findOne - should not apply defaultValue if value not found",
41
+ "findOne - should return an object for one-to-one joins",
42
+ "findOne - should return null for failed base model lookup that has joins",
43
+ "findOne - should return null for one-to-one join when joined record doesn't exist",
44
+ "findOne - should select fields with one-to-one join",
45
+ "findOne - should work with both one-to-one and one-to-many joins",
46
+ ] as const;
47
+
48
+ const toDisableMap = (testNames: readonly string[]) =>
49
+ Object.fromEntries(testNames.map((testName) => [testName, true]));
50
+
51
+ const toEnableOnlyMap = (testNames: readonly string[]) => ({
52
+ ALL: true,
53
+ ...Object.fromEntries(testNames.map((testName) => [testName, false])),
54
+ });
9
55
 
10
- // Hide vitest imports from esbuild, keep them out of the bundle
11
- import type {
12
- beforeEach as beforeEachType,
13
- test as testType,
14
- expect as expectType,
15
- } from "vitest";
16
- import type { runAdapterTest as runAdapterTestType } from "better-auth/adapters/test";
56
+ const UUID_SUITE_TESTS = ["init - tests"] as const;
17
57
 
18
- const getTestImports = async () => {
19
- const vitestImportName = "vitest";
20
- const { beforeEach, test, expect } = await import(vitestImportName);
21
- const betterAuthAdaptersTestImportName = "better-auth/adapters/test";
22
- const { runAdapterTest } = await import(betterAuthAdaptersTestImportName);
23
- return { beforeEach, test, expect, runAdapterTest } as {
24
- beforeEach: typeof beforeEachType;
25
- test: typeof testType;
26
- expect: typeof expectType;
27
- runAdapterTest: typeof runAdapterTestType;
28
- };
58
+ const getOverrideBetterAuthOptions = (opts: BetterAuthOptions) => ({
59
+ ...opts,
60
+ advanced: {
61
+ ...opts.advanced,
62
+ database: {
63
+ ...opts.advanced?.database,
64
+ generateId: "uuid",
65
+ },
66
+ },
67
+ });
68
+
69
+ type AdapterModule = ComponentApi["adapter"];
70
+ type TestProfileName =
71
+ | "adapterAdditionalFields"
72
+ | "adapterPluginTable"
73
+ | "adapterRenameField"
74
+ | "adapterRenameUserCustom"
75
+ | "adapterRenameUserTable"
76
+ | "adapterOrganizationJoins";
77
+
78
+ type InternalWithTestProfiles = {
79
+ adapter: AdapterModule;
80
+ adapterTest?: ComponentApi["adapterTest"];
81
+ testProfiles: Record<TestProfileName, AdapterModule>;
29
82
  };
30
83
 
31
- export const getAdapter: (
32
- ctx: GenericCtx<DataModel>
33
- ) => Parameters<typeof runAdapterTestType>[0]["getAdapter"] =
34
- (ctx: GenericCtx<DataModel>) =>
35
- async (opts?: Omit<BetterAuthOptions, "database">) => {
36
- const authComponent = createClient<DataModel>(api as any, {
37
- verbose: false,
38
- });
39
- const adapterFactory = authComponent.adapter(ctx);
40
- const options = {
41
- ...(opts ?? {}),
42
- user: {
43
- ...(opts?.user ?? {}),
44
- // We don't currently support custom schema for tests, need to find a
45
- // way to do this.
46
- fields: undefined,
47
- },
48
- };
49
- return adapterFactory(options);
50
- };
84
+ const internalWithTestProfiles = internal as unknown as InternalWithTestProfiles;
51
85
 
52
- // Tests need to run inside of a Convex function to use the Convex adapter
53
- export const runTests = action(
54
- async (
55
- ctx: GenericActionCtx<DataModel>,
56
- args: { disableTests: Record<string, boolean> }
57
- ) => {
58
- const { runAdapterTest } = await getTestImports();
59
- runAdapterTest({
60
- getAdapter: getAdapter(ctx),
61
- disableTests: args.disableTests,
62
- });
63
- }
64
- );
86
+ const baseProfileApi = {
87
+ adapter: internalWithTestProfiles.adapter,
88
+ adapterTest: internalWithTestProfiles.adapterTest,
89
+ };
65
90
 
66
- export const runCustomTests = action(
91
+ const profileApi = (name: TestProfileName): { adapter: AdapterModule } => {
92
+ return { adapter: internalWithTestProfiles.testProfiles[name] };
93
+ };
94
+
95
+ const additionalFieldsProfileApi = profileApi("adapterAdditionalFields");
96
+ const pluginTableProfileApi = profileApi("adapterPluginTable");
97
+ const renameFieldProfileApi = profileApi("adapterRenameField");
98
+ const renameUserCustomProfileApi = profileApi("adapterRenameUserCustom");
99
+ const renameUserTableProfileApi = profileApi("adapterRenameUserTable");
100
+ const organizationJoinsProfileApi = profileApi("adapterOrganizationJoins");
101
+
102
+ export const runTests = action(
67
103
  async (ctx: GenericActionCtx<DataModel>, _args: EmptyObject) => {
68
- const { beforeEach, test, expect } = await getTestImports();
69
- runCustomAdapterTests({
70
- beforeEach,
71
- test,
72
- expect,
73
- getAdapter: getAdapter(ctx),
74
- });
75
- }
76
- );
104
+ const testUtilsImport = "@better-auth/test-utils/adapter";
105
+ const { testAdapter } = await import(testUtilsImport);
106
+ const adapterFactoryImport = "../test/adapter-factory/index.js";
107
+ const {
108
+ coreNormalTestSuite,
109
+ coreAuthFlowTestSuite,
110
+ additionalFieldsNormalTestSuite,
111
+ additionalFieldsAuthFlowTestSuite,
112
+ pluginTableNormalTestSuite,
113
+ renameFieldAndJoinTestSuite,
114
+ renameModelUserCustomTestSuite,
115
+ renameModelUserTableTestSuite,
116
+ multiJoinsMissingRowsTestSuite,
117
+ transactionsTestSuite,
118
+ uuidTestSuite,
119
+ convexCustomTestSuite,
120
+ } = await import(adapterFactoryImport);
77
121
 
78
- function runCustomAdapterTests({
79
- beforeEach,
80
- test,
81
- expect,
82
- getAdapter,
83
- }: {
84
- getAdapter: Parameters<typeof runAdapterTestType>[0]["getAdapter"];
85
- beforeEach: typeof beforeEachType;
86
- test: typeof testType;
87
- expect: typeof expectType;
88
- }) {
89
- beforeEach(async () => {
90
- const adapter = await getAdapter();
91
- await adapter.deleteMany({
92
- model: "user",
93
- where: [],
94
- });
95
- await adapter.deleteMany({
96
- model: "session",
97
- where: [],
122
+ const baseProfileClient = createClient<DataModel>(baseProfileApi, {
123
+ verbose: false,
98
124
  });
99
- });
100
- test("should handle lone range operators", async () => {
101
- const adapter = await getAdapter();
102
- const user = await adapter.create({
103
- model: "user",
104
- data: {
105
- name: "ab",
106
- email: "a@a.com",
125
+ const additionalFieldsProfileClient = createClient<DataModel>(
126
+ additionalFieldsProfileApi,
127
+ {
128
+ verbose: false,
129
+ }
130
+ );
131
+ const pluginTableProfileClient = createClient<DataModel>(
132
+ pluginTableProfileApi,
133
+ {
134
+ verbose: false,
135
+ }
136
+ );
137
+ const renameFieldProfileClient = createClient<DataModel>(
138
+ renameFieldProfileApi,
139
+ {
140
+ verbose: false,
141
+ }
142
+ );
143
+ const renameUserCustomProfileClient = createClient<DataModel>(
144
+ renameUserCustomProfileApi,
145
+ {
146
+ verbose: false,
147
+ }
148
+ );
149
+ const renameUserTableProfileClient = createClient<DataModel>(
150
+ renameUserTableProfileApi,
151
+ {
152
+ verbose: false,
153
+ }
154
+ );
155
+ const organizationJoinsProfileClient = createClient<DataModel>(
156
+ organizationJoinsProfileApi,
157
+ {
158
+ verbose: false,
159
+ }
160
+ );
161
+
162
+ const { execute: executeBaseProfile } = await testAdapter({
163
+ adapter: () => {
164
+ return baseProfileClient.adapter(ctx);
165
+ },
166
+ runMigrations: () => {
167
+ // Convex schema is static — no migrations needed.
107
168
  },
169
+ overrideBetterAuthOptions: getOverrideBetterAuthOptions,
170
+ tests: [
171
+ coreNormalTestSuite({
172
+ disableTests: toDisableMap(NORMAL_DISABLED_TESTS),
173
+ }),
174
+ uuidTestSuite({
175
+ disableTests: toEnableOnlyMap(UUID_SUITE_TESTS),
176
+ }),
177
+ transactionsTestSuite({ disableTests: { ALL: true } }),
178
+ coreAuthFlowTestSuite(),
179
+ convexCustomTestSuite(),
180
+ ],
108
181
  });
109
- expect(
110
- await adapter.findMany({
111
- model: "user",
112
- where: [
113
- {
114
- field: "name",
115
- operator: "lt",
116
- value: "a",
117
- },
118
- ],
119
- })
120
- ).toEqual([]);
121
- expect(
122
- await adapter.findMany({
123
- model: "user",
124
- where: [
125
- {
126
- field: "name",
127
- operator: "lte",
128
- value: "a",
129
- },
130
- ],
131
- })
132
- ).toEqual([]);
133
- expect(
134
- await adapter.findMany({
135
- model: "user",
136
- where: [
137
- {
138
- field: "name",
139
- operator: "gt",
140
- value: "a",
141
- },
142
- ],
143
- })
144
- ).toEqual([user]);
145
- expect(
146
- await adapter.findMany({
147
- model: "user",
148
- where: [
149
- {
150
- field: "name",
151
- operator: "gte",
152
- value: "ab",
153
- },
154
- ],
155
- })
156
- ).toEqual([user]);
157
- });
158
182
 
159
- test("should handle compound indexes that include id field", async () => {
160
- const adapter = await getAdapter();
161
- const user = await adapter.create({
162
- model: "user",
163
- data: {
164
- name: "foo",
165
- email: "foo@bar.com",
183
+ const { execute: executeAdditionalFieldsProfile } = await testAdapter({
184
+ adapter: () => {
185
+ return additionalFieldsProfileClient.adapter(ctx);
186
+ },
187
+ runMigrations: () => {
188
+ // Convex schema is static — no migrations needed.
166
189
  },
190
+ overrideBetterAuthOptions: getOverrideBetterAuthOptions,
191
+ prefixTests: "profile:additional-fields",
192
+ tests: [
193
+ additionalFieldsNormalTestSuite(),
194
+ additionalFieldsAuthFlowTestSuite(),
195
+ ],
167
196
  });
168
- expect(
169
- await adapter.findOne({
170
- model: "user",
171
- where: [
172
- {
173
- field: "id",
174
- value: user.id,
175
- },
176
- {
177
- field: "name",
178
- value: "wrong name",
179
- },
180
- ],
181
- })
182
- ).toEqual(null);
183
- expect(
184
- await adapter.findOne({
185
- model: "user",
186
- where: [
187
- {
188
- field: "id",
189
- value: user.id,
190
- },
191
- {
192
- field: "name",
193
- value: "foo",
194
- },
195
- ],
196
- })
197
- ).toEqual(user);
198
- expect(
199
- await adapter.findOne({
200
- model: "user",
201
- where: [
202
- {
203
- field: "id",
204
- value: user.id,
205
- },
206
- {
207
- field: "name",
208
- value: "foo",
209
- operator: "lt",
210
- },
211
- ],
212
- })
213
- ).toEqual(null);
214
- expect(
215
- await adapter.findOne({
216
- model: "user",
217
- where: [
218
- {
219
- field: "id",
220
- value: user.id,
221
- },
222
- {
223
- field: "name",
224
- value: "foo",
225
- operator: "lte",
226
- },
227
- ],
228
- })
229
- ).toEqual(user);
230
- expect(
231
- await adapter.findOne({
232
- model: "user",
233
- where: [
234
- {
235
- field: "id",
236
- value: user.id,
237
- },
238
- {
239
- field: "name",
240
- value: "foo",
241
- operator: "gt",
242
- },
243
- ],
244
- })
245
- ).toEqual(null);
246
- expect(
247
- await adapter.findOne({
248
- model: "user",
249
- where: [
250
- {
251
- field: "id",
252
- value: user.id,
253
- },
254
- {
255
- field: "name",
256
- value: "foo",
257
- operator: "gte",
258
- },
259
- ],
260
- })
261
- ).toEqual(user);
262
- expect(
263
- await adapter.findOne({
264
- model: "user",
265
- where: [
266
- {
267
- field: "id",
268
- value: user.id,
269
- },
270
- {
271
- field: "name",
272
- operator: "in",
273
- value: ["wrong", "name"],
274
- },
275
- ],
276
- })
277
- ).toEqual(null);
278
- expect(
279
- await adapter.findOne({
280
- model: "user",
281
- where: [
282
- {
283
- field: "id",
284
- value: user.id,
285
- },
286
- {
287
- field: "name",
288
- operator: "in",
289
- value: ["foo"],
290
- },
291
- ],
292
- })
293
- ).toEqual(user);
294
- });
295
- test("should automatically paginate", async () => {
296
- const adapter = await getAdapter();
297
- for (let i = 0; i < 300; i++) {
298
- await adapter.create({
299
- model: "user",
300
- data: {
301
- name: `foo${i}`,
302
- email: `foo${i}@bar.com`,
303
- },
304
- });
305
- }
306
- // Better Auth defaults to a limit of 100
307
- expect(
308
- await adapter.findMany({
309
- model: "user",
310
- })
311
- ).toHaveLength(100);
312
197
 
313
- // Pagination has a hardcoded numItems max of 200, this tests that it can handle
314
- // specified limits beyond that
315
- expect(
316
- await adapter.findMany({
317
- model: "user",
318
- limit: 250,
319
- })
320
- ).toHaveLength(250);
321
- expect(
322
- await adapter.findMany({
323
- model: "user",
324
- limit: 350,
325
- })
326
- ).toHaveLength(300);
327
- });
328
- test("should handle OR where clauses", async () => {
329
- const adapter = await getAdapter();
330
- const user = await adapter.create({
331
- model: "user",
332
- data: {
333
- name: "foo",
334
- email: "foo@bar.com",
198
+ const { execute: executePluginTableProfile } = await testAdapter({
199
+ adapter: () => {
200
+ return pluginTableProfileClient.adapter(ctx);
335
201
  },
336
- });
337
- expect(
338
- await adapter.findOne({
339
- model: "user",
340
- where: [
341
- { field: "name", value: "bar", connector: "OR" },
342
- { field: "name", value: "foo", connector: "OR" },
343
- ],
344
- })
345
- ).toEqual(user);
346
- });
347
- test("should handle OR where clauses with sortBy", async () => {
348
- const adapter = await getAdapter();
349
- const fooUser = await adapter.create({
350
- model: "user",
351
- data: {
352
- name: "foo",
353
- email: "foo@bar.com",
202
+ runMigrations: () => {
203
+ // Convex schema is static — no migrations needed.
354
204
  },
205
+ overrideBetterAuthOptions: getOverrideBetterAuthOptions,
206
+ prefixTests: "profile:plugin-table",
207
+ tests: [pluginTableNormalTestSuite()],
355
208
  });
356
- const barUser = await adapter.create({
357
- model: "user",
358
- data: {
359
- name: "bar",
360
- email: "bar@bar.com",
209
+
210
+ const { execute: executeRenameFieldProfile } = await testAdapter({
211
+ adapter: () => {
212
+ return renameFieldProfileClient.adapter(ctx);
361
213
  },
362
- });
363
- await adapter.create({
364
- model: "user",
365
- data: {
366
- name: "baz",
367
- email: "baz@bar.com",
214
+ runMigrations: () => {
215
+ // Convex schema is static — no migrations needed.
368
216
  },
217
+ overrideBetterAuthOptions: getOverrideBetterAuthOptions,
218
+ prefixTests: "profile:rename-field-join",
219
+ tests: [renameFieldAndJoinTestSuite()],
369
220
  });
370
- expect(
371
- await adapter.findMany({
372
- model: "user",
373
- where: [
374
- { field: "name", value: "bar", connector: "OR" },
375
- { field: "name", value: "foo", connector: "OR" },
376
- ],
377
- sortBy: { field: "name", direction: "asc" },
378
- })
379
- ).toEqual([barUser, fooUser]);
380
- expect(
381
- await adapter.findMany({
382
- model: "user",
383
- where: [
384
- { field: "name", value: "bar", connector: "OR" },
385
- { field: "name", value: "foo", connector: "OR" },
386
- ],
387
- sortBy: { field: "name", direction: "desc" },
388
- })
389
- ).toEqual([fooUser, barUser]);
390
- });
391
- test("should handle count", async () => {
392
- const adapter = await getAdapter();
393
- await adapter.create({
394
- model: "user",
395
- data: {
396
- name: "foo",
397
- email: "foo@bar.com",
221
+
222
+ const { execute: executeRenameUserCustomProfile } = await testAdapter({
223
+ adapter: () => {
224
+ return renameUserCustomProfileClient.adapter(ctx);
398
225
  },
399
- });
400
- await adapter.create({
401
- model: "user",
402
- data: {
403
- name: "bar",
404
- email: "bar@bar.com",
226
+ runMigrations: () => {
227
+ // Convex schema is static — no migrations needed.
405
228
  },
229
+ overrideBetterAuthOptions: getOverrideBetterAuthOptions,
230
+ prefixTests: "profile:rename-user-custom",
231
+ tests: [renameModelUserCustomTestSuite()],
406
232
  });
407
- expect(
408
- await adapter.count({
409
- model: "user",
410
- where: [{ field: "name", value: "foo" }],
411
- })
412
- ).toEqual(1);
413
- });
414
- test("should handle queries with no index", async () => {
415
- const adapter = await getAdapter();
416
- const user = await adapter.create({
417
- model: "user",
418
- data: {
419
- name: "foo",
420
- email: "foo@bar.com",
421
- emailVerified: true,
233
+
234
+ const { execute: executeRenameUserTableProfile } = await testAdapter({
235
+ adapter: () => {
236
+ return renameUserTableProfileClient.adapter(ctx);
237
+ },
238
+ runMigrations: () => {
239
+ // Convex schema is static — no migrations needed.
422
240
  },
241
+ overrideBetterAuthOptions: getOverrideBetterAuthOptions,
242
+ prefixTests: "profile:rename-user-table",
243
+ tests: [renameModelUserTableTestSuite()],
423
244
  });
424
- expect(
425
- await adapter.findOne({
426
- model: "user",
427
- where: [{ field: "emailVerified", value: true }],
428
- })
429
- ).toEqual(user);
430
- expect(
431
- await adapter.findOne({
432
- model: "user",
433
- where: [{ field: "emailVerified", value: false }],
434
- })
435
- ).toEqual(null);
436
- });
437
245
 
438
- test("should handle compound operator on non-unique field without an index", async () => {
439
- const adapter = await getAdapter();
440
- await adapter.create({
441
- model: "account",
442
- data: {
443
- accountId: "foo",
444
- providerId: "bar",
445
- userId: "baz",
446
- accessTokenExpiresAt: null,
447
- createdAt: Date.now(),
448
- updatedAt: Date.now(),
246
+ const { execute: executeOrganizationJoinsProfile } = await testAdapter({
247
+ adapter: () => {
248
+ return organizationJoinsProfileClient.adapter(ctx);
249
+ },
250
+ runMigrations: () => {
251
+ // Convex schema is static — no migrations needed.
449
252
  },
253
+ overrideBetterAuthOptions: getOverrideBetterAuthOptions,
254
+ prefixTests: "profile:organization-joins",
255
+ tests: [multiJoinsMissingRowsTestSuite()],
450
256
  });
451
- expect(
452
- await adapter.findOne({
453
- model: "account",
454
- where: [
455
- {
456
- operator: "lt",
457
- connector: "AND",
458
- field: "accessTokenExpiresAt",
459
- value: Date.now(),
460
- },
461
- {
462
- operator: "ne",
463
- connector: "AND",
464
- field: "accessTokenExpiresAt",
465
- value: null,
466
- },
467
- ],
468
- })
469
- ).toEqual(null);
470
- });
471
257
 
472
- test("should fail to create a record with a unique field that already exists", async () => {
473
- const adapter = await getAdapter();
474
- await adapter.create({
475
- model: "user",
476
- data: { name: "foo", email: "foo@bar.com" },
258
+ await executeBaseProfile();
259
+ await executeAdditionalFieldsProfile();
260
+ await executePluginTableProfile();
261
+ await executeRenameFieldProfile();
262
+ await executeRenameUserCustomProfile();
263
+ await executeRenameUserTableProfile();
264
+ await executeOrganizationJoinsProfile();
265
+ }
266
+ );
267
+
268
+ // Keep this export during migration to avoid breaking generated component types.
269
+ export const runCustomTests = action(
270
+ async (ctx: GenericActionCtx<DataModel>, _args: EmptyObject) => {
271
+ const testUtilsImport = "@better-auth/test-utils/adapter";
272
+ const { testAdapter } = await import(testUtilsImport);
273
+ const adapterFactoryImport = "../test/adapter-factory/index.js";
274
+ const { convexCustomTestSuite } = await import(adapterFactoryImport);
275
+ const authComponent = createClient<DataModel>(baseProfileApi, {
276
+ verbose: false,
477
277
  });
478
- await expect(
479
- adapter.create({
480
- model: "user",
481
- data: { name: "foo", email: "foo@bar.com" },
482
- })
483
- ).rejects.toThrow("user email already exists");
484
- });
485
278
 
486
- test("should be able to compare against a date", async () => {
487
- const adapter = await getAdapter();
488
- const now = new Date().toISOString();
489
- const user = await adapter.create({
490
- model: "user",
491
- data: {
492
- name: "foo",
493
- email: "foo@bar.com",
494
- createdAt: now,
279
+ const { execute } = await testAdapter({
280
+ adapter: () => {
281
+ return authComponent.adapter(ctx);
495
282
  },
283
+ runMigrations: () => {},
284
+ overrideBetterAuthOptions: getOverrideBetterAuthOptions,
285
+ tests: [convexCustomTestSuite()],
496
286
  });
497
- expect(
498
- await adapter.findOne({
499
- model: "user",
500
- where: [{ field: "createdAt", value: now }],
501
- })
502
- ).toEqual(user);
503
- expect(user.createdAt).toBeInstanceOf(Date);
504
- });
505
- }
287
+ await execute();
288
+ }
289
+ );