@robelest/convex-auth 0.0.4-preview.25 → 0.0.4-preview.28

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 (666) hide show
  1. package/README.md +43 -36
  2. package/dist/bin.js +5765 -4880
  3. package/dist/browser/index.d.ts +30 -0
  4. package/dist/browser/index.js +93 -0
  5. package/dist/browser/locks.js +11 -0
  6. package/dist/browser/navigation.js +14 -0
  7. package/dist/{factors → browser}/passkey.js +23 -32
  8. package/dist/browser/runtime.js +92 -0
  9. package/dist/client/core/types.d.ts +452 -5
  10. package/dist/client/core/types.js +17 -0
  11. package/dist/client/errors.js +19 -0
  12. package/dist/client/factors/device.js +94 -0
  13. package/dist/{factors → client/factors}/totp.js +12 -4
  14. package/dist/client/index.d.ts +47 -1
  15. package/dist/client/index.js +269 -232
  16. package/dist/client/runtime/mutex.js +24 -0
  17. package/dist/client/runtime/proxy.js +30 -0
  18. package/dist/client/runtime/storage.js +45 -0
  19. package/dist/client/services/adapters.js +7 -0
  20. package/dist/client/services/http.js +6 -0
  21. package/dist/client/services/resolve.js +13 -0
  22. package/dist/client/services/runtime.js +6 -0
  23. package/dist/component/_generated/component.d.ts +1355 -1399
  24. package/dist/component/convex.config.d.ts +2 -2
  25. package/dist/component/index.d.ts +4 -26
  26. package/dist/component/index.js +1 -1
  27. package/dist/component/model.d.ts +26 -112
  28. package/dist/component/model.js +76 -54
  29. package/dist/component/modules.js +38 -0
  30. package/dist/component/public/factors/devices.js +1 -1
  31. package/dist/component/public/factors/passkeys.js +1 -1
  32. package/dist/component/public/factors/totp.js +1 -1
  33. package/dist/component/public/groups/core.js +2 -2
  34. package/dist/component/public/groups/invites.js +1 -1
  35. package/dist/component/public/groups/members.js +1 -1
  36. package/dist/component/public/identity/accounts.js +1 -1
  37. package/dist/component/public/identity/codes.js +1 -1
  38. package/dist/component/public/identity/sessions.js +39 -2
  39. package/dist/component/public/identity/tokens.js +82 -4
  40. package/dist/component/public/identity/users.js +1 -1
  41. package/dist/component/public/identity/verifiers.js +10 -4
  42. package/dist/component/public/security/keys.js +1 -1
  43. package/dist/component/public/security/limits.js +1 -1
  44. package/dist/component/public/{enterprise → sso}/audit.js +26 -26
  45. package/dist/component/public/sso/core.js +263 -0
  46. package/dist/component/public/sso/domains.js +280 -0
  47. package/dist/component/public/{enterprise → sso}/scim.js +87 -87
  48. package/dist/component/public/sso/secrets.js +125 -0
  49. package/dist/component/public/{enterprise → sso}/webhooks.js +59 -59
  50. package/dist/component/public.js +9 -9
  51. package/dist/component/schema.d.ts +472 -393
  52. package/dist/component/schema.js +36 -35
  53. package/dist/core/index.d.ts +380 -0
  54. package/dist/core/index.js +83 -0
  55. package/dist/otel.d.ts +69 -0
  56. package/dist/otel.js +82 -0
  57. package/dist/providers/anonymous.d.ts +15 -34
  58. package/dist/providers/anonymous.js +27 -35
  59. package/dist/providers/apple.d.ts +59 -0
  60. package/dist/providers/apple.js +58 -0
  61. package/dist/providers/credentials.d.ts +18 -34
  62. package/dist/providers/credentials.js +16 -27
  63. package/dist/providers/custom.d.ts +94 -0
  64. package/dist/providers/custom.js +119 -0
  65. package/dist/providers/device.d.ts +15 -49
  66. package/dist/providers/device.js +17 -34
  67. package/dist/providers/email.d.ts +21 -38
  68. package/dist/providers/email.js +36 -55
  69. package/dist/providers/github.d.ts +54 -0
  70. package/dist/providers/github.js +75 -0
  71. package/dist/providers/google.d.ts +54 -0
  72. package/dist/providers/google.js +61 -0
  73. package/dist/providers/index.d.ts +16 -12
  74. package/dist/providers/index.js +15 -11
  75. package/dist/providers/microsoft.d.ts +57 -0
  76. package/dist/providers/microsoft.js +101 -0
  77. package/dist/providers/passkey.d.ts +19 -35
  78. package/dist/providers/passkey.js +20 -30
  79. package/dist/providers/password.d.ts +17 -18
  80. package/dist/providers/password.js +121 -143
  81. package/dist/providers/phone.d.ts +13 -28
  82. package/dist/providers/phone.js +21 -46
  83. package/dist/providers/sso.d.ts +16 -36
  84. package/dist/providers/sso.js +21 -22
  85. package/dist/providers/totp.d.ts +13 -29
  86. package/dist/providers/totp.js +17 -27
  87. package/dist/server/auth-context.d.ts +204 -0
  88. package/dist/server/auth-context.js +76 -0
  89. package/dist/server/auth.d.ts +99 -244
  90. package/dist/server/auth.js +56 -152
  91. package/dist/server/componentContext.d.ts +12 -0
  92. package/dist/server/componentContext.js +1 -0
  93. package/dist/server/config.js +6 -67
  94. package/dist/server/constants.js +6 -0
  95. package/dist/server/contract.d.ts +105 -0
  96. package/dist/server/contract.js +43 -0
  97. package/dist/server/cookies.js +3 -2
  98. package/dist/server/core.js +31 -36
  99. package/dist/server/crypto.js +34 -44
  100. package/dist/server/db.js +6 -1
  101. package/dist/server/device.js +96 -130
  102. package/dist/server/env.js +48 -0
  103. package/dist/server/errors.js +20 -0
  104. package/dist/server/http.d.ts +15 -59
  105. package/dist/server/http.js +136 -120
  106. package/dist/server/identity.js +2 -2
  107. package/dist/server/index.d.ts +5 -4
  108. package/dist/server/index.js +3 -3
  109. package/dist/server/keys.js +10 -1
  110. package/dist/server/limits.js +26 -26
  111. package/dist/server/log.js +28 -0
  112. package/dist/server/mounts.d.ts +1107 -296
  113. package/dist/server/mounts.js +315 -196
  114. package/dist/server/mutations/account.js +11 -14
  115. package/dist/server/mutations/code.js +6 -5
  116. package/dist/server/mutations/invalidate.js +9 -11
  117. package/dist/server/mutations/oauth.js +112 -73
  118. package/dist/server/mutations/refresh.js +47 -97
  119. package/dist/server/mutations/register.js +37 -35
  120. package/dist/server/mutations/retrieve.js +16 -16
  121. package/dist/server/mutations/signature.js +15 -18
  122. package/dist/server/mutations/signin.js +10 -5
  123. package/dist/server/mutations/signout.js +11 -14
  124. package/dist/server/mutations/store.js +25 -18
  125. package/dist/server/mutations/verifier.js +11 -8
  126. package/dist/server/mutations/verify.js +53 -41
  127. package/dist/server/oauth/factory.js +44 -0
  128. package/dist/server/oauth/index.js +12 -0
  129. package/dist/server/oauth/runtime.js +248 -0
  130. package/dist/server/passkey.js +331 -365
  131. package/dist/server/payloads.d.ts +16 -0
  132. package/dist/server/payloads.js +30 -0
  133. package/dist/server/{ssr.d.ts → prefetch.d.ts} +2 -2
  134. package/dist/server/prefetch.js +635 -0
  135. package/dist/server/random.js +19 -0
  136. package/dist/server/redirects.js +10 -5
  137. package/dist/server/refresh.js +14 -86
  138. package/dist/server/runtime.d.ts +531 -31
  139. package/dist/server/runtime.js +106 -267
  140. package/dist/server/secret.js +44 -0
  141. package/dist/server/services/config.js +10 -0
  142. package/dist/server/services/group.js +211 -0
  143. package/dist/server/services/logger.js +8 -0
  144. package/dist/server/services/providers.js +22 -0
  145. package/dist/server/services/refresh.js +8 -0
  146. package/dist/server/services/resolve.js +27 -0
  147. package/dist/server/services/signin.js +8 -0
  148. package/dist/server/sessions.js +35 -34
  149. package/dist/server/signin.js +229 -140
  150. package/dist/server/{enterprise → sso}/config.js +10 -3
  151. package/dist/server/sso/domain.d.ts +614 -0
  152. package/dist/server/sso/domain.js +1175 -0
  153. package/dist/server/sso/http.js +1060 -0
  154. package/dist/server/sso/oidc.js +324 -0
  155. package/dist/server/sso/policies.js +59 -0
  156. package/dist/server/sso/policy.js +139 -0
  157. package/dist/server/sso/profile.js +22 -0
  158. package/dist/server/sso/provision.js +179 -0
  159. package/dist/{component/server/enterprise → server/sso}/saml.js +142 -56
  160. package/dist/{component/server/enterprise → server/sso}/scim.js +13 -7
  161. package/dist/server/sso/shared.js +74 -0
  162. package/dist/server/sso/validators.js +88 -0
  163. package/dist/server/sso/webhook.js +94 -0
  164. package/dist/server/tokens.js +16 -4
  165. package/dist/server/totp.js +155 -164
  166. package/dist/server/types.d.ts +306 -296
  167. package/dist/server/types.js +1 -30
  168. package/dist/server/url.js +32 -0
  169. package/dist/server/users.js +74 -40
  170. package/dist/server/utils/cache.js +51 -0
  171. package/dist/server/utils/dispatch.js +36 -0
  172. package/dist/server/utils/retry.js +24 -0
  173. package/dist/server/utils/span.js +32 -0
  174. package/dist/shared/errors.js +19 -0
  175. package/dist/shared/log.js +45 -0
  176. package/{src/test.ts → dist/test.d.ts} +21 -22
  177. package/dist/test.js +51 -0
  178. package/package.json +70 -42
  179. package/dist/authorization/index.d.ts.map +0 -1
  180. package/dist/authorization/index.js.map +0 -1
  181. package/dist/client/core/types.d.ts.map +0 -1
  182. package/dist/client/index.d.ts.map +0 -1
  183. package/dist/client/index.js.map +0 -1
  184. package/dist/component/_generated/api.d.ts +0 -75
  185. package/dist/component/_generated/api.d.ts.map +0 -1
  186. package/dist/component/_generated/api.js.map +0 -1
  187. package/dist/component/_generated/component.d.ts.map +0 -1
  188. package/dist/component/_generated/dataModel.d.ts +0 -42
  189. package/dist/component/_generated/dataModel.d.ts.map +0 -1
  190. package/dist/component/_generated/server.d.ts +0 -117
  191. package/dist/component/_generated/server.d.ts.map +0 -1
  192. package/dist/component/_generated/server.js.map +0 -1
  193. package/dist/component/_virtual/rolldown_runtime.js +0 -18
  194. package/dist/component/client/core/types.d.ts +0 -2
  195. package/dist/component/client/index.d.ts +0 -1
  196. package/dist/component/convex.config.d.ts.map +0 -1
  197. package/dist/component/convex.config.js.map +0 -1
  198. package/dist/component/functions.d.ts +0 -25
  199. package/dist/component/functions.d.ts.map +0 -1
  200. package/dist/component/functions.js.map +0 -1
  201. package/dist/component/index.d.ts.map +0 -1
  202. package/dist/component/model.d.ts.map +0 -1
  203. package/dist/component/model.js.map +0 -1
  204. package/dist/component/providers/anonymous.d.ts +0 -54
  205. package/dist/component/providers/anonymous.d.ts.map +0 -1
  206. package/dist/component/providers/credentials.d.ts +0 -38
  207. package/dist/component/providers/credentials.d.ts.map +0 -1
  208. package/dist/component/providers/device.d.ts +0 -67
  209. package/dist/component/providers/device.d.ts.map +0 -1
  210. package/dist/component/providers/email.d.ts +0 -62
  211. package/dist/component/providers/email.d.ts.map +0 -1
  212. package/dist/component/providers/oauth.d.ts +0 -25
  213. package/dist/component/providers/oauth.d.ts.map +0 -1
  214. package/dist/component/providers/oauth.js +0 -13
  215. package/dist/component/providers/oauth.js.map +0 -1
  216. package/dist/component/providers/passkey.d.ts +0 -57
  217. package/dist/component/providers/passkey.d.ts.map +0 -1
  218. package/dist/component/providers/password.d.ts +0 -88
  219. package/dist/component/providers/password.d.ts.map +0 -1
  220. package/dist/component/providers/phone.d.ts +0 -48
  221. package/dist/component/providers/phone.d.ts.map +0 -1
  222. package/dist/component/providers/sso.d.ts +0 -50
  223. package/dist/component/providers/sso.d.ts.map +0 -1
  224. package/dist/component/providers/totp.d.ts +0 -45
  225. package/dist/component/providers/totp.d.ts.map +0 -1
  226. package/dist/component/public/enterprise/audit.d.ts +0 -73
  227. package/dist/component/public/enterprise/audit.d.ts.map +0 -1
  228. package/dist/component/public/enterprise/audit.js.map +0 -1
  229. package/dist/component/public/enterprise/core.d.ts +0 -176
  230. package/dist/component/public/enterprise/core.d.ts.map +0 -1
  231. package/dist/component/public/enterprise/core.js +0 -292
  232. package/dist/component/public/enterprise/core.js.map +0 -1
  233. package/dist/component/public/enterprise/domains.d.ts +0 -174
  234. package/dist/component/public/enterprise/domains.d.ts.map +0 -1
  235. package/dist/component/public/enterprise/domains.js +0 -271
  236. package/dist/component/public/enterprise/domains.js.map +0 -1
  237. package/dist/component/public/enterprise/scim.d.ts +0 -245
  238. package/dist/component/public/enterprise/scim.d.ts.map +0 -1
  239. package/dist/component/public/enterprise/scim.js.map +0 -1
  240. package/dist/component/public/enterprise/secrets.d.ts +0 -78
  241. package/dist/component/public/enterprise/secrets.d.ts.map +0 -1
  242. package/dist/component/public/enterprise/secrets.js +0 -118
  243. package/dist/component/public/enterprise/secrets.js.map +0 -1
  244. package/dist/component/public/enterprise/webhooks.d.ts +0 -211
  245. package/dist/component/public/enterprise/webhooks.d.ts.map +0 -1
  246. package/dist/component/public/enterprise/webhooks.js.map +0 -1
  247. package/dist/component/public/factors/devices.d.ts +0 -157
  248. package/dist/component/public/factors/devices.d.ts.map +0 -1
  249. package/dist/component/public/factors/devices.js.map +0 -1
  250. package/dist/component/public/factors/passkeys.d.ts +0 -175
  251. package/dist/component/public/factors/passkeys.d.ts.map +0 -1
  252. package/dist/component/public/factors/passkeys.js.map +0 -1
  253. package/dist/component/public/factors/totp.d.ts +0 -189
  254. package/dist/component/public/factors/totp.d.ts.map +0 -1
  255. package/dist/component/public/factors/totp.js.map +0 -1
  256. package/dist/component/public/groups/core.d.ts +0 -137
  257. package/dist/component/public/groups/core.d.ts.map +0 -1
  258. package/dist/component/public/groups/core.js.map +0 -1
  259. package/dist/component/public/groups/invites.d.ts +0 -217
  260. package/dist/component/public/groups/invites.d.ts.map +0 -1
  261. package/dist/component/public/groups/invites.js.map +0 -1
  262. package/dist/component/public/groups/members.d.ts +0 -204
  263. package/dist/component/public/groups/members.d.ts.map +0 -1
  264. package/dist/component/public/groups/members.js.map +0 -1
  265. package/dist/component/public/identity/accounts.d.ts +0 -147
  266. package/dist/component/public/identity/accounts.d.ts.map +0 -1
  267. package/dist/component/public/identity/accounts.js.map +0 -1
  268. package/dist/component/public/identity/codes.d.ts +0 -104
  269. package/dist/component/public/identity/codes.d.ts.map +0 -1
  270. package/dist/component/public/identity/codes.js.map +0 -1
  271. package/dist/component/public/identity/sessions.d.ts +0 -128
  272. package/dist/component/public/identity/sessions.d.ts.map +0 -1
  273. package/dist/component/public/identity/sessions.js.map +0 -1
  274. package/dist/component/public/identity/tokens.d.ts +0 -169
  275. package/dist/component/public/identity/tokens.d.ts.map +0 -1
  276. package/dist/component/public/identity/tokens.js.map +0 -1
  277. package/dist/component/public/identity/users.d.ts +0 -212
  278. package/dist/component/public/identity/users.d.ts.map +0 -1
  279. package/dist/component/public/identity/users.js.map +0 -1
  280. package/dist/component/public/identity/verifiers.d.ts +0 -116
  281. package/dist/component/public/identity/verifiers.d.ts.map +0 -1
  282. package/dist/component/public/identity/verifiers.js.map +0 -1
  283. package/dist/component/public/security/keys.d.ts +0 -209
  284. package/dist/component/public/security/keys.d.ts.map +0 -1
  285. package/dist/component/public/security/keys.js.map +0 -1
  286. package/dist/component/public/security/limits.d.ts +0 -114
  287. package/dist/component/public/security/limits.d.ts.map +0 -1
  288. package/dist/component/public/security/limits.js.map +0 -1
  289. package/dist/component/public.d.ts +0 -28
  290. package/dist/component/public.d.ts.map +0 -1
  291. package/dist/component/schema.d.ts.map +0 -1
  292. package/dist/component/schema.js.map +0 -1
  293. package/dist/component/server/auth.d.ts +0 -447
  294. package/dist/component/server/auth.d.ts.map +0 -1
  295. package/dist/component/server/auth.js +0 -254
  296. package/dist/component/server/auth.js.map +0 -1
  297. package/dist/component/server/config.js +0 -121
  298. package/dist/component/server/config.js.map +0 -1
  299. package/dist/component/server/context.js +0 -53
  300. package/dist/component/server/context.js.map +0 -1
  301. package/dist/component/server/cookies.js +0 -47
  302. package/dist/component/server/cookies.js.map +0 -1
  303. package/dist/component/server/core.js +0 -576
  304. package/dist/component/server/core.js.map +0 -1
  305. package/dist/component/server/crypto.js +0 -56
  306. package/dist/component/server/crypto.js.map +0 -1
  307. package/dist/component/server/db.js +0 -87
  308. package/dist/component/server/db.js.map +0 -1
  309. package/dist/component/server/device.js +0 -152
  310. package/dist/component/server/device.js.map +0 -1
  311. package/dist/component/server/enterprise/config.js +0 -46
  312. package/dist/component/server/enterprise/config.js.map +0 -1
  313. package/dist/component/server/enterprise/domain.js +0 -974
  314. package/dist/component/server/enterprise/domain.js.map +0 -1
  315. package/dist/component/server/enterprise/http.js +0 -787
  316. package/dist/component/server/enterprise/http.js.map +0 -1
  317. package/dist/component/server/enterprise/oidc.js +0 -248
  318. package/dist/component/server/enterprise/oidc.js.map +0 -1
  319. package/dist/component/server/enterprise/policy.js +0 -85
  320. package/dist/component/server/enterprise/policy.js.map +0 -1
  321. package/dist/component/server/enterprise/saml.js.map +0 -1
  322. package/dist/component/server/enterprise/scim.js.map +0 -1
  323. package/dist/component/server/enterprise/shared.js +0 -51
  324. package/dist/component/server/enterprise/shared.js.map +0 -1
  325. package/dist/component/server/http.d.ts +0 -85
  326. package/dist/component/server/http.d.ts.map +0 -1
  327. package/dist/component/server/http.js +0 -351
  328. package/dist/component/server/http.js.map +0 -1
  329. package/dist/component/server/identity.js +0 -16
  330. package/dist/component/server/identity.js.map +0 -1
  331. package/dist/component/server/keys.js +0 -96
  332. package/dist/component/server/keys.js.map +0 -1
  333. package/dist/component/server/limits.js +0 -52
  334. package/dist/component/server/limits.js.map +0 -1
  335. package/dist/component/server/mutations/account.js +0 -46
  336. package/dist/component/server/mutations/account.js.map +0 -1
  337. package/dist/component/server/mutations/code.js +0 -68
  338. package/dist/component/server/mutations/code.js.map +0 -1
  339. package/dist/component/server/mutations/invalidate.js +0 -32
  340. package/dist/component/server/mutations/invalidate.js.map +0 -1
  341. package/dist/component/server/mutations/oauth.js +0 -116
  342. package/dist/component/server/mutations/oauth.js.map +0 -1
  343. package/dist/component/server/mutations/refresh.js +0 -119
  344. package/dist/component/server/mutations/refresh.js.map +0 -1
  345. package/dist/component/server/mutations/register.js +0 -87
  346. package/dist/component/server/mutations/register.js.map +0 -1
  347. package/dist/component/server/mutations/retrieve.js +0 -61
  348. package/dist/component/server/mutations/retrieve.js.map +0 -1
  349. package/dist/component/server/mutations/signature.js +0 -38
  350. package/dist/component/server/mutations/signature.js.map +0 -1
  351. package/dist/component/server/mutations/signin.js +0 -27
  352. package/dist/component/server/mutations/signin.js.map +0 -1
  353. package/dist/component/server/mutations/signout.js +0 -27
  354. package/dist/component/server/mutations/signout.js.map +0 -1
  355. package/dist/component/server/mutations/store/refs.js +0 -15
  356. package/dist/component/server/mutations/store/refs.js.map +0 -1
  357. package/dist/component/server/mutations/store.js +0 -70
  358. package/dist/component/server/mutations/store.js.map +0 -1
  359. package/dist/component/server/mutations/verifier.js +0 -18
  360. package/dist/component/server/mutations/verifier.js.map +0 -1
  361. package/dist/component/server/mutations/verify.js +0 -98
  362. package/dist/component/server/mutations/verify.js.map +0 -1
  363. package/dist/component/server/oauth.js +0 -242
  364. package/dist/component/server/oauth.js.map +0 -1
  365. package/dist/component/server/passkey.js +0 -415
  366. package/dist/component/server/passkey.js.map +0 -1
  367. package/dist/component/server/redirects.js +0 -40
  368. package/dist/component/server/redirects.js.map +0 -1
  369. package/dist/component/server/refresh.js +0 -99
  370. package/dist/component/server/refresh.js.map +0 -1
  371. package/dist/component/server/runtime.d.ts +0 -136
  372. package/dist/component/server/runtime.d.ts.map +0 -1
  373. package/dist/component/server/runtime.js +0 -456
  374. package/dist/component/server/runtime.js.map +0 -1
  375. package/dist/component/server/sessions.js +0 -71
  376. package/dist/component/server/sessions.js.map +0 -1
  377. package/dist/component/server/signin.js +0 -225
  378. package/dist/component/server/signin.js.map +0 -1
  379. package/dist/component/server/tokens.js +0 -17
  380. package/dist/component/server/tokens.js.map +0 -1
  381. package/dist/component/server/totp.js +0 -208
  382. package/dist/component/server/totp.js.map +0 -1
  383. package/dist/component/server/types.d.ts +0 -949
  384. package/dist/component/server/types.d.ts.map +0 -1
  385. package/dist/component/server/types.js +0 -79
  386. package/dist/component/server/types.js.map +0 -1
  387. package/dist/component/server/users.js +0 -123
  388. package/dist/component/server/users.js.map +0 -1
  389. package/dist/component/server/utils.js +0 -140
  390. package/dist/component/server/utils.js.map +0 -1
  391. package/dist/core/types.d.ts +0 -361
  392. package/dist/core/types.d.ts.map +0 -1
  393. package/dist/factors/device.js +0 -104
  394. package/dist/factors/device.js.map +0 -1
  395. package/dist/factors/passkey.js.map +0 -1
  396. package/dist/factors/totp.js.map +0 -1
  397. package/dist/providers/anonymous.d.ts.map +0 -1
  398. package/dist/providers/anonymous.js.map +0 -1
  399. package/dist/providers/credentials.d.ts.map +0 -1
  400. package/dist/providers/credentials.js.map +0 -1
  401. package/dist/providers/device.d.ts.map +0 -1
  402. package/dist/providers/device.js.map +0 -1
  403. package/dist/providers/email.d.ts.map +0 -1
  404. package/dist/providers/email.js.map +0 -1
  405. package/dist/providers/oauth.d.ts +0 -69
  406. package/dist/providers/oauth.d.ts.map +0 -1
  407. package/dist/providers/oauth.js +0 -43
  408. package/dist/providers/oauth.js.map +0 -1
  409. package/dist/providers/passkey.d.ts.map +0 -1
  410. package/dist/providers/passkey.js.map +0 -1
  411. package/dist/providers/password.d.ts.map +0 -1
  412. package/dist/providers/password.js.map +0 -1
  413. package/dist/providers/phone.d.ts.map +0 -1
  414. package/dist/providers/phone.js.map +0 -1
  415. package/dist/providers/sso.d.ts.map +0 -1
  416. package/dist/providers/sso.js.map +0 -1
  417. package/dist/providers/totp.d.ts.map +0 -1
  418. package/dist/providers/totp.js.map +0 -1
  419. package/dist/runtime/browser.js +0 -68
  420. package/dist/runtime/browser.js.map +0 -1
  421. package/dist/runtime/invite.js.map +0 -1
  422. package/dist/runtime/proxy.js +0 -70
  423. package/dist/runtime/proxy.js.map +0 -1
  424. package/dist/runtime/storage.js +0 -37
  425. package/dist/runtime/storage.js.map +0 -1
  426. package/dist/server/auth.d.ts.map +0 -1
  427. package/dist/server/auth.js.map +0 -1
  428. package/dist/server/config.d.ts +0 -1
  429. package/dist/server/config.js.map +0 -1
  430. package/dist/server/context.d.ts +0 -1
  431. package/dist/server/context.js.map +0 -1
  432. package/dist/server/cookies.d.ts +0 -1
  433. package/dist/server/cookies.js.map +0 -1
  434. package/dist/server/core.d.ts +0 -1315
  435. package/dist/server/core.d.ts.map +0 -1
  436. package/dist/server/core.js.map +0 -1
  437. package/dist/server/crypto.d.ts +0 -8
  438. package/dist/server/crypto.d.ts.map +0 -1
  439. package/dist/server/crypto.js.map +0 -1
  440. package/dist/server/db.d.ts +0 -1
  441. package/dist/server/db.js.map +0 -1
  442. package/dist/server/device.d.ts +0 -1
  443. package/dist/server/device.js.map +0 -1
  444. package/dist/server/enterprise/config.d.ts +0 -1
  445. package/dist/server/enterprise/config.js.map +0 -1
  446. package/dist/server/enterprise/domain.d.ts +0 -401
  447. package/dist/server/enterprise/domain.d.ts.map +0 -1
  448. package/dist/server/enterprise/domain.js +0 -974
  449. package/dist/server/enterprise/domain.js.map +0 -1
  450. package/dist/server/enterprise/http.d.ts +0 -26
  451. package/dist/server/enterprise/http.d.ts.map +0 -1
  452. package/dist/server/enterprise/http.js +0 -787
  453. package/dist/server/enterprise/http.js.map +0 -1
  454. package/dist/server/enterprise/oidc.d.ts +0 -1
  455. package/dist/server/enterprise/oidc.js +0 -248
  456. package/dist/server/enterprise/oidc.js.map +0 -1
  457. package/dist/server/enterprise/policy.d.ts +0 -1
  458. package/dist/server/enterprise/policy.js +0 -85
  459. package/dist/server/enterprise/policy.js.map +0 -1
  460. package/dist/server/enterprise/saml.d.ts +0 -1
  461. package/dist/server/enterprise/saml.js +0 -338
  462. package/dist/server/enterprise/saml.js.map +0 -1
  463. package/dist/server/enterprise/scim.d.ts +0 -1
  464. package/dist/server/enterprise/scim.js +0 -97
  465. package/dist/server/enterprise/scim.js.map +0 -1
  466. package/dist/server/enterprise/shared.d.ts +0 -5
  467. package/dist/server/enterprise/shared.d.ts.map +0 -1
  468. package/dist/server/enterprise/shared.js +0 -51
  469. package/dist/server/enterprise/shared.js.map +0 -1
  470. package/dist/server/enterprise/validators.d.ts +0 -1
  471. package/dist/server/enterprise/validators.js +0 -60
  472. package/dist/server/enterprise/validators.js.map +0 -1
  473. package/dist/server/http.d.ts.map +0 -1
  474. package/dist/server/http.js.map +0 -1
  475. package/dist/server/identity.d.ts +0 -1
  476. package/dist/server/identity.js.map +0 -1
  477. package/dist/server/keys.d.ts +0 -1
  478. package/dist/server/keys.js.map +0 -1
  479. package/dist/server/limits.d.ts +0 -1
  480. package/dist/server/limits.js.map +0 -1
  481. package/dist/server/mounts.d.ts.map +0 -1
  482. package/dist/server/mounts.js.map +0 -1
  483. package/dist/server/mutations/account.d.ts +0 -29
  484. package/dist/server/mutations/account.d.ts.map +0 -1
  485. package/dist/server/mutations/account.js.map +0 -1
  486. package/dist/server/mutations/code.d.ts +0 -30
  487. package/dist/server/mutations/code.d.ts.map +0 -1
  488. package/dist/server/mutations/code.js.map +0 -1
  489. package/dist/server/mutations/index.d.ts +0 -14
  490. package/dist/server/mutations/invalidate.d.ts +0 -20
  491. package/dist/server/mutations/invalidate.d.ts.map +0 -1
  492. package/dist/server/mutations/invalidate.js.map +0 -1
  493. package/dist/server/mutations/oauth.d.ts +0 -30
  494. package/dist/server/mutations/oauth.d.ts.map +0 -1
  495. package/dist/server/mutations/oauth.js.map +0 -1
  496. package/dist/server/mutations/refresh.d.ts +0 -21
  497. package/dist/server/mutations/refresh.d.ts.map +0 -1
  498. package/dist/server/mutations/refresh.js.map +0 -1
  499. package/dist/server/mutations/register.d.ts +0 -38
  500. package/dist/server/mutations/register.d.ts.map +0 -1
  501. package/dist/server/mutations/register.js.map +0 -1
  502. package/dist/server/mutations/retrieve.d.ts +0 -33
  503. package/dist/server/mutations/retrieve.d.ts.map +0 -1
  504. package/dist/server/mutations/retrieve.js.map +0 -1
  505. package/dist/server/mutations/signature.d.ts +0 -21
  506. package/dist/server/mutations/signature.d.ts.map +0 -1
  507. package/dist/server/mutations/signature.js.map +0 -1
  508. package/dist/server/mutations/signin.d.ts +0 -22
  509. package/dist/server/mutations/signin.d.ts.map +0 -1
  510. package/dist/server/mutations/signin.js.map +0 -1
  511. package/dist/server/mutations/signout.d.ts +0 -16
  512. package/dist/server/mutations/signout.d.ts.map +0 -1
  513. package/dist/server/mutations/signout.js.map +0 -1
  514. package/dist/server/mutations/store/refs.d.ts +0 -12
  515. package/dist/server/mutations/store/refs.d.ts.map +0 -1
  516. package/dist/server/mutations/store/refs.js.map +0 -1
  517. package/dist/server/mutations/store.d.ts +0 -306
  518. package/dist/server/mutations/store.d.ts.map +0 -1
  519. package/dist/server/mutations/store.js.map +0 -1
  520. package/dist/server/mutations/verifier.d.ts +0 -13
  521. package/dist/server/mutations/verifier.d.ts.map +0 -1
  522. package/dist/server/mutations/verifier.js.map +0 -1
  523. package/dist/server/mutations/verify.d.ts +0 -26
  524. package/dist/server/mutations/verify.d.ts.map +0 -1
  525. package/dist/server/mutations/verify.js.map +0 -1
  526. package/dist/server/oauth.d.ts +0 -1
  527. package/dist/server/oauth.js +0 -242
  528. package/dist/server/oauth.js.map +0 -1
  529. package/dist/server/passkey.d.ts +0 -27
  530. package/dist/server/passkey.d.ts.map +0 -1
  531. package/dist/server/passkey.js.map +0 -1
  532. package/dist/server/redirects.d.ts +0 -1
  533. package/dist/server/redirects.js.map +0 -1
  534. package/dist/server/refresh.d.ts +0 -1
  535. package/dist/server/refresh.js.map +0 -1
  536. package/dist/server/runtime.d.ts.map +0 -1
  537. package/dist/server/runtime.js.map +0 -1
  538. package/dist/server/sessions.d.ts +0 -1
  539. package/dist/server/sessions.js.map +0 -1
  540. package/dist/server/signin.d.ts +0 -1
  541. package/dist/server/signin.js.map +0 -1
  542. package/dist/server/ssr.d.ts.map +0 -1
  543. package/dist/server/ssr.js +0 -777
  544. package/dist/server/ssr.js.map +0 -1
  545. package/dist/server/templates.d.ts +0 -1
  546. package/dist/server/templates.js.map +0 -1
  547. package/dist/server/tokens.d.ts +0 -1
  548. package/dist/server/tokens.js.map +0 -1
  549. package/dist/server/totp.d.ts +0 -1
  550. package/dist/server/totp.js.map +0 -1
  551. package/dist/server/types.d.ts.map +0 -1
  552. package/dist/server/types.js.map +0 -1
  553. package/dist/server/users.d.ts +0 -1
  554. package/dist/server/users.js.map +0 -1
  555. package/dist/server/utils.d.ts +0 -1
  556. package/dist/server/utils.js +0 -140
  557. package/dist/server/utils.js.map +0 -1
  558. package/src/authorization/index.ts +0 -83
  559. package/src/cli/bin.ts +0 -5
  560. package/src/cli/command.ts +0 -70
  561. package/src/cli/index.ts +0 -1112
  562. package/src/cli/keys.ts +0 -23
  563. package/src/client/core/types.ts +0 -437
  564. package/src/client/factors/device.ts +0 -158
  565. package/src/client/factors/passkey.ts +0 -279
  566. package/src/client/factors/totp.ts +0 -150
  567. package/src/client/index.ts +0 -1124
  568. package/src/client/runtime/browser.ts +0 -112
  569. package/src/client/runtime/invite.ts +0 -63
  570. package/src/client/runtime/proxy.ts +0 -111
  571. package/src/client/runtime/storage.ts +0 -79
  572. package/src/component/_generated/api.ts +0 -96
  573. package/src/component/_generated/component.ts +0 -3774
  574. package/src/component/_generated/dataModel.ts +0 -60
  575. package/src/component/_generated/server.ts +0 -156
  576. package/src/component/convex.config.ts +0 -5
  577. package/src/component/functions.ts +0 -104
  578. package/src/component/index.ts +0 -42
  579. package/src/component/model.ts +0 -449
  580. package/src/component/public/enterprise/audit.ts +0 -125
  581. package/src/component/public/enterprise/core.ts +0 -355
  582. package/src/component/public/enterprise/domains.ts +0 -327
  583. package/src/component/public/enterprise/scim.ts +0 -397
  584. package/src/component/public/enterprise/secrets.ts +0 -133
  585. package/src/component/public/enterprise/webhooks.ts +0 -307
  586. package/src/component/public/factors/devices.ts +0 -224
  587. package/src/component/public/factors/passkeys.ts +0 -243
  588. package/src/component/public/factors/totp.ts +0 -259
  589. package/src/component/public/groups/core.ts +0 -481
  590. package/src/component/public/groups/invites.ts +0 -608
  591. package/src/component/public/groups/members.ts +0 -410
  592. package/src/component/public/identity/accounts.ts +0 -207
  593. package/src/component/public/identity/codes.ts +0 -149
  594. package/src/component/public/identity/sessions.ts +0 -210
  595. package/src/component/public/identity/tokens.ts +0 -251
  596. package/src/component/public/identity/users.ts +0 -355
  597. package/src/component/public/identity/verifiers.ts +0 -158
  598. package/src/component/public/security/keys.ts +0 -366
  599. package/src/component/public/security/limits.ts +0 -174
  600. package/src/component/public.ts +0 -27
  601. package/src/component/schema.ts +0 -505
  602. package/src/providers/anonymous.ts +0 -99
  603. package/src/providers/credentials.ts +0 -102
  604. package/src/providers/device.ts +0 -87
  605. package/src/providers/email.ts +0 -99
  606. package/src/providers/index.ts +0 -31
  607. package/src/providers/oauth.ts +0 -117
  608. package/src/providers/passkey.ts +0 -77
  609. package/src/providers/password.ts +0 -441
  610. package/src/providers/phone.ts +0 -93
  611. package/src/providers/sso.ts +0 -54
  612. package/src/providers/totp.ts +0 -62
  613. package/src/samlify.d.ts +0 -53
  614. package/src/server/auth.ts +0 -949
  615. package/src/server/config.ts +0 -200
  616. package/src/server/context.ts +0 -90
  617. package/src/server/cookies.ts +0 -49
  618. package/src/server/core.ts +0 -2004
  619. package/src/server/crypto.ts +0 -90
  620. package/src/server/db.ts +0 -203
  621. package/src/server/device.ts +0 -254
  622. package/src/server/enterprise/config.ts +0 -51
  623. package/src/server/enterprise/domain.ts +0 -1739
  624. package/src/server/enterprise/http.ts +0 -1331
  625. package/src/server/enterprise/oidc.ts +0 -500
  626. package/src/server/enterprise/policy.ts +0 -128
  627. package/src/server/enterprise/saml.ts +0 -578
  628. package/src/server/enterprise/scim.ts +0 -135
  629. package/src/server/enterprise/shared.ts +0 -134
  630. package/src/server/enterprise/validators.ts +0 -93
  631. package/src/server/http.ts +0 -790
  632. package/src/server/identity.ts +0 -18
  633. package/src/server/index.ts +0 -40
  634. package/src/server/keys.ts +0 -158
  635. package/src/server/limits.ts +0 -107
  636. package/src/server/mounts.ts +0 -924
  637. package/src/server/mutations/account.ts +0 -62
  638. package/src/server/mutations/code.ts +0 -119
  639. package/src/server/mutations/index.ts +0 -13
  640. package/src/server/mutations/invalidate.ts +0 -50
  641. package/src/server/mutations/oauth.ts +0 -243
  642. package/src/server/mutations/refresh.ts +0 -299
  643. package/src/server/mutations/register.ts +0 -155
  644. package/src/server/mutations/retrieve.ts +0 -109
  645. package/src/server/mutations/signature.ts +0 -57
  646. package/src/server/mutations/signin.ts +0 -54
  647. package/src/server/mutations/signout.ts +0 -43
  648. package/src/server/mutations/store/refs.ts +0 -10
  649. package/src/server/mutations/store.ts +0 -123
  650. package/src/server/mutations/verifier.ts +0 -34
  651. package/src/server/mutations/verify.ts +0 -200
  652. package/src/server/oauth.ts +0 -418
  653. package/src/server/passkey.ts +0 -838
  654. package/src/server/redirects.ts +0 -59
  655. package/src/server/refresh.ts +0 -218
  656. package/src/server/runtime.ts +0 -918
  657. package/src/server/sessions.ts +0 -132
  658. package/src/server/signin.ts +0 -445
  659. package/src/server/ssr.ts +0 -1747
  660. package/src/server/templates.ts +0 -82
  661. package/src/server/tokens.ts +0 -35
  662. package/src/server/totp.ts +0 -399
  663. package/src/server/types.ts +0 -1942
  664. package/src/server/users.ts +0 -291
  665. package/src/server/utils.ts +0 -220
  666. /package/dist/{runtime → client/runtime}/invite.js +0 -0
@@ -1,1124 +0,0 @@
1
- import { Fx } from "@robelest/fx";
2
- import { ConvexHttpClient } from "convex/browser";
3
- import { ConvexError, Value } from "convex/values";
4
-
5
- import type {
6
- AuthApiRefs,
7
- AuthClient,
8
- AuthFlowContext,
9
- AuthHandshakeErrorCode,
10
- AuthSession,
11
- AuthState,
12
- ClientOptions,
13
- ConvexTransport,
14
- DeviceClient,
15
- DeviceCodeResult,
16
- HandshakeWaiter,
17
- PasskeyClient,
18
- PendingInvite,
19
- SignInActionResult,
20
- SignInResult,
21
- Storage,
22
- TotpClient,
23
- } from "./core/types";
24
- import { createDeviceClient } from "./factors/device";
25
- import { createPasskeyClient } from "./factors/passkey";
26
- import { createTotpClient } from "./factors/totp";
27
- import { browserMutex, getStorageListenerRegistry } from "./runtime/browser";
28
- import { createInviteManager } from "./runtime/invite";
29
- import {
30
- createProxyHelpers,
31
- isRetriableProxyRefreshError,
32
- isTransientNetworkError,
33
- } from "./runtime/proxy";
34
- import { createStorageHelpers } from "./runtime/storage";
35
-
36
- export type {
37
- AuthApiRefs,
38
- AuthClient,
39
- AuthState,
40
- ClientOptions,
41
- DeviceClient,
42
- DeviceCodeResult,
43
- PasskeyClient,
44
- PendingInvite,
45
- SignInResult,
46
- Storage,
47
- TotpClient,
48
- } from "./core/types";
49
-
50
- const VERIFIER_STORAGE_KEY = "__convexAuthOAuthVerifier";
51
- const JWT_STORAGE_KEY = "__convexAuthJWT";
52
- const REFRESH_TOKEN_STORAGE_KEY = "__convexAuthRefreshToken";
53
- const INVITE_TOKEN_KEY = "__convexAuthPendingInvite";
54
- const INVITE_EMAIL_KEY = "__convexAuthPendingInviteEmail";
55
-
56
- const RETRY_BASE_MS = 500;
57
- const RETRY_MAX_RETRIES = 2;
58
- const AUTH_HANDSHAKE_TIMEOUT_MS = 5000;
59
-
60
- /**
61
- * Resolve the Convex deployment URL from the client.
62
- *
63
- * `ConvexReactClient` exposes `.url` directly.
64
- * `ConvexClient` exposes `.client.url` via `BaseConvexClient`.
65
- */
66
- function resolveUrl(convex: ConvexTransport, explicit?: string): string {
67
- if (explicit) return explicit;
68
- const c = convex as any;
69
- const url: unknown = c.url ?? c.client?.url;
70
- if (typeof url === "string") return url;
71
- throw new Error(
72
- "Could not determine Convex deployment URL. Pass `url` explicitly.",
73
- );
74
- }
75
-
76
- /**
77
- * Create a framework-agnostic auth client.
78
- *
79
- * Returns an object with `signIn`, `signOut`, `onChange`, `state`,
80
- * `passkey`, and `totp` — everything needed for client-side auth.
81
- *
82
- * ### SPA mode (default)
83
- *
84
- * ```ts
85
- * import { ConvexClient } from 'convex/browser';
86
- * import { client } from '@robelest/convex-auth/client';
87
- * import { api } from '../convex/_generated/api';
88
- *
89
- * const convex = new ConvexClient(CONVEX_URL);
90
- * const auth = client({ convex, api: api.auth });
91
- * ```
92
- *
93
- * ### SSR / proxy mode
94
- *
95
- * ```ts
96
- * const auth = client({
97
- * convex,
98
- * proxyPath: '/api/auth',
99
- * tokenSeed: tokenFromServer, // JWT read from httpOnly cookie during SSR
100
- * });
101
- * ```
102
- *
103
- * In proxy mode all auth operations go through the proxy URL.
104
- * Tokens are stored in httpOnly cookies server-side — the client
105
- * holds the JWT in memory only.
106
- *
107
- * @param options - Client configuration. See {@link ClientOptions}.
108
- * @typeParam Api - An AuthApiRefs type determining which factor helpers are available.
109
- * @returns Auth client with conditional `passkey`, `totp`, and `device` helpers.
110
- * @throws {Error} When the Convex deployment URL cannot be determined and `url` is not passed explicitly.
111
- * @throws {Error} When `proxyPath` is not set and the `api` option is missing.
112
- */
113
- export function client<
114
- Api extends AuthApiRefs<boolean, boolean, boolean> = AuthApiRefs,
115
- >(options: ClientOptions<Api>): AuthClient<Api> {
116
- const { convex, proxyPath, api: apiRefs } = options;
117
- const proxy = proxyPath;
118
-
119
- function requireApiRefs() {
120
- if (!apiRefs) {
121
- throw new Error(
122
- "The `api` option is required when `proxyPath` is not set. " +
123
- "Pass { api: api.auth }.",
124
- );
125
- }
126
- return apiRefs;
127
- }
128
-
129
- // In proxy mode, default storage to null (cookies handle persistence).
130
- const storage =
131
- options.storage !== undefined
132
- ? options.storage
133
- : proxy
134
- ? null
135
- : typeof window === "undefined"
136
- ? null
137
- : window.localStorage;
138
-
139
- const replaceUrl =
140
- options.replaceUrl ??
141
- ((url: string) => {
142
- if (typeof window !== "undefined") {
143
- window.history.replaceState({}, "", url);
144
- }
145
- });
146
-
147
- // ---------------------------------------------------------------------------
148
- // Location — SSR-safe URL reading
149
- // ---------------------------------------------------------------------------
150
-
151
- function getLocation(): URL | null {
152
- if (typeof options.location === "function") return options.location();
153
- if (options.location instanceof URL) return options.location;
154
- if (typeof window !== "undefined") return new URL(window.location.href);
155
- return null;
156
- }
157
-
158
- /**
159
- * SSR-safe URL parameter reader.
160
- *
161
- * Uses the `location` option if provided, otherwise falls back to
162
- * `window.location` (returns `null` during SSR where `window` is unavailable).
163
- *
164
- * @param name - The query parameter name.
165
- * @returns The parameter value, or `null` if not present or in SSR.
166
- *
167
- * @example
168
- * ```ts
169
- * const workspaceId = auth.param("workspace");
170
- * const tab = auth.param("tab") ?? "issues";
171
- * ```
172
- */
173
- function param(name: string): string | null {
174
- const loc = getLocation();
175
- return loc?.searchParams.get(name) ?? null;
176
- }
177
-
178
- function cleanUrlParams(params: string[]) {
179
- const loc = getLocation();
180
- if (!loc) return;
181
- const searchParams = new URLSearchParams(loc.search);
182
- let changed = false;
183
- for (const p of params) {
184
- if (searchParams.has(p)) {
185
- searchParams.delete(p);
186
- changed = true;
187
- }
188
- }
189
- if (changed) {
190
- const next = searchParams.toString()
191
- ? `${loc.pathname}?${searchParams}`
192
- : loc.pathname;
193
- void replaceUrl(next);
194
- }
195
- }
196
-
197
- const url = proxy ? undefined : resolveUrl(convex, options.url);
198
- const escapedNamespace = proxy
199
- ? proxy.replace(/[^a-zA-Z0-9]/g, "")
200
- : url!.replace(/[^a-zA-Z0-9]/g, "");
201
- const key = (name: string) => `${name}_${escapedNamespace}`;
202
- const {
203
- get: storageGet,
204
- set: storageSet,
205
- remove: storageRemove,
206
- } = createStorageHelpers({ storage, key });
207
- const { isAbsoluteUrl, proxyFetch, resolveProxyUrl } = createProxyHelpers({
208
- proxy,
209
- });
210
- const subscribers = new Set<() => void>();
211
- let disposeStorageListener: (() => void) | null = null;
212
-
213
- // Unauthenticated HTTP client for code verification & OAuth exchange.
214
- // Only needed in SPA mode — proxy mode routes everything through the proxy.
215
- const httpClient = proxy ? null : new ConvexHttpClient(url!);
216
-
217
- // ---------------------------------------------------------------------------
218
- // State
219
- // ---------------------------------------------------------------------------
220
-
221
- // If a server-provided token was supplied (SSR hydration), treat it as
222
- // immediately authenticated to avoid a handshake-only loading screen.
223
- const serverToken =
224
- typeof options.tokenSeed === "string" && options.tokenSeed.trim().length > 0
225
- ? options.tokenSeed
226
- : null;
227
- const hasServerToken = serverToken !== null;
228
-
229
- let token: string | null = serverToken;
230
- let isLoading = !hasServerToken;
231
- let authConfirmed = hasServerToken;
232
- let handshakePending = false;
233
- let authEpoch = 0;
234
- let destroyed = false;
235
- const handshakeWaiters = new Set<HandshakeWaiter>();
236
- let snapshot: AuthState = {
237
- phase: hasServerToken
238
- ? "authenticated"
239
- : isLoading
240
- ? "loading"
241
- : "unauthenticated",
242
- isLoading,
243
- isAuthenticated: hasServerToken,
244
- token,
245
- };
246
- let handlingCodeFlow = false;
247
-
248
- const HANDSHAKE_ERROR_MESSAGES: Record<AuthHandshakeErrorCode, string> = {
249
- AUTH_HANDSHAKE_TIMEOUT:
250
- "Sign-in succeeded but authentication confirmation timed out.",
251
- AUTH_HANDSHAKE_REJECTED:
252
- "Authentication was rejected while confirming the session.",
253
- };
254
-
255
- const createHandshakeError = (
256
- code: AuthHandshakeErrorCode,
257
- context: Record<string, unknown>,
258
- ) => {
259
- return new ConvexError({
260
- code,
261
- message: HANDSHAKE_ERROR_MESSAGES[code],
262
- ...context,
263
- } as Value);
264
- };
265
-
266
- const settleHandshakeWaiters = (
267
- epoch: number,
268
- outcome:
269
- | { type: "resolve" }
270
- | { type: "reject"; error: ConvexError<Value> },
271
- ) => {
272
- for (const waiter of Array.from(handshakeWaiters)) {
273
- if (waiter.epoch !== epoch) {
274
- continue;
275
- }
276
- clearTimeout(waiter.timeoutId);
277
- handshakeWaiters.delete(waiter);
278
- if (outcome.type === "resolve") {
279
- waiter.resolve();
280
- } else {
281
- waiter.reject(outcome.error);
282
- }
283
- }
284
- };
285
-
286
- const rejectObsoleteHandshakeWaiters = (activeEpoch: number) => {
287
- for (const waiter of Array.from(handshakeWaiters)) {
288
- if (waiter.epoch >= activeEpoch) {
289
- continue;
290
- }
291
- clearTimeout(waiter.timeoutId);
292
- handshakeWaiters.delete(waiter);
293
- waiter.reject(
294
- createHandshakeError("AUTH_HANDSHAKE_REJECTED", {
295
- ...waiter.context,
296
- reason: "token_changed",
297
- }),
298
- );
299
- }
300
- };
301
-
302
- const waitForAuthHandshake = async (context: AuthFlowContext) => {
303
- if (token === null) {
304
- return;
305
- }
306
- if (authConfirmed && !handshakePending) {
307
- return;
308
- }
309
- if (!handshakePending) {
310
- throw createHandshakeError("AUTH_HANDSHAKE_REJECTED", {
311
- ...context,
312
- reason: "auth_rejected",
313
- });
314
- }
315
-
316
- const epoch = authEpoch;
317
- await new Promise<void>((resolve, reject) => {
318
- const waiterRef: { current: HandshakeWaiter | null } = { current: null };
319
- const timeoutId = setTimeout(() => {
320
- if (waiterRef.current !== null) {
321
- handshakeWaiters.delete(waiterRef.current);
322
- }
323
- reject(
324
- createHandshakeError("AUTH_HANDSHAKE_TIMEOUT", {
325
- ...context,
326
- timeoutMs: AUTH_HANDSHAKE_TIMEOUT_MS,
327
- }),
328
- );
329
- }, AUTH_HANDSHAKE_TIMEOUT_MS);
330
-
331
- const waiter: HandshakeWaiter = {
332
- epoch,
333
- context,
334
- resolve,
335
- reject,
336
- timeoutId,
337
- };
338
- waiterRef.current = waiter;
339
- handshakeWaiters.add(waiter);
340
- });
341
- };
342
-
343
- const handleConvexAuthChange = (isAuthenticated: boolean) => {
344
- if (destroyed) {
345
- return;
346
- }
347
-
348
- if (isAuthenticated) {
349
- authConfirmed = true;
350
- handshakePending = false;
351
- settleHandshakeWaiters(authEpoch, { type: "resolve" });
352
- } else {
353
- authConfirmed = false;
354
- // Do not reject immediately while a handshake is pending.
355
- // Convex can transiently emit `false` while reauth is still in flight,
356
- // and a subsequent `true` confirms the same session.
357
- }
358
-
359
- if (updateSnapshot()) {
360
- notify();
361
- }
362
- };
363
-
364
- const notify = () => {
365
- for (const cb of subscribers) cb();
366
- };
367
-
368
- const updateSnapshot = () => {
369
- const phaseDispatch = {
370
- tag:
371
- token !== null && handshakePending
372
- ? "handshake"
373
- : isLoading
374
- ? "loading"
375
- : token !== null && authConfirmed
376
- ? "authenticated"
377
- : "unauthenticated",
378
- } as const;
379
-
380
- const phase = {
381
- handshake: "handshake",
382
- loading: "loading",
383
- authenticated: "authenticated",
384
- unauthenticated: "unauthenticated",
385
- }[phaseDispatch.tag] as AuthState["phase"];
386
-
387
- const next: AuthState = {
388
- phase,
389
- isLoading: phase === "loading" || phase === "handshake",
390
- isAuthenticated: phase === "authenticated",
391
- token,
392
- };
393
- if (
394
- snapshot.phase === next.phase &&
395
- snapshot.isLoading === next.isLoading &&
396
- snapshot.isAuthenticated === next.isAuthenticated &&
397
- snapshot.token === next.token
398
- ) {
399
- return false;
400
- }
401
- snapshot = next;
402
- return true;
403
- };
404
-
405
- const finalizeLoadingState = () => {
406
- if (!isLoading) {
407
- return;
408
- }
409
- isLoading = false;
410
- if (updateSnapshot()) {
411
- notify();
412
- }
413
- };
414
-
415
- const inviteManager = createInviteManager({
416
- param,
417
- storageGet,
418
- storageSet,
419
- storageRemove,
420
- cleanUrlParams,
421
- tokenKey: INVITE_TOKEN_KEY,
422
- emailKey: INVITE_EMAIL_KEY,
423
- });
424
- const getPendingInvite = () => inviteManager.getPendingInvite();
425
- const persistInvite = () => inviteManager.persistInvite();
426
- const acceptInvite = () => inviteManager.acceptInvite();
427
-
428
- // ---------------------------------------------------------------------------
429
- // Token management
430
- // ---------------------------------------------------------------------------
431
-
432
- const bindConvexAuth = () => {
433
- convex.setAuth(fetchAccessToken, handleConvexAuthChange);
434
- };
435
-
436
- const setToken = async (
437
- args:
438
- | {
439
- shouldStore: true;
440
- tokens: AuthSession | null;
441
- requireHandshake?: boolean;
442
- resyncConvexAuth?: boolean;
443
- }
444
- | {
445
- shouldStore: false;
446
- tokens: { token: string } | null;
447
- requireHandshake?: boolean;
448
- resyncConvexAuth?: boolean;
449
- },
450
- ) => {
451
- const previousToken = token;
452
-
453
- if (args.tokens === null) {
454
- token = null;
455
- if (args.shouldStore) {
456
- await storageRemove(JWT_STORAGE_KEY);
457
- await storageRemove(REFRESH_TOKEN_STORAGE_KEY);
458
- }
459
- } else {
460
- token = args.tokens.token;
461
- if (args.shouldStore && "refreshToken" in args.tokens) {
462
- await storageSet(JWT_STORAGE_KEY, args.tokens.token);
463
- await storageSet(REFRESH_TOKEN_STORAGE_KEY, args.tokens.refreshToken);
464
- }
465
- }
466
-
467
- if (token !== previousToken) {
468
- authEpoch += 1;
469
- rejectObsoleteHandshakeWaiters(authEpoch);
470
- }
471
-
472
- if (token === null) {
473
- authConfirmed = false;
474
- handshakePending = false;
475
- settleHandshakeWaiters(authEpoch, {
476
- type: "reject",
477
- error: createHandshakeError("AUTH_HANDSHAKE_REJECTED", {
478
- reason: "token_cleared",
479
- }),
480
- });
481
- } else {
482
- const shouldEnterHandshake =
483
- args.requireHandshake === true || !authConfirmed;
484
- if (shouldEnterHandshake) {
485
- authConfirmed = false;
486
- handshakePending = true;
487
- } else {
488
- handshakePending = false;
489
- }
490
- }
491
-
492
- const hadPendingLoad = isLoading;
493
- isLoading = false;
494
- const changed = updateSnapshot();
495
- if (args.resyncConvexAuth !== false) {
496
- bindConvexAuth();
497
- }
498
- if (hadPendingLoad || changed) {
499
- notify();
500
- }
501
- };
502
-
503
- const setTokenAndMaybeWait = async (
504
- args:
505
- | {
506
- shouldStore: true;
507
- tokens: AuthSession | null;
508
- waitForHandshake: boolean;
509
- context: AuthFlowContext;
510
- }
511
- | {
512
- shouldStore: false;
513
- tokens: { token: string } | null;
514
- waitForHandshake: boolean;
515
- context: AuthFlowContext;
516
- },
517
- ): Promise<boolean> => {
518
- const { waitForHandshake, context, ...tokenArgs } = args;
519
- await setToken({
520
- ...(tokenArgs as
521
- | { shouldStore: true; tokens: AuthSession | null }
522
- | { shouldStore: false; tokens: { token: string } | null }),
523
- requireHandshake: waitForHandshake,
524
- });
525
- if (tokenArgs.tokens === null) {
526
- return false;
527
- }
528
- if (waitForHandshake) {
529
- await waitForAuthHandshake(context);
530
- }
531
- return true;
532
- };
533
-
534
- // ---------------------------------------------------------------------------
535
- // Code verification with retries (SPA mode only)
536
- // ---------------------------------------------------------------------------
537
-
538
- const verifyCode = async (
539
- args: { code: string; verifier?: string } | { refreshToken: string },
540
- ) => {
541
- const verifyCodeRetryPolicy = Fx.retry.while(
542
- Fx.retry.compose(
543
- Fx.retry.jittered(Fx.retry.exponential(RETRY_BASE_MS)),
544
- Fx.retry.recurs(RETRY_MAX_RETRIES),
545
- ),
546
- (meta) => isTransientNetworkError(meta.input),
547
- );
548
-
549
- return Fx.run(
550
- Fx.from({
551
- ok: () =>
552
- httpClient!.action(
553
- requireApiRefs().signIn,
554
- "code" in args
555
- ? { params: { code: args.code }, verifier: args.verifier }
556
- : args,
557
- ),
558
- err: (e) => e,
559
- }).pipe(
560
- Fx.retry(verifyCodeRetryPolicy),
561
- Fx.recover((e) => Fx.fatal(e)),
562
- ),
563
- );
564
- };
565
-
566
- const verifyCodeAndSetToken = async (
567
- args: { code: string; verifier?: string } | { refreshToken: string },
568
- opts?: { resyncConvexAuth?: boolean },
569
- ) => {
570
- const { tokens } = await verifyCode(args);
571
- await setToken({
572
- shouldStore: true,
573
- tokens: (tokens as AuthSession | null) ?? null,
574
- resyncConvexAuth: opts?.resyncConvexAuth,
575
- });
576
- return tokens !== null;
577
- };
578
-
579
- const normalizeDeviceCodeResult = (device_code: any): DeviceCodeResult => {
580
- return {
581
- deviceCode: device_code.deviceCode,
582
- userCode: device_code.userCode,
583
- verificationUri:
584
- device_code.verification_uri ?? device_code.verificationUri,
585
- verificationUriComplete:
586
- device_code.verification_uri_complete ??
587
- device_code.verificationUriComplete,
588
- expiresIn: device_code.expiresIn,
589
- interval: device_code.interval,
590
- };
591
- };
592
-
593
- // ---------------------------------------------------------------------------
594
- // signIn
595
- // ---------------------------------------------------------------------------
596
-
597
- /**
598
- * Sign in with a provider.
599
- *
600
- * @param provider - Provider ID (e.g. `"email"`, `"password"`, `"google"`).
601
- * Omit when exchanging an OAuth code (the code carries the provider info).
602
- * @param args - Provider-specific arguments. Pass a `Record<string, Value>`
603
- * or `FormData`. Common fields: `email`, `password`, `code`, `redirectTo`.
604
- * @returns A {@link SignInResult} indicating the outcome.
605
- * @throws {ConvexError} When the server action rejects the sign-in attempt (e.g. invalid credentials, provider error, or rate limiting).
606
- *
607
- * @example Email magic link
608
- * ```ts
609
- * await auth.signIn('email', { email: 'user@example.com' });
610
- * ```
611
- *
612
- * @example Password
613
- * ```ts
614
- * const result = await auth.signIn('password', { email, password, flow: 'signIn' });
615
- * if (result.kind === 'totpRequired') {
616
- * await auth.totp.verify({ code: totpCode, verifier: result.verifier });
617
- * }
618
- * ```
619
- *
620
- * @example OAuth (triggers redirect)
621
- * ```ts
622
- * await auth.signIn('google'); // redirects to Google
623
- * ```
624
- */
625
- const signIn = async (
626
- provider?: string,
627
- args?: FormData | Record<string, Value>,
628
- ): Promise<SignInResult> => {
629
- // Persist invite before potential OAuth redirect
630
- await persistInvite();
631
-
632
- const params =
633
- args instanceof FormData
634
- ? (() => {
635
- const formParams: Record<string, Value> = {};
636
- args.forEach((value, key) => {
637
- formParams[key] = typeof value === "string" ? value : value.name;
638
- });
639
- return formParams;
640
- })()
641
- : (args ?? {});
642
- const flow =
643
- typeof params.flow === "string" && params.flow.length > 0
644
- ? params.flow
645
- : "signIn";
646
-
647
- const handleSignInActionResult = async (
648
- result: SignInActionResult,
649
- options: { shouldStore: boolean; persistVerifier: boolean },
650
- ): Promise<SignInResult> =>
651
- Fx.run(
652
- Fx.match(result, result.kind, {
653
- redirect: (redirectResult) =>
654
- Fx.promise(async () => {
655
- const redirectUrl = new URL(redirectResult.redirect);
656
- if (options.persistVerifier) {
657
- await storageSet(VERIFIER_STORAGE_KEY, redirectResult.verifier);
658
- }
659
- if (typeof window !== "undefined") {
660
- window.location.href = redirectUrl.toString();
661
- }
662
- return {
663
- kind: "redirect" as const,
664
- redirect: redirectUrl,
665
- verifier: redirectResult.verifier,
666
- };
667
- }),
668
- totpRequired: (totpRequiredResult) =>
669
- Fx.succeed({
670
- kind: "totpRequired" as const,
671
- verifier: totpRequiredResult.verifier,
672
- }),
673
- deviceCode: (deviceCodeResult) =>
674
- Fx.succeed({
675
- kind: "deviceCode" as const,
676
- deviceCode: normalizeDeviceCodeResult(
677
- deviceCodeResult.deviceCode,
678
- ),
679
- }),
680
- signedIn: (signedInResult) =>
681
- Fx.promise(async () => {
682
- const signingIn = await setTokenAndMaybeWait(
683
- options.shouldStore
684
- ? {
685
- shouldStore: true as const,
686
- tokens: signedInResult.tokens,
687
- waitForHandshake: true,
688
- context: { provider, flow },
689
- }
690
- : {
691
- shouldStore: false as const,
692
- tokens:
693
- signedInResult.tokens === null
694
- ? null
695
- : { token: signedInResult.tokens.token },
696
- waitForHandshake: true,
697
- context: { provider, flow },
698
- },
699
- );
700
- return signingIn
701
- ? ({ kind: "signedIn" as const } as SignInResult)
702
- : ({ kind: "started" as const } as SignInResult);
703
- }),
704
- started: (_startedResult) => Fx.succeed({ kind: "started" as const }),
705
- passkeyOptions: (_passkeyOptionsResult) =>
706
- Fx.succeed({ kind: "started" as const }),
707
- totpSetup: (_totpSetupResult) =>
708
- Fx.succeed({ kind: "started" as const }),
709
- }),
710
- );
711
-
712
- if (proxy) {
713
- const result = (await proxyFetch({
714
- action: "auth:signIn",
715
- args: { provider, params },
716
- })) as SignInActionResult;
717
- return handleSignInActionResult(result, {
718
- shouldStore: false,
719
- persistVerifier: false,
720
- });
721
- }
722
-
723
- // SPA mode: call Convex directly.
724
- const verifier = (await storageGet(VERIFIER_STORAGE_KEY)) ?? undefined;
725
- await storageRemove(VERIFIER_STORAGE_KEY);
726
- const result = (await convex.action(requireApiRefs().signIn, {
727
- provider,
728
- params,
729
- verifier,
730
- })) as SignInActionResult;
731
- return handleSignInActionResult(result, {
732
- shouldStore: true,
733
- persistVerifier: true,
734
- });
735
- };
736
-
737
- // ---------------------------------------------------------------------------
738
- // signOut
739
- // ---------------------------------------------------------------------------
740
-
741
- /**
742
- * Sign out the current user.
743
- *
744
- * Invalidates the server session and clears local token state.
745
- * Errors are silently caught — calling `signOut` on an already
746
- * signed-out user is a no-op.
747
- */
748
- const signOut = async () => {
749
- if (proxy) {
750
- await Fx.run(
751
- Fx.from({
752
- ok: () => proxyFetch({ action: "auth:signOut", args: {} }),
753
- err: () => undefined,
754
- }).pipe(Fx.recover(() => Fx.succeed(undefined))),
755
- );
756
- await setToken({ shouldStore: false, tokens: null });
757
- if (convex.clearAuth) convex.clearAuth();
758
- return;
759
- }
760
-
761
- // SPA mode.
762
- await Fx.run(
763
- Fx.from({
764
- ok: () => convex.action(requireApiRefs().signOut, {}),
765
- err: () => undefined,
766
- }).pipe(Fx.recover(() => Fx.succeed(undefined))),
767
- );
768
- await setToken({ shouldStore: true, tokens: null });
769
- if (convex.clearAuth) convex.clearAuth();
770
- };
771
-
772
- // ---------------------------------------------------------------------------
773
- // fetchAccessToken — called by convex.setAuth()
774
- // ---------------------------------------------------------------------------
775
-
776
- const fetchAccessToken = async ({
777
- forceRefreshToken,
778
- }: {
779
- forceRefreshToken: boolean;
780
- }): Promise<string | null> => {
781
- if (!forceRefreshToken) return token;
782
-
783
- if (proxy) {
784
- // Proxy mode: POST to the proxy to refresh.
785
- // The proxy reads the real refresh token from the httpOnly cookie.
786
- const resolvedProxyUrl = await resolveProxyUrl();
787
- if (
788
- typeof window === "undefined" &&
789
- !(await isAbsoluteUrl(resolvedProxyUrl))
790
- ) {
791
- finalizeLoadingState();
792
- return token;
793
- }
794
-
795
- const tokenBeforeRefresh = token;
796
- return await browserMutex("__convexAuthProxyRefresh", async () => {
797
- // Another tab/call may have already refreshed.
798
- if (token !== tokenBeforeRefresh) return token;
799
-
800
- const proxyRefreshRetryPolicy = Fx.retry.while(
801
- Fx.retry.compose(
802
- Fx.retry.jittered(Fx.retry.exponential(RETRY_BASE_MS)),
803
- Fx.retry.recurs(RETRY_MAX_RETRIES),
804
- ),
805
- (meta) => isRetriableProxyRefreshError(meta.input),
806
- );
807
-
808
- await Fx.run(
809
- Fx.from({
810
- ok: () =>
811
- proxyFetch({
812
- action: "auth:signIn",
813
- args: { refreshToken: true },
814
- }),
815
- err: (e) => e,
816
- }).pipe(
817
- Fx.retry(proxyRefreshRetryPolicy),
818
- Fx.chain((result: any) =>
819
- Fx.from({
820
- ok: async () => {
821
- if (result.tokens) {
822
- await setToken({
823
- shouldStore: false,
824
- tokens: { token: result.tokens.token },
825
- resyncConvexAuth: false,
826
- });
827
- } else {
828
- await setToken({
829
- shouldStore: false,
830
- tokens: null,
831
- resyncConvexAuth: false,
832
- });
833
- }
834
- },
835
- err: (e) => e,
836
- }),
837
- ),
838
- Fx.inspect((error) =>
839
- Fx.sync(() =>
840
- console.error("[convex-auth] Proxy refresh failed:", error),
841
- ),
842
- ),
843
- Fx.recover(() => {
844
- if (token === null) {
845
- finalizeLoadingState();
846
- }
847
- return Fx.succeed(undefined);
848
- }),
849
- ),
850
- );
851
- return token;
852
- });
853
- }
854
-
855
- // SPA mode: refresh via localStorage + httpClient.
856
- const tokenBeforeLockAcquisition = token;
857
- return await browserMutex(REFRESH_TOKEN_STORAGE_KEY, async () => {
858
- const tokenAfterLockAcquisition = token;
859
- if (tokenAfterLockAcquisition !== tokenBeforeLockAcquisition) {
860
- return tokenAfterLockAcquisition;
861
- }
862
- const refreshToken =
863
- (await storageGet(REFRESH_TOKEN_STORAGE_KEY)) ?? null;
864
- if (!refreshToken) {
865
- finalizeLoadingState();
866
- return null;
867
- }
868
- await verifyCodeAndSetToken(
869
- { refreshToken },
870
- { resyncConvexAuth: false },
871
- );
872
- return token;
873
- });
874
- };
875
-
876
- // ---------------------------------------------------------------------------
877
- // OAuth code flow (SPA mode only — server handles this in proxy mode)
878
- // ---------------------------------------------------------------------------
879
-
880
- const handleCodeFlow = async () => {
881
- if (typeof window === "undefined") return;
882
- if (handlingCodeFlow) return;
883
- const code = new URLSearchParams(window.location.search).get("code");
884
- if (!code) return;
885
- handlingCodeFlow = true;
886
- await Fx.run(
887
- Fx.from({
888
- ok: async () => {
889
- await signIn(undefined, { code });
890
- const codeUrl = new URL(window.location.href);
891
- codeUrl.searchParams.delete("code");
892
- await replaceUrl(codeUrl.pathname + codeUrl.search + codeUrl.hash);
893
- },
894
- err: (e) => e,
895
- }).pipe(
896
- Fx.recover(() => Fx.succeed(undefined)),
897
- Fx.tap(() =>
898
- Fx.sync(() => {
899
- handlingCodeFlow = false;
900
- }),
901
- ),
902
- Fx.inspect(() =>
903
- Fx.sync(() => {
904
- handlingCodeFlow = false;
905
- }),
906
- ),
907
- ),
908
- );
909
- // The flag is always reset — Fx.recover above ensures success path,
910
- // but reset defensively here too.
911
- handlingCodeFlow = false;
912
- };
913
-
914
- // ---------------------------------------------------------------------------
915
- // Hydrate from storage (SPA mode only)
916
- // ---------------------------------------------------------------------------
917
-
918
- const hydrateFromStorage = async () => {
919
- const storedToken = (await storageGet(JWT_STORAGE_KEY)) ?? null;
920
- await setToken({
921
- shouldStore: false,
922
- tokens: storedToken === null ? null : { token: storedToken },
923
- });
924
- };
925
-
926
- // ---------------------------------------------------------------------------
927
- // Subscribe
928
- // ---------------------------------------------------------------------------
929
-
930
- /**
931
- * Subscribe to auth state changes. Invokes the callback immediately
932
- * with the current state, then again on every state transition.
933
- *
934
- * ```ts
935
- * const unsub = auth.onChange(setState);
936
- * ```
937
- *
938
- * @param cb - Callback receiving the latest {@link AuthState}.
939
- * @returns An unsubscribe function.
940
- */
941
- const onChange = (cb: (state: AuthState) => void): (() => void) => {
942
- cb(snapshot);
943
- const wrapped = () => cb(snapshot);
944
- subscribers.add(wrapped);
945
- return () => {
946
- subscribers.delete(wrapped);
947
- };
948
- };
949
-
950
- // ---------------------------------------------------------------------------
951
- // Initialization
952
- // ---------------------------------------------------------------------------
953
-
954
- // Cross-tab sync via storage events (SPA mode only).
955
- if (!proxy && typeof window !== "undefined") {
956
- const registryKey = key(JWT_STORAGE_KEY);
957
- const registry = getStorageListenerRegistry();
958
- const existingListener = registry[registryKey];
959
- if (existingListener !== undefined) {
960
- window.removeEventListener("storage", existingListener);
961
- }
962
-
963
- const onStorage = (event: StorageEvent) => {
964
- Fx.detach(async () => {
965
- if (event.key !== key(JWT_STORAGE_KEY)) return;
966
- await setToken({
967
- shouldStore: false,
968
- tokens: event.newValue === null ? null : { token: event.newValue },
969
- });
970
- }, "[convex-auth] Storage event handler failed:");
971
- };
972
- window.addEventListener("storage", onStorage);
973
- registry[registryKey] = onStorage;
974
- disposeStorageListener = () => {
975
- if (registry[registryKey] === onStorage) {
976
- delete registry[registryKey];
977
- }
978
- window.removeEventListener("storage", onStorage);
979
- };
980
- }
981
-
982
- // Auto-wire: feed our tokens into the Convex client so
983
- // queries and mutations are automatically authenticated.
984
- bindConvexAuth();
985
-
986
- // Auto-hydrate and handle code flow.
987
- if (typeof window !== "undefined") {
988
- if (proxy) {
989
- // Proxy mode: eagerly resolve auth once on startup so routes that only
990
- // read auth state (and do not issue Convex queries yet) don't stay in
991
- // the initial loading phase.
992
- if (!hasServerToken) {
993
- Fx.detach(
994
- () => fetchAccessToken({ forceRefreshToken: true }),
995
- "[convex-auth] Proxy token refresh failed:",
996
- );
997
- }
998
- } else {
999
- // SPA mode: hydrate from localStorage, then handle OAuth code flow.
1000
- Fx.detach(async () => {
1001
- await Fx.run(
1002
- Fx.from({
1003
- ok: async () => {
1004
- await hydrateFromStorage();
1005
- await handleCodeFlow();
1006
- },
1007
- err: (e) => e,
1008
- }).pipe(
1009
- Fx.inspect((error) =>
1010
- Fx.sync(() =>
1011
- console.error(
1012
- "[convex-auth] Client initialization failed:",
1013
- error,
1014
- ),
1015
- ),
1016
- ),
1017
- Fx.recover((_error) =>
1018
- Fx.from({
1019
- ok: () => setToken({ shouldStore: false, tokens: null }),
1020
- err: (e) => e,
1021
- }).pipe(Fx.recover(() => Fx.succeed(undefined))),
1022
- ),
1023
- ),
1024
- );
1025
- }, "[convex-auth] SPA initialization failed:");
1026
- }
1027
- }
1028
-
1029
- // ---------------------------------------------------------------------------
1030
- // Auth factor helpers
1031
- // ---------------------------------------------------------------------------
1032
-
1033
- const passkey = createPasskeyClient({
1034
- proxy,
1035
- convex,
1036
- requireApiRefs,
1037
- proxyFetch,
1038
- setTokenAndMaybeWait,
1039
- });
1040
-
1041
- const totp = createTotpClient({
1042
- proxy,
1043
- convex,
1044
- requireApiRefs,
1045
- proxyFetch,
1046
- setTokenAndMaybeWait,
1047
- });
1048
-
1049
- const device = createDeviceClient({
1050
- proxy,
1051
- convex,
1052
- requireApiRefs,
1053
- proxyFetch,
1054
- setTokenAndMaybeWait,
1055
- });
1056
-
1057
- return {
1058
- /** Current auth state snapshot. */
1059
- get state(): AuthState {
1060
- return snapshot;
1061
- },
1062
- /** SSR-safe URL param reader. */
1063
- param,
1064
- /** Pending invite from URL or recovered from storage. Null if none. */
1065
- get invite(): PendingInvite | null {
1066
- const pendingInvite = getPendingInvite();
1067
- if (!pendingInvite) return null;
1068
- return {
1069
- token: pendingInvite.token,
1070
- email: pendingInvite.email,
1071
- accept: acceptInvite,
1072
- };
1073
- },
1074
- /** Sign in with a provider. See {@link SignInResult} for return shape. */
1075
- signIn,
1076
- /** Sign out and clear all token state. */
1077
- signOut,
1078
- /** Subscribe to auth state changes. Returns an unsubscribe function. */
1079
- onChange,
1080
- /** Passkey (WebAuthn) authentication helpers. */
1081
- passkey,
1082
- /** TOTP two-factor authentication helpers. */
1083
- totp,
1084
- /** Device authorization (RFC 8628) helpers. */
1085
- device,
1086
- /**
1087
- * Tear down this auth client instance.
1088
- *
1089
- * Removes the cross-tab `storage` event listener, clears all
1090
- * `onChange` subscribers, and rejects any in-flight handshake
1091
- * waiters. Call this when the client is no longer needed
1092
- * (e.g. on SPA unmount or hot-module replacement) to prevent
1093
- * memory leaks and stale callbacks.
1094
- *
1095
- * @example
1096
- * ```ts
1097
- * // SvelteKit onDestroy
1098
- * import { onDestroy } from "svelte";
1099
- * const auth = client({ convex, api: api.auth });
1100
- * onDestroy(() => auth.destroy());
1101
- * ```
1102
- *
1103
- * @example
1104
- * ```ts
1105
- * const unsubscribe = auth.onChange((state) => console.log(state.phase));
1106
- *
1107
- * // Later, during cleanup:
1108
- * unsubscribe();
1109
- * auth.destroy();
1110
- * ```
1111
- */
1112
- destroy: () => {
1113
- destroyed = true;
1114
- settleHandshakeWaiters(authEpoch, {
1115
- type: "reject",
1116
- error: createHandshakeError("AUTH_HANDSHAKE_REJECTED", {
1117
- reason: "destroyed",
1118
- }),
1119
- });
1120
- disposeStorageListener?.();
1121
- subscribers.clear();
1122
- },
1123
- } as AuthClient<Api>;
1124
- }