@robelest/convex-auth 0.0.4-preview.13 → 0.0.4-preview.16

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 (328) hide show
  1. package/README.md +140 -9
  2. package/dist/bin.cjs +5957 -5478
  3. package/dist/client/index.d.ts +3 -7
  4. package/dist/client/index.d.ts.map +1 -1
  5. package/dist/client/index.js +27 -26
  6. package/dist/client/index.js.map +1 -1
  7. package/dist/component/_generated/api.d.ts +14 -0
  8. package/dist/component/_generated/api.d.ts.map +1 -1
  9. package/dist/component/_generated/api.js.map +1 -1
  10. package/dist/component/_generated/component.d.ts +1672 -24
  11. package/dist/component/_generated/component.d.ts.map +1 -1
  12. package/dist/component/convex.config.d.ts +2 -2
  13. package/dist/component/convex.config.d.ts.map +1 -1
  14. package/dist/component/index.d.ts +1 -1
  15. package/dist/component/index.js +2 -2
  16. package/dist/component/model.d.ts +153 -0
  17. package/dist/component/model.d.ts.map +1 -0
  18. package/dist/component/model.js +343 -0
  19. package/dist/component/model.js.map +1 -0
  20. package/dist/component/providers/sso.d.ts +1 -1
  21. package/dist/component/public/enterprise.d.ts +54 -0
  22. package/dist/component/public/enterprise.d.ts.map +1 -0
  23. package/dist/component/public/enterprise.js +515 -0
  24. package/dist/component/public/enterprise.js.map +1 -0
  25. package/dist/component/public/factors.d.ts +52 -0
  26. package/dist/component/public/factors.d.ts.map +1 -0
  27. package/dist/component/public/factors.js +285 -0
  28. package/dist/component/public/factors.js.map +1 -0
  29. package/dist/component/public/groups.d.ts +116 -0
  30. package/dist/component/public/groups.d.ts.map +1 -0
  31. package/dist/component/public/groups.js +596 -0
  32. package/dist/component/public/groups.js.map +1 -0
  33. package/dist/component/public/identity.d.ts +93 -0
  34. package/dist/component/public/identity.d.ts.map +1 -0
  35. package/dist/component/public/identity.js +426 -0
  36. package/dist/component/public/identity.js.map +1 -0
  37. package/dist/component/public/keys.d.ts +41 -0
  38. package/dist/component/public/keys.d.ts.map +1 -0
  39. package/dist/component/public/keys.js +157 -0
  40. package/dist/component/public/keys.js.map +1 -0
  41. package/dist/component/public/shared.d.ts +26 -0
  42. package/dist/component/public/shared.d.ts.map +1 -0
  43. package/dist/component/public/shared.js +32 -0
  44. package/dist/component/public/shared.js.map +1 -0
  45. package/dist/component/public.d.ts +9 -321
  46. package/dist/component/public.d.ts.map +1 -1
  47. package/dist/component/public.js +6 -2145
  48. package/dist/component/schema.d.ts +406 -260
  49. package/dist/component/schema.js +37 -32
  50. package/dist/component/schema.js.map +1 -1
  51. package/dist/component/server/auth.d.ts +161 -15
  52. package/dist/component/server/auth.d.ts.map +1 -1
  53. package/dist/component/server/auth.js +100 -7
  54. package/dist/component/server/auth.js.map +1 -1
  55. package/dist/component/server/cookies.js +3 -0
  56. package/dist/component/server/cookies.js.map +1 -1
  57. package/dist/component/server/db.js +1 -0
  58. package/dist/component/server/db.js.map +1 -1
  59. package/dist/component/server/device.js +3 -1
  60. package/dist/component/server/device.js.map +1 -1
  61. package/dist/component/server/domains/core.js +629 -0
  62. package/dist/component/server/domains/core.js.map +1 -0
  63. package/dist/component/server/domains/sso.js +884 -0
  64. package/dist/component/server/domains/sso.js.map +1 -0
  65. package/dist/component/server/factory.d.ts +136 -0
  66. package/dist/component/server/factory.d.ts.map +1 -0
  67. package/dist/component/server/factory.js +1134 -0
  68. package/dist/component/server/factory.js.map +1 -0
  69. package/dist/component/server/fx.js +2 -1
  70. package/dist/component/server/fx.js.map +1 -1
  71. package/dist/component/server/http.js +287 -0
  72. package/dist/component/server/http.js.map +1 -0
  73. package/dist/component/server/identity.js +13 -0
  74. package/dist/component/server/identity.js.map +1 -0
  75. package/dist/component/server/keys.js +4 -0
  76. package/dist/component/server/keys.js.map +1 -1
  77. package/dist/component/server/mutations/account.js +1 -1
  78. package/dist/component/server/mutations/index.js +2 -2
  79. package/dist/component/server/mutations/index.js.map +1 -1
  80. package/dist/component/server/mutations/invalidate.js +1 -1
  81. package/dist/component/server/mutations/oauth.js +10 -7
  82. package/dist/component/server/mutations/oauth.js.map +1 -1
  83. package/dist/component/server/mutations/refresh.js +1 -1
  84. package/dist/component/server/mutations/register.js +1 -1
  85. package/dist/component/server/mutations/retrieve.js +1 -1
  86. package/dist/component/server/mutations/signature.js +1 -1
  87. package/dist/component/server/mutations/store.js +6 -3
  88. package/dist/component/server/mutations/store.js.map +1 -1
  89. package/dist/component/server/mutations/verify.js +1 -1
  90. package/dist/component/server/oauth.js +3 -0
  91. package/dist/component/server/oauth.js.map +1 -1
  92. package/dist/component/server/passkey.js +3 -2
  93. package/dist/component/server/passkey.js.map +1 -1
  94. package/dist/component/server/provider.js +2 -0
  95. package/dist/component/server/provider.js.map +1 -1
  96. package/dist/component/server/providers.js +10 -0
  97. package/dist/component/server/providers.js.map +1 -1
  98. package/dist/component/server/ratelimit.js +3 -0
  99. package/dist/component/server/ratelimit.js.map +1 -1
  100. package/dist/component/server/redirects.js +2 -0
  101. package/dist/component/server/redirects.js.map +1 -1
  102. package/dist/component/server/refresh.js +5 -0
  103. package/dist/component/server/refresh.js.map +1 -1
  104. package/dist/component/server/sessions.js +5 -0
  105. package/dist/component/server/sessions.js.map +1 -1
  106. package/dist/component/server/signin.js +2 -1
  107. package/dist/component/server/signin.js.map +1 -1
  108. package/dist/component/server/sso.js +166 -19
  109. package/dist/component/server/sso.js.map +1 -1
  110. package/dist/component/server/tokens.js +1 -0
  111. package/dist/component/server/tokens.js.map +1 -1
  112. package/dist/component/server/totp.js +4 -2
  113. package/dist/component/server/totp.js.map +1 -1
  114. package/dist/component/server/types.d.ts +106 -38
  115. package/dist/component/server/types.d.ts.map +1 -1
  116. package/dist/component/server/types.js.map +1 -1
  117. package/dist/component/server/users.js +1 -0
  118. package/dist/component/server/users.js.map +1 -1
  119. package/dist/component/server/utils.js +44 -2
  120. package/dist/component/server/utils.js.map +1 -1
  121. package/dist/providers/anonymous.d.ts +1 -1
  122. package/dist/providers/credentials.d.ts +1 -1
  123. package/dist/providers/password.d.ts +1 -1
  124. package/dist/providers/sso.d.ts +1 -1
  125. package/dist/providers/sso.js.map +1 -1
  126. package/dist/server/auth.d.ts +163 -17
  127. package/dist/server/auth.d.ts.map +1 -1
  128. package/dist/server/auth.js +100 -7
  129. package/dist/server/auth.js.map +1 -1
  130. package/dist/server/cookies.d.ts +1 -38
  131. package/dist/server/cookies.js +3 -0
  132. package/dist/server/cookies.js.map +1 -1
  133. package/dist/server/db.d.ts +1 -125
  134. package/dist/server/db.js +1 -0
  135. package/dist/server/db.js.map +1 -1
  136. package/dist/server/device.d.ts +1 -24
  137. package/dist/server/device.js +3 -1
  138. package/dist/server/device.js.map +1 -1
  139. package/dist/server/domains/core.d.ts +434 -0
  140. package/dist/server/domains/core.d.ts.map +1 -0
  141. package/dist/server/domains/core.js +629 -0
  142. package/dist/server/domains/core.js.map +1 -0
  143. package/dist/server/domains/sso.d.ts +409 -0
  144. package/dist/server/domains/sso.d.ts.map +1 -0
  145. package/dist/server/domains/sso.js +884 -0
  146. package/dist/server/domains/sso.js.map +1 -0
  147. package/dist/server/enterpriseValidators.d.ts +1 -0
  148. package/dist/server/enterpriseValidators.js +60 -0
  149. package/dist/server/enterpriseValidators.js.map +1 -0
  150. package/dist/server/factory.d.ts +136 -0
  151. package/dist/server/factory.d.ts.map +1 -0
  152. package/dist/server/factory.js +1134 -0
  153. package/dist/server/factory.js.map +1 -0
  154. package/dist/server/fx.d.ts +1 -16
  155. package/dist/server/fx.d.ts.map +1 -1
  156. package/dist/server/fx.js +1 -0
  157. package/dist/server/fx.js.map +1 -1
  158. package/dist/server/http.d.ts +59 -0
  159. package/dist/server/http.d.ts.map +1 -0
  160. package/dist/server/http.js +287 -0
  161. package/dist/server/http.js.map +1 -0
  162. package/dist/server/identity.d.ts +1 -0
  163. package/dist/server/identity.js +13 -0
  164. package/dist/server/identity.js.map +1 -0
  165. package/dist/server/index.d.ts +468 -1
  166. package/dist/server/index.d.ts.map +1 -1
  167. package/dist/server/index.js +530 -36
  168. package/dist/server/index.js.map +1 -1
  169. package/dist/server/keys.d.ts +1 -57
  170. package/dist/server/keys.js +4 -0
  171. package/dist/server/keys.js.map +1 -1
  172. package/dist/server/mutations/account.d.ts +7 -7
  173. package/dist/server/mutations/account.d.ts.map +1 -1
  174. package/dist/server/mutations/code.d.ts +13 -13
  175. package/dist/server/mutations/code.d.ts.map +1 -1
  176. package/dist/server/mutations/index.d.ts +107 -107
  177. package/dist/server/mutations/index.d.ts.map +1 -1
  178. package/dist/server/mutations/index.js +1 -1
  179. package/dist/server/mutations/index.js.map +1 -1
  180. package/dist/server/mutations/invalidate.d.ts +5 -5
  181. package/dist/server/mutations/invalidate.d.ts.map +1 -1
  182. package/dist/server/mutations/oauth.d.ts +10 -10
  183. package/dist/server/mutations/oauth.d.ts.map +1 -1
  184. package/dist/server/mutations/oauth.js +9 -6
  185. package/dist/server/mutations/oauth.js.map +1 -1
  186. package/dist/server/mutations/refresh.d.ts +4 -4
  187. package/dist/server/mutations/register.d.ts +12 -12
  188. package/dist/server/mutations/register.d.ts.map +1 -1
  189. package/dist/server/mutations/retrieve.d.ts +7 -7
  190. package/dist/server/mutations/signature.d.ts +5 -5
  191. package/dist/server/mutations/signin.d.ts +6 -6
  192. package/dist/server/mutations/signin.d.ts.map +1 -1
  193. package/dist/server/mutations/signout.d.ts +1 -1
  194. package/dist/server/mutations/store.d.ts +3 -2
  195. package/dist/server/mutations/store.d.ts.map +1 -1
  196. package/dist/server/mutations/store.js +6 -3
  197. package/dist/server/mutations/store.js.map +1 -1
  198. package/dist/server/mutations/verifier.d.ts +1 -1
  199. package/dist/server/mutations/verify.d.ts +11 -11
  200. package/dist/server/mutations/verify.d.ts.map +1 -1
  201. package/dist/server/oauth.d.ts +1 -59
  202. package/dist/server/oauth.js +3 -0
  203. package/dist/server/oauth.js.map +1 -1
  204. package/dist/server/passkey.d.ts.map +1 -1
  205. package/dist/server/passkey.js +3 -2
  206. package/dist/server/passkey.js.map +1 -1
  207. package/dist/server/provider.d.ts +1 -14
  208. package/dist/server/provider.d.ts.map +1 -1
  209. package/dist/server/provider.js +2 -0
  210. package/dist/server/provider.js.map +1 -1
  211. package/dist/server/providers.js +10 -0
  212. package/dist/server/providers.js.map +1 -1
  213. package/dist/server/ratelimit.d.ts +1 -22
  214. package/dist/server/ratelimit.js +3 -0
  215. package/dist/server/ratelimit.js.map +1 -1
  216. package/dist/server/redirects.d.ts +1 -10
  217. package/dist/server/redirects.js +2 -0
  218. package/dist/server/redirects.js.map +1 -1
  219. package/dist/server/refresh.d.ts +1 -37
  220. package/dist/server/refresh.js +5 -0
  221. package/dist/server/refresh.js.map +1 -1
  222. package/dist/server/sessions.d.ts +1 -28
  223. package/dist/server/sessions.js +5 -0
  224. package/dist/server/sessions.js.map +1 -1
  225. package/dist/server/signin.d.ts +1 -55
  226. package/dist/server/signin.js +2 -1
  227. package/dist/server/signin.js.map +1 -1
  228. package/dist/server/sso.d.ts +1 -348
  229. package/dist/server/sso.js +165 -18
  230. package/dist/server/sso.js.map +1 -1
  231. package/dist/server/templates.d.ts +1 -21
  232. package/dist/server/templates.js +1 -0
  233. package/dist/server/templates.js.map +1 -1
  234. package/dist/server/tokens.d.ts +1 -11
  235. package/dist/server/tokens.js +1 -0
  236. package/dist/server/tokens.js.map +1 -1
  237. package/dist/server/totp.d.ts +1 -23
  238. package/dist/server/totp.js +4 -2
  239. package/dist/server/totp.js.map +1 -1
  240. package/dist/server/types.d.ts +114 -77
  241. package/dist/server/types.d.ts.map +1 -1
  242. package/dist/server/types.js.map +1 -1
  243. package/dist/server/users.d.ts +1 -31
  244. package/dist/server/users.js +1 -0
  245. package/dist/server/users.js.map +1 -1
  246. package/dist/server/utils.d.ts +1 -27
  247. package/dist/server/utils.js +44 -2
  248. package/dist/server/utils.js.map +1 -1
  249. package/dist/server/version.d.ts +1 -1
  250. package/dist/server/version.js +1 -1
  251. package/dist/server/version.js.map +1 -1
  252. package/package.json +4 -5
  253. package/src/cli/bin.ts +5 -0
  254. package/src/cli/index.ts +22 -9
  255. package/src/cli/keys.ts +3 -0
  256. package/src/client/index.ts +36 -37
  257. package/src/component/_generated/api.ts +14 -0
  258. package/src/component/_generated/component.ts +2106 -9
  259. package/src/component/index.ts +3 -1
  260. package/src/component/model.ts +441 -0
  261. package/src/component/public/enterprise.ts +753 -0
  262. package/src/component/public/factors.ts +332 -0
  263. package/src/component/public/groups.ts +932 -0
  264. package/src/component/public/identity.ts +566 -0
  265. package/src/component/public/keys.ts +209 -0
  266. package/src/component/public/shared.ts +119 -0
  267. package/src/component/public.ts +5 -2965
  268. package/src/component/schema.ts +68 -63
  269. package/src/providers/sso.ts +1 -1
  270. package/src/server/auth.ts +413 -18
  271. package/src/server/cookies.ts +3 -0
  272. package/src/server/db.ts +3 -0
  273. package/src/server/device.ts +3 -1
  274. package/src/server/domains/core.ts +1071 -0
  275. package/src/server/domains/sso.ts +1749 -0
  276. package/src/server/enterpriseValidators.ts +93 -0
  277. package/src/server/factory.ts +2181 -0
  278. package/src/server/fx.ts +1 -0
  279. package/src/server/http.ts +529 -0
  280. package/src/server/identity.ts +18 -0
  281. package/src/server/index.ts +806 -40
  282. package/src/server/keys.ts +4 -0
  283. package/src/server/mutations/index.ts +1 -1
  284. package/src/server/mutations/oauth.ts +36 -8
  285. package/src/server/mutations/store.ts +6 -3
  286. package/src/server/oauth.ts +6 -0
  287. package/src/server/passkey.ts +3 -2
  288. package/src/server/provider.ts +2 -0
  289. package/src/server/providers.ts +20 -0
  290. package/src/server/ratelimit.ts +3 -0
  291. package/src/server/redirects.ts +2 -0
  292. package/src/server/refresh.ts +5 -0
  293. package/src/server/sessions.ts +5 -0
  294. package/src/server/signin.ts +1 -0
  295. package/src/server/sso.ts +259 -17
  296. package/src/server/templates.ts +1 -0
  297. package/src/server/tokens.ts +1 -0
  298. package/src/server/totp.ts +4 -2
  299. package/src/server/types.ts +178 -83
  300. package/src/server/users.ts +1 -0
  301. package/src/server/utils.ts +71 -1
  302. package/src/server/version.ts +1 -1
  303. package/dist/component/public.js.map +0 -1
  304. package/dist/component/server/implementation.d.ts +0 -1264
  305. package/dist/component/server/implementation.d.ts.map +0 -1
  306. package/dist/component/server/implementation.js +0 -2365
  307. package/dist/component/server/implementation.js.map +0 -1
  308. package/dist/server/cookies.d.ts.map +0 -1
  309. package/dist/server/db.d.ts.map +0 -1
  310. package/dist/server/device.d.ts.map +0 -1
  311. package/dist/server/implementation.d.ts +0 -1264
  312. package/dist/server/implementation.d.ts.map +0 -1
  313. package/dist/server/implementation.js +0 -2365
  314. package/dist/server/implementation.js.map +0 -1
  315. package/dist/server/keys.d.ts.map +0 -1
  316. package/dist/server/oauth.d.ts.map +0 -1
  317. package/dist/server/ratelimit.d.ts.map +0 -1
  318. package/dist/server/redirects.d.ts.map +0 -1
  319. package/dist/server/refresh.d.ts.map +0 -1
  320. package/dist/server/sessions.d.ts.map +0 -1
  321. package/dist/server/signin.d.ts.map +0 -1
  322. package/dist/server/sso.d.ts.map +0 -1
  323. package/dist/server/templates.d.ts.map +0 -1
  324. package/dist/server/tokens.d.ts.map +0 -1
  325. package/dist/server/totp.d.ts.map +0 -1
  326. package/dist/server/users.d.ts.map +0 -1
  327. package/dist/server/utils.d.ts.map +0 -1
  328. package/src/server/implementation.ts +0 -5336
@@ -0,0 +1,629 @@
1
+ import { AuthError, Fx } from "../fx.js";
2
+ import { TOKEN_SUB_CLAIM_DIVIDER, generateRandomString, sha256 } from "../utils.js";
3
+ import { buildScopeChecker, checkKeyRateLimit, generateApiKey, hashApiKey } from "../keys.js";
4
+ import { materializeProvider } from "../providers.js";
5
+ import { signInImpl } from "../signin.js";
6
+
7
+ //#region src/server/domains/core.ts
8
+ /**
9
+ * Build the core auth domains that back the canonical app API surface.
10
+ */
11
+ function createCoreDomains(deps) {
12
+ const { config, getAuth, callInvalidateSessions, callCreateAccountFromCredentials, callRetrieveAccountWithCredentials, callModifyAccount, getEnrichCtx, inviteTokenAlphabet, inviteTokenLength } = deps;
13
+ const roleDefinitions = config.authorization.roles;
14
+ const getRoleDefinition = (roleId) => {
15
+ const role = roleDefinitions[roleId];
16
+ if (!role) throw new AuthError("INVALID_PARAMETERS", `Unknown roleId "${roleId}".`).toConvexError();
17
+ return role;
18
+ };
19
+ const normalizeRoleIds = (roleIds) => {
20
+ const normalized = Array.from(new Set(roleIds ?? []));
21
+ for (const roleId of normalized) getRoleDefinition(roleId);
22
+ return normalized;
23
+ };
24
+ const resolveGrantedPermissions = (roleIds) => {
25
+ const grants = /* @__PURE__ */ new Set();
26
+ for (const roleId of roleIds ?? []) {
27
+ const role = getRoleDefinition(roleId);
28
+ for (const grant of role.grants) grants.add(grant);
29
+ }
30
+ return Array.from(grants).sort();
31
+ };
32
+ const user = {
33
+ current: async (ctx, request) => {
34
+ const identity = await ctx.auth.getUserIdentity();
35
+ if (identity !== null) {
36
+ const [userId] = identity.subject.split(TOKEN_SUB_CLAIM_DIVIDER);
37
+ return userId;
38
+ }
39
+ if (request !== void 0 && "runMutation" in ctx && ctx.runMutation) {
40
+ const authHeader = request.headers.get("Authorization");
41
+ if (authHeader?.startsWith("Bearer sk_")) {
42
+ const rawKey = authHeader.slice(7);
43
+ try {
44
+ return (await getAuth().key.verify(ctx, rawKey)).userId;
45
+ } catch {
46
+ return null;
47
+ }
48
+ }
49
+ }
50
+ return null;
51
+ },
52
+ require: async (ctx, request) => {
53
+ const userId = await user.current(ctx, request);
54
+ if (userId === null) throw new AuthError("NOT_SIGNED_IN").toConvexError();
55
+ return userId;
56
+ },
57
+ get: async (ctx, userId) => {
58
+ return await ctx.runQuery(config.component.public.userGetById, { userId });
59
+ },
60
+ list: async (ctx, opts = {}) => {
61
+ return await ctx.runQuery(config.component.public.userList, opts);
62
+ },
63
+ viewer: async (ctx) => {
64
+ const userId = await user.current(ctx);
65
+ if (userId === null) return null;
66
+ return await ctx.runQuery(config.component.public.userGetById, { userId });
67
+ },
68
+ update: async (ctx, userId, data) => {
69
+ await ctx.runMutation(config.component.public.userPatch, {
70
+ userId,
71
+ data
72
+ });
73
+ return {
74
+ ok: true,
75
+ userId
76
+ };
77
+ },
78
+ setActiveGroup: async (ctx, opts) => {
79
+ const doc = await user.get(ctx, opts.userId);
80
+ const existingExtend = doc !== null && doc.extend !== null && typeof doc.extend === "object" && !Array.isArray(doc.extend) ? { ...doc.extend } : {};
81
+ if (opts.groupId === null) {
82
+ const { lastActiveGroup: _omit, ...rest } = existingExtend;
83
+ await user.update(ctx, opts.userId, { extend: rest });
84
+ return {
85
+ ok: true,
86
+ userId: opts.userId,
87
+ groupId: null
88
+ };
89
+ }
90
+ await user.update(ctx, opts.userId, { extend: {
91
+ ...existingExtend,
92
+ lastActiveGroup: opts.groupId
93
+ } });
94
+ return {
95
+ ok: true,
96
+ userId: opts.userId,
97
+ groupId: opts.groupId
98
+ };
99
+ },
100
+ getActiveGroup: async (ctx, opts) => {
101
+ const doc = await user.get(ctx, opts.userId);
102
+ if (doc !== null && doc.extend !== null && typeof doc.extend === "object" && !Array.isArray(doc.extend)) {
103
+ const val = doc.extend.lastActiveGroup;
104
+ if (typeof val === "string") return val;
105
+ }
106
+ return null;
107
+ },
108
+ delete: async (ctx, userId, opts) => {
109
+ const cascade = opts?.cascade !== false;
110
+ const [sessions, accounts, keys, members, passkeys, totps] = await Promise.all([
111
+ ctx.runQuery(config.component.public.sessionListByUser, { userId }),
112
+ ctx.runQuery(config.component.public.accountListByUser, { userId }),
113
+ ctx.runQuery(config.component.public.keyListByUserId, { userId }),
114
+ ctx.runQuery(config.component.public.memberListByUser, { userId }),
115
+ ctx.runQuery(config.component.public.passkeyListByUserId, { userId }),
116
+ ctx.runQuery(config.component.public.totpListByUserId, { userId })
117
+ ]);
118
+ const totalLinked = sessions.length + accounts.length + keys.length + members.length + passkeys.length + totps.length;
119
+ if (!cascade && totalLinked > 0) throw new AuthError("INVALID_PARAMETERS", `Cannot delete user with ${totalLinked} linked records. Pass { cascade: true } to delete all linked records, or remove them manually first.`).toConvexError();
120
+ const deletions = [];
121
+ for (const s of sessions) deletions.push(ctx.runMutation(config.component.public.sessionDelete, { sessionId: s._id }));
122
+ for (const a of accounts) deletions.push(ctx.runMutation(config.component.public.accountDelete, { accountId: a._id }));
123
+ for (const k of keys) deletions.push(ctx.runMutation(config.component.public.keyDelete, { keyId: k._id }));
124
+ for (const m of members) deletions.push(ctx.runMutation(config.component.public.memberRemove, { memberId: m._id }));
125
+ for (const p of passkeys) deletions.push(ctx.runMutation(config.component.public.passkeyDelete, { passkeyId: p._id }));
126
+ for (const t of totps) deletions.push(ctx.runMutation(config.component.public.totpDelete, { totpId: t._id }));
127
+ await Promise.all(deletions);
128
+ await ctx.runMutation(config.component.public.userDelete, { userId });
129
+ return {
130
+ ok: true,
131
+ userId
132
+ };
133
+ }
134
+ };
135
+ const session = {
136
+ current: async (ctx) => {
137
+ const identity = await ctx.auth.getUserIdentity();
138
+ if (identity === null) return null;
139
+ const [, sessionId] = identity.subject.split(TOKEN_SUB_CLAIM_DIVIDER);
140
+ return sessionId;
141
+ },
142
+ invalidate: async (ctx, args) => {
143
+ await callInvalidateSessions(ctx, args);
144
+ return {
145
+ ok: true,
146
+ userId: args.userId,
147
+ except: args.except ?? []
148
+ };
149
+ },
150
+ get: async (ctx, sessionId) => {
151
+ return await ctx.runQuery(config.component.public.sessionGetById, { sessionId });
152
+ },
153
+ list: async (ctx, opts) => {
154
+ return await ctx.runQuery(config.component.public.sessionListByUser, { userId: opts.userId });
155
+ }
156
+ };
157
+ const account = {
158
+ create: async (ctx, args) => {
159
+ return {
160
+ ok: true,
161
+ ...await callCreateAccountFromCredentials(ctx, args)
162
+ };
163
+ },
164
+ get: async (ctx, args) => {
165
+ const result = await callRetrieveAccountWithCredentials(ctx, args);
166
+ if (typeof result === "string") throw new AuthError("ACCOUNT_NOT_FOUND", result).toConvexError();
167
+ return result;
168
+ },
169
+ update: async (ctx, args) => {
170
+ await callModifyAccount(ctx, args);
171
+ return {
172
+ ok: true,
173
+ accountId: args.account.id
174
+ };
175
+ },
176
+ delete: async (ctx, accountId) => {
177
+ const doc = await ctx.runQuery(config.component.public.accountGetById, { accountId });
178
+ if (doc === null) throw new AuthError("ACCOUNT_NOT_FOUND", "Account not found.").toConvexError();
179
+ if ((await ctx.runQuery(config.component.public.accountListByUser, { userId: doc.userId })).length <= 1) throw new AuthError("INVALID_PARAMETERS", "Cannot unlink the user's only account. This would lock them out.").toConvexError();
180
+ await ctx.runMutation(config.component.public.accountDelete, { accountId });
181
+ return {
182
+ ok: true,
183
+ accountId
184
+ };
185
+ },
186
+ listPasskeys: async (ctx, opts) => {
187
+ return await ctx.runQuery(config.component.public.passkeyListByUserId, opts);
188
+ },
189
+ renamePasskey: async (ctx, passkeyId, name) => {
190
+ await ctx.runMutation(config.component.public.passkeyUpdateMeta, {
191
+ passkeyId,
192
+ data: { name }
193
+ });
194
+ return {
195
+ ok: true,
196
+ passkeyId
197
+ };
198
+ },
199
+ deletePasskey: async (ctx, passkeyId) => {
200
+ await ctx.runMutation(config.component.public.passkeyDelete, { passkeyId });
201
+ return {
202
+ ok: true,
203
+ passkeyId
204
+ };
205
+ },
206
+ listTotps: async (ctx, opts) => {
207
+ return await ctx.runQuery(config.component.public.totpListByUserId, opts);
208
+ },
209
+ deleteTotp: async (ctx, totpId) => {
210
+ await ctx.runMutation(config.component.public.totpDelete, { totpId });
211
+ return {
212
+ ok: true,
213
+ totpId
214
+ };
215
+ }
216
+ };
217
+ const provider = { signIn: async (ctx, providerConfig, args) => {
218
+ const result = await signInImpl(getEnrichCtx()(ctx), materializeProvider(providerConfig), args, {
219
+ generateTokens: false,
220
+ allowExtraProviders: true
221
+ });
222
+ return result.kind === "signedIn" ? result.signedIn !== null ? {
223
+ userId: result.signedIn.userId,
224
+ sessionId: result.signedIn.sessionId
225
+ } : null : null;
226
+ } };
227
+ const group = {
228
+ create: async (ctx, data) => {
229
+ return {
230
+ ok: true,
231
+ groupId: await ctx.runMutation(config.component.public.groupCreate, data)
232
+ };
233
+ },
234
+ get: async (ctx, groupId) => {
235
+ return await ctx.runQuery(config.component.public.groupGet, { groupId });
236
+ },
237
+ list: async (ctx, opts) => {
238
+ return await ctx.runQuery(config.component.public.groupList, {
239
+ where: opts?.where,
240
+ limit: opts?.limit,
241
+ cursor: opts?.cursor,
242
+ orderBy: opts?.orderBy,
243
+ order: opts?.order
244
+ });
245
+ },
246
+ update: async (ctx, groupId, data) => {
247
+ await ctx.runMutation(config.component.public.groupUpdate, {
248
+ groupId,
249
+ data
250
+ });
251
+ return {
252
+ ok: true,
253
+ groupId
254
+ };
255
+ },
256
+ delete: async (ctx, groupId) => {
257
+ await ctx.runMutation(config.component.public.groupDelete, { groupId });
258
+ return {
259
+ ok: true,
260
+ groupId
261
+ };
262
+ },
263
+ ancestors: async (ctx, opts) => {
264
+ const maxDepth = Math.max(0, Math.floor(opts.maxDepth ?? 32));
265
+ const visited = /* @__PURE__ */ new Set();
266
+ const ancestors = [];
267
+ let cycleDetected = false;
268
+ let maxDepthReached = false;
269
+ let currentGroupId = opts.groupId;
270
+ let depth = 0;
271
+ let isFirst = true;
272
+ while (currentGroupId !== void 0) {
273
+ if (depth > maxDepth) {
274
+ maxDepthReached = true;
275
+ break;
276
+ }
277
+ if (visited.has(currentGroupId)) {
278
+ cycleDetected = true;
279
+ break;
280
+ }
281
+ visited.add(currentGroupId);
282
+ const doc = await group.get(ctx, currentGroupId);
283
+ if (doc === null) break;
284
+ if (isFirst) {
285
+ isFirst = false;
286
+ if (opts.includeSelf) ancestors.push(doc);
287
+ currentGroupId = doc.parentGroupId;
288
+ depth += 1;
289
+ continue;
290
+ }
291
+ ancestors.push(doc);
292
+ currentGroupId = doc.parentGroupId;
293
+ depth += 1;
294
+ }
295
+ return {
296
+ ancestors,
297
+ cycleDetected,
298
+ maxDepthReached
299
+ };
300
+ }
301
+ };
302
+ const member = {
303
+ create: async (ctx, data) => {
304
+ const roleIds = normalizeRoleIds(data.roleIds);
305
+ return {
306
+ ok: true,
307
+ memberId: await ctx.runMutation(config.component.public.memberAdd, {
308
+ ...data,
309
+ roleIds
310
+ })
311
+ };
312
+ },
313
+ get: async (ctx, memberId) => {
314
+ return await ctx.runQuery(config.component.public.memberGet, { memberId });
315
+ },
316
+ getByUserAndGroup: async (ctx, opts) => {
317
+ return await ctx.runQuery(config.component.public.memberGetByGroupAndUser, opts);
318
+ },
319
+ list: async (ctx, opts) => {
320
+ return await ctx.runQuery(config.component.public.memberList, {
321
+ where: opts?.where,
322
+ limit: opts?.limit,
323
+ cursor: opts?.cursor,
324
+ orderBy: opts?.orderBy,
325
+ order: opts?.order
326
+ });
327
+ },
328
+ delete: async (ctx, memberId) => {
329
+ await ctx.runMutation(config.component.public.memberRemove, { memberId });
330
+ return {
331
+ ok: true,
332
+ memberId
333
+ };
334
+ },
335
+ update: async (ctx, memberId, data) => {
336
+ const nextData = { ...data };
337
+ if ("roleIds" in nextData) nextData.roleIds = normalizeRoleIds(Array.isArray(nextData.roleIds) ? nextData.roleIds : void 0);
338
+ await ctx.runMutation(config.component.public.memberUpdate, {
339
+ memberId,
340
+ data: nextData
341
+ });
342
+ return {
343
+ ok: true,
344
+ memberId
345
+ };
346
+ },
347
+ inherit: async (ctx, opts) => {
348
+ const requestedRoleIds = normalizeRoleIds(opts.roleIds);
349
+ const roleFilter = requestedRoleIds.length > 0 ? new Set(requestedRoleIds) : null;
350
+ const requiredGrants = Array.from(new Set(opts.grants ?? []));
351
+ const maxDepth = Math.max(0, Math.floor(opts.maxDepth ?? 32));
352
+ const visited = /* @__PURE__ */ new Set();
353
+ const traversedGroupIds = [];
354
+ let currentGroupId = opts.groupId;
355
+ let depth = 0;
356
+ let cycleDetected = false;
357
+ let maxDepthReached = false;
358
+ while (currentGroupId !== void 0) {
359
+ if (depth > maxDepth) {
360
+ maxDepthReached = true;
361
+ break;
362
+ }
363
+ if (visited.has(currentGroupId)) {
364
+ cycleDetected = true;
365
+ break;
366
+ }
367
+ visited.add(currentGroupId);
368
+ traversedGroupIds.push(currentGroupId);
369
+ const membership = await member.getByUserAndGroup(ctx, {
370
+ userId: opts.userId,
371
+ groupId: currentGroupId
372
+ });
373
+ const membershipRoleIds = membership?.roleIds ?? [];
374
+ const membershipGrants = resolveGrantedPermissions(membershipRoleIds);
375
+ if (membership !== null && (roleFilter === null || membershipRoleIds.some((roleId) => roleFilter.has(roleId))) && requiredGrants.every((grant) => membershipGrants.includes(grant))) return {
376
+ requestedGroupId: opts.groupId,
377
+ matchedGroupId: currentGroupId,
378
+ membership,
379
+ roleIds: membershipRoleIds,
380
+ grants: membershipGrants,
381
+ missingGrants: [],
382
+ depth,
383
+ isDirect: depth === 0,
384
+ isInherited: depth > 0,
385
+ traversedGroupIds,
386
+ cycleDetected: false,
387
+ maxDepthReached: false
388
+ };
389
+ const doc = await group.get(ctx, currentGroupId);
390
+ if (doc === null || doc.parentGroupId === void 0) break;
391
+ currentGroupId = doc.parentGroupId;
392
+ depth += 1;
393
+ }
394
+ return {
395
+ requestedGroupId: opts.groupId,
396
+ matchedGroupId: null,
397
+ membership: null,
398
+ roleIds: [],
399
+ grants: [],
400
+ missingGrants: requiredGrants,
401
+ depth: null,
402
+ isDirect: false,
403
+ isInherited: false,
404
+ traversedGroupIds,
405
+ cycleDetected,
406
+ maxDepthReached
407
+ };
408
+ },
409
+ require: async (ctx, opts) => {
410
+ const result = await member.inherit(ctx, opts);
411
+ if (result.membership === null) throw new AuthError("FORBIDDEN", `User ${opts.userId} has no membership on group ${opts.groupId} or its ancestors.`).toConvexError();
412
+ return {
413
+ membership: result.membership,
414
+ matchedGroupId: result.matchedGroupId,
415
+ roleIds: result.roleIds,
416
+ grants: result.grants,
417
+ isDirect: result.isDirect,
418
+ isInherited: result.isInherited,
419
+ depth: result.depth
420
+ };
421
+ }
422
+ };
423
+ const access = {
424
+ check: async (ctx, opts) => {
425
+ const requiredGrants = Array.from(new Set(opts.grants));
426
+ const result = await member.inherit(ctx, {
427
+ userId: opts.userId,
428
+ groupId: opts.groupId,
429
+ grants: requiredGrants,
430
+ maxDepth: opts.maxDepth
431
+ });
432
+ const missingGrants = requiredGrants.filter((grant) => !result.grants.includes(grant));
433
+ return {
434
+ ok: result.membership !== null && missingGrants.length === 0,
435
+ membership: result.membership,
436
+ matchedGroupId: result.matchedGroupId,
437
+ roleIds: result.roleIds,
438
+ grants: result.grants,
439
+ missingGrants,
440
+ isDirect: result.isDirect,
441
+ isInherited: result.isInherited,
442
+ depth: result.depth
443
+ };
444
+ },
445
+ require: async (ctx, opts) => {
446
+ const result = await access.check(ctx, opts);
447
+ if (!result.ok) throw new AuthError("FORBIDDEN", `User ${opts.userId} is missing required grants on group ${opts.groupId}: ${result.missingGrants.join(", ")}.`).toConvexError();
448
+ return result;
449
+ }
450
+ };
451
+ const invite = {
452
+ create: async (ctx, data) => {
453
+ const roleIds = normalizeRoleIds(data.roleIds);
454
+ const token = generateRandomString(inviteTokenLength, inviteTokenAlphabet);
455
+ const tokenHash = await sha256(token);
456
+ return {
457
+ ok: true,
458
+ inviteId: await ctx.runMutation(config.component.public.inviteCreate, {
459
+ ...data,
460
+ roleIds,
461
+ tokenHash,
462
+ status: "pending"
463
+ }),
464
+ token
465
+ };
466
+ },
467
+ get: async (ctx, inviteId) => {
468
+ return await ctx.runQuery(config.component.public.inviteGet, { inviteId });
469
+ },
470
+ token: {
471
+ get: async (ctx, token) => {
472
+ const tokenHash = await sha256(token);
473
+ return await ctx.runQuery(config.component.public.inviteGetByTokenHash, { tokenHash });
474
+ },
475
+ accept: async (ctx, args) => {
476
+ const tokenHash = await sha256(args.token);
477
+ return {
478
+ ok: true,
479
+ ...await ctx.runMutation(config.component.public.inviteAcceptByToken, {
480
+ tokenHash,
481
+ acceptedByUserId: args.acceptedByUserId
482
+ })
483
+ };
484
+ }
485
+ },
486
+ list: async (ctx, opts) => {
487
+ return await ctx.runQuery(config.component.public.inviteList, {
488
+ where: opts?.where,
489
+ limit: opts?.limit,
490
+ cursor: opts?.cursor,
491
+ orderBy: opts?.orderBy,
492
+ order: opts?.order
493
+ });
494
+ },
495
+ accept: async (ctx, inviteId, acceptedByUserId) => {
496
+ await ctx.runMutation(config.component.public.inviteAccept, {
497
+ inviteId,
498
+ ...acceptedByUserId ? { acceptedByUserId } : {}
499
+ });
500
+ return {
501
+ ok: true,
502
+ inviteId,
503
+ acceptedByUserId: acceptedByUserId ?? null
504
+ };
505
+ },
506
+ revoke: async (ctx, inviteId) => {
507
+ await ctx.runMutation(config.component.public.inviteRevoke, { inviteId });
508
+ return {
509
+ ok: true,
510
+ inviteId
511
+ };
512
+ }
513
+ };
514
+ const key = {
515
+ create: async (ctx, opts) => {
516
+ const { raw, hashedKey, displayPrefix } = await generateApiKey("sk_");
517
+ return {
518
+ ok: true,
519
+ keyId: await ctx.runMutation(config.component.public.keyInsert, {
520
+ userId: opts.userId,
521
+ prefix: displayPrefix,
522
+ hashedKey,
523
+ name: opts.name,
524
+ scopes: opts.scopes,
525
+ rateLimit: opts.rateLimit,
526
+ expiresAt: opts.expiresAt,
527
+ metadata: opts.metadata
528
+ }),
529
+ secret: raw
530
+ };
531
+ },
532
+ verify: async (ctx, rawKey) => {
533
+ const hashedKey = await hashApiKey(rawKey);
534
+ const doc = await ctx.runQuery(config.component.public.keyGetByHashedKey, { hashedKey });
535
+ return Fx.run(Fx.gen(function* () {
536
+ yield* Fx.guard(!doc, Fx.fail(new AuthError("INVALID_API_KEY")));
537
+ const k = doc;
538
+ yield* Fx.guard(k.revoked, Fx.fail(new AuthError("API_KEY_REVOKED")));
539
+ yield* Fx.guard(!!(k.expiresAt && k.expiresAt < Date.now()), Fx.fail(new AuthError("API_KEY_EXPIRED")));
540
+ const patchData = { lastUsedAt: Date.now() };
541
+ if (k.rateLimit) {
542
+ const { limited, newState } = checkKeyRateLimit(k.rateLimit, k.rateLimitState ?? void 0);
543
+ yield* Fx.guard(limited, Fx.fail(new AuthError("API_KEY_RATE_LIMITED")));
544
+ patchData.rateLimitState = newState;
545
+ }
546
+ yield* Fx.promise(() => ctx.runMutation(config.component.public.keyPatch, {
547
+ keyId: k._id,
548
+ data: patchData
549
+ }));
550
+ return {
551
+ userId: k.userId,
552
+ keyId: k._id,
553
+ scopes: buildScopeChecker(k.scopes)
554
+ };
555
+ }).pipe(Fx.recover((e) => Fx.fatal(e.toConvexError()))));
556
+ },
557
+ list: async (ctx, opts) => {
558
+ return await ctx.runQuery(config.component.public.keyList, {
559
+ where: opts?.where,
560
+ limit: opts?.limit,
561
+ cursor: opts?.cursor,
562
+ orderBy: opts?.orderBy,
563
+ order: opts?.order
564
+ });
565
+ },
566
+ get: async (ctx, keyId) => {
567
+ return await ctx.runQuery(config.component.public.keyGetById, { keyId });
568
+ },
569
+ update: async (ctx, keyId, data) => {
570
+ await ctx.runMutation(config.component.public.keyPatch, {
571
+ keyId,
572
+ data
573
+ });
574
+ return {
575
+ ok: true,
576
+ keyId
577
+ };
578
+ },
579
+ revoke: async (ctx, keyId) => {
580
+ await ctx.runMutation(config.component.public.keyPatch, {
581
+ keyId,
582
+ data: { revoked: true }
583
+ });
584
+ return {
585
+ ok: true,
586
+ keyId
587
+ };
588
+ },
589
+ delete: async (ctx, keyId) => {
590
+ await ctx.runMutation(config.component.public.keyDelete, { keyId });
591
+ return {
592
+ ok: true,
593
+ keyId
594
+ };
595
+ },
596
+ rotate: async (ctx, keyId, opts) => {
597
+ const existing = await ctx.runQuery(config.component.public.keyGetById, { keyId });
598
+ if (!existing) throw new AuthError("INVALID_PARAMETERS", "API key not found.").toConvexError();
599
+ if (existing.revoked === true) throw new AuthError("API_KEY_REVOKED", "Cannot rotate a key that is already revoked.").toConvexError();
600
+ await ctx.runMutation(config.component.public.keyPatch, {
601
+ keyId,
602
+ data: { revoked: true }
603
+ });
604
+ return await key.create(ctx, {
605
+ userId: existing.userId,
606
+ name: opts?.name ?? existing.name,
607
+ scopes: existing.scopes ?? [],
608
+ rateLimit: existing.rateLimit,
609
+ expiresAt: opts?.expiresAt,
610
+ metadata: existing.metadata
611
+ });
612
+ }
613
+ };
614
+ return {
615
+ user,
616
+ session,
617
+ account,
618
+ provider,
619
+ group,
620
+ member,
621
+ access,
622
+ invite,
623
+ key
624
+ };
625
+ }
626
+
627
+ //#endregion
628
+ export { createCoreDomains };
629
+ //# sourceMappingURL=core.js.map