@convex-dev/better-auth 0.8.0-alpha.9 → 0.8.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 (301) hide show
  1. package/dist/commonjs/auth.d.ts +4 -0
  2. package/dist/commonjs/auth.d.ts.map +1 -0
  3. package/dist/commonjs/auth.js +44 -0
  4. package/dist/commonjs/auth.js.map +1 -0
  5. package/dist/commonjs/client/adapter.d.ts +8 -10
  6. package/dist/commonjs/client/adapter.d.ts.map +1 -1
  7. package/dist/commonjs/client/adapter.js +48 -32
  8. package/dist/commonjs/client/adapter.js.map +1 -1
  9. package/dist/commonjs/client/adapterUtils.d.ts +66 -0
  10. package/dist/commonjs/client/adapterUtils.d.ts.map +1 -0
  11. package/dist/commonjs/client/adapterUtils.js +429 -0
  12. package/dist/commonjs/client/adapterUtils.js.map +1 -0
  13. package/dist/commonjs/client/createSchema.d.ts +24 -0
  14. package/dist/commonjs/client/createSchema.d.ts.map +1 -0
  15. package/dist/commonjs/client/createSchema.js +101 -0
  16. package/dist/commonjs/client/createSchema.js.map +1 -0
  17. package/dist/commonjs/client/index.d.ts +449 -601
  18. package/dist/commonjs/client/index.d.ts.map +1 -1
  19. package/dist/commonjs/client/index.js +339 -212
  20. package/dist/commonjs/client/index.js.map +1 -1
  21. package/dist/commonjs/component/adapter.d.ts +128 -0
  22. package/dist/commonjs/component/adapter.d.ts.map +1 -0
  23. package/dist/commonjs/component/adapter.js +5 -0
  24. package/dist/commonjs/component/adapter.js.map +1 -0
  25. package/dist/commonjs/component/adapterTest.d.ts +3 -5
  26. package/dist/commonjs/component/adapterTest.d.ts.map +1 -1
  27. package/dist/commonjs/component/adapterTest.js +3 -17
  28. package/dist/commonjs/component/adapterTest.js.map +1 -1
  29. package/dist/commonjs/component/schema.d.ts +451 -207
  30. package/dist/commonjs/component/schema.d.ts.map +1 -1
  31. package/dist/commonjs/component/schema.js +50 -177
  32. package/dist/commonjs/component/schema.js.map +1 -1
  33. package/dist/commonjs/component/util.d.ts.map +1 -1
  34. package/dist/commonjs/nextjs/index.d.ts +1 -2
  35. package/dist/commonjs/nextjs/index.d.ts.map +1 -1
  36. package/dist/commonjs/nextjs/index.js +3 -2
  37. package/dist/commonjs/nextjs/index.js.map +1 -1
  38. package/dist/commonjs/plugins/convex/client.d.ts +2 -5
  39. package/dist/commonjs/plugins/convex/client.d.ts.map +1 -1
  40. package/dist/commonjs/plugins/convex/client.js.map +1 -1
  41. package/dist/commonjs/plugins/convex/index.d.ts +7 -134
  42. package/dist/commonjs/plugins/convex/index.d.ts.map +1 -1
  43. package/dist/commonjs/plugins/convex/index.js +10 -125
  44. package/dist/commonjs/plugins/convex/index.js.map +1 -1
  45. package/dist/commonjs/plugins/cross-domain/index.js +2 -2
  46. package/dist/commonjs/plugins/cross-domain/index.js.map +1 -1
  47. package/dist/commonjs/react-start/index.d.ts +17 -36
  48. package/dist/commonjs/react-start/index.d.ts.map +1 -1
  49. package/dist/commonjs/react-start/index.js +43 -31
  50. package/dist/commonjs/react-start/index.js.map +1 -1
  51. package/dist/commonjs/src/auth.d.ts +3085 -0
  52. package/dist/commonjs/src/auth.d.ts.map +1 -0
  53. package/dist/commonjs/src/auth.js +72 -0
  54. package/dist/commonjs/src/auth.js.map +1 -0
  55. package/dist/commonjs/src/client/adapter.d.ts +18 -0
  56. package/dist/commonjs/src/client/adapter.d.ts.map +1 -0
  57. package/dist/commonjs/src/client/adapter.js +211 -0
  58. package/dist/commonjs/src/client/adapter.js.map +1 -0
  59. package/dist/commonjs/src/client/createSchema.d.ts +25 -0
  60. package/dist/commonjs/src/client/createSchema.d.ts.map +1 -0
  61. package/dist/commonjs/src/client/createSchema.js +103 -0
  62. package/dist/commonjs/src/client/createSchema.js.map +1 -0
  63. package/dist/commonjs/src/client/index.d.ts +3310 -0
  64. package/dist/commonjs/src/client/index.d.ts.map +1 -0
  65. package/dist/commonjs/src/client/index.js +377 -0
  66. package/dist/commonjs/src/client/index.js.map +1 -0
  67. package/dist/commonjs/src/client/plugins/index.d.ts +3 -0
  68. package/dist/commonjs/src/client/plugins/index.d.ts.map +1 -0
  69. package/dist/commonjs/src/client/plugins/index.js +3 -0
  70. package/dist/commonjs/src/client/plugins/index.js.map +1 -0
  71. package/dist/commonjs/src/component/_generated/api.d.ts +12 -0
  72. package/dist/commonjs/src/component/_generated/api.d.ts.map +1 -0
  73. package/dist/commonjs/src/component/_generated/api.js +22 -0
  74. package/dist/commonjs/src/component/_generated/api.js.map +1 -0
  75. package/dist/commonjs/src/component/_generated/server.d.ts +64 -0
  76. package/dist/commonjs/src/component/_generated/server.d.ts.map +1 -0
  77. package/dist/commonjs/src/component/_generated/server.js +74 -0
  78. package/dist/commonjs/src/component/_generated/server.js.map +1 -0
  79. package/dist/commonjs/src/component/adapter.d.ts +355 -0
  80. package/dist/commonjs/src/component/adapter.d.ts.map +1 -0
  81. package/dist/commonjs/src/component/adapter.js +573 -0
  82. package/dist/commonjs/src/component/adapter.js.map +1 -0
  83. package/dist/commonjs/src/component/adapterTest.d.ts +18 -0
  84. package/dist/commonjs/src/component/adapterTest.d.ts.map +1 -0
  85. package/dist/commonjs/src/component/adapterTest.js +75 -0
  86. package/dist/commonjs/src/component/adapterTest.js.map +1 -0
  87. package/dist/commonjs/src/component/convex.config.d.ts +3 -0
  88. package/dist/commonjs/src/component/convex.config.d.ts.map +1 -0
  89. package/dist/commonjs/src/component/convex.config.js +4 -0
  90. package/dist/commonjs/src/component/convex.config.js.map +1 -0
  91. package/dist/commonjs/src/component/schema.d.ts +562 -0
  92. package/dist/commonjs/src/component/schema.d.ts.map +1 -0
  93. package/dist/commonjs/src/component/schema.js +217 -0
  94. package/dist/commonjs/src/component/schema.js.map +1 -0
  95. package/dist/commonjs/src/nextjs/index.d.ts +10 -0
  96. package/dist/commonjs/src/nextjs/index.d.ts.map +1 -0
  97. package/dist/commonjs/src/nextjs/index.js +43 -0
  98. package/dist/commonjs/src/nextjs/index.js.map +1 -0
  99. package/dist/commonjs/src/plugins/convex/client.d.ts +9 -0
  100. package/dist/commonjs/src/plugins/convex/client.d.ts.map +1 -0
  101. package/dist/commonjs/src/plugins/convex/client.js +7 -0
  102. package/dist/commonjs/src/plugins/convex/client.js.map +1 -0
  103. package/dist/commonjs/src/plugins/convex/index.d.ts +415 -0
  104. package/dist/commonjs/src/plugins/convex/index.d.ts.map +1 -0
  105. package/dist/commonjs/src/plugins/convex/index.js +354 -0
  106. package/dist/commonjs/src/plugins/convex/index.js.map +1 -0
  107. package/dist/commonjs/src/plugins/cross-domain/client.d.ts +132 -0
  108. package/dist/commonjs/src/plugins/cross-domain/client.d.ts.map +1 -0
  109. package/dist/commonjs/src/plugins/cross-domain/client.js +176 -0
  110. package/dist/commonjs/src/plugins/cross-domain/client.js.map +1 -0
  111. package/dist/commonjs/src/plugins/cross-domain/index.d.ts +83 -0
  112. package/dist/commonjs/src/plugins/cross-domain/index.d.ts.map +1 -0
  113. package/dist/commonjs/src/plugins/cross-domain/index.js +153 -0
  114. package/dist/commonjs/src/plugins/cross-domain/index.js.map +1 -0
  115. package/dist/commonjs/src/plugins/index.d.ts +3 -0
  116. package/dist/commonjs/src/plugins/index.d.ts.map +1 -0
  117. package/dist/commonjs/src/plugins/index.js +3 -0
  118. package/dist/commonjs/src/plugins/index.js.map +1 -0
  119. package/dist/commonjs/src/react/client.d.ts +31 -0
  120. package/dist/commonjs/src/react/client.d.ts.map +1 -0
  121. package/dist/commonjs/src/react/client.js +96 -0
  122. package/dist/commonjs/src/react/client.js.map +1 -0
  123. package/dist/commonjs/src/react/index.d.ts +9 -0
  124. package/dist/commonjs/src/react/index.d.ts.map +1 -0
  125. package/dist/commonjs/src/react/index.js +15 -0
  126. package/dist/commonjs/src/react/index.js.map +1 -0
  127. package/dist/commonjs/src/react-start/index.d.ts +45 -0
  128. package/dist/commonjs/src/react-start/index.d.ts.map +1 -0
  129. package/dist/commonjs/src/react-start/index.js +60 -0
  130. package/dist/commonjs/src/react-start/index.js.map +1 -0
  131. package/dist/commonjs/src/utils/index.d.ts +9 -0
  132. package/dist/commonjs/src/utils/index.d.ts.map +1 -0
  133. package/dist/commonjs/src/utils/index.js +35 -0
  134. package/dist/commonjs/src/utils/index.js.map +1 -0
  135. package/dist/esm/auth.d.ts +4 -0
  136. package/dist/esm/auth.d.ts.map +1 -0
  137. package/dist/esm/auth.js +44 -0
  138. package/dist/esm/auth.js.map +1 -0
  139. package/dist/esm/client/adapter.d.ts +8 -10
  140. package/dist/esm/client/adapter.d.ts.map +1 -1
  141. package/dist/esm/client/adapter.js +48 -32
  142. package/dist/esm/client/adapter.js.map +1 -1
  143. package/dist/esm/client/adapterUtils.d.ts +66 -0
  144. package/dist/esm/client/adapterUtils.d.ts.map +1 -0
  145. package/dist/esm/client/adapterUtils.js +429 -0
  146. package/dist/esm/client/adapterUtils.js.map +1 -0
  147. package/dist/esm/client/createSchema.d.ts +24 -0
  148. package/dist/esm/client/createSchema.d.ts.map +1 -0
  149. package/dist/esm/client/createSchema.js +101 -0
  150. package/dist/esm/client/createSchema.js.map +1 -0
  151. package/dist/esm/client/index.d.ts +449 -601
  152. package/dist/esm/client/index.d.ts.map +1 -1
  153. package/dist/esm/client/index.js +339 -212
  154. package/dist/esm/client/index.js.map +1 -1
  155. package/dist/esm/component/adapter.d.ts +128 -0
  156. package/dist/esm/component/adapter.d.ts.map +1 -0
  157. package/dist/esm/component/adapter.js +5 -0
  158. package/dist/esm/component/adapter.js.map +1 -0
  159. package/dist/esm/component/adapterTest.d.ts +3 -5
  160. package/dist/esm/component/adapterTest.d.ts.map +1 -1
  161. package/dist/esm/component/adapterTest.js +3 -17
  162. package/dist/esm/component/adapterTest.js.map +1 -1
  163. package/dist/esm/component/schema.d.ts +451 -207
  164. package/dist/esm/component/schema.d.ts.map +1 -1
  165. package/dist/esm/component/schema.js +50 -177
  166. package/dist/esm/component/schema.js.map +1 -1
  167. package/dist/esm/component/util.d.ts.map +1 -1
  168. package/dist/esm/nextjs/index.d.ts +1 -2
  169. package/dist/esm/nextjs/index.d.ts.map +1 -1
  170. package/dist/esm/nextjs/index.js +3 -2
  171. package/dist/esm/nextjs/index.js.map +1 -1
  172. package/dist/esm/plugins/convex/client.d.ts +2 -5
  173. package/dist/esm/plugins/convex/client.d.ts.map +1 -1
  174. package/dist/esm/plugins/convex/client.js.map +1 -1
  175. package/dist/esm/plugins/convex/index.d.ts +7 -134
  176. package/dist/esm/plugins/convex/index.d.ts.map +1 -1
  177. package/dist/esm/plugins/convex/index.js +10 -125
  178. package/dist/esm/plugins/convex/index.js.map +1 -1
  179. package/dist/esm/plugins/cross-domain/index.js +2 -2
  180. package/dist/esm/plugins/cross-domain/index.js.map +1 -1
  181. package/dist/esm/react-start/index.d.ts +17 -36
  182. package/dist/esm/react-start/index.d.ts.map +1 -1
  183. package/dist/esm/react-start/index.js +43 -31
  184. package/dist/esm/react-start/index.js.map +1 -1
  185. package/dist/esm/src/auth.d.ts +3085 -0
  186. package/dist/esm/src/auth.d.ts.map +1 -0
  187. package/dist/esm/src/auth.js +72 -0
  188. package/dist/esm/src/auth.js.map +1 -0
  189. package/dist/esm/src/client/adapter.d.ts +18 -0
  190. package/dist/esm/src/client/adapter.d.ts.map +1 -0
  191. package/dist/esm/src/client/adapter.js +211 -0
  192. package/dist/esm/src/client/adapter.js.map +1 -0
  193. package/dist/esm/src/client/createSchema.d.ts +25 -0
  194. package/dist/esm/src/client/createSchema.d.ts.map +1 -0
  195. package/dist/esm/src/client/createSchema.js +103 -0
  196. package/dist/esm/src/client/createSchema.js.map +1 -0
  197. package/dist/esm/src/client/index.d.ts +3310 -0
  198. package/dist/esm/src/client/index.d.ts.map +1 -0
  199. package/dist/esm/src/client/index.js +377 -0
  200. package/dist/esm/src/client/index.js.map +1 -0
  201. package/dist/esm/src/client/plugins/index.d.ts +3 -0
  202. package/dist/esm/src/client/plugins/index.d.ts.map +1 -0
  203. package/dist/esm/src/client/plugins/index.js +3 -0
  204. package/dist/esm/src/client/plugins/index.js.map +1 -0
  205. package/dist/esm/src/component/_generated/api.d.ts +12 -0
  206. package/dist/esm/src/component/_generated/api.d.ts.map +1 -0
  207. package/dist/esm/src/component/_generated/api.js +22 -0
  208. package/dist/esm/src/component/_generated/api.js.map +1 -0
  209. package/dist/esm/src/component/_generated/server.d.ts +64 -0
  210. package/dist/esm/src/component/_generated/server.d.ts.map +1 -0
  211. package/dist/esm/src/component/_generated/server.js +74 -0
  212. package/dist/esm/src/component/_generated/server.js.map +1 -0
  213. package/dist/esm/src/component/adapter.d.ts +355 -0
  214. package/dist/esm/src/component/adapter.d.ts.map +1 -0
  215. package/dist/esm/src/component/adapter.js +573 -0
  216. package/dist/esm/src/component/adapter.js.map +1 -0
  217. package/dist/esm/src/component/adapterTest.d.ts +18 -0
  218. package/dist/esm/src/component/adapterTest.d.ts.map +1 -0
  219. package/dist/esm/src/component/adapterTest.js +75 -0
  220. package/dist/esm/src/component/adapterTest.js.map +1 -0
  221. package/dist/esm/src/component/convex.config.d.ts +3 -0
  222. package/dist/esm/src/component/convex.config.d.ts.map +1 -0
  223. package/dist/esm/src/component/convex.config.js +4 -0
  224. package/dist/esm/src/component/convex.config.js.map +1 -0
  225. package/dist/esm/src/component/schema.d.ts +562 -0
  226. package/dist/esm/src/component/schema.d.ts.map +1 -0
  227. package/dist/esm/src/component/schema.js +217 -0
  228. package/dist/esm/src/component/schema.js.map +1 -0
  229. package/dist/esm/src/nextjs/index.d.ts +10 -0
  230. package/dist/esm/src/nextjs/index.d.ts.map +1 -0
  231. package/dist/esm/src/nextjs/index.js +43 -0
  232. package/dist/esm/src/nextjs/index.js.map +1 -0
  233. package/dist/esm/src/plugins/convex/client.d.ts +9 -0
  234. package/dist/esm/src/plugins/convex/client.d.ts.map +1 -0
  235. package/dist/esm/src/plugins/convex/client.js +7 -0
  236. package/dist/esm/src/plugins/convex/client.js.map +1 -0
  237. package/dist/esm/src/plugins/convex/index.d.ts +415 -0
  238. package/dist/esm/src/plugins/convex/index.d.ts.map +1 -0
  239. package/dist/esm/src/plugins/convex/index.js +354 -0
  240. package/dist/esm/src/plugins/convex/index.js.map +1 -0
  241. package/dist/esm/src/plugins/cross-domain/client.d.ts +132 -0
  242. package/dist/esm/src/plugins/cross-domain/client.d.ts.map +1 -0
  243. package/dist/esm/src/plugins/cross-domain/client.js +176 -0
  244. package/dist/esm/src/plugins/cross-domain/client.js.map +1 -0
  245. package/dist/esm/src/plugins/cross-domain/index.d.ts +83 -0
  246. package/dist/esm/src/plugins/cross-domain/index.d.ts.map +1 -0
  247. package/dist/esm/src/plugins/cross-domain/index.js +153 -0
  248. package/dist/esm/src/plugins/cross-domain/index.js.map +1 -0
  249. package/dist/esm/src/plugins/index.d.ts +3 -0
  250. package/dist/esm/src/plugins/index.d.ts.map +1 -0
  251. package/dist/esm/src/plugins/index.js +3 -0
  252. package/dist/esm/src/plugins/index.js.map +1 -0
  253. package/dist/esm/src/react/client.d.ts +31 -0
  254. package/dist/esm/src/react/client.d.ts.map +1 -0
  255. package/dist/esm/src/react/client.js +96 -0
  256. package/dist/esm/src/react/client.js.map +1 -0
  257. package/dist/esm/src/react/index.d.ts +9 -0
  258. package/dist/esm/src/react/index.d.ts.map +1 -0
  259. package/dist/esm/src/react/index.js +15 -0
  260. package/dist/esm/src/react/index.js.map +1 -0
  261. package/dist/esm/src/react-start/index.d.ts +45 -0
  262. package/dist/esm/src/react-start/index.d.ts.map +1 -0
  263. package/dist/esm/src/react-start/index.js +60 -0
  264. package/dist/esm/src/react-start/index.js.map +1 -0
  265. package/dist/esm/src/utils/index.d.ts +9 -0
  266. package/dist/esm/src/utils/index.d.ts.map +1 -0
  267. package/dist/esm/src/utils/index.js +35 -0
  268. package/dist/esm/src/utils/index.js.map +1 -0
  269. package/package.json +21 -4
  270. package/src/auth.ts +57 -0
  271. package/src/client/adapter.test.ts +15 -0
  272. package/src/client/adapter.ts +83 -58
  273. package/src/{component/lib.ts → client/adapterUtils.ts} +106 -256
  274. package/src/client/createSchema.ts +149 -0
  275. package/src/client/index.ts +561 -317
  276. package/src/component/_generated/api.d.ts +1711 -547
  277. package/src/component/adapter.ts +13 -0
  278. package/src/component/adapterTest.ts +8 -34
  279. package/src/component/schema.ts +58 -192
  280. package/src/nextjs/index.ts +5 -5
  281. package/src/plugins/convex/client.ts +2 -3
  282. package/src/plugins/convex/index.ts +15 -147
  283. package/src/plugins/cross-domain/index.ts +2 -2
  284. package/src/react-start/index.ts +76 -44
  285. package/dist/commonjs/client/cors.d.ts +0 -77
  286. package/dist/commonjs/client/cors.d.ts.map +0 -1
  287. package/dist/commonjs/client/cors.js +0 -297
  288. package/dist/commonjs/client/cors.js.map +0 -1
  289. package/dist/commonjs/util.d.ts +0 -2
  290. package/dist/commonjs/util.d.ts.map +0 -1
  291. package/dist/commonjs/util.js +0 -8
  292. package/dist/commonjs/util.js.map +0 -1
  293. package/dist/esm/client/cors.d.ts +0 -77
  294. package/dist/esm/client/cors.d.ts.map +0 -1
  295. package/dist/esm/client/cors.js +0 -297
  296. package/dist/esm/client/cors.js.map +0 -1
  297. package/dist/esm/util.d.ts +0 -2
  298. package/dist/esm/util.d.ts.map +0 -1
  299. package/dist/esm/util.js +0 -8
  300. package/dist/esm/util.js.map +0 -1
  301. package/src/component/util.ts +0 -4
@@ -1,17 +1,18 @@
1
- import { mutation, query, QueryCtx } from "../component/_generated/server";
2
1
  import { asyncMap } from "convex-helpers";
3
- import { Infer, v } from "convex/values";
4
- import { Doc, Id, TableNames } from "../component/_generated/dataModel";
5
- import schema, { specialFields } from "../component/schema";
2
+ import { GenericId, Infer, v } from "convex/values";
6
3
  import {
4
+ DocumentByName,
5
+ GenericDataModel,
6
+ GenericQueryCtx,
7
7
  PaginationOptions,
8
- paginationOptsValidator,
9
8
  PaginationResult,
9
+ SchemaDefinition,
10
+ TableNamesInDataModel,
10
11
  } from "convex/server";
11
- import { partial } from "convex-helpers/validators";
12
12
  import { stream } from "convex-helpers/server/stream";
13
13
  import { mergedStream } from "convex-helpers/server/stream";
14
14
  import { stripIndent } from "common-tags";
15
+ import { BetterAuthDbSchema } from "better-auth/db";
15
16
 
16
17
  export const adapterWhereValidator = v.object({
17
18
  field: v.string(),
@@ -52,11 +53,15 @@ export const adapterArgsValidator = v.object({
52
53
  select: v.optional(v.array(v.string())),
53
54
  limit: v.optional(v.number()),
54
55
  offset: v.optional(v.number()),
55
- unique: v.optional(v.boolean()),
56
56
  });
57
57
 
58
- const isUniqueField = (model: TableNames, field: string) => {
59
- const fields = specialFields[model as keyof typeof specialFields];
58
+ const isUniqueField = (
59
+ betterAuthSchema: BetterAuthDbSchema,
60
+ model: string,
61
+ field: string
62
+ ) => {
63
+ const fields =
64
+ betterAuthSchema[model as keyof typeof betterAuthSchema]["fields"];
60
65
  if (!fields) {
61
66
  return false;
62
67
  }
@@ -65,38 +70,45 @@ const isUniqueField = (model: TableNames, field: string) => {
65
70
  .map(([key]) => key)
66
71
  .includes(field);
67
72
  };
68
- const hasUniqueFields = (model: TableNames, input: Record<string, any>) => {
73
+ export const hasUniqueFields = (
74
+ betterAuthSchema: BetterAuthDbSchema,
75
+ model: string,
76
+ input: Record<string, any>
77
+ ) => {
69
78
  for (const field of Object.keys(input)) {
70
- if (isUniqueField(model, field)) {
79
+ if (isUniqueField(betterAuthSchema, model, field)) {
71
80
  return true;
72
81
  }
73
82
  }
74
83
  return false;
75
84
  };
76
85
 
77
- const findIndex = (args: {
78
- model: string;
79
- where?: {
80
- field: string;
81
- operator?:
82
- | "lt"
83
- | "lte"
84
- | "gt"
85
- | "gte"
86
- | "eq"
87
- | "in"
88
- | "ne"
89
- | "contains"
90
- | "starts_with"
91
- | "ends_with";
92
- value: string | number | boolean | null | string[] | number[];
93
- connector?: "AND" | "OR";
94
- }[];
95
- sortBy?: {
96
- field: string;
97
- direction: "asc" | "desc";
98
- };
99
- }) => {
86
+ const findIndex = (
87
+ schema: SchemaDefinition<any, any>,
88
+ args: {
89
+ model: string;
90
+ where?: {
91
+ field: string;
92
+ operator?:
93
+ | "lt"
94
+ | "lte"
95
+ | "gt"
96
+ | "gte"
97
+ | "eq"
98
+ | "in"
99
+ | "ne"
100
+ | "contains"
101
+ | "starts_with"
102
+ | "ends_with";
103
+ value: string | number | boolean | null | string[] | number[];
104
+ connector?: "AND" | "OR";
105
+ }[];
106
+ sortBy?: {
107
+ field: string;
108
+ direction: "asc" | "desc";
109
+ };
110
+ }
111
+ ) => {
100
112
  if (
101
113
  (args.where?.length ?? 0) > 1 &&
102
114
  args.where?.some((w) => w.connector === "OR")
@@ -188,7 +200,7 @@ const findIndex = (args: {
188
200
  indexDescriptor: "by_creation_time",
189
201
  fields: [],
190
202
  }
191
- : indexes.find(({ fields }) => {
203
+ : indexes.find(({ fields }: { fields: string[] }) => {
192
204
  const fieldsMatch = indexFields.every(
193
205
  (field, idx) => field === fields[idx]
194
206
  );
@@ -220,21 +232,25 @@ const findIndex = (args: {
220
232
  };
221
233
  };
222
234
 
223
- const checkUniqueFields = async (
224
- ctx: QueryCtx,
225
- table: TableNames,
235
+ export const checkUniqueFields = async <
236
+ Schema extends SchemaDefinition<any, any>,
237
+ >(
238
+ ctx: GenericQueryCtx<GenericDataModel>,
239
+ schema: Schema,
240
+ betterAuthSchema: BetterAuthDbSchema,
241
+ table: string,
226
242
  input: Record<string, any>,
227
- doc?: Doc<any>
243
+ doc?: Record<string, any>
228
244
  ) => {
229
- if (!hasUniqueFields(table, input)) {
245
+ if (!hasUniqueFields(betterAuthSchema, table, input)) {
230
246
  return;
231
247
  }
232
248
  for (const field of Object.keys(input)) {
233
- if (!isUniqueField(table, field)) {
249
+ if (!isUniqueField(betterAuthSchema, table, field)) {
234
250
  continue;
235
251
  }
236
252
  const { index } =
237
- findIndex({
253
+ findIndex(schema, {
238
254
  model: table,
239
255
  where: [
240
256
  { field, operator: "eq", value: input[field as keyof typeof input] },
@@ -256,33 +272,17 @@ const checkUniqueFields = async (
256
272
  };
257
273
 
258
274
  // This handles basic select (stripping out the other fields if there
259
- // is a select arg), but also swaps in the app userId for any user id
260
- // reference fields.
261
- const selectFields = async <T extends TableNames, D extends Doc<T>>(
262
- ctx: QueryCtx,
275
+ // is a select arg).
276
+ export const selectFields = async <
277
+ T extends TableNamesInDataModel<GenericDataModel>,
278
+ D extends DocumentByName<GenericDataModel, T>,
279
+ >(
263
280
  doc: D | null,
264
281
  select?: string[]
265
282
  ) => {
266
283
  if (!doc) {
267
284
  return null;
268
285
  }
269
- const modelSpecialFields =
270
- specialFields[doc._table as keyof typeof specialFields];
271
- const userIdField = modelSpecialFields
272
- ? Object.entries(modelSpecialFields).find(
273
- ([_, field]) => field.references?.model === "user"
274
- )
275
- : undefined;
276
- if (userIdField) {
277
- const userIdFieldName = userIdField[0] as keyof typeof doc;
278
- const userId = doc[userIdFieldName];
279
- if (userId) {
280
- const user = await ctx.db.get(userId as unknown as Id<"user">);
281
- if (user) {
282
- (doc as any)[userIdFieldName] = user.userId;
283
- }
284
- }
285
- }
286
286
  if (!select?.length) {
287
287
  return doc;
288
288
  }
@@ -295,8 +295,11 @@ const selectFields = async <T extends TableNames, D extends Doc<T>>(
295
295
  // Manually filter an individual document by where clauses. This is used to
296
296
  // simplify queries that can only return 0 or 1 documents, or "in" clauses that
297
297
  // query multiple single documents in parallel.
298
- const filterByWhere = (
299
- doc: Doc<any>,
298
+ const filterByWhere = <
299
+ T extends TableNamesInDataModel<GenericDataModel>,
300
+ D extends DocumentByName<GenericDataModel, T>,
301
+ >(
302
+ doc: D | null,
300
303
  where?: Infer<typeof adapterWhereValidator>[],
301
304
  // Optionally filter which where clauses to apply.
302
305
  filterWhere?: (w: Infer<typeof adapterWhereValidator>) => any
@@ -374,11 +377,13 @@ const filterByWhere = (
374
377
  };
375
378
 
376
379
  const generateQuery = (
377
- ctx: QueryCtx,
380
+ ctx: GenericQueryCtx<GenericDataModel>,
381
+ schema: SchemaDefinition<any, any>,
378
382
  args: Infer<typeof adapterArgsValidator>
379
383
  ) => {
380
- const { index, values, boundField, indexFields } = findIndex(args) ?? {};
381
- const query = stream(ctx.db, schema).query(args.model as any);
384
+ const { index, values, boundField, indexFields } =
385
+ findIndex(schema, args) ?? {};
386
+ const query = stream(ctx.db as any, schema).query(args.model as any);
382
387
  const hasValues =
383
388
  values?.eq?.length ||
384
389
  values?.lt ||
@@ -443,12 +448,17 @@ const generateQuery = (
443
448
  // This is the core function for reading from the database, it parses and
444
449
  // validates where conditions, selects indexes, and allows the caller to
445
450
  // optionally paginate as needed. Every response is a pagination result.
446
- const paginate = async (
447
- ctx: QueryCtx,
451
+ export const paginate = async <
452
+ Doc extends DocumentByName<GenericDataModel, T>,
453
+ T extends TableNamesInDataModel<GenericDataModel>,
454
+ >(
455
+ ctx: GenericQueryCtx<GenericDataModel>,
456
+ schema: SchemaDefinition<any, any>,
457
+ betterAuthSchema: BetterAuthDbSchema,
448
458
  args: Infer<typeof adapterArgsValidator> & {
449
459
  paginationOpts: PaginationOptions;
450
460
  }
451
- ): Promise<PaginationResult<Doc<any>>> => {
461
+ ): Promise<PaginationResult<Doc>> => {
452
462
  if (args.offset) {
453
463
  throw new Error(`offset not supported: ${JSON.stringify(args.offset)}`);
454
464
  }
@@ -473,17 +483,17 @@ const paginate = async (
473
483
  const uniqueWhere = args.where?.find(
474
484
  (w) =>
475
485
  (!w.operator || w.operator === "eq") &&
476
- (isUniqueField(args.model as TableNames, w.field) || w.field === "id")
486
+ (isUniqueField(betterAuthSchema, args.model, w.field) || w.field === "id")
477
487
  );
478
488
  if (uniqueWhere) {
479
489
  const { index } =
480
- findIndex({
490
+ findIndex(schema, {
481
491
  model: args.model,
482
492
  where: [uniqueWhere],
483
493
  }) || {};
484
494
  const doc =
485
495
  uniqueWhere.field === "id"
486
- ? await ctx.db.get(uniqueWhere.value as Id<TableNames>)
496
+ ? await ctx.db.get(uniqueWhere.value as GenericId<T>)
487
497
  : await ctx.db
488
498
  .query(args.model as any)
489
499
  .withIndex(index?.indexDescriptor as any, (q) =>
@@ -494,7 +504,7 @@ const paginate = async (
494
504
  // Apply all other clauses as static filters to our 0 or 1 result.
495
505
  if (filterByWhere(doc, args.where, (w) => w !== uniqueWhere)) {
496
506
  return {
497
- page: [await selectFields(ctx, doc, args.select)].filter(Boolean),
507
+ page: [await selectFields(doc, args.select)].filter(Boolean) as Doc[],
498
508
  isDone: true,
499
509
  continueCursor: "",
500
510
  };
@@ -525,18 +535,18 @@ const paginate = async (
525
535
  // For ids, just use asyncMap + .get()
526
536
  if (inWhere.field === "id") {
527
537
  const docs = await asyncMap(inWhere.value as any[], async (value) => {
528
- return ctx.db.get(value as Id<TableNames>);
538
+ return ctx.db.get(value as GenericId<T>);
529
539
  });
530
540
  const filteredDocs = docs
531
- .flatMap((doc) => doc || [])
541
+ .flatMap((doc) => (doc ? [doc] : []))
532
542
  .filter((doc) => filterByWhere(doc, args.where, (w) => w !== inWhere));
533
543
 
534
544
  return {
535
545
  page: filteredDocs.sort((a, b) => {
536
546
  if (args.sortBy?.field === "createdAt") {
537
547
  return args.sortBy.direction === "asc"
538
- ? a._creationTime - b._creationTime
539
- : b._creationTime - a._creationTime;
548
+ ? (a._creationTime as number) - (b._creationTime as number)
549
+ : (b._creationTime as number) - (a._creationTime as number);
540
550
  }
541
551
  if (args.sortBy) {
542
552
  const aValue = a[args.sortBy.field as keyof typeof a];
@@ -545,21 +555,21 @@ const paginate = async (
545
555
  return 0;
546
556
  }
547
557
  return args.sortBy.direction === "asc"
548
- ? aValue > bValue
558
+ ? aValue! > bValue!
549
559
  ? 1
550
560
  : -1
551
- : aValue > bValue
561
+ : aValue! > bValue!
552
562
  ? -1
553
563
  : 1;
554
564
  }
555
565
  return 0;
556
- }),
566
+ }) as Doc[],
557
567
  isDone: true,
558
568
  continueCursor: "",
559
569
  };
560
570
  }
561
571
  const streams = inWhere.value.map((value) => {
562
- return generateQuery(ctx, {
572
+ return generateQuery(ctx, schema, {
563
573
  ...args,
564
574
  where: args.where?.map((w) => {
565
575
  if (w === inWhere) {
@@ -579,195 +589,35 @@ const paginate = async (
579
589
  return {
580
590
  ...result,
581
591
  page: await asyncMap(result.page, (doc) =>
582
- selectFields(ctx, doc, args.select)
592
+ selectFields(doc, args.select)
583
593
  ),
584
594
  };
585
595
  }
586
596
 
587
- const query = generateQuery(ctx, args);
597
+ const query = generateQuery(ctx, schema, args);
588
598
  const result = await query.paginate(paginationOpts);
589
599
  return {
590
600
  ...result,
591
- page: await asyncMap(result.page, (doc) =>
592
- selectFields(ctx, doc, args.select)
593
- ),
601
+ page: await asyncMap(result.page, (doc) => selectFields(doc, args.select)),
594
602
  };
595
603
  };
596
604
 
597
- const listOne = async (
598
- ctx: QueryCtx,
605
+ export const listOne = async <
606
+ Doc extends DocumentByName<GenericDataModel, T>,
607
+ T extends TableNamesInDataModel<GenericDataModel>,
608
+ >(
609
+ ctx: GenericQueryCtx<GenericDataModel>,
610
+ schema: SchemaDefinition<any, any>,
611
+ betterAuthSchema: BetterAuthDbSchema,
599
612
  args: Infer<typeof adapterArgsValidator>
600
- ): Promise<Doc<any> | null> => {
613
+ ): Promise<Doc | null> => {
601
614
  return (
602
- await paginate(ctx, {
615
+ await paginate(ctx, schema, betterAuthSchema, {
603
616
  ...args,
604
617
  paginationOpts: {
605
618
  numItems: 1,
606
619
  cursor: null,
607
620
  },
608
621
  })
609
- ).page[0];
622
+ ).page[0] as Doc | null;
610
623
  };
611
-
612
- export const create = mutation({
613
- args: {
614
- input: v.union(
615
- ...Object.entries(schema.tables).map(([model, table]) =>
616
- v.object({
617
- model: v.literal(model),
618
- data: v.object(table.validator.fields),
619
- })
620
- )
621
- ),
622
- },
623
- handler: async (ctx, args) => {
624
- await checkUniqueFields(
625
- ctx,
626
- args.input.model as TableNames,
627
- args.input.data
628
- );
629
-
630
- const id = await ctx.db.insert(args.input.model as any, args.input.data);
631
- const doc = await ctx.db.get(id);
632
- if (!doc) {
633
- throw new Error(`Failed to create ${args.input.model}`);
634
- }
635
- return doc;
636
- },
637
- });
638
-
639
- export const findOne = query({
640
- args: adapterArgsValidator,
641
- handler: async (ctx, args) => {
642
- return listOne(ctx, args);
643
- },
644
- });
645
-
646
- export const findMany = query({
647
- args: {
648
- ...adapterArgsValidator.fields,
649
- paginationOpts: paginationOptsValidator,
650
- },
651
- handler: async (ctx, args) => {
652
- return await paginate(ctx, args);
653
- },
654
- });
655
-
656
- export const updateOne = mutation({
657
- args: {
658
- input: v.union(
659
- ...Object.entries(schema.tables).map(([model, table]) =>
660
- v.object({
661
- model: v.literal(model),
662
- where: v.optional(v.array(adapterWhereValidator)),
663
- update: v.object(partial(table.validator.fields)),
664
- })
665
- )
666
- ),
667
- },
668
- handler: async (ctx, args) => {
669
- const doc = await listOne(ctx, args.input);
670
- if (!doc) {
671
- throw new Error(`Failed to update ${args.input.model}`);
672
- }
673
- await checkUniqueFields(
674
- ctx,
675
- args.input.model as TableNames,
676
- args.input.update,
677
- doc
678
- );
679
- await ctx.db.patch(doc._id, args.input.update as any);
680
- const updatedDoc = await ctx.db.get(doc._id);
681
- if (!updatedDoc) {
682
- throw new Error(`Failed to update ${args.input.model}`);
683
- }
684
- return updatedDoc;
685
- },
686
- });
687
-
688
- export const updateMany = mutation({
689
- args: {
690
- input: v.union(
691
- ...Object.entries(schema.tables).map(([model, table]) =>
692
- v.object({
693
- ...adapterArgsValidator.fields,
694
- model: v.literal(model),
695
- where: v.optional(v.array(adapterWhereValidator)),
696
- update: v.object(partial(table.validator.fields)),
697
- paginationOpts: paginationOptsValidator,
698
- })
699
- )
700
- ),
701
- },
702
- handler: async (ctx, args) => {
703
- const { page, ...result } = await paginate(ctx, args.input);
704
- if (args.input.update) {
705
- if (
706
- hasUniqueFields(
707
- args.input.model as TableNames,
708
- args.input.update ?? {}
709
- ) &&
710
- page.length > 1
711
- ) {
712
- throw new Error(
713
- `Attempted to set unique fields in multiple documents in ${args.input.model} with the same value. Fields: ${Object.keys(args.input.update ?? {}).join(", ")}`
714
- );
715
- }
716
- await asyncMap(page, async (doc) => {
717
- await checkUniqueFields(
718
- ctx,
719
- args.input.model as TableNames,
720
- args.input.update ?? {},
721
- doc
722
- );
723
- await ctx.db.patch(doc._id, args.input.update as any);
724
- });
725
- }
726
- return {
727
- ...result,
728
- count: page.length,
729
- };
730
- },
731
- });
732
-
733
- export const deleteOne = mutation({
734
- args: adapterArgsValidator,
735
- handler: async (ctx, args) => {
736
- const doc = await listOne(ctx, args);
737
- if (!doc) {
738
- return;
739
- }
740
- await ctx.db.delete(doc._id);
741
- return doc;
742
- },
743
- });
744
-
745
- export const deleteMany = mutation({
746
- args: {
747
- ...adapterArgsValidator.fields,
748
- paginationOpts: paginationOptsValidator,
749
- },
750
- handler: async (ctx, args) => {
751
- const { page, ...result } = await paginate(ctx, args);
752
- await asyncMap(page, async (doc) => {
753
- await ctx.db.delete(doc._id);
754
- });
755
- return {
756
- ...result,
757
- count: page.length,
758
- };
759
- },
760
- });
761
-
762
- // Get the session via sessionId in jwt claims
763
- // TODO: this needs a refresh, subquery only necessary for actions
764
- export const getCurrentSession = query({
765
- args: {},
766
- handler: async (ctx) => {
767
- const identity = await ctx.auth.getUserIdentity();
768
- if (!identity) {
769
- return null;
770
- }
771
- return ctx.db.get(identity.sessionId as Id<"session">);
772
- },
773
- });
@@ -0,0 +1,149 @@
1
+ import { BetterAuthDbSchema, type FieldAttribute } from "better-auth/db";
2
+
3
+ // Manually add fields to index on for schema generation,
4
+ // all fields in the schema specialFields are automatically indexed
5
+ export const indexFields = {
6
+ account: ["accountId", ["accountId", "providerId"], ["providerId", "userId"]],
7
+ rateLimit: ["key"],
8
+ session: ["expiresAt", ["expiresAt", "userId"]],
9
+ verification: ["expiresAt", "identifier"],
10
+ user: [["email", "name"], "name", "userId"],
11
+ passkey: ["credentialID"],
12
+ apikey: ["key"],
13
+ member: [["organizationId", "userId"]],
14
+ invitation: [
15
+ ["email", "organizationId", "status"],
16
+ ["organizationId", "status"],
17
+ ],
18
+ oauthConsent: [["clientId", "userId"]],
19
+ ssoProvider: ["organizationId", "domain"],
20
+ subscription: ["stripeSubscriptionId", "stripeCustomerId", "referenceId"],
21
+ };
22
+
23
+ // Return map of unique, sortable, and reference fields
24
+ const specialFields = (tables: BetterAuthDbSchema) =>
25
+ Object.fromEntries(
26
+ Object.entries(tables)
27
+ .map(([key, table]) => {
28
+ const fields = Object.fromEntries(
29
+ Object.entries(table.fields)
30
+ .map(([fieldKey, field]) => [
31
+ fieldKey,
32
+ {
33
+ ...(field.sortable ? { sortable: true } : {}),
34
+ ...(field.unique ? { unique: true } : {}),
35
+ ...(field.references ? { references: field.references } : {}),
36
+ },
37
+ ])
38
+ .filter(([_key, value]) =>
39
+ typeof value === "object" ? Object.keys(value).length > 0 : true
40
+ )
41
+ );
42
+ return [key, fields];
43
+ })
44
+ .filter(([_key, value]) =>
45
+ typeof value === "object" ? Object.keys(value).length > 0 : true
46
+ )
47
+ );
48
+
49
+ const mergedIndexFields = (tables: BetterAuthDbSchema) =>
50
+ Object.fromEntries(
51
+ Object.entries(tables).map(([key]) => {
52
+ const manualIndexes = indexFields[key as keyof typeof indexFields] || [];
53
+ const specialFieldIndexes = Object.keys(
54
+ specialFields(tables)[key as keyof ReturnType<typeof specialFields>] ||
55
+ {}
56
+ ).filter(
57
+ (index) =>
58
+ !manualIndexes.some((m) =>
59
+ Array.isArray(m) ? m[0] === index : m === index
60
+ )
61
+ );
62
+ return [key, manualIndexes.concat(specialFieldIndexes)];
63
+ })
64
+ );
65
+
66
+ export const createSchema = async ({
67
+ file,
68
+ tables,
69
+ }: {
70
+ tables: BetterAuthDbSchema;
71
+ file?: string;
72
+ }) => {
73
+ process.env.IS_GENERATING_SCHEMA = "1";
74
+ let code: string = `// This file is auto-generated. Do not edit this file manually.
75
+ // To regenerate the schema, run:
76
+ // \`npx @better-auth/cli generate --output ${file} -y\`
77
+
78
+ import { defineSchema, defineTable } from "convex/server";
79
+ import { v } from "convex/values";
80
+
81
+ export const tables = {
82
+ `;
83
+
84
+ for (const tableKey in tables) {
85
+ const table = tables[tableKey]!;
86
+ const modelName = table.modelName;
87
+
88
+ // No id fields in Convex schema
89
+ const fields = Object.fromEntries(
90
+ Object.entries(table.fields).filter(([key]) => key !== "id")
91
+ );
92
+
93
+ function getType(name: string, field: FieldAttribute) {
94
+ const type = field.type as
95
+ | "string"
96
+ | "number"
97
+ | "boolean"
98
+ | "date"
99
+ | `${"string" | "number"}[]`;
100
+
101
+ const typeMap: Record<typeof type, string> = {
102
+ string: `v.string()`,
103
+ boolean: `v.boolean()`,
104
+ number: `v.number()`,
105
+ date: `v.number()`,
106
+ "number[]": `v.array(v.number())`,
107
+ "string[]": `v.array(v.string())`,
108
+ } as const;
109
+ return typeMap[type];
110
+ }
111
+
112
+ const indexes =
113
+ mergedIndexFields(tables)[
114
+ modelName as keyof typeof mergedIndexFields
115
+ ]?.map((index) => {
116
+ const indexArray = Array.isArray(index) ? index.sort() : [index];
117
+ const indexName = indexArray.join("_");
118
+ return `.index("${indexName}", ${JSON.stringify(indexArray)})`;
119
+ }) || [];
120
+
121
+ const schema = `${modelName}: defineTable({
122
+ ${Object.keys(fields)
123
+ .map((field) => {
124
+ const attr = fields[field]!;
125
+ const type = getType(field, attr as FieldAttribute);
126
+ const optional = (fieldSchema: string) =>
127
+ attr.required
128
+ ? fieldSchema
129
+ : `v.optional(v.union(v.null(), ${fieldSchema}))`;
130
+ return ` ${field}: ${optional(type)},`;
131
+ })
132
+ .join("\n")}
133
+ })${indexes.length > 0 ? `\n ${indexes.join("\n ")}` : ""},\n`;
134
+ code += ` ${schema}`;
135
+ }
136
+
137
+ code += `};
138
+
139
+ const schema = defineSchema(tables);
140
+
141
+ export default schema;
142
+ `;
143
+
144
+ return {
145
+ code,
146
+ path: file ?? "./schema.ts",
147
+ overwrite: true,
148
+ };
149
+ };