@convex-dev/better-auth 0.8.0-alpha.9 → 0.8.1

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 +337 -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 +42 -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 +337 -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 +42 -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 +558 -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,76 +1,87 @@
1
1
  import {
2
2
  type Auth as ConvexAuth,
3
+ DataModelFromSchemaDefinition,
3
4
  type DefaultFunctionArgs,
4
5
  type Expand,
6
+ FunctionHandle,
5
7
  type FunctionReference,
6
8
  GenericActionCtx,
7
9
  type GenericDataModel,
8
10
  GenericMutationCtx,
9
11
  type GenericQueryCtx,
12
+ GenericSchema,
10
13
  type HttpRouter,
14
+ SchemaDefinition,
11
15
  httpActionGeneric,
12
16
  internalMutationGeneric,
17
+ mutationGeneric,
18
+ paginationOptsValidator,
13
19
  queryGeneric,
14
20
  } from "convex/server";
15
21
  import { type GenericId, Infer, v } from "convex/values";
16
- import type { api } from "../component/_generated/api";
17
- import schema from "../component/schema";
18
22
  import { convexAdapter } from "./adapter";
19
- import { betterAuth } from "better-auth";
20
- import { omit } from "convex-helpers";
21
- import { createCookieGetter } from "better-auth/cookies";
22
- import { fetchQuery } from "convex/nextjs";
23
- import { JWT_COOKIE_NAME } from "../plugins/convex";
23
+ import { AdapterInstance, betterAuth } from "better-auth";
24
+ import { asyncMap } from "convex-helpers";
24
25
  import { requireEnv } from "../utils";
25
- import { parse, partial } from "convex-helpers/validators";
26
- import { adapterArgsValidator, adapterWhereValidator } from "../component/lib";
26
+ import { partial } from "convex-helpers/validators";
27
+ import {
28
+ adapterWhereValidator,
29
+ checkUniqueFields,
30
+ hasUniqueFields,
31
+ listOne,
32
+ paginate,
33
+ selectFields,
34
+ } from "./adapterUtils";
27
35
  import { corsRouter } from "convex-helpers/server/cors";
28
36
  import { version as convexVersion } from "convex";
29
37
  import semver from "semver";
38
+ import defaultSchema from "../component/schema";
39
+ import { getAuthTables } from "better-auth/db";
40
+ import { api } from "../component/_generated/api";
30
41
 
31
42
  export { convexAdapter };
32
43
 
44
+ export type CreateAdapter = <Ctx extends RunCtx>(ctx: Ctx) => AdapterInstance;
45
+
33
46
  if (semver.lt(convexVersion, "1.25.0")) {
34
47
  throw new Error("Convex version must be at least 1.25.0");
35
48
  }
36
49
 
37
- const createUserFields = omit(schema.tables.user.validator.fields, ["userId"]);
38
- const createUserValidator = v.object(createUserFields);
39
- const createPermissiveArgsValidator = v.object({
40
- input: v.object({
41
- model: v.literal("user"),
42
- data: v.record(
43
- v.string(),
50
+ const whereValidator = (
51
+ schema: SchemaDefinition<any, any>,
52
+ tableName: string
53
+ ) =>
54
+ v.object({
55
+ field: v.union(
56
+ ...Object.keys(schema.tables[tableName].validator.fields).map((field) =>
57
+ v.literal(field)
58
+ ),
59
+ v.literal("id")
60
+ ),
61
+ operator: v.optional(
44
62
  v.union(
45
- v.string(),
46
- v.number(),
47
- v.boolean(),
48
- v.array(v.string()),
49
- v.array(v.number()),
50
- v.null()
63
+ v.literal("lt"),
64
+ v.literal("lte"),
65
+ v.literal("gt"),
66
+ v.literal("gte"),
67
+ v.literal("eq"),
68
+ v.literal("in"),
69
+ v.literal("ne"),
70
+ v.literal("contains"),
71
+ v.literal("starts_with"),
72
+ v.literal("ends_with")
51
73
  )
52
74
  ),
53
- }),
54
- });
55
- const createUserArgsValidator = v.object({
56
- input: v.object({
57
- model: v.literal("user"),
58
- data: v.object(createUserFields),
59
- }),
60
- });
61
- const updateUserArgsValidator = v.object({
62
- input: v.object({
63
- model: v.literal("user"),
64
- where: v.optional(v.array(adapterWhereValidator)),
65
- update: v.object(partial(createUserFields)),
66
- }),
67
- });
68
- const createSessionArgsValidator = v.object({
69
- input: v.object({
70
- model: v.literal("session"),
71
- data: v.object(schema.tables.session.validator.fields),
72
- }),
73
- });
75
+ value: v.union(
76
+ v.string(),
77
+ v.number(),
78
+ v.boolean(),
79
+ v.array(v.string()),
80
+ v.array(v.number()),
81
+ v.null()
82
+ ),
83
+ connector: v.optional(v.union(v.literal("AND"), v.literal("OR"))),
84
+ });
74
85
 
75
86
  export type EventFunction<T extends DefaultFunctionArgs> = FunctionReference<
76
87
  "mutation",
@@ -78,330 +89,560 @@ export type EventFunction<T extends DefaultFunctionArgs> = FunctionReference<
78
89
  T
79
90
  >;
80
91
 
92
+ export type GenericCtx<DataModel extends GenericDataModel = GenericDataModel> =
93
+ | GenericQueryCtx<DataModel>
94
+ | GenericMutationCtx<DataModel>
95
+ | GenericActionCtx<DataModel>;
96
+
81
97
  export type AuthFunctions = {
82
- createUser: FunctionReference<
83
- "mutation",
84
- "internal",
85
- Infer<typeof createPermissiveArgsValidator>
86
- >;
87
- deleteUser: FunctionReference<
88
- "mutation",
89
- "internal",
90
- Infer<typeof adapterArgsValidator>
91
- >;
92
- updateUser: FunctionReference<
93
- "mutation",
94
- "internal",
95
- Infer<typeof updateUserArgsValidator>
96
- >;
97
- createSession: FunctionReference<
98
- "mutation",
99
- "internal",
100
- Infer<typeof createSessionArgsValidator>
101
- >;
98
+ onCreate?: FunctionReference<"mutation", "internal", { [key: string]: any }>;
99
+ onUpdate?: FunctionReference<"mutation", "internal", { [key: string]: any }>;
100
+ onDelete?: FunctionReference<"mutation", "internal", { [key: string]: any }>;
102
101
  };
103
102
 
104
- export type PublicAuthFunctions = {
105
- isAuthenticated: FunctionReference<"query", "public">;
106
- };
103
+ export const createApi = <
104
+ DataModel extends GenericDataModel,
105
+ Schema extends SchemaDefinition<any, any>,
106
+ >(
107
+ schema: Schema,
108
+ createAuth: (ctx: GenericCtx<DataModel>) => ReturnType<typeof betterAuth>
109
+ ) => {
110
+ const betterAuthSchema = getAuthTables(createAuth({} as any)!.options);
111
+ return {
112
+ create: mutationGeneric({
113
+ args: {
114
+ input: v.union(
115
+ ...Object.entries(schema.tables).map(([model, table]) =>
116
+ v.object({
117
+ model: v.literal(model),
118
+ data: v.object((table as any).validator.fields),
119
+ })
120
+ )
121
+ ),
122
+ select: v.optional(v.array(v.string())),
123
+ onCreateHandle: v.optional(v.string()),
124
+ },
125
+ handler: async (ctx, args) => {
126
+ await checkUniqueFields(
127
+ ctx,
128
+ schema,
129
+ betterAuthSchema,
130
+ args.input.model,
131
+ args.input.data
132
+ );
133
+ const id = await ctx.db.insert(
134
+ args.input.model as any,
135
+ args.input.data
136
+ );
137
+ const doc = await ctx.db.get(id);
138
+ if (!doc) {
139
+ throw new Error(`Failed to create ${args.input.model}`);
140
+ }
141
+ const result = selectFields(doc, args.select);
142
+ if (args.onCreateHandle) {
143
+ await ctx.runMutation(
144
+ args.onCreateHandle as FunctionHandle<"mutation">,
145
+ {
146
+ model: args.input.model,
147
+ doc,
148
+ }
149
+ );
150
+ }
151
+ return result;
152
+ },
153
+ }),
154
+ findOne: queryGeneric({
155
+ args: {
156
+ model: v.union(
157
+ ...Object.keys(schema.tables).map((model) => v.literal(model))
158
+ ),
159
+ where: v.optional(v.array(adapterWhereValidator)),
160
+ select: v.optional(v.array(v.string())),
161
+ },
162
+ handler: async (ctx, args) => {
163
+ return await listOne(ctx, schema, betterAuthSchema, args);
164
+ },
165
+ }),
166
+ findMany: queryGeneric({
167
+ args: {
168
+ model: v.union(
169
+ ...Object.keys(schema.tables).map((model) => v.literal(model))
170
+ ),
171
+ where: v.optional(v.array(adapterWhereValidator)),
172
+ limit: v.optional(v.number()),
173
+ sortBy: v.optional(
174
+ v.object({
175
+ direction: v.union(v.literal("asc"), v.literal("desc")),
176
+ field: v.string(),
177
+ })
178
+ ),
179
+ offset: v.optional(v.number()),
180
+ paginationOpts: paginationOptsValidator,
181
+ },
182
+ handler: async (ctx, args) => {
183
+ return await paginate(ctx, schema, betterAuthSchema, args);
184
+ },
185
+ }),
186
+ updateOne: mutationGeneric({
187
+ args: {
188
+ input: v.union(
189
+ ...Object.entries(schema.tables).map(
190
+ ([tableName, table]: [string, Schema["tables"][string]]) => {
191
+ const fields = partial(table.validator.fields);
192
+ return v.object({
193
+ model: v.literal(tableName),
194
+ update: v.object(fields),
195
+ where: v.optional(v.array(whereValidator(schema, tableName))),
196
+ });
197
+ }
198
+ )
199
+ ),
200
+ onUpdateHandle: v.optional(v.string()),
201
+ },
202
+ handler: async (ctx, args) => {
203
+ const doc = await listOne(ctx, schema, betterAuthSchema, args.input);
204
+ if (!doc) {
205
+ throw new Error(`Failed to update ${args.input.model}`);
206
+ }
207
+ await checkUniqueFields(
208
+ ctx,
209
+ schema,
210
+ betterAuthSchema,
211
+ args.input.model,
212
+ args.input.update,
213
+ doc
214
+ );
215
+ await ctx.db.patch(
216
+ doc._id as GenericId<string>,
217
+ args.input.update as any
218
+ );
219
+ const updatedDoc = await ctx.db.get(doc._id as GenericId<string>);
220
+ if (!updatedDoc) {
221
+ throw new Error(`Failed to update ${args.input.model}`);
222
+ }
223
+ if (args.onUpdateHandle) {
224
+ await ctx.runMutation(
225
+ args.onUpdateHandle as FunctionHandle<"mutation">,
226
+ {
227
+ model: args.input.model,
228
+ oldDoc: doc,
229
+ newDoc: updatedDoc,
230
+ }
231
+ );
232
+ }
233
+ return updatedDoc;
234
+ },
235
+ }),
236
+ updateMany: mutationGeneric({
237
+ args: {
238
+ input: v.union(
239
+ ...Object.entries(schema.tables).map(
240
+ ([tableName, table]: [string, Schema["tables"][string]]) => {
241
+ const fields = partial(table.validator.fields);
242
+ return v.object({
243
+ model: v.literal(tableName),
244
+ update: v.object(fields),
245
+ where: v.optional(v.array(whereValidator(schema, tableName))),
246
+ });
247
+ }
248
+ )
249
+ ),
250
+ paginationOpts: paginationOptsValidator,
251
+ onUpdateHandle: v.optional(v.string()),
252
+ },
253
+ handler: async (ctx, args) => {
254
+ const { page, ...result } = await paginate(
255
+ ctx,
256
+ schema,
257
+ betterAuthSchema,
258
+ {
259
+ ...args.input,
260
+ paginationOpts: args.paginationOpts,
261
+ }
262
+ );
263
+ if (args.input.update) {
264
+ if (
265
+ hasUniqueFields(
266
+ betterAuthSchema,
267
+ args.input.model,
268
+ args.input.update ?? {}
269
+ ) &&
270
+ page.length > 1
271
+ ) {
272
+ throw new Error(
273
+ `Attempted to set unique fields in multiple documents in ${args.input.model} with the same value. Fields: ${Object.keys(args.input.update ?? {}).join(", ")}`
274
+ );
275
+ }
276
+ await asyncMap(page, async (doc) => {
277
+ await checkUniqueFields(
278
+ ctx,
279
+ schema,
280
+ betterAuthSchema,
281
+ args.input.model,
282
+ args.input.update ?? {},
283
+ doc
284
+ );
285
+ await ctx.db.patch(
286
+ doc._id as GenericId<string>,
287
+ args.input.update as any
288
+ );
107
289
 
108
- export class BetterAuth<UserId extends string = string> {
109
- constructor(
110
- public component: UseApi<typeof api>,
111
- public config: {
112
- authFunctions: AuthFunctions;
113
- publicAuthFunctions?: PublicAuthFunctions;
114
- verbose?: boolean;
115
- }
116
- ) {}
290
+ if (args.onUpdateHandle) {
291
+ await ctx.runMutation(
292
+ args.onUpdateHandle as FunctionHandle<"mutation">,
293
+ {
294
+ model: args.input.model,
295
+ oldDoc: doc,
296
+ newDoc: await ctx.db.get(doc._id as GenericId<string>),
297
+ }
298
+ );
299
+ }
300
+ });
301
+ }
302
+ return {
303
+ ...result,
304
+ count: page.length,
305
+ ids: page.map((doc) => doc._id),
306
+ };
307
+ },
308
+ }),
309
+ deleteOne: mutationGeneric({
310
+ args: {
311
+ input: v.union(
312
+ ...Object.keys(schema.tables).map((tableName: string) => {
313
+ return v.object({
314
+ model: v.literal(tableName),
315
+ where: v.optional(v.array(whereValidator(schema, tableName))),
316
+ });
317
+ })
318
+ ),
319
+ onDeleteHandle: v.optional(v.string()),
320
+ },
321
+ handler: async (ctx, args) => {
322
+ const doc = await listOne(ctx, schema, betterAuthSchema, args.input);
323
+ if (!doc) {
324
+ return;
325
+ }
326
+ await ctx.db.delete(doc._id as GenericId<string>);
327
+ if (args.onDeleteHandle) {
328
+ await ctx.runMutation(
329
+ args.onDeleteHandle as FunctionHandle<"mutation">,
330
+ { model: args.input.model, doc }
331
+ );
332
+ }
333
+ return doc;
334
+ },
335
+ }),
336
+ deleteMany: mutationGeneric({
337
+ args: {
338
+ input: v.union(
339
+ ...Object.keys(schema.tables).map((tableName: string) => {
340
+ return v.object({
341
+ model: v.literal(tableName),
342
+ where: v.optional(v.array(whereValidator(schema, tableName))),
343
+ });
344
+ })
345
+ ),
346
+ paginationOpts: paginationOptsValidator,
347
+ onDeleteHandle: v.optional(v.string()),
348
+ },
349
+ handler: async (ctx, args) => {
350
+ const { page, ...result } = await paginate(
351
+ ctx,
352
+ schema,
353
+ betterAuthSchema,
354
+ {
355
+ ...args.input,
356
+ paginationOpts: args.paginationOpts,
357
+ }
358
+ );
359
+ await asyncMap(page, async (doc) => {
360
+ if (args.onDeleteHandle) {
361
+ await ctx.runMutation(
362
+ args.onDeleteHandle as FunctionHandle<"mutation">,
363
+ {
364
+ model: args.input.model,
365
+ doc,
366
+ }
367
+ );
368
+ }
369
+ await ctx.db.delete(doc._id as GenericId<string>);
370
+ });
371
+ return {
372
+ ...result,
373
+ count: page.length,
374
+ ids: page.map((doc) => doc._id),
375
+ };
376
+ },
377
+ }),
378
+ };
379
+ };
117
380
 
118
- async isAuthenticated(token?: string | null) {
119
- if (!this.config.publicAuthFunctions?.isAuthenticated) {
120
- throw new Error(
121
- "isAuthenticated function not found. It must be a named export in convex/auth.ts"
122
- );
123
- }
124
- return fetchQuery(
125
- this.config.publicAuthFunctions.isAuthenticated,
126
- {},
127
- { token: token ?? undefined }
128
- );
129
- }
381
+ export type Triggers<
382
+ DataModel extends GenericDataModel,
383
+ Schema extends SchemaDefinition<any, any>,
384
+ > = {
385
+ [K in keyof Schema["tables"]]?: {
386
+ onCreate?: <Ctx extends GenericMutationCtx<DataModel>>(
387
+ ctx: Ctx,
388
+ doc: Infer<Schema["tables"][K]["validator"]> & {
389
+ _id: string;
390
+ _creationTime: number;
391
+ }
392
+ ) => Promise<void>;
393
+ onUpdate?: <Ctx extends GenericMutationCtx<DataModel>>(
394
+ ctx: Ctx,
395
+ oldDoc: Infer<Schema["tables"][K]["validator"]> & {
396
+ _id: string;
397
+ _creationTime: number;
398
+ },
399
+ newDoc: Infer<Schema["tables"][K]["validator"]> & {
400
+ _id: string;
401
+ _creationTime: number;
402
+ }
403
+ ) => Promise<void>;
404
+ onDelete?: <Ctx extends GenericMutationCtx<DataModel>>(
405
+ ctx: Ctx,
406
+ doc: Infer<Schema["tables"][K]["validator"]> & {
407
+ _id: string;
408
+ _creationTime: number;
409
+ }
410
+ ) => Promise<void>;
411
+ };
412
+ };
130
413
 
131
- async getHeaders(ctx: RunQueryCtx & { auth: ConvexAuth }) {
132
- const session = await ctx.runQuery(this.component.lib.getCurrentSession);
133
- return new Headers({
134
- ...(session?.token ? { authorization: `Bearer ${session.token}` } : {}),
135
- ...(session?.ipAddress ? { "x-forwarded-for": session.ipAddress } : {}),
136
- });
414
+ export const createClient = <
415
+ DataModel extends GenericDataModel,
416
+ Schema extends SchemaDefinition<GenericSchema, true> = typeof defaultSchema,
417
+ >(
418
+ component: UseApi<typeof api>,
419
+ config?: {
420
+ local?: {
421
+ schema?: Schema;
422
+ };
423
+ authFunctions?: AuthFunctions;
424
+ verbose?: boolean;
425
+ triggers?: Triggers<DataModel, Schema>;
137
426
  }
138
-
139
- // TODO: use the proper id type for auth functions
140
- async getAuthUserId(ctx: RunQueryCtx & { auth: ConvexAuth }) {
427
+ ) => {
428
+ const safeGetAuthUser = async (ctx: GenericQueryCtx<DataModel>) => {
141
429
  const identity = await ctx.auth.getUserIdentity();
142
430
  if (!identity) {
143
- return null;
431
+ return;
144
432
  }
145
- return identity.subject as UserId;
146
- }
147
433
 
148
- // Convenience function for getting the Better Auth user
149
- async getAuthUser(ctx: RunQueryCtx & { auth: ConvexAuth }) {
150
- const identity = await ctx.auth.getUserIdentity();
151
- if (!identity) {
152
- return null;
153
- }
154
- const doc:
155
- | null
156
- | (Infer<typeof schema.tables.user.validator> & {
157
- _id: string;
158
- _creationTime: number;
159
- }) = await ctx.runQuery(this.component.lib.findOne, {
434
+ type BetterAuthDataModel = DataModelFromSchemaDefinition<Schema>;
435
+
436
+ const doc = (await ctx.runQuery(component.adapter.findOne, {
160
437
  model: "user",
161
438
  where: [
162
439
  {
163
- field: "userId",
440
+ field: "id",
164
441
  value: identity.subject,
165
442
  },
166
443
  ],
167
- });
444
+ })) as BetterAuthDataModel["user"]["document"] | null;
168
445
  if (!doc) {
169
- return null;
170
- }
171
- // Type narrowing
172
- if (!("emailVerified" in doc)) {
173
- throw new Error("invalid user");
446
+ return;
174
447
  }
175
- return omit(doc, ["_id", "_creationTime"]);
176
- }
177
-
178
- async getIdTokenCookieName(
179
- createAuth: (ctx: GenericActionCtx<any>) => ReturnType<typeof betterAuth>
180
- ) {
181
- const auth = createAuth({} as any);
182
- const createCookie = createCookieGetter(auth.options);
183
- const cookie = createCookie(JWT_COOKIE_NAME);
184
- return cookie.name;
185
- }
448
+ return doc;
449
+ };
450
+ return {
451
+ component,
452
+ adapter: (ctx: GenericCtx<DataModel>) =>
453
+ convexAdapter<DataModel, typeof ctx, Schema>(ctx, component, config),
454
+ getHeaders: async (ctx: RunQueryCtx & { auth: ConvexAuth }) => {
455
+ const identity = await ctx.auth.getUserIdentity();
456
+ if (!identity) {
457
+ return new Headers();
458
+ }
459
+ const session = await ctx.runQuery(component.adapter.findOne, {
460
+ model: "session",
461
+ where: [
462
+ {
463
+ field: "userId",
464
+ value: identity.subject,
465
+ },
466
+ ],
467
+ });
468
+ return new Headers({
469
+ ...(session?.token ? { authorization: `Bearer ${session.token}` } : {}),
470
+ ...(session?.ipAddress
471
+ ? { "x-forwarded-for": session.ipAddress as string }
472
+ : {}),
473
+ });
474
+ },
186
475
 
187
- async updateUserMetadata(
188
- ctx: GenericMutationCtx<GenericDataModel>,
189
- userId: UserId,
190
- metadata: Omit<
191
- Partial<Infer<typeof schema.tables.user.validator>>,
192
- "userId"
193
- >
194
- ) {
195
- return ctx.runMutation(this.component.lib.updateOne, {
196
- input: {
197
- model: "user",
198
- where: [{ field: "userId", value: userId }],
199
- update: metadata,
200
- },
201
- });
202
- }
476
+ safeGetAuthUser,
203
477
 
204
- async getUserByUsername(
205
- ctx: GenericQueryCtx<GenericDataModel>,
206
- username: string
207
- ) {
208
- const user:
209
- | null
210
- | (Infer<typeof schema.tables.user.validator> & {
211
- _id: string;
212
- _creationTime: number;
213
- }) = await ctx.runQuery(this.component.lib.findOne, {
214
- model: "user",
215
- where: [{ field: "username", value: username }],
216
- });
217
- if (!user) {
218
- return null;
219
- }
220
- return omit(user, ["_id", "_creationTime"]);
221
- }
478
+ getAuthUser: async (ctx: GenericQueryCtx<DataModel>) => {
479
+ const user = await safeGetAuthUser(ctx);
480
+ if (!user) {
481
+ throw new Error("Unauthenticated");
482
+ }
483
+ return user;
484
+ },
222
485
 
223
- createAuthFunctions<DataModel extends GenericDataModel>(opts: {
224
- onCreateUser: (
225
- ctx: GenericMutationCtx<DataModel>,
226
- user: Infer<typeof createUserValidator>
227
- ) => Promise<UserId>;
228
- onDeleteUser?: (
229
- ctx: GenericMutationCtx<DataModel>,
230
- id: UserId
231
- ) => void | Promise<void>;
232
- onUpdateUser?: (
233
- ctx: GenericMutationCtx<DataModel>,
234
- user: Infer<typeof schema.tables.user.validator>
235
- ) => void | Promise<void>;
236
- onCreateSession?: (
486
+ // Replaces 0.7 behavior of returning a new user id from
487
+ // onCreateUser
488
+ setUserId: async (
237
489
  ctx: GenericMutationCtx<DataModel>,
238
- session: Infer<typeof schema.tables.session.validator>
239
- ) => void | Promise<void>;
240
- }) {
241
- return {
242
- isAuthenticated: queryGeneric({
243
- args: v.object({}),
244
- handler: async (ctx) => {
245
- const identity = await ctx.auth.getUserIdentity();
246
- return identity !== null;
490
+ authId: string,
491
+ userId: string
492
+ ) => {
493
+ await ctx.runMutation(component.adapter.updateOne, {
494
+ input: {
495
+ model: "user",
496
+ where: [{ field: "id", value: authId }],
497
+ update: { userId },
247
498
  },
248
- }),
249
- createUser: internalMutationGeneric({
250
- args: createPermissiveArgsValidator,
251
- handler: async (ctx, args) => {
252
- const userId = await opts.onCreateUser(ctx, args.input.data as any);
253
- const parsedArgs = parse(createUserArgsValidator, args);
254
- return ctx.runMutation(this.component.lib.create, {
255
- input: {
256
- ...parsedArgs.input,
257
- data: { ...parsedArgs.input.data, userId },
258
- },
259
- });
499
+ });
500
+ },
501
+
502
+ triggersApi: () => ({
503
+ onCreate: internalMutationGeneric({
504
+ args: {
505
+ doc: v.any(),
506
+ model: v.string(),
260
507
  },
261
- }),
262
- deleteUser: internalMutationGeneric({
263
- args: adapterArgsValidator,
264
508
  handler: async (ctx, args) => {
265
- const doc = await ctx.runMutation(this.component.lib.deleteOne, args);
266
- if (doc && opts.onDeleteUser) {
267
- await opts.onDeleteUser(ctx, doc.userId as UserId);
268
- }
269
- return doc;
509
+ await config?.triggers?.[args.model]?.onCreate?.(ctx, args.doc);
270
510
  },
271
511
  }),
272
- updateUser: internalMutationGeneric({
273
- args: updateUserArgsValidator,
512
+ onUpdate: internalMutationGeneric({
513
+ args: {
514
+ oldDoc: v.any(),
515
+ newDoc: v.any(),
516
+ model: v.string(),
517
+ },
274
518
  handler: async (ctx, args) => {
275
- const updatedUser = await ctx.runMutation(
276
- this.component.lib.updateOne,
277
- { input: args.input }
519
+ await config?.triggers?.[args.model]?.onUpdate?.(
520
+ ctx,
521
+ args.oldDoc,
522
+ args.newDoc
278
523
  );
279
- // Type narrowing
280
- if (!("emailVerified" in updatedUser)) {
281
- throw new Error("invalid user");
282
- }
283
- if (opts.onUpdateUser) {
284
- await opts.onUpdateUser(ctx, omit(updatedUser, ["_id"]));
285
- }
286
- return updatedUser;
287
524
  },
288
525
  }),
289
- createSession: internalMutationGeneric({
290
- args: createSessionArgsValidator,
526
+ onDelete: internalMutationGeneric({
527
+ args: {
528
+ doc: v.any(),
529
+ model: v.string(),
530
+ },
291
531
  handler: async (ctx, args) => {
292
- const session = await ctx.runMutation(this.component.lib.create, {
293
- input: args.input,
294
- });
295
- await opts.onCreateSession?.(ctx, session);
296
- return session;
532
+ await config?.triggers?.[args.model]?.onDelete?.(ctx, args.doc);
297
533
  },
298
534
  }),
299
- };
300
- }
535
+ }),
301
536
 
302
- registerRoutes(
303
- http: HttpRouter,
304
- createAuth: (ctx: GenericActionCtx<any>) => ReturnType<typeof betterAuth>,
305
- opts: {
306
- cors?:
307
- | boolean
308
- | {
309
- // These values are appended to the default values
310
- allowedOrigins?: string[];
311
- allowedHeaders?: string[];
312
- exposedHeaders?: string[];
313
- };
314
- } = {}
315
- ) {
316
- const betterAuthOptions = createAuth({} as any).options;
317
- const path = betterAuthOptions.basePath ?? "/api/auth";
318
- const authRequestHandler = httpActionGeneric(async (ctx, request) => {
319
- if (this.config.verbose) {
320
- console.log("options.baseURL", betterAuthOptions.baseURL);
321
- console.log("request headers", request.headers);
322
- }
323
- const auth = createAuth(ctx);
324
- const response = await auth.handler(request);
325
- if (this.config?.verbose) {
326
- console.log("response headers", response.headers);
537
+ registerRoutes: (
538
+ http: HttpRouter,
539
+ createAuth: (ctx: GenericCtx<DataModel>) => ReturnType<typeof betterAuth>,
540
+ opts: {
541
+ cors?:
542
+ | boolean
543
+ | {
544
+ // These values are appended to the default values
545
+ allowedOrigins?: string[];
546
+ allowedHeaders?: string[];
547
+ exposedHeaders?: string[];
548
+ };
549
+ } = {}
550
+ ) => {
551
+ const authDummy = createAuth({} as any);
552
+ const path = authDummy.options.basePath ?? "/api/auth";
553
+ const authRequestHandler = httpActionGeneric(async (ctx, request) => {
554
+ if (config?.verbose) {
555
+ console.log("options.baseURL", authDummy.options.baseURL);
556
+ console.log("request headers", request.headers);
557
+ }
558
+ const auth = createAuth(ctx as any);
559
+ const response = await auth.handler(request);
560
+ if (config?.verbose) {
561
+ console.log("response headers", response.headers);
562
+ }
563
+ return response;
564
+ });
565
+ const wellKnown = http.lookup("/.well-known/openid-configuration", "GET");
566
+
567
+ // If registerRoutes is used multiple times, this may already be defined
568
+ if (!wellKnown) {
569
+ // Redirect root well-known to api well-known
570
+ http.route({
571
+ path: "/.well-known/openid-configuration",
572
+ method: "GET",
573
+ handler: httpActionGeneric(async () => {
574
+ const url = `${requireEnv("CONVEX_SITE_URL")}${path}/convex/.well-known/openid-configuration`;
575
+ return Response.redirect(url);
576
+ }),
577
+ });
327
578
  }
328
- return response;
329
- });
330
579
 
331
- const wellKnown = http.lookup("/.well-known/openid-configuration", "GET");
580
+ if (!opts.cors) {
581
+ http.route({
582
+ pathPrefix: `${path}/`,
583
+ method: "GET",
584
+ handler: authRequestHandler,
585
+ });
332
586
 
333
- // If registerRoutes is used multiple times, this may already be defined
334
- if (!wellKnown) {
335
- // Redirect root well-known to api well-known
336
- http.route({
337
- path: "/.well-known/openid-configuration",
338
- method: "GET",
339
- handler: httpActionGeneric(async () => {
340
- const url = `${requireEnv("CONVEX_SITE_URL")}${path}/convex/.well-known/openid-configuration`;
341
- return Response.redirect(url);
342
- }),
587
+ http.route({
588
+ pathPrefix: `${path}/`,
589
+ method: "POST",
590
+ handler: authRequestHandler,
591
+ });
592
+
593
+ return;
594
+ }
595
+ const corsOpts =
596
+ typeof opts.cors === "boolean"
597
+ ? { allowedOrigins: [], allowedHeaders: [], exposedHeaders: [] }
598
+ : opts.cors;
599
+ let trustedOriginsOption:
600
+ | string[]
601
+ | ((request: Request) => string[] | Promise<string[]>)
602
+ | undefined;
603
+ const cors = corsRouter(http, {
604
+ allowedOrigins: async (request) => {
605
+ trustedOriginsOption =
606
+ trustedOriginsOption ??
607
+ (await authDummy.$context).options.trustedOrigins ??
608
+ [];
609
+ const trustedOrigins = Array.isArray(trustedOriginsOption)
610
+ ? trustedOriginsOption
611
+ : await trustedOriginsOption(request);
612
+ return trustedOrigins
613
+ .map((origin) =>
614
+ // Strip trailing wildcards, unsupported for allowedOrigins
615
+ origin.endsWith("*") && origin.length > 1
616
+ ? origin.slice(0, -1)
617
+ : origin
618
+ )
619
+ .concat(corsOpts.allowedOrigins ?? []);
620
+ },
621
+ allowCredentials: true,
622
+ allowedHeaders: ["Content-Type", "Better-Auth-Cookie"].concat(
623
+ corsOpts.allowedHeaders ?? []
624
+ ),
625
+ exposedHeaders: ["Set-Better-Auth-Cookie"].concat(
626
+ corsOpts.exposedHeaders ?? []
627
+ ),
628
+ debug: config?.verbose,
629
+ enforceAllowOrigins: false,
343
630
  });
344
- }
345
631
 
346
- if (!opts.cors) {
347
- http.route({
632
+ cors.route({
348
633
  pathPrefix: `${path}/`,
349
634
  method: "GET",
350
635
  handler: authRequestHandler,
351
636
  });
352
637
 
353
- http.route({
638
+ cors.route({
354
639
  pathPrefix: `${path}/`,
355
640
  method: "POST",
356
641
  handler: authRequestHandler,
357
642
  });
358
-
359
- return;
360
- }
361
- const corsOpts =
362
- typeof opts.cors === "boolean"
363
- ? { allowedOrigins: [], allowedHeaders: [], exposedHeaders: [] }
364
- : opts.cors;
365
- const cors = corsRouter(http, {
366
- allowedOrigins: async (request) => {
367
- const trustedOriginsOption =
368
- (await createAuth({} as any).$context).options.trustedOrigins ?? [];
369
- const trustedOrigins = Array.isArray(trustedOriginsOption)
370
- ? trustedOriginsOption
371
- : await trustedOriginsOption(request);
372
- return trustedOrigins
373
- .map((origin) =>
374
- // Strip trailing wildcards, unsupported for allowedOrigins
375
- origin.endsWith("*") && origin.length > 1
376
- ? origin.slice(0, -1)
377
- : origin
378
- )
379
- .concat(corsOpts.allowedOrigins ?? []);
380
- },
381
- allowCredentials: true,
382
- allowedHeaders: ["Content-Type", "Better-Auth-Cookie"].concat(
383
- corsOpts.allowedHeaders ?? []
384
- ),
385
- exposedHeaders: ["Set-Better-Auth-Cookie"].concat(
386
- corsOpts.exposedHeaders ?? []
387
- ),
388
- debug: this.config?.verbose,
389
- enforceAllowOrigins: false,
390
- });
391
-
392
- cors.route({
393
- pathPrefix: `${path}/`,
394
- method: "GET",
395
- handler: authRequestHandler,
396
- });
397
-
398
- cors.route({
399
- pathPrefix: `${path}/`,
400
- method: "POST",
401
- handler: authRequestHandler,
402
- });
403
- }
404
- }
643
+ },
644
+ };
645
+ };
405
646
 
406
647
  /* Type utils follow */
407
648