@stackframe/react 2.7.20

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 (316) hide show
  1. package/CHANGELOG.md +1415 -0
  2. package/LICENSE +7 -0
  3. package/README.md +26 -0
  4. package/dist/components/credential-sign-in.d.mts +5 -0
  5. package/dist/components/credential-sign-in.d.ts +5 -0
  6. package/dist/components/credential-sign-in.js +103 -0
  7. package/dist/components/credential-sign-in.js.map +1 -0
  8. package/dist/components/credential-sign-up.d.mts +7 -0
  9. package/dist/components/credential-sign-up.d.ts +7 -0
  10. package/dist/components/credential-sign-up.js +138 -0
  11. package/dist/components/credential-sign-up.js.map +1 -0
  12. package/dist/components/elements/form-warning.d.mts +7 -0
  13. package/dist/components/elements/form-warning.d.ts +7 -0
  14. package/dist/components/elements/form-warning.js +39 -0
  15. package/dist/components/elements/form-warning.js.map +1 -0
  16. package/dist/components/elements/maybe-full-page.d.mts +11 -0
  17. package/dist/components/elements/maybe-full-page.d.ts +11 -0
  18. package/dist/components/elements/maybe-full-page.js +74 -0
  19. package/dist/components/elements/maybe-full-page.js.map +1 -0
  20. package/dist/components/elements/separator-with-text.d.mts +7 -0
  21. package/dist/components/elements/separator-with-text.d.ts +7 -0
  22. package/dist/components/elements/separator-with-text.js +41 -0
  23. package/dist/components/elements/separator-with-text.js.map +1 -0
  24. package/dist/components/elements/sidebar-layout.d.mts +19 -0
  25. package/dist/components/elements/sidebar-layout.d.ts +19 -0
  26. package/dist/components/elements/sidebar-layout.js +126 -0
  27. package/dist/components/elements/sidebar-layout.js.map +1 -0
  28. package/dist/components/elements/ssr-layout-effect.d.mts +8 -0
  29. package/dist/components/elements/ssr-layout-effect.d.ts +8 -0
  30. package/dist/components/elements/ssr-layout-effect.js +47 -0
  31. package/dist/components/elements/ssr-layout-effect.js.map +1 -0
  32. package/dist/components/elements/user-avatar.d.mts +13 -0
  33. package/dist/components/elements/user-avatar.d.ts +13 -0
  34. package/dist/components/elements/user-avatar.js +41 -0
  35. package/dist/components/elements/user-avatar.js.map +1 -0
  36. package/dist/components/iframe-preventer.d.mts +8 -0
  37. package/dist/components/iframe-preventer.d.ts +8 -0
  38. package/dist/components/iframe-preventer.js +52 -0
  39. package/dist/components/iframe-preventer.js.map +1 -0
  40. package/dist/components/link.d.mts +14 -0
  41. package/dist/components/link.d.ts +14 -0
  42. package/dist/components/link.js +51 -0
  43. package/dist/components/link.js.map +1 -0
  44. package/dist/components/magic-link-sign-in.d.mts +5 -0
  45. package/dist/components/magic-link-sign-in.d.ts +5 -0
  46. package/dist/components/magic-link-sign-in.js +151 -0
  47. package/dist/components/magic-link-sign-in.js.map +1 -0
  48. package/dist/components/message-cards/known-error-message-card.d.mts +9 -0
  49. package/dist/components/message-cards/known-error-message-card.d.ts +9 -0
  50. package/dist/components/message-cards/known-error-message-card.js +61 -0
  51. package/dist/components/message-cards/known-error-message-card.js.map +1 -0
  52. package/dist/components/message-cards/message-card.d.mts +14 -0
  53. package/dist/components/message-cards/message-card.d.ts +14 -0
  54. package/dist/components/message-cards/message-card.js +45 -0
  55. package/dist/components/message-cards/message-card.js.map +1 -0
  56. package/dist/components/message-cards/predefined-message-card.d.mts +8 -0
  57. package/dist/components/message-cards/predefined-message-card.d.ts +8 -0
  58. package/dist/components/message-cards/predefined-message-card.js +107 -0
  59. package/dist/components/message-cards/predefined-message-card.js.map +1 -0
  60. package/dist/components/oauth-button-group.d.mts +14 -0
  61. package/dist/components/oauth-button-group.d.ts +14 -0
  62. package/dist/components/oauth-button-group.js +43 -0
  63. package/dist/components/oauth-button-group.js.map +1 -0
  64. package/dist/components/oauth-button.d.mts +8 -0
  65. package/dist/components/oauth-button.d.ts +8 -0
  66. package/dist/components/oauth-button.js +210 -0
  67. package/dist/components/oauth-button.js.map +1 -0
  68. package/dist/components/passkey-button.d.mts +7 -0
  69. package/dist/components/passkey-button.d.ts +7 -0
  70. package/dist/components/passkey-button.js +58 -0
  71. package/dist/components/passkey-button.js.map +1 -0
  72. package/dist/components/profile-image-editor.d.mts +11 -0
  73. package/dist/components/profile-image-editor.d.ts +11 -0
  74. package/dist/components/profile-image-editor.js +162 -0
  75. package/dist/components/profile-image-editor.js.map +1 -0
  76. package/dist/components/selected-team-switcher.d.mts +21 -0
  77. package/dist/components/selected-team-switcher.d.ts +21 -0
  78. package/dist/components/selected-team-switcher.js +119 -0
  79. package/dist/components/selected-team-switcher.js.map +1 -0
  80. package/dist/components/team-icon.d.mts +18 -0
  81. package/dist/components/team-icon.d.ts +18 -0
  82. package/dist/components/team-icon.js +39 -0
  83. package/dist/components/team-icon.js.map +1 -0
  84. package/dist/components/user-button.d.mts +15 -0
  85. package/dist/components/user-button.d.ts +15 -0
  86. package/dist/components/user-button.js +120 -0
  87. package/dist/components/user-button.js.map +1 -0
  88. package/dist/components-page/account-settings.d.mts +24 -0
  89. package/dist/components-page/account-settings.d.ts +24 -0
  90. package/dist/components-page/account-settings.js +1095 -0
  91. package/dist/components-page/account-settings.js.map +1 -0
  92. package/dist/components-page/auth-page.d.mts +24 -0
  93. package/dist/components-page/auth-page.d.ts +24 -0
  94. package/dist/components-page/auth-page.js +123 -0
  95. package/dist/components-page/auth-page.js.map +1 -0
  96. package/dist/components-page/email-verification.d.mts +8 -0
  97. package/dist/components-page/email-verification.d.ts +8 -0
  98. package/dist/components-page/email-verification.js +100 -0
  99. package/dist/components-page/email-verification.js.map +1 -0
  100. package/dist/components-page/error-page.d.mts +8 -0
  101. package/dist/components-page/error-page.d.ts +8 -0
  102. package/dist/components-page/error-page.js +97 -0
  103. package/dist/components-page/error-page.js.map +1 -0
  104. package/dist/components-page/forgot-password.d.mts +10 -0
  105. package/dist/components-page/forgot-password.d.ts +10 -0
  106. package/dist/components-page/forgot-password.js +117 -0
  107. package/dist/components-page/forgot-password.js.map +1 -0
  108. package/dist/components-page/magic-link-callback.d.mts +8 -0
  109. package/dist/components-page/magic-link-callback.d.ts +8 -0
  110. package/dist/components-page/magic-link-callback.js +110 -0
  111. package/dist/components-page/magic-link-callback.js.map +1 -0
  112. package/dist/components-page/oauth-callback.d.mts +7 -0
  113. package/dist/components-page/oauth-callback.d.ts +7 -0
  114. package/dist/components-page/oauth-callback.js +75 -0
  115. package/dist/components-page/oauth-callback.js.map +1 -0
  116. package/dist/components-page/password-reset.d.mts +12 -0
  117. package/dist/components-page/password-reset.d.ts +12 -0
  118. package/dist/components-page/password-reset.js +179 -0
  119. package/dist/components-page/password-reset.js.map +1 -0
  120. package/dist/components-page/sign-in.d.mts +10 -0
  121. package/dist/components-page/sign-in.d.ts +10 -0
  122. package/dist/components-page/sign-in.js +44 -0
  123. package/dist/components-page/sign-in.js.map +1 -0
  124. package/dist/components-page/sign-out.d.mts +7 -0
  125. package/dist/components-page/sign-out.d.ts +7 -0
  126. package/dist/components-page/sign-out.js +57 -0
  127. package/dist/components-page/sign-out.js.map +1 -0
  128. package/dist/components-page/sign-up.d.mts +11 -0
  129. package/dist/components-page/sign-up.d.ts +11 -0
  130. package/dist/components-page/sign-up.js +47 -0
  131. package/dist/components-page/sign-up.js.map +1 -0
  132. package/dist/components-page/stack-handler.d.mts +51 -0
  133. package/dist/components-page/stack-handler.d.ts +51 -0
  134. package/dist/components-page/stack-handler.js +244 -0
  135. package/dist/components-page/stack-handler.js.map +1 -0
  136. package/dist/components-page/team-creation.d.mts +7 -0
  137. package/dist/components-page/team-creation.d.ts +7 -0
  138. package/dist/components-page/team-creation.js +92 -0
  139. package/dist/components-page/team-creation.js.map +1 -0
  140. package/dist/components-page/team-invitation.d.mts +8 -0
  141. package/dist/components-page/team-invitation.d.ts +8 -0
  142. package/dist/components-page/team-invitation.js +144 -0
  143. package/dist/components-page/team-invitation.js.map +1 -0
  144. package/dist/esm/components/credential-sign-in.js +79 -0
  145. package/dist/esm/components/credential-sign-in.js.map +1 -0
  146. package/dist/esm/components/credential-sign-up.js +104 -0
  147. package/dist/esm/components/credential-sign-up.js.map +1 -0
  148. package/dist/esm/components/elements/form-warning.js +15 -0
  149. package/dist/esm/components/elements/form-warning.js.map +1 -0
  150. package/dist/esm/components/elements/maybe-full-page.js +50 -0
  151. package/dist/esm/components/elements/maybe-full-page.js.map +1 -0
  152. package/dist/esm/components/elements/separator-with-text.js +17 -0
  153. package/dist/esm/components/elements/separator-with-text.js.map +1 -0
  154. package/dist/esm/components/elements/sidebar-layout.js +102 -0
  155. package/dist/esm/components/elements/sidebar-layout.js.map +1 -0
  156. package/dist/esm/components/elements/ssr-layout-effect.js +23 -0
  157. package/dist/esm/components/elements/ssr-layout-effect.js.map +1 -0
  158. package/dist/esm/components/elements/user-avatar.js +16 -0
  159. package/dist/esm/components/elements/user-avatar.js.map +1 -0
  160. package/dist/esm/components/iframe-preventer.js +28 -0
  161. package/dist/esm/components/iframe-preventer.js.map +1 -0
  162. package/dist/esm/components/link.js +26 -0
  163. package/dist/esm/components/link.js.map +1 -0
  164. package/dist/esm/components/magic-link-sign-in.js +127 -0
  165. package/dist/esm/components/magic-link-sign-in.js.map +1 -0
  166. package/dist/esm/components/message-cards/known-error-message-card.js +37 -0
  167. package/dist/esm/components/message-cards/known-error-message-card.js.map +1 -0
  168. package/dist/esm/components/message-cards/message-card.js +21 -0
  169. package/dist/esm/components/message-cards/message-card.js.map +1 -0
  170. package/dist/esm/components/message-cards/predefined-message-card.js +83 -0
  171. package/dist/esm/components/message-cards/predefined-message-card.js.map +1 -0
  172. package/dist/esm/components/oauth-button-group.js +19 -0
  173. package/dist/esm/components/oauth-button-group.js.map +1 -0
  174. package/dist/esm/components/oauth-button.js +176 -0
  175. package/dist/esm/components/oauth-button.js.map +1 -0
  176. package/dist/esm/components/passkey-button.js +34 -0
  177. package/dist/esm/components/passkey-button.js.map +1 -0
  178. package/dist/esm/components/profile-image-editor.js +126 -0
  179. package/dist/esm/components/profile-image-editor.js.map +1 -0
  180. package/dist/esm/components/selected-team-switcher.js +107 -0
  181. package/dist/esm/components/selected-team-switcher.js.map +1 -0
  182. package/dist/esm/components/team-icon.js +14 -0
  183. package/dist/esm/components/team-icon.js.map +1 -0
  184. package/dist/esm/components/user-button.js +96 -0
  185. package/dist/esm/components/user-button.js.map +1 -0
  186. package/dist/esm/components-page/account-settings.js +1058 -0
  187. package/dist/esm/components-page/account-settings.js.map +1 -0
  188. package/dist/esm/components-page/auth-page.js +99 -0
  189. package/dist/esm/components-page/auth-page.js.map +1 -0
  190. package/dist/esm/components-page/email-verification.js +66 -0
  191. package/dist/esm/components-page/email-verification.js.map +1 -0
  192. package/dist/esm/components-page/error-page.js +73 -0
  193. package/dist/esm/components-page/error-page.js.map +1 -0
  194. package/dist/esm/components-page/forgot-password.js +92 -0
  195. package/dist/esm/components-page/forgot-password.js.map +1 -0
  196. package/dist/esm/components-page/magic-link-callback.js +76 -0
  197. package/dist/esm/components-page/magic-link-callback.js.map +1 -0
  198. package/dist/esm/components-page/oauth-callback.js +51 -0
  199. package/dist/esm/components-page/oauth-callback.js.map +1 -0
  200. package/dist/esm/components-page/password-reset.js +145 -0
  201. package/dist/esm/components-page/password-reset.js.map +1 -0
  202. package/dist/esm/components-page/sign-in.js +19 -0
  203. package/dist/esm/components-page/sign-in.js.map +1 -0
  204. package/dist/esm/components-page/sign-out.js +23 -0
  205. package/dist/esm/components-page/sign-out.js.map +1 -0
  206. package/dist/esm/components-page/sign-up.js +23 -0
  207. package/dist/esm/components-page/sign-up.js.map +1 -0
  208. package/dist/esm/components-page/stack-handler.js +223 -0
  209. package/dist/esm/components-page/stack-handler.js.map +1 -0
  210. package/dist/esm/components-page/team-creation.js +68 -0
  211. package/dist/esm/components-page/team-creation.js.map +1 -0
  212. package/dist/esm/components-page/team-invitation.js +110 -0
  213. package/dist/esm/components-page/team-invitation.js.map +1 -0
  214. package/dist/esm/generated/global-css.js +6 -0
  215. package/dist/esm/generated/global-css.js.map +1 -0
  216. package/dist/esm/generated/quetzal-translations.js +2397 -0
  217. package/dist/esm/generated/quetzal-translations.js.map +1 -0
  218. package/dist/esm/global.d.js +1 -0
  219. package/dist/esm/global.d.js.map +1 -0
  220. package/dist/esm/index.js +46 -0
  221. package/dist/esm/index.js.map +1 -0
  222. package/dist/esm/lib/auth.js +98 -0
  223. package/dist/esm/lib/auth.js.map +1 -0
  224. package/dist/esm/lib/cookie.js +244 -0
  225. package/dist/esm/lib/cookie.js.map +1 -0
  226. package/dist/esm/lib/hooks.js +30 -0
  227. package/dist/esm/lib/hooks.js.map +1 -0
  228. package/dist/esm/lib/stack-app.js +2398 -0
  229. package/dist/esm/lib/stack-app.js.map +1 -0
  230. package/dist/esm/lib/translations.js +23 -0
  231. package/dist/esm/lib/translations.js.map +1 -0
  232. package/dist/esm/providers/stack-provider-client.js +29 -0
  233. package/dist/esm/providers/stack-provider-client.js.map +1 -0
  234. package/dist/esm/providers/stack-provider.js +25 -0
  235. package/dist/esm/providers/stack-provider.js.map +1 -0
  236. package/dist/esm/providers/theme-provider.js +71 -0
  237. package/dist/esm/providers/theme-provider.js.map +1 -0
  238. package/dist/esm/providers/translation-provider-client.js +18 -0
  239. package/dist/esm/providers/translation-provider-client.js.map +1 -0
  240. package/dist/esm/providers/translation-provider.js +18 -0
  241. package/dist/esm/providers/translation-provider.js.map +1 -0
  242. package/dist/esm/utils/browser-script.js +112 -0
  243. package/dist/esm/utils/browser-script.js.map +1 -0
  244. package/dist/esm/utils/constants.js +66 -0
  245. package/dist/esm/utils/constants.js.map +1 -0
  246. package/dist/esm/utils/url.js +30 -0
  247. package/dist/esm/utils/url.js.map +1 -0
  248. package/dist/generated/global-css.d.mts +3 -0
  249. package/dist/generated/global-css.d.ts +3 -0
  250. package/dist/generated/global-css.js +31 -0
  251. package/dist/generated/global-css.js.map +1 -0
  252. package/dist/generated/quetzal-translations.d.mts +4 -0
  253. package/dist/generated/quetzal-translations.d.ts +4 -0
  254. package/dist/generated/quetzal-translations.js +2423 -0
  255. package/dist/generated/quetzal-translations.js.map +1 -0
  256. package/dist/global.d.d.mts +2 -0
  257. package/dist/global.d.d.ts +2 -0
  258. package/dist/global.d.js +2 -0
  259. package/dist/global.d.js.map +1 -0
  260. package/dist/index.d.mts +41 -0
  261. package/dist/index.d.ts +41 -0
  262. package/dist/index.js +103 -0
  263. package/dist/index.js.map +1 -0
  264. package/dist/lib/auth.d.mts +33 -0
  265. package/dist/lib/auth.d.ts +33 -0
  266. package/dist/lib/auth.js +125 -0
  267. package/dist/lib/auth.js.map +1 -0
  268. package/dist/lib/cookie.d.mts +33 -0
  269. package/dist/lib/cookie.d.ts +33 -0
  270. package/dist/lib/cookie.js +291 -0
  271. package/dist/lib/cookie.js.map +1 -0
  272. package/dist/lib/hooks.d.mts +41 -0
  273. package/dist/lib/hooks.d.ts +41 -0
  274. package/dist/lib/hooks.js +56 -0
  275. package/dist/lib/hooks.js.map +1 -0
  276. package/dist/lib/stack-app.d.mts +775 -0
  277. package/dist/lib/stack-app.d.ts +775 -0
  278. package/dist/lib/stack-app.js +2438 -0
  279. package/dist/lib/stack-app.js.map +1 -0
  280. package/dist/lib/translations.d.mts +5 -0
  281. package/dist/lib/translations.d.ts +5 -0
  282. package/dist/lib/translations.js +58 -0
  283. package/dist/lib/translations.js.map +1 -0
  284. package/dist/providers/stack-provider-client.d.mts +27 -0
  285. package/dist/providers/stack-provider-client.d.ts +27 -0
  286. package/dist/providers/stack-provider-client.js +65 -0
  287. package/dist/providers/stack-provider-client.js.map +1 -0
  288. package/dist/providers/stack-provider.d.mts +30 -0
  289. package/dist/providers/stack-provider.d.ts +30 -0
  290. package/dist/providers/stack-provider.js +46 -0
  291. package/dist/providers/stack-provider.js.map +1 -0
  292. package/dist/providers/theme-provider.d.mts +40 -0
  293. package/dist/providers/theme-provider.d.ts +40 -0
  294. package/dist/providers/theme-provider.js +105 -0
  295. package/dist/providers/theme-provider.js.map +1 -0
  296. package/dist/providers/translation-provider-client.d.mts +14 -0
  297. package/dist/providers/translation-provider-client.d.ts +14 -0
  298. package/dist/providers/translation-provider-client.js +43 -0
  299. package/dist/providers/translation-provider-client.js.map +1 -0
  300. package/dist/providers/translation-provider.d.mts +10 -0
  301. package/dist/providers/translation-provider.d.ts +10 -0
  302. package/dist/providers/translation-provider.js +43 -0
  303. package/dist/providers/translation-provider.js.map +1 -0
  304. package/dist/utils/browser-script.d.mts +7 -0
  305. package/dist/utils/browser-script.d.ts +7 -0
  306. package/dist/utils/browser-script.js +137 -0
  307. package/dist/utils/browser-script.js.map +1 -0
  308. package/dist/utils/constants.d.mts +79 -0
  309. package/dist/utils/constants.d.ts +79 -0
  310. package/dist/utils/constants.js +99 -0
  311. package/dist/utils/constants.js.map +1 -0
  312. package/dist/utils/url.d.mts +4 -0
  313. package/dist/utils/url.d.ts +4 -0
  314. package/dist/utils/url.js +56 -0
  315. package/dist/utils/url.js.map +1 -0
  316. package/package.json +96 -0
@@ -0,0 +1,2398 @@
1
+ // src/lib/stack-app.ts
2
+ import { WebAuthnError, startAuthentication, startRegistration } from "@simplewebauthn/browser";
3
+ import { KnownErrors, StackAdminInterface, StackClientInterface, StackServerInterface } from "@stackframe/stack-shared";
4
+ import { getProductionModeErrors } from "@stackframe/stack-shared/dist/helpers/production-mode";
5
+ import { InternalSession } from "@stackframe/stack-shared/dist/sessions";
6
+ import { encodeBase64 } from "@stackframe/stack-shared/dist/utils/bytes";
7
+ import { AsyncCache } from "@stackframe/stack-shared/dist/utils/caches";
8
+ import { isBrowserLike } from "@stackframe/stack-shared/dist/utils/env";
9
+ import { StackAssertionError, concatStacktraces, throwErr } from "@stackframe/stack-shared/dist/utils/errors";
10
+ import { DependenciesMap } from "@stackframe/stack-shared/dist/utils/maps";
11
+ import { deepPlainEquals, filterUndefined, omit, pick } from "@stackframe/stack-shared/dist/utils/objects";
12
+ import { neverResolve, runAsynchronously, wait } from "@stackframe/stack-shared/dist/utils/promises";
13
+ import { suspend, suspendIfSsr } from "@stackframe/stack-shared/dist/utils/react";
14
+ import { Result } from "@stackframe/stack-shared/dist/utils/results";
15
+ import { Store, storeLock } from "@stackframe/stack-shared/dist/utils/stores";
16
+ import { mergeScopeStrings } from "@stackframe/stack-shared/dist/utils/strings";
17
+ import { getRelativePart, isRelative } from "@stackframe/stack-shared/dist/utils/urls";
18
+ import { generateUuid } from "@stackframe/stack-shared/dist/utils/uuids";
19
+ import * as cookie from "cookie";
20
+ import React, { useCallback, useMemo } from "react";
21
+ import { constructRedirectUrl } from "../utils/url";
22
+ import { addNewOAuthProviderOrScope, callOAuthCallback, signInWithOAuth } from "./auth";
23
+ import { createBrowserCookieHelper, createCookieHelper, createEmptyCookieHelper, deleteCookieClient, getCookieClient, setOrDeleteCookie, setOrDeleteCookieClient } from "./cookie";
24
+ var isReactServer = false;
25
+ var clientVersion = "js @stackframe/react@2.7.20";
26
+ if (clientVersion.startsWith("STACK_COMPILE_TIME")) {
27
+ throw new StackAssertionError("Client version was not replaced. Something went wrong during build!");
28
+ }
29
+ var process = globalThis.process ?? { env: {} };
30
+ function getUrls(partial) {
31
+ const handler = partial.handler ?? "/handler";
32
+ const home = partial.home ?? "/";
33
+ const afterSignIn = partial.afterSignIn ?? home;
34
+ return {
35
+ handler,
36
+ signIn: `${handler}/sign-in`,
37
+ afterSignIn: home,
38
+ signUp: `${handler}/sign-up`,
39
+ afterSignUp: afterSignIn,
40
+ signOut: `${handler}/sign-out`,
41
+ afterSignOut: home,
42
+ emailVerification: `${handler}/email-verification`,
43
+ passwordReset: `${handler}/password-reset`,
44
+ forgotPassword: `${handler}/forgot-password`,
45
+ oauthCallback: `${handler}/oauth-callback`,
46
+ magicLinkCallback: `${handler}/magic-link-callback`,
47
+ home,
48
+ accountSettings: `${handler}/account-settings`,
49
+ error: `${handler}/error`,
50
+ teamInvitation: `${handler}/team-invitation`,
51
+ ...filterUndefined(partial)
52
+ };
53
+ }
54
+ function getDefaultProjectId() {
55
+ return process.env.NEXT_PUBLIC_STACK_PROJECT_ID || throwErr(new Error("Welcome to Stack Auth! It seems that you haven't provided a project ID. Please create a project on the Stack dashboard at https://app.stack-auth.com and put it in the NEXT_PUBLIC_STACK_PROJECT_ID environment variable."));
56
+ }
57
+ function getDefaultPublishableClientKey() {
58
+ return process.env.NEXT_PUBLIC_STACK_PUBLISHABLE_CLIENT_KEY || throwErr(new Error("Welcome to Stack Auth! It seems that you haven't provided a publishable client key. Please create an API key for your project on the Stack dashboard at https://app.stack-auth.com and copy your publishable client key into the NEXT_PUBLIC_STACK_PUBLISHABLE_CLIENT_KEY environment variable."));
59
+ }
60
+ function getDefaultSecretServerKey() {
61
+ return process.env.STACK_SECRET_SERVER_KEY || throwErr(new Error("No secret server key provided. Please copy your key from the Stack dashboard and put your it in the STACK_SECRET_SERVER_KEY environment variable."));
62
+ }
63
+ function getDefaultSuperSecretAdminKey() {
64
+ return process.env.STACK_SUPER_SECRET_ADMIN_KEY || throwErr(new Error("No super secret admin key provided. Please copy your key from the Stack dashboard and put it in the STACK_SUPER_SECRET_ADMIN_KEY environment variable."));
65
+ }
66
+ function getBaseUrl(userSpecifiedBaseUrl) {
67
+ let url;
68
+ if (userSpecifiedBaseUrl) {
69
+ if (typeof userSpecifiedBaseUrl === "string") {
70
+ url = userSpecifiedBaseUrl;
71
+ } else {
72
+ if (isBrowserLike()) {
73
+ url = userSpecifiedBaseUrl.browser;
74
+ } else {
75
+ url = userSpecifiedBaseUrl.server;
76
+ }
77
+ }
78
+ } else {
79
+ if (isBrowserLike()) {
80
+ url = process.env.NEXT_PUBLIC_BROWSER_STACK_API_URL;
81
+ } else {
82
+ url = process.env.NEXT_PUBLIC_SERVER_STACK_API_URL;
83
+ }
84
+ url = url || process.env.NEXT_PUBLIC_STACK_API_URL || process.env.NEXT_PUBLIC_STACK_URL || defaultBaseUrl;
85
+ }
86
+ return url.endsWith("/") ? url.slice(0, -1) : url;
87
+ }
88
+ var defaultBaseUrl = "https://api.stack-auth.com";
89
+ function createEmptyTokenStore() {
90
+ return new Store({
91
+ refreshToken: null,
92
+ accessToken: null
93
+ });
94
+ }
95
+ var cachePromiseByComponentId = /* @__PURE__ */ new Map();
96
+ function useAsyncCache(cache, dependencies, caller) {
97
+ suspendIfSsr(caller);
98
+ const id = React.useId();
99
+ const subscribe = useCallback((cb) => {
100
+ const { unsubscribe } = cache.onStateChange(dependencies, () => {
101
+ cachePromiseByComponentId.delete(id);
102
+ cb();
103
+ });
104
+ return unsubscribe;
105
+ }, [cache, ...dependencies]);
106
+ const getSnapshot = useCallback(() => {
107
+ if (!cachePromiseByComponentId.has(id)) {
108
+ cachePromiseByComponentId.set(id, cache.getOrWait(dependencies, "read-write"));
109
+ }
110
+ return cachePromiseByComponentId.get(id);
111
+ }, [cache, ...dependencies]);
112
+ const promise = React.useSyncExternalStore(
113
+ subscribe,
114
+ getSnapshot,
115
+ () => throwErr(new Error("getServerSnapshot should never be called in useAsyncCache because we restrict to CSR earlier"))
116
+ );
117
+ const result = React.use(promise);
118
+ if (result.status === "error") {
119
+ const error = result.error;
120
+ if (error instanceof Error && !error.__stackHasConcatenatedStacktraces) {
121
+ concatStacktraces(error, new Error());
122
+ error.__stackHasConcatenatedStacktraces = true;
123
+ }
124
+ throw error;
125
+ }
126
+ return result.data;
127
+ }
128
+ var stackAppInternalsSymbol = Symbol.for("StackAuth--DO-NOT-USE-OR-YOU-WILL-BE-FIRED--StackAppInternals");
129
+ var allClientApps = /* @__PURE__ */ new Map();
130
+ var createCache = (fetcher) => {
131
+ return new AsyncCache(
132
+ async (dependencies) => await Result.fromThrowingAsync(async () => await fetcher(dependencies)),
133
+ {}
134
+ );
135
+ };
136
+ var createCacheBySession = (fetcher) => {
137
+ return new AsyncCache(
138
+ async ([session, ...extraDependencies]) => await Result.fromThrowingAsync(async () => await fetcher(session, extraDependencies)),
139
+ {
140
+ onSubscribe: ([session], refresh) => {
141
+ const handler = session.onInvalidate(() => refresh());
142
+ return () => handler.unsubscribe();
143
+ }
144
+ }
145
+ );
146
+ };
147
+ var numberOfAppsCreated = 0;
148
+ var _StackClientAppImpl = class __StackClientAppImpl {
149
+ constructor(_options) {
150
+ this._options = _options;
151
+ this._uniqueIdentifier = void 0;
152
+ this.__DEMO_ENABLE_SLIGHT_FETCH_DELAY = false;
153
+ this._ownedAdminApps = new DependenciesMap();
154
+ this._currentUserCache = createCacheBySession(async (session) => {
155
+ if (this.__DEMO_ENABLE_SLIGHT_FETCH_DELAY) {
156
+ await wait(2e3);
157
+ }
158
+ if (session.isKnownToBeInvalid()) {
159
+ return null;
160
+ }
161
+ return await this._interface.getClientUserByToken(session);
162
+ });
163
+ this._currentProjectCache = createCache(async () => {
164
+ return Result.orThrow(await this._interface.getClientProject());
165
+ });
166
+ this._ownedProjectsCache = createCacheBySession(async (session) => {
167
+ return await this._interface.listProjects(session);
168
+ });
169
+ this._currentUserPermissionsCache = createCacheBySession(async (session, [teamId, recursive]) => {
170
+ return await this._interface.listCurrentUserTeamPermissions({ teamId, recursive }, session);
171
+ });
172
+ this._currentUserTeamsCache = createCacheBySession(async (session) => {
173
+ return await this._interface.listCurrentUserTeams(session);
174
+ });
175
+ this._currentUserOAuthConnectionAccessTokensCache = createCacheBySession(
176
+ async (session, [providerId, scope]) => {
177
+ try {
178
+ const result = await this._interface.createProviderAccessToken(providerId, scope || "", session);
179
+ return { accessToken: result.access_token };
180
+ } catch (err) {
181
+ if (!(err instanceof KnownErrors.OAuthConnectionDoesNotHaveRequiredScope || err instanceof KnownErrors.OAuthConnectionNotConnectedToUser)) {
182
+ throw err;
183
+ }
184
+ }
185
+ return null;
186
+ }
187
+ );
188
+ this._currentUserOAuthConnectionCache = createCacheBySession(
189
+ async (session, [providerId, scope, redirect]) => {
190
+ return await this._getUserOAuthConnectionCacheFn({
191
+ getUser: async () => Result.orThrow(await this._currentUserCache.getOrWait([session], "write-only")),
192
+ getOrWaitOAuthToken: async () => Result.orThrow(await this._currentUserOAuthConnectionAccessTokensCache.getOrWait([session, providerId, scope || ""], "write-only")),
193
+ useOAuthToken: () => useAsyncCache(this._currentUserOAuthConnectionAccessTokensCache, [session, providerId, scope || ""], "useOAuthToken"),
194
+ providerId,
195
+ scope,
196
+ redirect,
197
+ session
198
+ });
199
+ }
200
+ );
201
+ this._teamMemberProfilesCache = createCacheBySession(
202
+ async (session, [teamId]) => {
203
+ return await this._interface.listTeamMemberProfiles({ teamId }, session);
204
+ }
205
+ );
206
+ this._teamInvitationsCache = createCacheBySession(
207
+ async (session, [teamId]) => {
208
+ return await this._interface.listTeamInvitations({ teamId }, session);
209
+ }
210
+ );
211
+ this._currentUserTeamProfileCache = createCacheBySession(
212
+ async (session, [teamId]) => {
213
+ return await this._interface.getTeamMemberProfile({ teamId, userId: "me" }, session);
214
+ }
215
+ );
216
+ this._clientContactChannelsCache = createCacheBySession(
217
+ async (session) => {
218
+ return await this._interface.listClientContactChannels(session);
219
+ }
220
+ );
221
+ this._memoryTokenStore = createEmptyTokenStore();
222
+ this._requestTokenStores = /* @__PURE__ */ new WeakMap();
223
+ this._storedBrowserCookieTokenStore = null;
224
+ /**
225
+ * A map from token stores and session keys to sessions.
226
+ *
227
+ * This isn't just a map from session keys to sessions for two reasons:
228
+ *
229
+ * - So we can garbage-collect Session objects when the token store is garbage-collected
230
+ * - So different token stores are separated and don't leak information between each other, eg. if the same user sends two requests to the same server they should get a different session object
231
+ */
232
+ this._sessionsByTokenStoreAndSessionKey = /* @__PURE__ */ new WeakMap();
233
+ if ("interface" in _options) {
234
+ this._interface = _options.interface;
235
+ } else {
236
+ this._interface = new StackClientInterface({
237
+ getBaseUrl: () => getBaseUrl(_options.baseUrl),
238
+ projectId: _options.projectId ?? getDefaultProjectId(),
239
+ clientVersion,
240
+ publishableClientKey: _options.publishableClientKey ?? getDefaultPublishableClientKey(),
241
+ prepareRequest: async () => {
242
+ }
243
+ });
244
+ }
245
+ this._tokenStoreInit = _options.tokenStore;
246
+ this._redirectMethod = _options.redirectMethod || "none";
247
+ this._urlOptions = _options.urls ?? {};
248
+ this._oauthScopesOnSignIn = _options.oauthScopesOnSignIn ?? {};
249
+ if (_options.uniqueIdentifier) {
250
+ this._uniqueIdentifier = _options.uniqueIdentifier;
251
+ this._initUniqueIdentifier();
252
+ }
253
+ if (!_options.noAutomaticPrefetch) {
254
+ numberOfAppsCreated++;
255
+ if (numberOfAppsCreated > 10) {
256
+ (process.env.NODE_ENV === "development" ? console.log : console.warn)(`You have created more than 10 Stack apps with automatic pre-fetch enabled (${numberOfAppsCreated}). This is usually a sign of a memory leak, but can sometimes be caused by hot reload of your tech stack. If you are getting this error and it is not caused by hot reload, make sure to minimize the number of Stack apps per page (usually, one per project). (If it is caused by hot reload and does not occur in production, you can safely ignore it.)`);
257
+ }
258
+ }
259
+ }
260
+ async _createCookieHelper() {
261
+ if (this._tokenStoreInit === "nextjs-cookie" || this._tokenStoreInit === "cookie") {
262
+ return await createCookieHelper();
263
+ } else {
264
+ return await createEmptyCookieHelper();
265
+ }
266
+ }
267
+ async _getUserOAuthConnectionCacheFn(options) {
268
+ const user = await options.getUser();
269
+ let hasConnection = true;
270
+ if (!user || !user.oauth_providers.find((p) => p.id === options.providerId)) {
271
+ hasConnection = false;
272
+ }
273
+ const token = await options.getOrWaitOAuthToken();
274
+ if (!token) {
275
+ hasConnection = false;
276
+ }
277
+ if (!hasConnection && options.redirect) {
278
+ if (!options.session) {
279
+ throw new Error("No session found. You might be calling getConnectedAccount with redirect without having a user session.");
280
+ }
281
+ await addNewOAuthProviderOrScope(
282
+ this._interface,
283
+ {
284
+ provider: options.providerId,
285
+ redirectUrl: this.urls.oauthCallback,
286
+ errorRedirectUrl: this.urls.error,
287
+ providerScope: mergeScopeStrings(options.scope || "", (this._oauthScopesOnSignIn[options.providerId] ?? []).join(" "))
288
+ },
289
+ options.session
290
+ );
291
+ return await neverResolve();
292
+ } else if (!hasConnection) {
293
+ return null;
294
+ }
295
+ const app = this;
296
+ return {
297
+ id: options.providerId,
298
+ async getAccessToken() {
299
+ const result = await options.getOrWaitOAuthToken();
300
+ if (!result) {
301
+ throw new StackAssertionError("No access token available");
302
+ }
303
+ return result;
304
+ },
305
+ useAccessToken() {
306
+ const result = options.useOAuthToken();
307
+ if (!result) {
308
+ throw new StackAssertionError("No access token available");
309
+ }
310
+ return result;
311
+ }
312
+ };
313
+ }
314
+ _initUniqueIdentifier() {
315
+ if (!this._uniqueIdentifier) {
316
+ throw new StackAssertionError("Unique identifier not initialized");
317
+ }
318
+ if (allClientApps.has(this._uniqueIdentifier)) {
319
+ throw new StackAssertionError("A Stack client app with the same unique identifier already exists");
320
+ }
321
+ allClientApps.set(this._uniqueIdentifier, [this._options.checkString ?? "default check string", this]);
322
+ }
323
+ /**
324
+ * Cloudflare workers does not allow use of randomness on the global scope (on which the Stack app is probably
325
+ * initialized). For that reason, we generate the unique identifier lazily when it is first needed instead of in the
326
+ * constructor.
327
+ */
328
+ _getUniqueIdentifier() {
329
+ if (!this._uniqueIdentifier) {
330
+ this._uniqueIdentifier = generateUuid();
331
+ this._initUniqueIdentifier();
332
+ }
333
+ return this._uniqueIdentifier;
334
+ }
335
+ async _checkFeatureSupport(name, options) {
336
+ return await this._interface.checkFeatureSupport({ ...options, name });
337
+ }
338
+ _useCheckFeatureSupport(name, options) {
339
+ runAsynchronously(this._checkFeatureSupport(name, options));
340
+ throw new StackAssertionError(`${name} is not currently supported. Please reach out to Stack support for more information.`);
341
+ }
342
+ get _refreshTokenCookieName() {
343
+ return `stack-refresh-${this.projectId}`;
344
+ }
345
+ _getTokensFromCookies(cookies) {
346
+ const refreshToken = cookies.refreshTokenCookie;
347
+ const accessTokenObject = cookies.accessTokenCookie?.startsWith('["') ? JSON.parse(cookies.accessTokenCookie) : null;
348
+ const accessToken = accessTokenObject && refreshToken === accessTokenObject[0] ? accessTokenObject[1] : null;
349
+ return {
350
+ refreshToken,
351
+ accessToken
352
+ };
353
+ }
354
+ get _accessTokenCookieName() {
355
+ return `stack-access`;
356
+ }
357
+ _getBrowserCookieTokenStore() {
358
+ if (!isBrowserLike()) {
359
+ throw new Error("Cannot use cookie token store on the server!");
360
+ }
361
+ if (this._storedBrowserCookieTokenStore === null) {
362
+ const getCurrentValue = (old) => {
363
+ const tokens = this._getTokensFromCookies({
364
+ refreshTokenCookie: getCookieClient(this._refreshTokenCookieName) ?? getCookieClient("stack-refresh"),
365
+ // keep old cookie name for backwards-compatibility
366
+ accessTokenCookie: getCookieClient(this._accessTokenCookieName)
367
+ });
368
+ return {
369
+ refreshToken: tokens.refreshToken,
370
+ accessToken: tokens.accessToken ?? (old?.refreshToken === tokens.refreshToken ? old.accessToken : null)
371
+ };
372
+ };
373
+ this._storedBrowserCookieTokenStore = new Store(getCurrentValue(null));
374
+ let hasSucceededInWriting = true;
375
+ setInterval(() => {
376
+ if (hasSucceededInWriting) {
377
+ const oldValue = this._storedBrowserCookieTokenStore.get();
378
+ const currentValue = getCurrentValue(oldValue);
379
+ if (!deepPlainEquals(currentValue, oldValue)) {
380
+ this._storedBrowserCookieTokenStore.set(currentValue);
381
+ }
382
+ }
383
+ }, 100);
384
+ this._storedBrowserCookieTokenStore.onChange((value) => {
385
+ try {
386
+ setOrDeleteCookieClient(this._refreshTokenCookieName, value.refreshToken, { maxAge: 60 * 60 * 24 * 365 });
387
+ setOrDeleteCookieClient(this._accessTokenCookieName, value.accessToken ? JSON.stringify([value.refreshToken, value.accessToken]) : null, { maxAge: 60 * 60 * 24 });
388
+ deleteCookieClient("stack-refresh");
389
+ hasSucceededInWriting = true;
390
+ } catch (e) {
391
+ if (!isBrowserLike()) {
392
+ hasSucceededInWriting = false;
393
+ } else {
394
+ throw e;
395
+ }
396
+ }
397
+ });
398
+ }
399
+ return this._storedBrowserCookieTokenStore;
400
+ }
401
+ _getOrCreateTokenStore(cookieHelper, overrideTokenStoreInit) {
402
+ const tokenStoreInit = overrideTokenStoreInit === void 0 ? this._tokenStoreInit : overrideTokenStoreInit;
403
+ switch (tokenStoreInit) {
404
+ case "cookie": {
405
+ return this._getBrowserCookieTokenStore();
406
+ }
407
+ case "nextjs-cookie": {
408
+ if (isBrowserLike()) {
409
+ return this._getBrowserCookieTokenStore();
410
+ } else {
411
+ const tokens = this._getTokensFromCookies({
412
+ refreshTokenCookie: cookieHelper.get(this._refreshTokenCookieName) ?? cookieHelper.get("stack-refresh"),
413
+ // keep old cookie name for backwards-compatibility
414
+ accessTokenCookie: cookieHelper.get(this._accessTokenCookieName)
415
+ });
416
+ const store = new Store(tokens);
417
+ store.onChange((value) => {
418
+ runAsynchronously(async () => {
419
+ await Promise.all([
420
+ setOrDeleteCookie(this._refreshTokenCookieName, value.refreshToken, { maxAge: 60 * 60 * 24 * 365, noOpIfServerComponent: true }),
421
+ setOrDeleteCookie(this._accessTokenCookieName, value.accessToken ? JSON.stringify([value.refreshToken, value.accessToken]) : null, { maxAge: 60 * 60 * 24, noOpIfServerComponent: true })
422
+ ]);
423
+ });
424
+ });
425
+ return store;
426
+ }
427
+ }
428
+ case "memory": {
429
+ return this._memoryTokenStore;
430
+ }
431
+ default: {
432
+ if (tokenStoreInit === null) {
433
+ return createEmptyTokenStore();
434
+ } else if (typeof tokenStoreInit === "object" && "headers" in tokenStoreInit) {
435
+ if (this._requestTokenStores.has(tokenStoreInit)) return this._requestTokenStores.get(tokenStoreInit);
436
+ const stackAuthHeader = tokenStoreInit.headers.get("x-stack-auth");
437
+ if (stackAuthHeader) {
438
+ let parsed2;
439
+ try {
440
+ parsed2 = JSON.parse(stackAuthHeader);
441
+ if (typeof parsed2 !== "object") throw new Error("x-stack-auth header must be a JSON object");
442
+ if (parsed2 === null) throw new Error("x-stack-auth header must not be null");
443
+ } catch (e) {
444
+ throw new Error(`Invalid x-stack-auth header: ${stackAuthHeader}`, { cause: e });
445
+ }
446
+ return this._getOrCreateTokenStore(cookieHelper, {
447
+ accessToken: parsed2.accessToken ?? null,
448
+ refreshToken: parsed2.refreshToken ?? null
449
+ });
450
+ }
451
+ const cookieHeader = tokenStoreInit.headers.get("cookie");
452
+ const parsed = cookie.parse(cookieHeader || "");
453
+ const res = new Store({
454
+ refreshToken: parsed[this._refreshTokenCookieName] || parsed["stack-refresh"] || null,
455
+ // keep old cookie name for backwards-compatibility
456
+ accessToken: parsed[this._accessTokenCookieName] || null
457
+ });
458
+ this._requestTokenStores.set(tokenStoreInit, res);
459
+ return res;
460
+ } else if ("accessToken" in tokenStoreInit || "refreshToken" in tokenStoreInit) {
461
+ return new Store({
462
+ refreshToken: tokenStoreInit.refreshToken,
463
+ accessToken: tokenStoreInit.accessToken
464
+ });
465
+ }
466
+ throw new Error(`Invalid token store ${tokenStoreInit}`);
467
+ }
468
+ }
469
+ }
470
+ _useTokenStore(overrideTokenStoreInit) {
471
+ suspendIfSsr();
472
+ const cookieHelper = createBrowserCookieHelper();
473
+ const tokenStore = this._getOrCreateTokenStore(cookieHelper, overrideTokenStoreInit);
474
+ return tokenStore;
475
+ }
476
+ _getSessionFromTokenStore(tokenStore) {
477
+ const tokenObj = tokenStore.get();
478
+ const sessionKey = InternalSession.calculateSessionKey(tokenObj);
479
+ const existing = sessionKey ? this._sessionsByTokenStoreAndSessionKey.get(tokenStore)?.get(sessionKey) : null;
480
+ if (existing) return existing;
481
+ const session = this._interface.createSession({
482
+ refreshToken: tokenObj.refreshToken,
483
+ accessToken: tokenObj.accessToken
484
+ });
485
+ session.onAccessTokenChange((newAccessToken) => {
486
+ tokenStore.update((old) => ({
487
+ ...old,
488
+ accessToken: newAccessToken?.token ?? null
489
+ }));
490
+ });
491
+ session.onInvalidate(() => {
492
+ tokenStore.update((old) => ({
493
+ ...old,
494
+ accessToken: null,
495
+ refreshToken: null
496
+ }));
497
+ });
498
+ let sessionsBySessionKey = this._sessionsByTokenStoreAndSessionKey.get(tokenStore) ?? /* @__PURE__ */ new Map();
499
+ this._sessionsByTokenStoreAndSessionKey.set(tokenStore, sessionsBySessionKey);
500
+ sessionsBySessionKey.set(sessionKey, session);
501
+ return session;
502
+ }
503
+ async _getSession(overrideTokenStoreInit) {
504
+ const tokenStore = this._getOrCreateTokenStore(await this._createCookieHelper(), overrideTokenStoreInit);
505
+ return this._getSessionFromTokenStore(tokenStore);
506
+ }
507
+ _useSession(overrideTokenStoreInit) {
508
+ const tokenStore = this._useTokenStore(overrideTokenStoreInit);
509
+ const subscribe = useCallback((cb) => {
510
+ const { unsubscribe } = tokenStore.onChange(() => {
511
+ cb();
512
+ });
513
+ return unsubscribe;
514
+ }, [tokenStore]);
515
+ const getSnapshot = useCallback(() => this._getSessionFromTokenStore(tokenStore), [tokenStore]);
516
+ return React.useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
517
+ }
518
+ async _signInToAccountWithTokens(tokens) {
519
+ if (!("accessToken" in tokens) || !("refreshToken" in tokens)) {
520
+ throw new StackAssertionError("Invalid tokens object; can't sign in with this", { tokens });
521
+ }
522
+ const tokenStore = this._getOrCreateTokenStore(await this._createCookieHelper());
523
+ tokenStore.set(tokens);
524
+ }
525
+ _hasPersistentTokenStore(overrideTokenStoreInit) {
526
+ return (overrideTokenStoreInit !== void 0 ? overrideTokenStoreInit : this._tokenStoreInit) !== null;
527
+ }
528
+ _ensurePersistentTokenStore(overrideTokenStoreInit) {
529
+ if (!this._hasPersistentTokenStore(overrideTokenStoreInit)) {
530
+ throw new Error("Cannot call this function on a Stack app without a persistent token store. Make sure the tokenStore option on the constructor is set to a non-null value when initializing Stack.\n\nStack uses token stores to access access tokens of the current user. For example, on web frontends it is commonly the string value 'cookies' for cookie storage.");
531
+ }
532
+ }
533
+ _isInternalProject() {
534
+ return this.projectId === "internal";
535
+ }
536
+ _ensureInternalProject() {
537
+ if (!this._isInternalProject()) {
538
+ throw new Error("Cannot call this function on a Stack app with a project ID other than 'internal'.");
539
+ }
540
+ }
541
+ _clientProjectFromCrud(crud) {
542
+ return {
543
+ id: crud.id,
544
+ displayName: crud.display_name,
545
+ config: {
546
+ signUpEnabled: crud.config.sign_up_enabled,
547
+ credentialEnabled: crud.config.credential_enabled,
548
+ magicLinkEnabled: crud.config.magic_link_enabled,
549
+ passkeyEnabled: crud.config.passkey_enabled,
550
+ clientTeamCreationEnabled: crud.config.client_team_creation_enabled,
551
+ clientUserDeletionEnabled: crud.config.client_user_deletion_enabled,
552
+ oauthProviders: crud.config.enabled_oauth_providers.map((p) => ({
553
+ id: p.id
554
+ }))
555
+ }
556
+ };
557
+ }
558
+ _clientTeamPermissionFromCrud(crud) {
559
+ return {
560
+ id: crud.id
561
+ };
562
+ }
563
+ _clientTeamUserFromCrud(crud) {
564
+ return {
565
+ id: crud.user_id,
566
+ teamProfile: {
567
+ displayName: crud.display_name,
568
+ profileImageUrl: crud.profile_image_url
569
+ }
570
+ };
571
+ }
572
+ _clientTeamInvitationFromCrud(session, crud) {
573
+ return {
574
+ id: crud.id,
575
+ recipientEmail: crud.recipient_email,
576
+ expiresAt: new Date(crud.expires_at_millis),
577
+ revoke: async () => {
578
+ await this._interface.revokeTeamInvitation(crud.id, crud.team_id, session);
579
+ await this._teamInvitationsCache.refresh([session, crud.team_id]);
580
+ }
581
+ };
582
+ }
583
+ _clientTeamFromCrud(crud, session) {
584
+ const app = this;
585
+ return {
586
+ id: crud.id,
587
+ displayName: crud.display_name,
588
+ profileImageUrl: crud.profile_image_url,
589
+ clientMetadata: crud.client_metadata,
590
+ clientReadOnlyMetadata: crud.client_read_only_metadata,
591
+ async inviteUser(options) {
592
+ if (!options.callbackUrl && !await app._getCurrentUrl()) {
593
+ throw new Error("Cannot invite user without a callback URL from the server or without a redirect method. Make sure you pass the `callbackUrl` option: `inviteUser({ email, callbackUrl: ... })`");
594
+ }
595
+ await app._interface.sendTeamInvitation({
596
+ teamId: crud.id,
597
+ email: options.email,
598
+ session,
599
+ callbackUrl: options.callbackUrl ?? constructRedirectUrl(app.urls.teamInvitation)
600
+ });
601
+ await app._teamInvitationsCache.refresh([session, crud.id]);
602
+ },
603
+ async listUsers() {
604
+ const result = Result.orThrow(await app._teamMemberProfilesCache.getOrWait([session, crud.id], "write-only"));
605
+ return result.map((crud2) => app._clientTeamUserFromCrud(crud2));
606
+ },
607
+ useUsers() {
608
+ const result = useAsyncCache(app._teamMemberProfilesCache, [session, crud.id], "team.useUsers()");
609
+ return result.map((crud2) => app._clientTeamUserFromCrud(crud2));
610
+ },
611
+ async listInvitations() {
612
+ const result = Result.orThrow(await app._teamInvitationsCache.getOrWait([session, crud.id], "write-only"));
613
+ return result.map((crud2) => app._clientTeamInvitationFromCrud(session, crud2));
614
+ },
615
+ useInvitations() {
616
+ const result = useAsyncCache(app._teamInvitationsCache, [session, crud.id], "team.useInvitations()");
617
+ return result.map((crud2) => app._clientTeamInvitationFromCrud(session, crud2));
618
+ },
619
+ async update(data) {
620
+ await app._interface.updateTeam({ data: teamUpdateOptionsToCrud(data), teamId: crud.id }, session);
621
+ await app._currentUserTeamsCache.refresh([session]);
622
+ },
623
+ async delete() {
624
+ await app._interface.deleteTeam(crud.id, session);
625
+ await app._currentUserTeamsCache.refresh([session]);
626
+ }
627
+ };
628
+ }
629
+ _clientContactChannelFromCrud(crud, session) {
630
+ const app = this;
631
+ return {
632
+ id: crud.id,
633
+ value: crud.value,
634
+ type: crud.type,
635
+ isVerified: crud.is_verified,
636
+ isPrimary: crud.is_primary,
637
+ usedForAuth: crud.used_for_auth,
638
+ async sendVerificationEmail() {
639
+ await app._interface.sendCurrentUserContactChannelVerificationEmail(crud.id, constructRedirectUrl(app.urls.emailVerification), session);
640
+ },
641
+ async update(data) {
642
+ await app._interface.updateClientContactChannel(crud.id, contactChannelUpdateOptionsToCrud(data), session);
643
+ await app._clientContactChannelsCache.refresh([session]);
644
+ },
645
+ async delete() {
646
+ await app._interface.deleteClientContactChannel(crud.id, session);
647
+ await app._clientContactChannelsCache.refresh([session]);
648
+ }
649
+ };
650
+ }
651
+ _createAuth(session) {
652
+ const app = this;
653
+ return {
654
+ _internalSession: session,
655
+ currentSession: {
656
+ async getTokens() {
657
+ const tokens = await session.getOrFetchLikelyValidTokens(2e4);
658
+ return {
659
+ accessToken: tokens?.accessToken.token ?? null,
660
+ refreshToken: tokens?.refreshToken?.token ?? null
661
+ };
662
+ }
663
+ },
664
+ async getAuthHeaders() {
665
+ return {
666
+ "x-stack-auth": JSON.stringify(await this.getAuthJson())
667
+ };
668
+ },
669
+ async getAuthJson() {
670
+ const tokens = await this.currentSession.getTokens();
671
+ return tokens;
672
+ },
673
+ async registerPasskey(options) {
674
+ const hostname = (await app._getCurrentUrl())?.hostname;
675
+ if (!hostname) {
676
+ throw new StackAssertionError("hostname must be provided if the Stack App does not have a redirect method");
677
+ }
678
+ const initiationResult = await app._interface.initiatePasskeyRegistration({}, session);
679
+ if (initiationResult.status !== "ok") {
680
+ return Result.error(new KnownErrors.PasskeyRegistrationFailed("Failed to get initiation options for passkey registration"));
681
+ }
682
+ const { options_json, code } = initiationResult.data;
683
+ if (options_json.rp.id !== "THIS_VALUE_WILL_BE_REPLACED.example.com") {
684
+ throw new StackAssertionError(`Expected returned RP ID from server to equal sentinel, but found ${options_json.rp.id}`);
685
+ }
686
+ options_json.rp.id = hostname;
687
+ let attResp;
688
+ try {
689
+ attResp = await startRegistration({ optionsJSON: options_json });
690
+ debugger;
691
+ } catch (error) {
692
+ if (error instanceof WebAuthnError) {
693
+ return Result.error(new KnownErrors.PasskeyWebAuthnError(error.message, error.name));
694
+ } else {
695
+ return Result.error(new KnownErrors.PasskeyRegistrationFailed("Failed to start passkey registration"));
696
+ }
697
+ }
698
+ const registrationResult = await app._interface.registerPasskey({ credential: attResp, code }, session);
699
+ await app._refreshUser(session);
700
+ return registrationResult;
701
+ },
702
+ signOut(options) {
703
+ return app._signOut(session, options);
704
+ }
705
+ };
706
+ }
707
+ _editableTeamProfileFromCrud(crud, session) {
708
+ const app = this;
709
+ return {
710
+ displayName: crud.display_name,
711
+ profileImageUrl: crud.profile_image_url,
712
+ async update(update) {
713
+ await app._interface.updateTeamMemberProfile({
714
+ teamId: crud.team_id,
715
+ userId: crud.user_id,
716
+ profile: {
717
+ display_name: update.displayName,
718
+ profile_image_url: update.profileImageUrl
719
+ }
720
+ }, session);
721
+ await app._currentUserTeamProfileCache.refresh([session, crud.team_id]);
722
+ }
723
+ };
724
+ }
725
+ _createBaseUser(crud) {
726
+ return {
727
+ id: crud.id,
728
+ displayName: crud.display_name,
729
+ primaryEmail: crud.primary_email,
730
+ primaryEmailVerified: crud.primary_email_verified,
731
+ profileImageUrl: crud.profile_image_url,
732
+ signedUpAt: new Date(crud.signed_up_at_millis),
733
+ clientMetadata: crud.client_metadata,
734
+ clientReadOnlyMetadata: crud.client_read_only_metadata,
735
+ hasPassword: crud.has_password,
736
+ emailAuthEnabled: crud.auth_with_email,
737
+ otpAuthEnabled: crud.otp_auth_enabled,
738
+ oauthProviders: crud.oauth_providers,
739
+ passkeyAuthEnabled: crud.passkey_auth_enabled,
740
+ isMultiFactorRequired: crud.requires_totp_mfa,
741
+ toClientJson() {
742
+ return crud;
743
+ }
744
+ };
745
+ }
746
+ _createUserExtraFromCurrent(crud, session) {
747
+ const app = this;
748
+ async function getConnectedAccount(id, options) {
749
+ const scopeString = options?.scopes?.join(" ");
750
+ return Result.orThrow(await app._currentUserOAuthConnectionCache.getOrWait([session, id, scopeString || "", options?.or === "redirect"], "write-only"));
751
+ }
752
+ function useConnectedAccount(id, options) {
753
+ const scopeString = options?.scopes?.join(" ");
754
+ return useAsyncCache(app._currentUserOAuthConnectionCache, [session, id, scopeString || "", options?.or === "redirect"], "user.useConnectedAccount()");
755
+ }
756
+ return {
757
+ setDisplayName(displayName) {
758
+ return this.update({ displayName });
759
+ },
760
+ setClientMetadata(metadata) {
761
+ return this.update({ clientMetadata: metadata });
762
+ },
763
+ async setSelectedTeam(team) {
764
+ await this.update({ selectedTeamId: team?.id ?? null });
765
+ },
766
+ getConnectedAccount,
767
+ useConnectedAccount,
768
+ async getTeam(teamId) {
769
+ const teams = await this.listTeams();
770
+ return teams.find((t) => t.id === teamId) ?? null;
771
+ },
772
+ useTeam(teamId) {
773
+ const teams = this.useTeams();
774
+ return useMemo(() => {
775
+ return teams.find((t) => t.id === teamId) ?? null;
776
+ }, [teams, teamId]);
777
+ },
778
+ async listTeams() {
779
+ const teams = Result.orThrow(await app._currentUserTeamsCache.getOrWait([session], "write-only"));
780
+ return teams.map((crud2) => app._clientTeamFromCrud(crud2, session));
781
+ },
782
+ useTeams() {
783
+ const teams = useAsyncCache(app._currentUserTeamsCache, [session], "user.useTeams()");
784
+ return useMemo(() => teams.map((crud2) => app._clientTeamFromCrud(crud2, session)), [teams]);
785
+ },
786
+ async createTeam(data) {
787
+ const crud2 = await app._interface.createClientTeam(teamCreateOptionsToCrud(data, "me"), session);
788
+ await app._currentUserTeamsCache.refresh([session]);
789
+ return app._clientTeamFromCrud(crud2, session);
790
+ },
791
+ async leaveTeam(team) {
792
+ await app._interface.leaveTeam(team.id, session);
793
+ },
794
+ async listPermissions(scope, options) {
795
+ const recursive = options?.recursive ?? true;
796
+ const permissions = Result.orThrow(await app._currentUserPermissionsCache.getOrWait([session, scope.id, recursive], "write-only"));
797
+ return permissions.map((crud2) => app._clientTeamPermissionFromCrud(crud2));
798
+ },
799
+ usePermissions(scope, options) {
800
+ const recursive = options?.recursive ?? true;
801
+ const permissions = useAsyncCache(app._currentUserPermissionsCache, [session, scope.id, recursive], "user.usePermissions()");
802
+ return useMemo(() => permissions.map((crud2) => app._clientTeamPermissionFromCrud(crud2)), [permissions]);
803
+ },
804
+ usePermission(scope, permissionId) {
805
+ const permissions = this.usePermissions(scope);
806
+ return useMemo(() => permissions.find((p) => p.id === permissionId) ?? null, [permissions, permissionId]);
807
+ },
808
+ async getPermission(scope, permissionId) {
809
+ const permissions = await this.listPermissions(scope);
810
+ return permissions.find((p) => p.id === permissionId) ?? null;
811
+ },
812
+ async hasPermission(scope, permissionId) {
813
+ return await this.getPermission(scope, permissionId) !== null;
814
+ },
815
+ async update(update) {
816
+ return await app._updateClientUser(update, session);
817
+ },
818
+ async sendVerificationEmail(options) {
819
+ if (!crud.primary_email) {
820
+ throw new StackAssertionError("User does not have a primary email");
821
+ }
822
+ if (!options?.callbackUrl && !await app._getCurrentUrl()) {
823
+ throw new Error("Cannot send verification email without a callback URL from the server or without a redirect method. Make sure you pass the `callbackUrl` option: `sendVerificationEmail({ callbackUrl: ... })`");
824
+ }
825
+ return await app._interface.sendVerificationEmail(crud.primary_email, options?.callbackUrl ?? constructRedirectUrl(app.urls.emailVerification), session);
826
+ },
827
+ async updatePassword(options) {
828
+ const result = await app._interface.updatePassword(options, session);
829
+ await app._currentUserCache.refresh([session]);
830
+ return result;
831
+ },
832
+ async setPassword(options) {
833
+ const result = await app._interface.setPassword(options, session);
834
+ await app._currentUserCache.refresh([session]);
835
+ return result;
836
+ },
837
+ selectedTeam: crud.selected_team && this._clientTeamFromCrud(crud.selected_team, session),
838
+ async getTeamProfile(team) {
839
+ const result = Result.orThrow(await app._currentUserTeamProfileCache.getOrWait([session, team.id], "write-only"));
840
+ return app._editableTeamProfileFromCrud(result, session);
841
+ },
842
+ useTeamProfile(team) {
843
+ const result = useAsyncCache(app._currentUserTeamProfileCache, [session, team.id], "user.useTeamProfile()");
844
+ return app._editableTeamProfileFromCrud(result, session);
845
+ },
846
+ async delete() {
847
+ await app._interface.deleteCurrentUser(session);
848
+ session.markInvalid();
849
+ },
850
+ async listContactChannels() {
851
+ const result = Result.orThrow(await app._clientContactChannelsCache.getOrWait([session], "write-only"));
852
+ return result.map((crud2) => app._clientContactChannelFromCrud(crud2, session));
853
+ },
854
+ useContactChannels() {
855
+ const result = useAsyncCache(app._clientContactChannelsCache, [session], "user.useContactChannels()");
856
+ return result.map((crud2) => app._clientContactChannelFromCrud(crud2, session));
857
+ },
858
+ async createContactChannel(data) {
859
+ const crud2 = await app._interface.createClientContactChannel(contactChannelCreateOptionsToCrud("me", data), session);
860
+ await app._clientContactChannelsCache.refresh([session]);
861
+ return app._clientContactChannelFromCrud(crud2, session);
862
+ }
863
+ };
864
+ }
865
+ _createInternalUserExtra(session) {
866
+ const app = this;
867
+ this._ensureInternalProject();
868
+ return {
869
+ createProject(newProject) {
870
+ return app._createProject(session, newProject);
871
+ },
872
+ listOwnedProjects() {
873
+ return app._listOwnedProjects(session);
874
+ },
875
+ useOwnedProjects() {
876
+ return app._useOwnedProjects(session);
877
+ }
878
+ };
879
+ }
880
+ _currentUserFromCrud(crud, session) {
881
+ const currentUser = {
882
+ ...this._createBaseUser(crud),
883
+ ...this._createAuth(session),
884
+ ...this._createUserExtraFromCurrent(crud, session),
885
+ ...this._isInternalProject() ? this._createInternalUserExtra(session) : {}
886
+ };
887
+ Object.freeze(currentUser);
888
+ return currentUser;
889
+ }
890
+ _getOwnedAdminApp(forProjectId, session) {
891
+ if (!this._ownedAdminApps.has([session, forProjectId])) {
892
+ this._ownedAdminApps.set([session, forProjectId], new _StackAdminAppImpl({
893
+ baseUrl: this._interface.options.getBaseUrl(),
894
+ projectId: forProjectId,
895
+ tokenStore: null,
896
+ projectOwnerSession: session,
897
+ noAutomaticPrefetch: true
898
+ }));
899
+ }
900
+ return this._ownedAdminApps.get([session, forProjectId]);
901
+ }
902
+ get projectId() {
903
+ return this._interface.projectId;
904
+ }
905
+ async _isTrusted(url) {
906
+ return isRelative(url);
907
+ }
908
+ get urls() {
909
+ return getUrls(this._urlOptions);
910
+ }
911
+ async _getCurrentUrl() {
912
+ if (this._redirectMethod === "none") {
913
+ return null;
914
+ }
915
+ return new URL(window.location.href);
916
+ }
917
+ async _redirectTo(options) {
918
+ if (this._redirectMethod === "none") {
919
+ return;
920
+ } else if (typeof this._redirectMethod === "object" && this._redirectMethod.navigate) {
921
+ this._redirectMethod.navigate(options.url.toString());
922
+ } else {
923
+ if (options.replace) {
924
+ window.location.replace(options.url);
925
+ } else {
926
+ window.location.assign(options.url);
927
+ }
928
+ }
929
+ await wait(2e3);
930
+ }
931
+ useNavigate() {
932
+ if (typeof this._redirectMethod === "object") {
933
+ return this._redirectMethod.useNavigate();
934
+ } else if (this._redirectMethod === "window") {
935
+ return () => window.location.assign;
936
+ } else {
937
+ return (to) => {
938
+ };
939
+ }
940
+ }
941
+ async _redirectIfTrusted(url, options) {
942
+ if (!await this._isTrusted(url)) {
943
+ throw new Error(`Redirect URL ${url} is not trusted; should be relative.`);
944
+ }
945
+ return await this._redirectTo({ url, ...options });
946
+ }
947
+ async _redirectToHandler(handlerName, options) {
948
+ let url = this.urls[handlerName];
949
+ if (!url) {
950
+ throw new Error(`No URL for handler name ${handlerName}`);
951
+ }
952
+ if (!options?.noRedirectBack) {
953
+ if (handlerName === "afterSignIn" || handlerName === "afterSignUp") {
954
+ if (isReactServer || typeof window === "undefined") {
955
+ try {
956
+ await this._checkFeatureSupport("rsc-handler-" + handlerName, {});
957
+ } catch (e) {
958
+ }
959
+ } else {
960
+ const queryParams = new URLSearchParams(window.location.search);
961
+ url = queryParams.get("after_auth_return_to") || url;
962
+ }
963
+ } else if (handlerName === "signIn" || handlerName === "signUp") {
964
+ if (isReactServer || typeof window === "undefined") {
965
+ try {
966
+ await this._checkFeatureSupport("rsc-handler-" + handlerName, {});
967
+ } catch (e) {
968
+ }
969
+ } else {
970
+ const currentUrl = new URL(window.location.href);
971
+ const nextUrl = new URL(url, currentUrl);
972
+ if (currentUrl.searchParams.has("after_auth_return_to")) {
973
+ nextUrl.searchParams.set("after_auth_return_to", currentUrl.searchParams.get("after_auth_return_to"));
974
+ } else if (currentUrl.protocol === nextUrl.protocol && currentUrl.host === nextUrl.host) {
975
+ nextUrl.searchParams.set("after_auth_return_to", getRelativePart(currentUrl));
976
+ }
977
+ url = getRelativePart(nextUrl);
978
+ }
979
+ }
980
+ }
981
+ await this._redirectIfTrusted(url, options);
982
+ }
983
+ async redirectToSignIn(options) {
984
+ return await this._redirectToHandler("signIn", options);
985
+ }
986
+ async redirectToSignUp(options) {
987
+ return await this._redirectToHandler("signUp", options);
988
+ }
989
+ async redirectToSignOut(options) {
990
+ return await this._redirectToHandler("signOut", options);
991
+ }
992
+ async redirectToEmailVerification(options) {
993
+ return await this._redirectToHandler("emailVerification", options);
994
+ }
995
+ async redirectToPasswordReset(options) {
996
+ return await this._redirectToHandler("passwordReset", options);
997
+ }
998
+ async redirectToForgotPassword(options) {
999
+ return await this._redirectToHandler("forgotPassword", options);
1000
+ }
1001
+ async redirectToHome(options) {
1002
+ return await this._redirectToHandler("home", options);
1003
+ }
1004
+ async redirectToOAuthCallback(options) {
1005
+ return await this._redirectToHandler("oauthCallback", options);
1006
+ }
1007
+ async redirectToMagicLinkCallback(options) {
1008
+ return await this._redirectToHandler("magicLinkCallback", options);
1009
+ }
1010
+ async redirectToAfterSignIn(options) {
1011
+ return await this._redirectToHandler("afterSignIn", options);
1012
+ }
1013
+ async redirectToAfterSignUp(options) {
1014
+ return await this._redirectToHandler("afterSignUp", options);
1015
+ }
1016
+ async redirectToAfterSignOut(options) {
1017
+ return await this._redirectToHandler("afterSignOut", options);
1018
+ }
1019
+ async redirectToAccountSettings(options) {
1020
+ return await this._redirectToHandler("accountSettings", options);
1021
+ }
1022
+ async redirectToError(options) {
1023
+ return await this._redirectToHandler("error", options);
1024
+ }
1025
+ async redirectToTeamInvitation(options) {
1026
+ return await this._redirectToHandler("teamInvitation", options);
1027
+ }
1028
+ async sendForgotPasswordEmail(email, options) {
1029
+ if (!options?.callbackUrl && !await this._getCurrentUrl()) {
1030
+ throw new Error("Cannot send forgot password email without a callback URL from the server or without a redirect method. Make sure you pass the `callbackUrl` option: `sendForgotPasswordEmail({ email, callbackUrl: ... })`");
1031
+ }
1032
+ return await this._interface.sendForgotPasswordEmail(email, options?.callbackUrl ?? constructRedirectUrl(this.urls.passwordReset));
1033
+ }
1034
+ async sendMagicLinkEmail(email, options) {
1035
+ if (!options?.callbackUrl && !await this._getCurrentUrl()) {
1036
+ throw new Error("Cannot send magic link email without a callback URL from the server or without a redirect method. Make sure you pass the `callbackUrl` option: `sendMagicLinkEmail({ email, callbackUrl: ... })`");
1037
+ }
1038
+ return await this._interface.sendMagicLinkEmail(email, options?.callbackUrl ?? constructRedirectUrl(this.urls.magicLinkCallback));
1039
+ }
1040
+ async resetPassword(options) {
1041
+ return await this._interface.resetPassword(options);
1042
+ }
1043
+ async verifyPasswordResetCode(code) {
1044
+ return await this._interface.verifyPasswordResetCode(code);
1045
+ }
1046
+ async verifyTeamInvitationCode(code) {
1047
+ return await this._interface.acceptTeamInvitation({
1048
+ type: "check",
1049
+ code,
1050
+ session: await this._getSession()
1051
+ });
1052
+ }
1053
+ async acceptTeamInvitation(code) {
1054
+ const result = await this._interface.acceptTeamInvitation({
1055
+ type: "use",
1056
+ code,
1057
+ session: await this._getSession()
1058
+ });
1059
+ if (result.status === "ok") {
1060
+ return Result.ok(void 0);
1061
+ } else {
1062
+ return Result.error(result.error);
1063
+ }
1064
+ }
1065
+ async getTeamInvitationDetails(code) {
1066
+ const result = await this._interface.acceptTeamInvitation({
1067
+ type: "details",
1068
+ code,
1069
+ session: await this._getSession()
1070
+ });
1071
+ if (result.status === "ok") {
1072
+ return Result.ok({ teamDisplayName: result.data.team_display_name });
1073
+ } else {
1074
+ return Result.error(result.error);
1075
+ }
1076
+ }
1077
+ async verifyEmail(code) {
1078
+ const result = await this._interface.verifyEmail(code);
1079
+ await this._currentUserCache.refresh([await this._getSession()]);
1080
+ await this._clientContactChannelsCache.refresh([await this._getSession()]);
1081
+ return result;
1082
+ }
1083
+ async getUser(options) {
1084
+ this._ensurePersistentTokenStore(options?.tokenStore);
1085
+ const session = await this._getSession(options?.tokenStore);
1086
+ const crud = Result.orThrow(await this._currentUserCache.getOrWait([session], "write-only"));
1087
+ if (crud === null) {
1088
+ switch (options?.or) {
1089
+ case "redirect": {
1090
+ await this.redirectToSignIn({ replace: true });
1091
+ break;
1092
+ }
1093
+ case "throw": {
1094
+ throw new Error("User is not signed in but getUser was called with { or: 'throw' }");
1095
+ }
1096
+ default: {
1097
+ return null;
1098
+ }
1099
+ }
1100
+ }
1101
+ return crud && this._currentUserFromCrud(crud, session);
1102
+ }
1103
+ useUser(options) {
1104
+ this._ensurePersistentTokenStore(options?.tokenStore);
1105
+ const session = this._useSession(options?.tokenStore);
1106
+ const crud = useAsyncCache(this._currentUserCache, [session], "useUser()");
1107
+ if (crud === null) {
1108
+ switch (options?.or) {
1109
+ case "redirect": {
1110
+ runAsynchronously(this.redirectToSignIn({ replace: true }));
1111
+ suspend();
1112
+ throw new StackAssertionError("suspend should never return");
1113
+ }
1114
+ case "throw": {
1115
+ throw new Error("User is not signed in but useUser was called with { or: 'throw' }");
1116
+ }
1117
+ case void 0:
1118
+ case "return-null": {
1119
+ }
1120
+ }
1121
+ }
1122
+ return useMemo(() => {
1123
+ return crud && this._currentUserFromCrud(crud, session);
1124
+ }, [crud, session, options?.or]);
1125
+ }
1126
+ async _updateClientUser(update, session) {
1127
+ const res = await this._interface.updateClientUser(userUpdateOptionsToCrud(update), session);
1128
+ await this._refreshUser(session);
1129
+ return res;
1130
+ }
1131
+ async signInWithOAuth(provider) {
1132
+ if (typeof window === "undefined") {
1133
+ throw new Error("signInWithOAuth can currently only be called in a browser environment");
1134
+ }
1135
+ this._ensurePersistentTokenStore();
1136
+ await signInWithOAuth(
1137
+ this._interface,
1138
+ {
1139
+ provider,
1140
+ redirectUrl: this.urls.oauthCallback,
1141
+ errorRedirectUrl: this.urls.error,
1142
+ providerScope: this._oauthScopesOnSignIn[provider]?.join(" ")
1143
+ }
1144
+ );
1145
+ }
1146
+ /**
1147
+ * @deprecated
1148
+ * TODO remove
1149
+ */
1150
+ async _experimentalMfa(error, session) {
1151
+ const otp = prompt("Please enter the six-digit TOTP code from your authenticator app.");
1152
+ if (!otp) {
1153
+ throw new KnownErrors.InvalidTotpCode();
1154
+ }
1155
+ return await this._interface.totpMfa(
1156
+ error.details?.attempt_code ?? throwErr("attempt code missing"),
1157
+ otp,
1158
+ session
1159
+ );
1160
+ }
1161
+ /**
1162
+ * @deprecated
1163
+ * TODO remove
1164
+ */
1165
+ async _catchMfaRequiredError(callback) {
1166
+ try {
1167
+ return await callback();
1168
+ } catch (e) {
1169
+ if (e instanceof KnownErrors.MultiFactorAuthenticationRequired) {
1170
+ return Result.ok(await this._experimentalMfa(e, await this._getSession()));
1171
+ }
1172
+ throw e;
1173
+ }
1174
+ }
1175
+ async signInWithCredential(options) {
1176
+ this._ensurePersistentTokenStore();
1177
+ const session = await this._getSession();
1178
+ let result;
1179
+ try {
1180
+ result = await this._catchMfaRequiredError(async () => {
1181
+ return await this._interface.signInWithCredential(options.email, options.password, session);
1182
+ });
1183
+ } catch (e) {
1184
+ if (e instanceof KnownErrors.InvalidTotpCode) {
1185
+ return Result.error(e);
1186
+ }
1187
+ throw e;
1188
+ }
1189
+ if (result.status === "ok") {
1190
+ await this._signInToAccountWithTokens(result.data);
1191
+ if (!options.noRedirect) {
1192
+ await this.redirectToAfterSignIn({ replace: true });
1193
+ }
1194
+ return Result.ok(void 0);
1195
+ } else {
1196
+ return Result.error(result.error);
1197
+ }
1198
+ }
1199
+ async signUpWithCredential(options) {
1200
+ this._ensurePersistentTokenStore();
1201
+ const session = await this._getSession();
1202
+ const emailVerificationRedirectUrl = constructRedirectUrl(this.urls.emailVerification);
1203
+ const result = await this._interface.signUpWithCredential(
1204
+ options.email,
1205
+ options.password,
1206
+ emailVerificationRedirectUrl,
1207
+ session
1208
+ );
1209
+ if (result.status === "ok") {
1210
+ await this._signInToAccountWithTokens(result.data);
1211
+ if (!options.noRedirect) {
1212
+ await this.redirectToAfterSignUp({ replace: true });
1213
+ }
1214
+ return Result.ok(void 0);
1215
+ } else {
1216
+ return Result.error(result.error);
1217
+ }
1218
+ }
1219
+ async signInWithMagicLink(code) {
1220
+ this._ensurePersistentTokenStore();
1221
+ let result;
1222
+ try {
1223
+ result = await this._catchMfaRequiredError(async () => {
1224
+ return await this._interface.signInWithMagicLink(code);
1225
+ });
1226
+ } catch (e) {
1227
+ if (e instanceof KnownErrors.InvalidTotpCode) {
1228
+ return Result.error(e);
1229
+ }
1230
+ throw e;
1231
+ }
1232
+ if (result.status === "ok") {
1233
+ await this._signInToAccountWithTokens(result.data);
1234
+ if (result.data.newUser) {
1235
+ await this.redirectToAfterSignUp({ replace: true });
1236
+ } else {
1237
+ await this.redirectToAfterSignIn({ replace: true });
1238
+ }
1239
+ return Result.ok(void 0);
1240
+ } else {
1241
+ return Result.error(result.error);
1242
+ }
1243
+ }
1244
+ async signInWithPasskey() {
1245
+ this._ensurePersistentTokenStore();
1246
+ const session = await this._getSession();
1247
+ let result;
1248
+ try {
1249
+ result = await this._catchMfaRequiredError(async () => {
1250
+ const initiationResult = await this._interface.initiatePasskeyAuthentication({}, session);
1251
+ if (initiationResult.status !== "ok") {
1252
+ return Result.error(new KnownErrors.PasskeyAuthenticationFailed("Failed to get initiation options for passkey authentication"));
1253
+ }
1254
+ const { options_json, code } = initiationResult.data;
1255
+ if (options_json.rpId !== "THIS_VALUE_WILL_BE_REPLACED.example.com") {
1256
+ throw new StackAssertionError(`Expected returned RP ID from server to equal sentinel, but found ${options_json.rpId}`);
1257
+ }
1258
+ options_json.rpId = window.location.hostname;
1259
+ const authentication_response = await startAuthentication({ optionsJSON: options_json });
1260
+ return await this._interface.signInWithPasskey({ authentication_response, code });
1261
+ });
1262
+ } catch (error) {
1263
+ if (error instanceof WebAuthnError) {
1264
+ return Result.error(new KnownErrors.PasskeyWebAuthnError(error.message, error.name));
1265
+ } else {
1266
+ return Result.error(new KnownErrors.PasskeyAuthenticationFailed("Failed to sign in with passkey"));
1267
+ }
1268
+ }
1269
+ if (result.status === "ok") {
1270
+ await this._signInToAccountWithTokens(result.data);
1271
+ await this.redirectToAfterSignIn({ replace: true });
1272
+ return Result.ok(void 0);
1273
+ } else {
1274
+ return Result.error(result.error);
1275
+ }
1276
+ }
1277
+ async callOAuthCallback() {
1278
+ if (typeof window === "undefined") {
1279
+ throw new Error("callOAuthCallback can currently only be called in a browser environment");
1280
+ }
1281
+ this._ensurePersistentTokenStore();
1282
+ let result;
1283
+ try {
1284
+ result = await this._catchMfaRequiredError(async () => {
1285
+ return await callOAuthCallback(this._interface, this.urls.oauthCallback);
1286
+ });
1287
+ } catch (e) {
1288
+ if (e instanceof KnownErrors.InvalidTotpCode) {
1289
+ alert("Invalid TOTP code. Please try signing in again.");
1290
+ return false;
1291
+ } else {
1292
+ throw e;
1293
+ }
1294
+ }
1295
+ if (result.status === "ok" && result.data) {
1296
+ await this._signInToAccountWithTokens(result.data);
1297
+ if ("afterCallbackRedirectUrl" in result.data && result.data.afterCallbackRedirectUrl) {
1298
+ await this._redirectTo({ url: result.data.afterCallbackRedirectUrl, replace: true });
1299
+ return true;
1300
+ } else if (result.data.newUser) {
1301
+ await this.redirectToAfterSignUp({ replace: true });
1302
+ return true;
1303
+ } else {
1304
+ await this.redirectToAfterSignIn({ replace: true });
1305
+ return true;
1306
+ }
1307
+ }
1308
+ return false;
1309
+ }
1310
+ async _signOut(session, options) {
1311
+ await storeLock.withWriteLock(async () => {
1312
+ await this._interface.signOut(session);
1313
+ if (options?.redirectUrl) {
1314
+ await this._redirectTo({ url: options.redirectUrl, replace: true });
1315
+ } else {
1316
+ await this.redirectToAfterSignOut();
1317
+ }
1318
+ });
1319
+ }
1320
+ async signOut(options) {
1321
+ const user = await this.getUser();
1322
+ if (user) {
1323
+ await user.signOut(options);
1324
+ }
1325
+ }
1326
+ async getProject() {
1327
+ const crud = Result.orThrow(await this._currentProjectCache.getOrWait([], "write-only"));
1328
+ return this._clientProjectFromCrud(crud);
1329
+ }
1330
+ useProject() {
1331
+ const crud = useAsyncCache(this._currentProjectCache, [], "useProject()");
1332
+ return useMemo(() => this._clientProjectFromCrud(crud), [crud]);
1333
+ }
1334
+ async _listOwnedProjects(session) {
1335
+ this._ensureInternalProject();
1336
+ const crud = Result.orThrow(await this._ownedProjectsCache.getOrWait([session], "write-only"));
1337
+ return crud.map((j) => this._getOwnedAdminApp(j.id, session)._adminOwnedProjectFromCrud(
1338
+ j,
1339
+ () => this._refreshOwnedProjects(session)
1340
+ ));
1341
+ }
1342
+ _useOwnedProjects(session) {
1343
+ this._ensureInternalProject();
1344
+ const projects = useAsyncCache(this._ownedProjectsCache, [session], "useOwnedProjects()");
1345
+ return useMemo(() => projects.map((j) => this._getOwnedAdminApp(j.id, session)._adminOwnedProjectFromCrud(
1346
+ j,
1347
+ () => this._refreshOwnedProjects(session)
1348
+ )), [projects]);
1349
+ }
1350
+ async _createProject(session, newProject) {
1351
+ this._ensureInternalProject();
1352
+ const crud = await this._interface.createProject(adminProjectCreateOptionsToCrud(newProject), session);
1353
+ const res = this._getOwnedAdminApp(crud.id, session)._adminOwnedProjectFromCrud(
1354
+ crud,
1355
+ () => this._refreshOwnedProjects(session)
1356
+ );
1357
+ await this._refreshOwnedProjects(session);
1358
+ return res;
1359
+ }
1360
+ async _refreshUser(session) {
1361
+ await this._refreshSession(session);
1362
+ }
1363
+ async _refreshSession(session) {
1364
+ await this._currentUserCache.refresh([session]);
1365
+ }
1366
+ async _refreshUsers() {
1367
+ }
1368
+ async _refreshProject() {
1369
+ await this._currentProjectCache.refresh([]);
1370
+ }
1371
+ async _refreshOwnedProjects(session) {
1372
+ await this._ownedProjectsCache.refresh([session]);
1373
+ }
1374
+ static get [stackAppInternalsSymbol]() {
1375
+ return {
1376
+ fromClientJson: (json) => {
1377
+ const providedCheckString = JSON.stringify(omit(json, [
1378
+ /* none currently */
1379
+ ]));
1380
+ const existing = allClientApps.get(json.uniqueIdentifier);
1381
+ if (existing) {
1382
+ const [existingCheckString, clientApp] = existing;
1383
+ if (existingCheckString !== providedCheckString) {
1384
+ throw new StackAssertionError("The provided app JSON does not match the configuration of the existing client app with the same unique identifier", { providedObj: json, existingString: existingCheckString });
1385
+ }
1386
+ return clientApp;
1387
+ }
1388
+ return new __StackClientAppImpl({
1389
+ ...json,
1390
+ checkString: providedCheckString
1391
+ });
1392
+ }
1393
+ };
1394
+ }
1395
+ get [stackAppInternalsSymbol]() {
1396
+ return {
1397
+ toClientJson: () => {
1398
+ if (!("publishableClientKey" in this._interface.options)) {
1399
+ throw new StackAssertionError("Cannot serialize to JSON from an application without a publishable client key");
1400
+ }
1401
+ if (typeof this._redirectMethod !== "string") {
1402
+ throw new StackAssertionError("Cannot serialize to JSON from an application with a non-string redirect method");
1403
+ }
1404
+ return {
1405
+ baseUrl: this._options.baseUrl,
1406
+ projectId: this.projectId,
1407
+ publishableClientKey: this._interface.options.publishableClientKey,
1408
+ tokenStore: this._tokenStoreInit,
1409
+ urls: this._urlOptions,
1410
+ oauthScopesOnSignIn: this._oauthScopesOnSignIn,
1411
+ uniqueIdentifier: this._getUniqueIdentifier(),
1412
+ redirectMethod: this._redirectMethod
1413
+ };
1414
+ },
1415
+ setCurrentUser: (userJsonPromise) => {
1416
+ runAsynchronously(async () => {
1417
+ await this._currentUserCache.forceSetCachedValueAsync([await this._getSession()], Result.fromPromise(userJsonPromise));
1418
+ });
1419
+ },
1420
+ sendRequest: async (path, requestOptions, requestType = "client") => {
1421
+ return await this._interface.sendClientRequest(path, requestOptions, await this._getSession(), requestType);
1422
+ }
1423
+ };
1424
+ }
1425
+ };
1426
+ var _StackServerAppImpl = class extends _StackClientAppImpl {
1427
+ constructor(options) {
1428
+ super("interface" in options ? {
1429
+ interface: options.interface,
1430
+ tokenStore: options.tokenStore,
1431
+ urls: options.urls,
1432
+ oauthScopesOnSignIn: options.oauthScopesOnSignIn
1433
+ } : {
1434
+ interface: new StackServerInterface({
1435
+ getBaseUrl: () => getBaseUrl(options.baseUrl),
1436
+ projectId: options.projectId ?? getDefaultProjectId(),
1437
+ clientVersion,
1438
+ publishableClientKey: options.publishableClientKey ?? getDefaultPublishableClientKey(),
1439
+ secretServerKey: options.secretServerKey ?? getDefaultSecretServerKey()
1440
+ }),
1441
+ baseUrl: options.baseUrl,
1442
+ projectId: options.projectId,
1443
+ publishableClientKey: options.publishableClientKey,
1444
+ tokenStore: options.tokenStore,
1445
+ urls: options.urls ?? {},
1446
+ oauthScopesOnSignIn: options.oauthScopesOnSignIn ?? {},
1447
+ redirectMethod: options.redirectMethod
1448
+ });
1449
+ // TODO override the client user cache to use the server user cache, so we save some requests
1450
+ this._currentServerUserCache = createCacheBySession(async (session) => {
1451
+ if (session.isKnownToBeInvalid()) {
1452
+ return null;
1453
+ }
1454
+ return await this._interface.getServerUserByToken(session);
1455
+ });
1456
+ this._serverUsersCache = createCache(async ([cursor, limit, orderBy, desc, query]) => {
1457
+ return await this._interface.listServerUsers({ cursor, limit, orderBy, desc, query });
1458
+ });
1459
+ this._serverUserCache = createCache(async ([userId]) => {
1460
+ const user = await this._interface.getServerUserById(userId);
1461
+ return Result.or(user, null);
1462
+ });
1463
+ this._serverTeamsCache = createCache(async ([userId]) => {
1464
+ return await this._interface.listServerTeams({ userId });
1465
+ });
1466
+ this._serverTeamUserPermissionsCache = createCache(async ([teamId, userId, recursive]) => {
1467
+ return await this._interface.listServerTeamPermissions({ teamId, userId, recursive }, null);
1468
+ });
1469
+ this._serverUserOAuthConnectionAccessTokensCache = createCache(
1470
+ async ([userId, providerId, scope]) => {
1471
+ try {
1472
+ const result = await this._interface.createServerProviderAccessToken(userId, providerId, scope || "");
1473
+ return { accessToken: result.access_token };
1474
+ } catch (err) {
1475
+ if (!(err instanceof KnownErrors.OAuthConnectionDoesNotHaveRequiredScope || err instanceof KnownErrors.OAuthConnectionNotConnectedToUser)) {
1476
+ throw err;
1477
+ }
1478
+ }
1479
+ return null;
1480
+ }
1481
+ );
1482
+ this._serverUserOAuthConnectionCache = createCache(
1483
+ async ([userId, providerId, scope, redirect]) => {
1484
+ return await this._getUserOAuthConnectionCacheFn({
1485
+ getUser: async () => Result.orThrow(await this._serverUserCache.getOrWait([userId], "write-only")),
1486
+ getOrWaitOAuthToken: async () => Result.orThrow(await this._serverUserOAuthConnectionAccessTokensCache.getOrWait([userId, providerId, scope || ""], "write-only")),
1487
+ useOAuthToken: () => useAsyncCache(this._serverUserOAuthConnectionAccessTokensCache, [userId, providerId, scope || ""], "user.useConnectedAccount()"),
1488
+ providerId,
1489
+ scope,
1490
+ redirect,
1491
+ session: null
1492
+ });
1493
+ }
1494
+ );
1495
+ this._serverTeamMemberProfilesCache = createCache(
1496
+ async ([teamId]) => {
1497
+ return await this._interface.listServerTeamMemberProfiles({ teamId });
1498
+ }
1499
+ );
1500
+ this._serverTeamInvitationsCache = createCache(
1501
+ async ([teamId]) => {
1502
+ return await this._interface.listServerTeamInvitations({ teamId });
1503
+ }
1504
+ );
1505
+ this._serverUserTeamProfileCache = createCache(
1506
+ async ([teamId, userId]) => {
1507
+ return await this._interface.getServerTeamMemberProfile({ teamId, userId });
1508
+ }
1509
+ );
1510
+ this._serverContactChannelsCache = createCache(
1511
+ async ([userId]) => {
1512
+ return await this._interface.listServerContactChannels(userId);
1513
+ }
1514
+ );
1515
+ }
1516
+ async _updateServerUser(userId, update) {
1517
+ const result = await this._interface.updateServerUser(userId, serverUserUpdateOptionsToCrud(update));
1518
+ await this._refreshUsers();
1519
+ return result;
1520
+ }
1521
+ _serverEditableTeamProfileFromCrud(crud) {
1522
+ const app = this;
1523
+ return {
1524
+ displayName: crud.display_name,
1525
+ profileImageUrl: crud.profile_image_url,
1526
+ async update(update) {
1527
+ await app._interface.updateServerTeamMemberProfile({
1528
+ teamId: crud.team_id,
1529
+ userId: crud.user_id,
1530
+ profile: {
1531
+ display_name: update.displayName,
1532
+ profile_image_url: update.profileImageUrl
1533
+ }
1534
+ });
1535
+ await app._serverUserTeamProfileCache.refresh([crud.team_id, crud.user_id]);
1536
+ }
1537
+ };
1538
+ }
1539
+ _serverContactChannelFromCrud(userId, crud) {
1540
+ const app = this;
1541
+ return {
1542
+ id: crud.id,
1543
+ value: crud.value,
1544
+ type: crud.type,
1545
+ isVerified: crud.is_verified,
1546
+ isPrimary: crud.is_primary,
1547
+ usedForAuth: crud.used_for_auth,
1548
+ async sendVerificationEmail(options) {
1549
+ if (!options?.callbackUrl && !await app._getCurrentUrl()) {
1550
+ throw new Error("Cannot send verification email without a callback URL from the server or without a redirect method. Make sure you pass the `callbackUrl` option: `sendVerificationEmail({ callbackUrl: ... })`");
1551
+ }
1552
+ await app._interface.sendServerContactChannelVerificationEmail(userId, crud.id, options?.callbackUrl ?? constructRedirectUrl(app.urls.emailVerification));
1553
+ },
1554
+ async update(data) {
1555
+ await app._interface.updateServerContactChannel(userId, crud.id, serverContactChannelUpdateOptionsToCrud(data));
1556
+ },
1557
+ async delete() {
1558
+ await app._interface.deleteServerContactChannel(userId, crud.id);
1559
+ }
1560
+ };
1561
+ }
1562
+ _serverUserFromCrud(crud) {
1563
+ const app = this;
1564
+ async function getConnectedAccount(id, options) {
1565
+ const scopeString = options?.scopes?.join(" ");
1566
+ return Result.orThrow(await app._serverUserOAuthConnectionCache.getOrWait([crud.id, id, scopeString || "", options?.or === "redirect"], "write-only"));
1567
+ }
1568
+ function useConnectedAccount(id, options) {
1569
+ const scopeString = options?.scopes?.join(" ");
1570
+ return useAsyncCache(app._serverUserOAuthConnectionCache, [crud.id, id, scopeString || "", options?.or === "redirect"], "user.useConnectedAccount()");
1571
+ }
1572
+ return {
1573
+ ...super._createBaseUser(crud),
1574
+ lastActiveAt: new Date(crud.last_active_at_millis),
1575
+ serverMetadata: crud.server_metadata,
1576
+ async setPrimaryEmail(email, options) {
1577
+ await app._updateServerUser(crud.id, { primaryEmail: email, primaryEmailVerified: options?.verified });
1578
+ },
1579
+ async grantPermission(scope, permissionId) {
1580
+ await app._interface.grantServerTeamUserPermission(scope.id, crud.id, permissionId);
1581
+ for (const recursive of [true, false]) {
1582
+ await app._serverTeamUserPermissionsCache.refresh([scope.id, crud.id, recursive]);
1583
+ }
1584
+ },
1585
+ async revokePermission(scope, permissionId) {
1586
+ await app._interface.revokeServerTeamUserPermission(scope.id, crud.id, permissionId);
1587
+ for (const recursive of [true, false]) {
1588
+ await app._serverTeamUserPermissionsCache.refresh([scope.id, crud.id, recursive]);
1589
+ }
1590
+ },
1591
+ async delete() {
1592
+ const res = await app._interface.deleteServerServerUser(crud.id);
1593
+ await app._refreshUsers();
1594
+ return res;
1595
+ },
1596
+ async createSession(options) {
1597
+ const tokens = await app._interface.createServerUserSession(crud.id, options.expiresInMillis ?? 1e3 * 60 * 60 * 24 * 365);
1598
+ return {
1599
+ async getTokens() {
1600
+ return tokens;
1601
+ }
1602
+ };
1603
+ },
1604
+ async setDisplayName(displayName) {
1605
+ return await this.update({ displayName });
1606
+ },
1607
+ async setClientMetadata(metadata) {
1608
+ return await this.update({ clientMetadata: metadata });
1609
+ },
1610
+ async setClientReadOnlyMetadata(metadata) {
1611
+ return await this.update({ clientReadOnlyMetadata: metadata });
1612
+ },
1613
+ async setServerMetadata(metadata) {
1614
+ return await this.update({ serverMetadata: metadata });
1615
+ },
1616
+ async setSelectedTeam(team) {
1617
+ return await this.update({ selectedTeamId: team?.id ?? null });
1618
+ },
1619
+ getConnectedAccount,
1620
+ useConnectedAccount,
1621
+ selectedTeam: crud.selected_team ? app._serverTeamFromCrud(crud.selected_team) : null,
1622
+ async getTeam(teamId) {
1623
+ const teams = await this.listTeams();
1624
+ return teams.find((t) => t.id === teamId) ?? null;
1625
+ },
1626
+ useTeam(teamId) {
1627
+ const teams = this.useTeams();
1628
+ return useMemo(() => {
1629
+ return teams.find((t) => t.id === teamId) ?? null;
1630
+ }, [teams, teamId]);
1631
+ },
1632
+ async listTeams() {
1633
+ const teams = Result.orThrow(await app._serverTeamsCache.getOrWait([crud.id], "write-only"));
1634
+ return teams.map((t) => app._serverTeamFromCrud(t));
1635
+ },
1636
+ useTeams() {
1637
+ const teams = useAsyncCache(app._serverTeamsCache, [crud.id], "user.useTeams()");
1638
+ return useMemo(() => teams.map((t) => app._serverTeamFromCrud(t)), [teams]);
1639
+ },
1640
+ createTeam: async (data) => {
1641
+ const team = await app._interface.createServerTeam(serverTeamCreateOptionsToCrud({
1642
+ creatorUserId: crud.id,
1643
+ ...data
1644
+ }));
1645
+ await app._serverTeamsCache.refresh([void 0]);
1646
+ return app._serverTeamFromCrud(team);
1647
+ },
1648
+ leaveTeam: async (team) => {
1649
+ await app._interface.leaveServerTeam({ teamId: team.id, userId: crud.id });
1650
+ },
1651
+ async listPermissions(scope, options) {
1652
+ const recursive = options?.recursive ?? true;
1653
+ const permissions = Result.orThrow(await app._serverTeamUserPermissionsCache.getOrWait([scope.id, crud.id, recursive], "write-only"));
1654
+ return permissions.map((crud2) => app._serverPermissionFromCrud(crud2));
1655
+ },
1656
+ usePermissions(scope, options) {
1657
+ const recursive = options?.recursive ?? true;
1658
+ const permissions = useAsyncCache(app._serverTeamUserPermissionsCache, [scope.id, crud.id, recursive], "user.usePermissions()");
1659
+ return useMemo(() => permissions.map((crud2) => app._serverPermissionFromCrud(crud2)), [permissions]);
1660
+ },
1661
+ async getPermission(scope, permissionId) {
1662
+ const permissions = await this.listPermissions(scope);
1663
+ return permissions.find((p) => p.id === permissionId) ?? null;
1664
+ },
1665
+ usePermission(scope, permissionId) {
1666
+ const permissions = this.usePermissions(scope);
1667
+ return useMemo(() => permissions.find((p) => p.id === permissionId) ?? null, [permissions, permissionId]);
1668
+ },
1669
+ async hasPermission(scope, permissionId) {
1670
+ return await this.getPermission(scope, permissionId) !== null;
1671
+ },
1672
+ async update(update) {
1673
+ await app._updateServerUser(crud.id, update);
1674
+ },
1675
+ async sendVerificationEmail() {
1676
+ return await app._checkFeatureSupport("sendVerificationEmail() on ServerUser", {});
1677
+ },
1678
+ async updatePassword(options) {
1679
+ const result = await this.update({ password: options.newPassword });
1680
+ await app._serverUserCache.refresh([crud.id]);
1681
+ return result;
1682
+ },
1683
+ async setPassword(options) {
1684
+ const result = await this.update(options);
1685
+ await app._serverUserCache.refresh([crud.id]);
1686
+ return result;
1687
+ },
1688
+ async getTeamProfile(team) {
1689
+ const result = Result.orThrow(await app._serverUserTeamProfileCache.getOrWait([team.id, crud.id], "write-only"));
1690
+ return app._serverEditableTeamProfileFromCrud(result);
1691
+ },
1692
+ useTeamProfile(team) {
1693
+ const result = useAsyncCache(app._serverUserTeamProfileCache, [team.id, crud.id], "user.useTeamProfile()");
1694
+ return useMemo(() => app._serverEditableTeamProfileFromCrud(result), [result]);
1695
+ },
1696
+ async listContactChannels() {
1697
+ const result = Result.orThrow(await app._serverContactChannelsCache.getOrWait([crud.id], "write-only"));
1698
+ return result.map((data) => app._serverContactChannelFromCrud(crud.id, data));
1699
+ },
1700
+ useContactChannels() {
1701
+ const result = useAsyncCache(app._serverContactChannelsCache, [crud.id], "user.useContactChannels()");
1702
+ return useMemo(() => result.map((data) => app._serverContactChannelFromCrud(crud.id, data)), [result]);
1703
+ },
1704
+ createContactChannel: async (data) => {
1705
+ const contactChannel = await app._interface.createServerContactChannel(serverContactChannelCreateOptionsToCrud(crud.id, data));
1706
+ await app._serverContactChannelsCache.refresh([crud.id]);
1707
+ return app._serverContactChannelFromCrud(crud.id, contactChannel);
1708
+ }
1709
+ };
1710
+ }
1711
+ _serverTeamUserFromCrud(crud) {
1712
+ return {
1713
+ ...this._serverUserFromCrud(crud.user),
1714
+ teamProfile: {
1715
+ displayName: crud.display_name,
1716
+ profileImageUrl: crud.profile_image_url
1717
+ }
1718
+ };
1719
+ }
1720
+ _serverTeamInvitationFromCrud(crud) {
1721
+ return {
1722
+ id: crud.id,
1723
+ recipientEmail: crud.recipient_email,
1724
+ expiresAt: new Date(crud.expires_at_millis),
1725
+ revoke: async () => {
1726
+ await this._interface.revokeServerTeamInvitation(crud.id, crud.team_id);
1727
+ }
1728
+ };
1729
+ }
1730
+ _currentUserFromCrud(crud, session) {
1731
+ const app = this;
1732
+ const currentUser = {
1733
+ ...this._serverUserFromCrud(crud),
1734
+ ...this._createAuth(session),
1735
+ ...this._isInternalProject() ? this._createInternalUserExtra(session) : {}
1736
+ };
1737
+ Object.freeze(currentUser);
1738
+ return currentUser;
1739
+ }
1740
+ _serverTeamFromCrud(crud) {
1741
+ const app = this;
1742
+ return {
1743
+ id: crud.id,
1744
+ displayName: crud.display_name,
1745
+ profileImageUrl: crud.profile_image_url,
1746
+ createdAt: new Date(crud.created_at_millis),
1747
+ clientMetadata: crud.client_metadata,
1748
+ clientReadOnlyMetadata: crud.client_read_only_metadata,
1749
+ serverMetadata: crud.server_metadata,
1750
+ async update(update) {
1751
+ await app._interface.updateServerTeam(crud.id, serverTeamUpdateOptionsToCrud(update));
1752
+ await app._serverTeamsCache.refresh([void 0]);
1753
+ },
1754
+ async delete() {
1755
+ await app._interface.deleteServerTeam(crud.id);
1756
+ await app._serverTeamsCache.refresh([void 0]);
1757
+ },
1758
+ async listUsers() {
1759
+ const result = Result.orThrow(await app._serverTeamMemberProfilesCache.getOrWait([crud.id], "write-only"));
1760
+ return result.map((u) => app._serverTeamUserFromCrud(u));
1761
+ },
1762
+ useUsers() {
1763
+ const result = useAsyncCache(app._serverTeamMemberProfilesCache, [crud.id], "team.useUsers()");
1764
+ return useMemo(() => result.map((u) => app._serverTeamUserFromCrud(u)), [result]);
1765
+ },
1766
+ async addUser(userId) {
1767
+ await app._interface.addServerUserToTeam({
1768
+ teamId: crud.id,
1769
+ userId
1770
+ });
1771
+ await app._serverTeamMemberProfilesCache.refresh([crud.id]);
1772
+ },
1773
+ async removeUser(userId) {
1774
+ await app._interface.removeServerUserFromTeam({
1775
+ teamId: crud.id,
1776
+ userId
1777
+ });
1778
+ await app._serverTeamMemberProfilesCache.refresh([crud.id]);
1779
+ },
1780
+ async inviteUser(options) {
1781
+ if (!options.callbackUrl && !await app._getCurrentUrl()) {
1782
+ throw new Error("Cannot invite user without a callback URL from the server or without a redirect method. Make sure you pass the `callbackUrl` option: `inviteUser({ email, callbackUrl: ... })`");
1783
+ }
1784
+ await app._interface.sendServerTeamInvitation({
1785
+ teamId: crud.id,
1786
+ email: options.email,
1787
+ callbackUrl: options.callbackUrl ?? constructRedirectUrl(app.urls.teamInvitation)
1788
+ });
1789
+ await app._serverTeamInvitationsCache.refresh([crud.id]);
1790
+ },
1791
+ async listInvitations() {
1792
+ const result = Result.orThrow(await app._serverTeamInvitationsCache.getOrWait([crud.id], "write-only"));
1793
+ return result.map((crud2) => app._serverTeamInvitationFromCrud(crud2));
1794
+ },
1795
+ useInvitations() {
1796
+ const result = useAsyncCache(app._serverTeamInvitationsCache, [crud.id], "team.useInvitations()");
1797
+ return useMemo(() => result.map((crud2) => app._serverTeamInvitationFromCrud(crud2)), [result]);
1798
+ }
1799
+ };
1800
+ }
1801
+ async createUser(options) {
1802
+ const crud = await this._interface.createServerUser(serverUserCreateOptionsToCrud(options));
1803
+ await this._refreshUsers();
1804
+ return this._serverUserFromCrud(crud);
1805
+ }
1806
+ async getUser(options) {
1807
+ if (typeof options === "string") {
1808
+ return await this.getServerUserById(options);
1809
+ } else {
1810
+ this._ensurePersistentTokenStore(options?.tokenStore);
1811
+ const session = await this._getSession(options?.tokenStore);
1812
+ const crud = Result.orThrow(await this._currentServerUserCache.getOrWait([session], "write-only"));
1813
+ if (crud === null) {
1814
+ switch (options?.or) {
1815
+ case "redirect": {
1816
+ await this.redirectToSignIn({ replace: true });
1817
+ break;
1818
+ }
1819
+ case "throw": {
1820
+ throw new Error("User is not signed in but getUser was called with { or: 'throw' }");
1821
+ }
1822
+ default: {
1823
+ return null;
1824
+ }
1825
+ }
1826
+ }
1827
+ return crud && this._currentUserFromCrud(crud, session);
1828
+ }
1829
+ }
1830
+ async getServerUser() {
1831
+ console.warn("stackServerApp.getServerUser is deprecated; use stackServerApp.getUser instead");
1832
+ return await this.getUser();
1833
+ }
1834
+ async getServerUserById(userId) {
1835
+ const crud = Result.orThrow(await this._serverUserCache.getOrWait([userId], "write-only"));
1836
+ return crud && this._serverUserFromCrud(crud);
1837
+ }
1838
+ useUser(options) {
1839
+ if (typeof options === "string") {
1840
+ return this.useUserById(options);
1841
+ } else {
1842
+ this._ensurePersistentTokenStore(options?.tokenStore);
1843
+ const session = this._useSession(options?.tokenStore);
1844
+ const crud = useAsyncCache(this._currentServerUserCache, [session], "useUser()");
1845
+ if (crud === null) {
1846
+ switch (options?.or) {
1847
+ case "redirect": {
1848
+ runAsynchronously(this.redirectToSignIn({ replace: true }));
1849
+ suspend();
1850
+ throw new StackAssertionError("suspend should never return");
1851
+ }
1852
+ case "throw": {
1853
+ throw new Error("User is not signed in but useUser was called with { or: 'throw' }");
1854
+ }
1855
+ case void 0:
1856
+ case "return-null": {
1857
+ }
1858
+ }
1859
+ }
1860
+ return useMemo(() => {
1861
+ return crud && this._currentUserFromCrud(crud, session);
1862
+ }, [crud, session, options?.or]);
1863
+ }
1864
+ }
1865
+ useUserById(userId) {
1866
+ const crud = useAsyncCache(this._serverUserCache, [userId], "useUserById()");
1867
+ return useMemo(() => {
1868
+ return crud && this._serverUserFromCrud(crud);
1869
+ }, [crud]);
1870
+ }
1871
+ async listUsers(options) {
1872
+ const crud = Result.orThrow(await this._serverUsersCache.getOrWait([options?.cursor, options?.limit, options?.orderBy, options?.desc, options?.query], "write-only"));
1873
+ const result = crud.items.map((j) => this._serverUserFromCrud(j));
1874
+ result.nextCursor = crud.pagination?.next_cursor ?? null;
1875
+ return result;
1876
+ }
1877
+ useUsers(options) {
1878
+ const crud = useAsyncCache(this._serverUsersCache, [options?.cursor, options?.limit, options?.orderBy, options?.desc, options?.query], "useServerUsers()");
1879
+ const result = crud.items.map((j) => this._serverUserFromCrud(j));
1880
+ result.nextCursor = crud.pagination?.next_cursor ?? null;
1881
+ return result;
1882
+ }
1883
+ _serverPermissionFromCrud(crud) {
1884
+ return {
1885
+ id: crud.id
1886
+ };
1887
+ }
1888
+ _serverTeamPermissionDefinitionFromCrud(crud) {
1889
+ return {
1890
+ id: crud.id,
1891
+ description: crud.description,
1892
+ containedPermissionIds: crud.contained_permission_ids
1893
+ };
1894
+ }
1895
+ async listTeams() {
1896
+ const teams = Result.orThrow(await this._serverTeamsCache.getOrWait([void 0], "write-only"));
1897
+ return teams.map((t) => this._serverTeamFromCrud(t));
1898
+ }
1899
+ async createTeam(data) {
1900
+ const team = await this._interface.createServerTeam(serverTeamCreateOptionsToCrud(data));
1901
+ await this._serverTeamsCache.refresh([void 0]);
1902
+ return this._serverTeamFromCrud(team);
1903
+ }
1904
+ useTeams() {
1905
+ const teams = useAsyncCache(this._serverTeamsCache, [void 0], "useServerTeams()");
1906
+ return useMemo(() => {
1907
+ return teams.map((t) => this._serverTeamFromCrud(t));
1908
+ }, [teams]);
1909
+ }
1910
+ async getTeam(teamId) {
1911
+ const teams = await this.listTeams();
1912
+ return teams.find((t) => t.id === teamId) ?? null;
1913
+ }
1914
+ useTeam(teamId) {
1915
+ const teams = this.useTeams();
1916
+ return useMemo(() => {
1917
+ return teams.find((t) => t.id === teamId) ?? null;
1918
+ }, [teams, teamId]);
1919
+ }
1920
+ async _refreshSession(session) {
1921
+ await Promise.all([
1922
+ super._refreshUser(session),
1923
+ this._currentServerUserCache.refresh([session])
1924
+ ]);
1925
+ }
1926
+ async _refreshUsers() {
1927
+ await Promise.all([
1928
+ super._refreshUsers(),
1929
+ this._serverUserCache.refreshWhere(() => true),
1930
+ this._serverUsersCache.refreshWhere(() => true),
1931
+ this._serverContactChannelsCache.refreshWhere(() => true)
1932
+ ]);
1933
+ }
1934
+ };
1935
+ var _StackAdminAppImpl = class extends _StackServerAppImpl {
1936
+ constructor(options) {
1937
+ super({
1938
+ interface: new StackAdminInterface({
1939
+ getBaseUrl: () => getBaseUrl(options.baseUrl),
1940
+ projectId: options.projectId ?? getDefaultProjectId(),
1941
+ clientVersion,
1942
+ ..."projectOwnerSession" in options ? {
1943
+ projectOwnerSession: options.projectOwnerSession
1944
+ } : {
1945
+ publishableClientKey: options.publishableClientKey ?? getDefaultPublishableClientKey(),
1946
+ secretServerKey: options.secretServerKey ?? getDefaultSecretServerKey(),
1947
+ superSecretAdminKey: options.superSecretAdminKey ?? getDefaultSuperSecretAdminKey()
1948
+ }
1949
+ }),
1950
+ baseUrl: options.baseUrl,
1951
+ projectId: options.projectId,
1952
+ tokenStore: options.tokenStore,
1953
+ urls: options.urls,
1954
+ oauthScopesOnSignIn: options.oauthScopesOnSignIn,
1955
+ redirectMethod: options.redirectMethod
1956
+ });
1957
+ this._adminProjectCache = createCache(async () => {
1958
+ return await this._interface.getProject();
1959
+ });
1960
+ this._apiKeysCache = createCache(async () => {
1961
+ return await this._interface.listApiKeys();
1962
+ });
1963
+ this._adminEmailTemplatesCache = createCache(async () => {
1964
+ return await this._interface.listEmailTemplates();
1965
+ });
1966
+ this._adminTeamPermissionDefinitionsCache = createCache(async () => {
1967
+ return await this._interface.listPermissionDefinitions();
1968
+ });
1969
+ this._svixTokenCache = createCache(async () => {
1970
+ return await this._interface.getSvixToken();
1971
+ });
1972
+ this._metricsCache = createCache(async () => {
1973
+ return await this._interface.getMetrics();
1974
+ });
1975
+ }
1976
+ _adminOwnedProjectFromCrud(data, onRefresh) {
1977
+ if (this._tokenStoreInit !== null) {
1978
+ throw new StackAssertionError("Owned apps must always have tokenStore === null \u2014 did you not create this project with app._createOwnedApp()?");
1979
+ ;
1980
+ }
1981
+ return {
1982
+ ...this._adminProjectFromCrud(data, onRefresh),
1983
+ app: this
1984
+ };
1985
+ }
1986
+ _adminProjectFromCrud(data, onRefresh) {
1987
+ if (data.id !== this.projectId) {
1988
+ throw new StackAssertionError(`The project ID of the provided project JSON (${data.id}) does not match the project ID of the app (${this.projectId})!`);
1989
+ }
1990
+ const app = this;
1991
+ return {
1992
+ id: data.id,
1993
+ displayName: data.display_name,
1994
+ description: data.description,
1995
+ createdAt: new Date(data.created_at_millis),
1996
+ userCount: data.user_count,
1997
+ isProductionMode: data.is_production_mode,
1998
+ config: {
1999
+ id: data.config.id,
2000
+ signUpEnabled: data.config.sign_up_enabled,
2001
+ credentialEnabled: data.config.credential_enabled,
2002
+ magicLinkEnabled: data.config.magic_link_enabled,
2003
+ passkeyEnabled: data.config.passkey_enabled,
2004
+ clientTeamCreationEnabled: data.config.client_team_creation_enabled,
2005
+ clientUserDeletionEnabled: data.config.client_user_deletion_enabled,
2006
+ allowLocalhost: data.config.allow_localhost,
2007
+ oauthProviders: data.config.oauth_providers.map((p) => p.type === "shared" ? {
2008
+ id: p.id,
2009
+ enabled: p.enabled,
2010
+ type: "shared"
2011
+ } : {
2012
+ id: p.id,
2013
+ enabled: p.enabled,
2014
+ type: "standard",
2015
+ clientId: p.client_id ?? throwErr("Client ID is missing"),
2016
+ clientSecret: p.client_secret ?? throwErr("Client secret is missing"),
2017
+ facebookConfigId: p.facebook_config_id,
2018
+ microsoftTenantId: p.microsoft_tenant_id
2019
+ }),
2020
+ emailConfig: data.config.email_config.type === "shared" ? {
2021
+ type: "shared"
2022
+ } : {
2023
+ type: "standard",
2024
+ host: data.config.email_config.host ?? throwErr("Email host is missing"),
2025
+ port: data.config.email_config.port ?? throwErr("Email port is missing"),
2026
+ username: data.config.email_config.username ?? throwErr("Email username is missing"),
2027
+ password: data.config.email_config.password ?? throwErr("Email password is missing"),
2028
+ senderName: data.config.email_config.sender_name ?? throwErr("Email sender name is missing"),
2029
+ senderEmail: data.config.email_config.sender_email ?? throwErr("Email sender email is missing")
2030
+ },
2031
+ domains: data.config.domains.map((d) => ({
2032
+ domain: d.domain,
2033
+ handlerPath: d.handler_path
2034
+ })),
2035
+ createTeamOnSignUp: data.config.create_team_on_sign_up,
2036
+ teamCreatorDefaultPermissions: data.config.team_creator_default_permissions,
2037
+ teamMemberDefaultPermissions: data.config.team_member_default_permissions
2038
+ },
2039
+ async update(update) {
2040
+ await app._interface.updateProject(adminProjectUpdateOptionsToCrud(update));
2041
+ await onRefresh();
2042
+ },
2043
+ async delete() {
2044
+ await app._interface.deleteProject();
2045
+ },
2046
+ async getProductionModeErrors() {
2047
+ return getProductionModeErrors(data);
2048
+ },
2049
+ useProductionModeErrors() {
2050
+ return getProductionModeErrors(data);
2051
+ }
2052
+ };
2053
+ }
2054
+ _adminEmailTemplateFromCrud(data) {
2055
+ return {
2056
+ type: data.type,
2057
+ subject: data.subject,
2058
+ content: data.content,
2059
+ isDefault: data.is_default
2060
+ };
2061
+ }
2062
+ async getProject() {
2063
+ return this._adminProjectFromCrud(
2064
+ Result.orThrow(await this._adminProjectCache.getOrWait([], "write-only")),
2065
+ () => this._refreshProject()
2066
+ );
2067
+ }
2068
+ useProject() {
2069
+ const crud = useAsyncCache(this._adminProjectCache, [], "useProjectAdmin()");
2070
+ return useMemo(() => this._adminProjectFromCrud(
2071
+ crud,
2072
+ () => this._refreshProject()
2073
+ ), [crud]);
2074
+ }
2075
+ _createApiKeyBaseFromCrud(data) {
2076
+ const app = this;
2077
+ return {
2078
+ id: data.id,
2079
+ description: data.description,
2080
+ expiresAt: new Date(data.expires_at_millis),
2081
+ manuallyRevokedAt: data.manually_revoked_at_millis ? new Date(data.manually_revoked_at_millis) : null,
2082
+ createdAt: new Date(data.created_at_millis),
2083
+ isValid() {
2084
+ return this.whyInvalid() === null;
2085
+ },
2086
+ whyInvalid() {
2087
+ if (this.expiresAt.getTime() < Date.now()) return "expired";
2088
+ if (this.manuallyRevokedAt) return "manually-revoked";
2089
+ return null;
2090
+ },
2091
+ async revoke() {
2092
+ const res = await app._interface.revokeApiKeyById(data.id);
2093
+ await app._refreshApiKeys();
2094
+ return res;
2095
+ }
2096
+ };
2097
+ }
2098
+ _createApiKeyFromCrud(data) {
2099
+ return {
2100
+ ...this._createApiKeyBaseFromCrud(data),
2101
+ publishableClientKey: data.publishable_client_key ? { lastFour: data.publishable_client_key.last_four } : null,
2102
+ secretServerKey: data.secret_server_key ? { lastFour: data.secret_server_key.last_four } : null,
2103
+ superSecretAdminKey: data.super_secret_admin_key ? { lastFour: data.super_secret_admin_key.last_four } : null
2104
+ };
2105
+ }
2106
+ _createApiKeyFirstViewFromCrud(data) {
2107
+ return {
2108
+ ...this._createApiKeyBaseFromCrud(data),
2109
+ publishableClientKey: data.publishable_client_key,
2110
+ secretServerKey: data.secret_server_key,
2111
+ superSecretAdminKey: data.super_secret_admin_key
2112
+ };
2113
+ }
2114
+ async listApiKeys() {
2115
+ const crud = Result.orThrow(await this._apiKeysCache.getOrWait([], "write-only"));
2116
+ return crud.map((j) => this._createApiKeyFromCrud(j));
2117
+ }
2118
+ useApiKeys() {
2119
+ const crud = useAsyncCache(this._apiKeysCache, [], "useApiKeys()");
2120
+ return useMemo(() => {
2121
+ return crud.map((j) => this._createApiKeyFromCrud(j));
2122
+ }, [crud]);
2123
+ }
2124
+ async createApiKey(options) {
2125
+ const crud = await this._interface.createApiKey(apiKeyCreateOptionsToCrud(options));
2126
+ await this._refreshApiKeys();
2127
+ return this._createApiKeyFirstViewFromCrud(crud);
2128
+ }
2129
+ useEmailTemplates() {
2130
+ const crud = useAsyncCache(this._adminEmailTemplatesCache, [], "useEmailTemplates()");
2131
+ return useMemo(() => {
2132
+ return crud.map((j) => this._adminEmailTemplateFromCrud(j));
2133
+ }, [crud]);
2134
+ }
2135
+ async listEmailTemplates() {
2136
+ const crud = Result.orThrow(await this._adminEmailTemplatesCache.getOrWait([], "write-only"));
2137
+ return crud.map((j) => this._adminEmailTemplateFromCrud(j));
2138
+ }
2139
+ async updateEmailTemplate(type, data) {
2140
+ await this._interface.updateEmailTemplate(type, adminEmailTemplateUpdateOptionsToCrud(data));
2141
+ await this._adminEmailTemplatesCache.refresh([]);
2142
+ }
2143
+ async resetEmailTemplate(type) {
2144
+ await this._interface.resetEmailTemplate(type);
2145
+ await this._adminEmailTemplatesCache.refresh([]);
2146
+ }
2147
+ async createTeamPermissionDefinition(data) {
2148
+ const crud = await this._interface.createPermissionDefinition(serverTeamPermissionDefinitionCreateOptionsToCrud(data));
2149
+ await this._adminTeamPermissionDefinitionsCache.refresh([]);
2150
+ return this._serverTeamPermissionDefinitionFromCrud(crud);
2151
+ }
2152
+ async updateTeamPermissionDefinition(permissionId, data) {
2153
+ await this._interface.updatePermissionDefinition(permissionId, serverTeamPermissionDefinitionUpdateOptionsToCrud(data));
2154
+ await this._adminTeamPermissionDefinitionsCache.refresh([]);
2155
+ }
2156
+ async deleteTeamPermissionDefinition(permissionId) {
2157
+ await this._interface.deletePermissionDefinition(permissionId);
2158
+ await this._adminTeamPermissionDefinitionsCache.refresh([]);
2159
+ }
2160
+ async listTeamPermissionDefinitions() {
2161
+ const crud = Result.orThrow(await this._adminTeamPermissionDefinitionsCache.getOrWait([], "write-only"));
2162
+ return crud.map((p) => this._serverTeamPermissionDefinitionFromCrud(p));
2163
+ }
2164
+ useTeamPermissionDefinitions() {
2165
+ const crud = useAsyncCache(this._adminTeamPermissionDefinitionsCache, [], "usePermissions()");
2166
+ return useMemo(() => {
2167
+ return crud.map((p) => this._serverTeamPermissionDefinitionFromCrud(p));
2168
+ }, [crud]);
2169
+ }
2170
+ useSvixToken() {
2171
+ const crud = useAsyncCache(this._svixTokenCache, [], "useSvixToken()");
2172
+ return crud.token;
2173
+ }
2174
+ async _refreshProject() {
2175
+ await Promise.all([
2176
+ super._refreshProject(),
2177
+ this._adminProjectCache.refresh([])
2178
+ ]);
2179
+ }
2180
+ async _refreshApiKeys() {
2181
+ await this._apiKeysCache.refresh([]);
2182
+ }
2183
+ get [stackAppInternalsSymbol]() {
2184
+ return {
2185
+ ...super[stackAppInternalsSymbol],
2186
+ useMetrics: () => {
2187
+ return useAsyncCache(this._metricsCache, [], "useMetrics()");
2188
+ }
2189
+ };
2190
+ }
2191
+ async sendTestEmail(options) {
2192
+ const response = await this._interface.sendTestEmail({
2193
+ recipient_email: options.recipientEmail,
2194
+ email_config: {
2195
+ ...pick(options.emailConfig, ["host", "port", "username", "password"]),
2196
+ sender_email: options.emailConfig.senderEmail,
2197
+ sender_name: options.emailConfig.senderName
2198
+ }
2199
+ });
2200
+ if (response.success) {
2201
+ return Result.ok(void 0);
2202
+ } else {
2203
+ return Result.error({ errorMessage: response.error_message ?? throwErr("Email test error not specified") });
2204
+ }
2205
+ }
2206
+ };
2207
+ function contactChannelCreateOptionsToCrud(userId, options) {
2208
+ return {
2209
+ value: options.value,
2210
+ type: options.type,
2211
+ used_for_auth: options.usedForAuth,
2212
+ user_id: userId
2213
+ };
2214
+ }
2215
+ function contactChannelUpdateOptionsToCrud(options) {
2216
+ return {
2217
+ value: options.value,
2218
+ used_for_auth: options.usedForAuth,
2219
+ is_primary: options.isPrimary
2220
+ };
2221
+ }
2222
+ function serverContactChannelUpdateOptionsToCrud(options) {
2223
+ return {
2224
+ value: options.value,
2225
+ is_verified: options.isVerified,
2226
+ used_for_auth: options.usedForAuth
2227
+ };
2228
+ }
2229
+ function serverContactChannelCreateOptionsToCrud(userId, options) {
2230
+ return {
2231
+ type: options.type,
2232
+ value: options.value,
2233
+ is_verified: options.isVerified,
2234
+ user_id: userId,
2235
+ used_for_auth: options.usedForAuth
2236
+ };
2237
+ }
2238
+ function userUpdateOptionsToCrud(options) {
2239
+ return {
2240
+ display_name: options.displayName,
2241
+ client_metadata: options.clientMetadata,
2242
+ selected_team_id: options.selectedTeamId,
2243
+ totp_secret_base64: options.totpMultiFactorSecret != null ? encodeBase64(options.totpMultiFactorSecret) : options.totpMultiFactorSecret,
2244
+ profile_image_url: options.profileImageUrl,
2245
+ otp_auth_enabled: options.otpAuthEnabled,
2246
+ passkey_auth_enabled: options.passkeyAuthEnabled
2247
+ };
2248
+ }
2249
+ function serverUserUpdateOptionsToCrud(options) {
2250
+ return {
2251
+ display_name: options.displayName,
2252
+ primary_email: options.primaryEmail,
2253
+ client_metadata: options.clientMetadata,
2254
+ client_read_only_metadata: options.clientReadOnlyMetadata,
2255
+ server_metadata: options.serverMetadata,
2256
+ selected_team_id: options.selectedTeamId,
2257
+ primary_email_auth_enabled: options.primaryEmailAuthEnabled,
2258
+ primary_email_verified: options.primaryEmailVerified,
2259
+ password: options.password,
2260
+ profile_image_url: options.profileImageUrl,
2261
+ totp_secret_base64: options.totpMultiFactorSecret != null ? encodeBase64(options.totpMultiFactorSecret) : options.totpMultiFactorSecret
2262
+ };
2263
+ }
2264
+ function serverUserCreateOptionsToCrud(options) {
2265
+ return {
2266
+ primary_email: options.primaryEmail,
2267
+ password: options.password,
2268
+ otp_auth_enabled: options.otpAuthEnabled,
2269
+ primary_email_auth_enabled: options.primaryEmailAuthEnabled,
2270
+ display_name: options.displayName,
2271
+ primary_email_verified: options.primaryEmailVerified,
2272
+ client_metadata: options.clientMetadata,
2273
+ client_read_only_metadata: options.clientReadOnlyMetadata,
2274
+ server_metadata: options.serverMetadata
2275
+ };
2276
+ }
2277
+ function adminProjectUpdateOptionsToCrud(options) {
2278
+ return {
2279
+ display_name: options.displayName,
2280
+ description: options.description,
2281
+ is_production_mode: options.isProductionMode,
2282
+ config: {
2283
+ domains: options.config?.domains?.map((d) => ({
2284
+ domain: d.domain,
2285
+ handler_path: d.handlerPath
2286
+ })),
2287
+ oauth_providers: options.config?.oauthProviders?.map((p) => ({
2288
+ id: p.id,
2289
+ enabled: p.enabled,
2290
+ type: p.type,
2291
+ ...p.type === "standard" && {
2292
+ client_id: p.clientId,
2293
+ client_secret: p.clientSecret,
2294
+ facebook_config_id: p.facebookConfigId,
2295
+ microsoft_tenant_id: p.microsoftTenantId
2296
+ }
2297
+ })),
2298
+ email_config: options.config?.emailConfig && (options.config.emailConfig.type === "shared" ? {
2299
+ type: "shared"
2300
+ } : {
2301
+ type: "standard",
2302
+ host: options.config.emailConfig.host,
2303
+ port: options.config.emailConfig.port,
2304
+ username: options.config.emailConfig.username,
2305
+ password: options.config.emailConfig.password,
2306
+ sender_name: options.config.emailConfig.senderName,
2307
+ sender_email: options.config.emailConfig.senderEmail
2308
+ }),
2309
+ sign_up_enabled: options.config?.signUpEnabled,
2310
+ credential_enabled: options.config?.credentialEnabled,
2311
+ magic_link_enabled: options.config?.magicLinkEnabled,
2312
+ passkey_enabled: options.config?.passkeyEnabled,
2313
+ allow_localhost: options.config?.allowLocalhost,
2314
+ create_team_on_sign_up: options.config?.createTeamOnSignUp,
2315
+ client_team_creation_enabled: options.config?.clientTeamCreationEnabled,
2316
+ client_user_deletion_enabled: options.config?.clientUserDeletionEnabled,
2317
+ team_creator_default_permissions: options.config?.teamCreatorDefaultPermissions,
2318
+ team_member_default_permissions: options.config?.teamMemberDefaultPermissions
2319
+ }
2320
+ };
2321
+ }
2322
+ function adminProjectCreateOptionsToCrud(options) {
2323
+ return {
2324
+ ...adminProjectUpdateOptionsToCrud(options),
2325
+ display_name: options.displayName
2326
+ };
2327
+ }
2328
+ function apiKeyCreateOptionsToCrud(options) {
2329
+ return {
2330
+ description: options.description,
2331
+ expires_at_millis: options.expiresAt.getTime(),
2332
+ has_publishable_client_key: options.hasPublishableClientKey,
2333
+ has_secret_server_key: options.hasSecretServerKey,
2334
+ has_super_secret_admin_key: options.hasSuperSecretAdminKey
2335
+ };
2336
+ }
2337
+ function teamUpdateOptionsToCrud(options) {
2338
+ return {
2339
+ display_name: options.displayName,
2340
+ profile_image_url: options.profileImageUrl,
2341
+ client_metadata: options.clientMetadata
2342
+ };
2343
+ }
2344
+ function teamCreateOptionsToCrud(options, creatorUserId) {
2345
+ return {
2346
+ display_name: options.displayName,
2347
+ profile_image_url: options.profileImageUrl,
2348
+ creator_user_id: creatorUserId
2349
+ };
2350
+ }
2351
+ function serverTeamCreateOptionsToCrud(options) {
2352
+ return {
2353
+ display_name: options.displayName,
2354
+ profile_image_url: options.profileImageUrl,
2355
+ creator_user_id: options.creatorUserId
2356
+ };
2357
+ }
2358
+ function serverTeamUpdateOptionsToCrud(options) {
2359
+ return {
2360
+ display_name: options.displayName,
2361
+ profile_image_url: options.profileImageUrl,
2362
+ client_metadata: options.clientMetadata,
2363
+ client_read_only_metadata: options.clientReadOnlyMetadata,
2364
+ server_metadata: options.serverMetadata
2365
+ };
2366
+ }
2367
+ function serverTeamPermissionDefinitionCreateOptionsToCrud(options) {
2368
+ return {
2369
+ id: options.id,
2370
+ description: options.description,
2371
+ contained_permission_ids: options.containedPermissionIds
2372
+ };
2373
+ }
2374
+ function serverTeamPermissionDefinitionUpdateOptionsToCrud(options) {
2375
+ return {
2376
+ id: options.id,
2377
+ description: options.description,
2378
+ contained_permission_ids: options.containedPermissionIds
2379
+ };
2380
+ }
2381
+ var StackClientApp = _StackClientAppImpl;
2382
+ var StackServerApp = _StackServerAppImpl;
2383
+ var StackAdminApp = _StackAdminAppImpl;
2384
+ function adminEmailTemplateUpdateOptionsToCrud(options) {
2385
+ return {
2386
+ subject: options.subject,
2387
+ content: options.content
2388
+ };
2389
+ }
2390
+ export {
2391
+ StackAdminApp,
2392
+ StackClientApp,
2393
+ StackServerApp,
2394
+ serverTeamPermissionDefinitionCreateOptionsToCrud,
2395
+ serverTeamPermissionDefinitionUpdateOptionsToCrud,
2396
+ stackAppInternalsSymbol
2397
+ };
2398
+ //# sourceMappingURL=stack-app.js.map