@stackframe/stack 2.8.56 → 2.8.58

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 (62) hide show
  1. package/dist/components-page/account-settings/email-and-auth/emails-section.js +4 -3
  2. package/dist/components-page/account-settings/email-and-auth/emails-section.js.map +1 -1
  3. package/dist/components-page/onboarding.js +170 -0
  4. package/dist/components-page/onboarding.js.map +1 -0
  5. package/dist/components-page/stack-handler-client.js +13 -1
  6. package/dist/components-page/stack-handler-client.js.map +1 -1
  7. package/dist/components-page/team-invitation.js +15 -1
  8. package/dist/components-page/team-invitation.js.map +1 -1
  9. package/dist/esm/components-page/account-settings/email-and-auth/emails-section.js +4 -3
  10. package/dist/esm/components-page/account-settings/email-and-auth/emails-section.js.map +1 -1
  11. package/dist/esm/components-page/onboarding.js +146 -0
  12. package/dist/esm/components-page/onboarding.js.map +1 -0
  13. package/dist/esm/components-page/stack-handler-client.js +13 -1
  14. package/dist/esm/components-page/stack-handler-client.js.map +1 -1
  15. package/dist/esm/components-page/team-invitation.js +15 -1
  16. package/dist/esm/components-page/team-invitation.js.map +1 -1
  17. package/dist/esm/generated/global-css.js +1 -1
  18. package/dist/esm/generated/global-css.js.map +1 -1
  19. package/dist/esm/lib/stack-app/apps/implementations/admin-app-impl.js +235 -0
  20. package/dist/esm/lib/stack-app/apps/implementations/admin-app-impl.js.map +1 -1
  21. package/dist/esm/lib/stack-app/apps/implementations/client-app-impl.js +147 -25
  22. package/dist/esm/lib/stack-app/apps/implementations/client-app-impl.js.map +1 -1
  23. package/dist/esm/lib/stack-app/apps/implementations/common.js +2 -1
  24. package/dist/esm/lib/stack-app/apps/implementations/common.js.map +1 -1
  25. package/dist/esm/lib/stack-app/apps/implementations/server-app-impl.js +40 -27
  26. package/dist/esm/lib/stack-app/apps/implementations/server-app-impl.js.map +1 -1
  27. package/dist/esm/lib/stack-app/apps/interfaces/admin-app.js.map +1 -1
  28. package/dist/esm/lib/stack-app/apps/interfaces/client-app.js.map +1 -1
  29. package/dist/esm/lib/stack-app/apps/interfaces/server-app.js.map +1 -1
  30. package/dist/esm/lib/stack-app/common.js.map +1 -1
  31. package/dist/esm/lib/stack-app/index.js.map +1 -1
  32. package/dist/esm/lib/stack-app/projects/index.js +4 -0
  33. package/dist/esm/lib/stack-app/projects/index.js.map +1 -1
  34. package/dist/esm/lib/stack-app/teams/index.js.map +1 -1
  35. package/dist/esm/lib/stack-app/users/index.js +13 -12
  36. package/dist/esm/lib/stack-app/users/index.js.map +1 -1
  37. package/dist/generated/global-css.js +1 -1
  38. package/dist/generated/global-css.js.map +1 -1
  39. package/dist/index.d.mts +269 -16
  40. package/dist/index.d.ts +269 -16
  41. package/dist/lib/stack-app/apps/implementations/admin-app-impl.js +235 -0
  42. package/dist/lib/stack-app/apps/implementations/admin-app-impl.js.map +1 -1
  43. package/dist/lib/stack-app/apps/implementations/client-app-impl.js +145 -23
  44. package/dist/lib/stack-app/apps/implementations/client-app-impl.js.map +1 -1
  45. package/dist/lib/stack-app/apps/implementations/common.js +2 -1
  46. package/dist/lib/stack-app/apps/implementations/common.js.map +1 -1
  47. package/dist/lib/stack-app/apps/implementations/server-app-impl.js +38 -25
  48. package/dist/lib/stack-app/apps/implementations/server-app-impl.js.map +1 -1
  49. package/dist/lib/stack-app/apps/interfaces/admin-app.js.map +1 -1
  50. package/dist/lib/stack-app/apps/interfaces/client-app.js.map +1 -1
  51. package/dist/lib/stack-app/apps/interfaces/server-app.js.map +1 -1
  52. package/dist/lib/stack-app/common.js.map +1 -1
  53. package/dist/lib/stack-app/email/index.js.map +1 -1
  54. package/dist/lib/stack-app/index.js.map +1 -1
  55. package/dist/lib/stack-app/project-configs/index.js.map +1 -1
  56. package/dist/lib/stack-app/projects/index.js +4 -0
  57. package/dist/lib/stack-app/projects/index.js.map +1 -1
  58. package/dist/lib/stack-app/teams/index.js.map +1 -1
  59. package/dist/lib/stack-app/users/index.js +15 -14
  60. package/dist/lib/stack-app/users/index.js.map +1 -1
  61. package/package.json +6 -5
  62. package/CHANGELOG.md +0 -2072
@@ -10,7 +10,7 @@ import { parseJson } from "@stackframe/stack-shared/dist/utils/json";
10
10
  import { DependenciesMap } from "@stackframe/stack-shared/dist/utils/maps";
11
11
  import { deepPlainEquals, omit } from "@stackframe/stack-shared/dist/utils/objects";
12
12
  import { neverResolve, runAsynchronously, wait } from "@stackframe/stack-shared/dist/utils/promises";
13
- import { suspend, suspendIfSsr } from "@stackframe/stack-shared/dist/utils/react";
13
+ import { suspend, suspendIfSsr, use } from "@stackframe/stack-shared/dist/utils/react";
14
14
  import { Result } from "@stackframe/stack-shared/dist/utils/results";
15
15
  import { Store, storeLock } from "@stackframe/stack-shared/dist/utils/stores";
16
16
  import { deindent, mergeScopeStrings } from "@stackframe/stack-shared/dist/utils/strings";
@@ -27,7 +27,7 @@ import { stackAppInternalsSymbol } from "../../common.js";
27
27
  import { contactChannelCreateOptionsToCrud, contactChannelUpdateOptionsToCrud } from "../../contact-channels/index.js";
28
28
  import { adminProjectCreateOptionsToCrud } from "../../projects/index.js";
29
29
  import { teamCreateOptionsToCrud, teamUpdateOptionsToCrud } from "../../teams/index.js";
30
- import { attachUserDestructureGuard, userUpdateOptionsToCrud } from "../../users/index.js";
30
+ import { userUpdateOptionsToCrud, withUserDestructureGuard } from "../../users/index.js";
31
31
  import { clientVersion, createCache, createCacheBySession, createEmptyTokenStore, getBaseUrl, getDefaultExtraRequestHeaders, getDefaultProjectId, getDefaultPublishableClientKey, getUrls, resolveConstructorOptions } from "./common.js";
32
32
  import { useAsyncCache } from "./common.js";
33
33
  import * as sc from "@stackframe/stack-sc";
@@ -946,22 +946,65 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
946
946
  _internalSession: session,
947
947
  currentSession: {
948
948
  async getTokens() {
949
- const tokens = await session.getOrFetchLikelyValidTokens(2e4);
949
+ const tokens = await session.getOrFetchLikelyValidTokens(2e4, 75e3);
950
950
  return {
951
951
  accessToken: tokens?.accessToken.token ?? null,
952
952
  refreshToken: tokens?.refreshToken?.token ?? null
953
953
  };
954
+ },
955
+ useTokens() {
956
+ const [_, setCounter] = React.useState(0);
957
+ React.useEffect(() => {
958
+ const { unsubscribe: unsubscribeRefresh } = session.startRefreshingAccessToken(3e4, 6e4);
959
+ const { unsubscribe: unsubscribeInvalidate } = session.onInvalidate(() => setCounter((c) => c + 1));
960
+ const { unsubscribe: unsubscribeAccessTokenChange } = session.onAccessTokenChange(() => setCounter((c) => c + 1));
961
+ return () => {
962
+ unsubscribeRefresh();
963
+ unsubscribeInvalidate();
964
+ unsubscribeAccessTokenChange();
965
+ };
966
+ }, []);
967
+ let accessToken = session.isKnownToBeInvalid() ? null : session.getAccessTokenIfNotExpiredYet(2e4, 75e3);
968
+ if (accessToken === null) {
969
+ accessToken = use(session.getOrFetchLikelyValidTokens(2e4, 75e3))?.accessToken ?? null;
970
+ }
971
+ return {
972
+ accessToken: accessToken?.token ?? null,
973
+ refreshToken: session.getRefreshToken()?.token ?? null
974
+ };
954
975
  }
955
976
  },
977
+ async getAccessToken() {
978
+ const tokens = await this.currentSession.getTokens();
979
+ return tokens.accessToken;
980
+ },
981
+ useAccessToken() {
982
+ return this.currentSession.useTokens().accessToken;
983
+ },
984
+ async getRefreshToken() {
985
+ const tokens = await this.currentSession.getTokens();
986
+ return tokens.refreshToken;
987
+ },
988
+ useRefreshToken() {
989
+ return this.currentSession.useTokens().refreshToken;
990
+ },
956
991
  async getAuthHeaders() {
957
992
  return {
958
993
  "x-stack-auth": JSON.stringify(await this.getAuthJson())
959
994
  };
960
995
  },
996
+ useAuthHeaders() {
997
+ return {
998
+ "x-stack-auth": JSON.stringify(this.useAuthJson())
999
+ };
1000
+ },
961
1001
  async getAuthJson() {
962
1002
  const tokens = await this.currentSession.getTokens();
963
1003
  return tokens;
964
1004
  },
1005
+ useAuthJson() {
1006
+ return this.currentSession.useTokens();
1007
+ },
965
1008
  signOut(options) {
966
1009
  return app._signOut(session, options);
967
1010
  }
@@ -1002,6 +1045,8 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1002
1045
  passkeyAuthEnabled: crud.passkey_auth_enabled,
1003
1046
  isMultiFactorRequired: crud.requires_totp_mfa,
1004
1047
  isAnonymous: crud.is_anonymous,
1048
+ isRestricted: crud.is_restricted,
1049
+ restrictedReason: crud.restricted_reason,
1005
1050
  toClientJson() {
1006
1051
  return crud;
1007
1052
  }
@@ -1032,7 +1077,7 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1032
1077
  return this.update({ clientMetadata: metadata });
1033
1078
  },
1034
1079
  async setSelectedTeam(team) {
1035
- await this.update({ selectedTeamId: team?.id ?? null });
1080
+ await this.update({ selectedTeamId: typeof team === "string" ? team : team?.id ?? null });
1036
1081
  },
1037
1082
  getConnectedAccount,
1038
1083
  useConnectedAccount,
@@ -1312,6 +1357,25 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1312
1357
  const response = Result.orThrow(await this._customProductsCache.getOrWait([session, options.customCustomerId, options.cursor ?? null, options.limit ?? null], "write-only"));
1313
1358
  return this._customerProductsFromResponse(response);
1314
1359
  }
1360
+ async cancelSubscription(options) {
1361
+ const session = await this._getSession();
1362
+ const user = await this.getUser();
1363
+ if (!user) {
1364
+ throw new KnownErrors.UserAuthenticationRequired();
1365
+ }
1366
+ const customerType = "teamId" in options ? "team" : "user";
1367
+ const customerId = "teamId" in options ? options.teamId : user.id;
1368
+ await this._interface.cancelSubscription({
1369
+ customer_type: customerType,
1370
+ customer_id: customerId,
1371
+ product_id: options.productId
1372
+ }, session);
1373
+ if (customerType === "user") {
1374
+ await this._userProductsCache.invalidateWhere(([cachedSession, userId]) => cachedSession === session && userId === customerId);
1375
+ } else {
1376
+ await this._teamProductsCache.invalidateWhere(([cachedSession, teamId]) => cachedSession === session && teamId === customerId);
1377
+ }
1378
+ }
1315
1379
  useProducts(options) {
1316
1380
  const session = this._useSession();
1317
1381
  const cache = "userId" in options ? this._userProductsCache : "teamId" in options ? this._teamProductsCache : this._customProductsCache;
@@ -1321,15 +1385,13 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1321
1385
  return this._customerProductsFromResponse(response);
1322
1386
  }
1323
1387
  _currentUserFromCrud(crud, session) {
1324
- const currentUser = {
1388
+ const currentUser = withUserDestructureGuard({
1325
1389
  ...this._createBaseUser(crud),
1326
1390
  ...this._createAuth(session),
1327
1391
  ...this._createUserExtraFromCurrent(crud, session),
1328
1392
  ...this._isInternalProject() ? this._createInternalUserExtra(session) : {},
1329
1393
  ...this._createCustomer(crud.id, "user", session)
1330
- };
1331
- attachUserDestructureGuard(currentUser);
1332
- Object.freeze(currentUser);
1394
+ });
1333
1395
  return currentUser;
1334
1396
  }
1335
1397
  _clientSessionFromCrud(crud) {
@@ -1417,7 +1479,7 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1417
1479
  const queryParams = new URLSearchParams(window.location.search);
1418
1480
  url = queryParams.get("after_auth_return_to") || url;
1419
1481
  }
1420
- } else if (handlerName === "signIn" || handlerName === "signUp") {
1482
+ } else if (handlerName === "signIn" || handlerName === "signUp" || handlerName === "onboarding") {
1421
1483
  if (isReactServer2 || typeof window === "undefined") {
1422
1484
  } else {
1423
1485
  const currentUrl = new URL(window.location.href);
@@ -1466,6 +1528,9 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1466
1528
  async redirectToAfterSignUp(options) {
1467
1529
  return await this._redirectToHandler("afterSignUp", options);
1468
1530
  }
1531
+ async redirectToOnboarding(options) {
1532
+ return await this._redirectToHandler("onboarding", options);
1533
+ }
1469
1534
  async redirectToAfterSignOut(options) {
1470
1535
  return await this._redirectToHandler("afterSignOut", options);
1471
1536
  }
@@ -1531,16 +1596,22 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1531
1596
  return result;
1532
1597
  }
1533
1598
  async getUser(options) {
1599
+ if (options?.or === "anonymous" && options.includeRestricted === false) {
1600
+ throw new Error("Cannot use { or: 'anonymous' } with { includeRestricted: false }. Anonymous users implicitly include restricted users.");
1601
+ }
1534
1602
  this._ensurePersistentTokenStore(options?.tokenStore);
1535
1603
  const session = await this._getSession(options?.tokenStore);
1536
1604
  let crud = Result.orThrow(await this._currentUserCache.getOrWait([session], "write-only"));
1537
- if (crud?.is_anonymous && options?.or !== "anonymous" && options?.or !== "anonymous-if-exists[deprecated]") {
1538
- crud = null;
1539
- }
1540
- if (crud === null) {
1605
+ const includeAnonymous = options?.or === "anonymous" || options?.or === "anonymous-if-exists[deprecated]";
1606
+ const includeRestricted = options?.includeRestricted === true || includeAnonymous;
1607
+ if (crud === null || crud.is_anonymous && !includeAnonymous || crud.is_restricted && !includeRestricted) {
1541
1608
  switch (options?.or) {
1542
1609
  case "redirect": {
1543
- await this.redirectToSignIn({ replace: true });
1610
+ if (!crud?.is_anonymous && crud?.is_restricted) {
1611
+ await this.redirectToOnboarding({ replace: true });
1612
+ } else {
1613
+ await this.redirectToSignIn({ replace: true });
1614
+ }
1544
1615
  break;
1545
1616
  }
1546
1617
  case "throw": {
@@ -1548,7 +1619,7 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1548
1619
  }
1549
1620
  case "anonymous": {
1550
1621
  const tokens = await this._signUpAnonymously();
1551
- return await this.getUser({ tokenStore: tokens, or: "anonymous-if-exists[deprecated]" }) ?? throwErr("Something went wrong while signing up anonymously");
1622
+ return await this.getUser({ tokenStore: tokens, or: "anonymous-if-exists[deprecated]", includeRestricted: true }) ?? throwErr("Something went wrong while signing up anonymously");
1552
1623
  }
1553
1624
  case void 0:
1554
1625
  case "anonymous-if-exists[deprecated]":
@@ -1560,16 +1631,22 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1560
1631
  return crud && this._currentUserFromCrud(crud, session);
1561
1632
  }
1562
1633
  useUser(options) {
1634
+ if (options?.or === "anonymous" && options.includeRestricted === false) {
1635
+ throw new Error("Cannot use { or: 'anonymous' } with { includeRestricted: false }. Anonymous users implicitly include restricted users.");
1636
+ }
1563
1637
  this._ensurePersistentTokenStore(options?.tokenStore);
1564
1638
  const session = this._useSession(options?.tokenStore);
1565
1639
  let crud = useAsyncCache(this._currentUserCache, [session], "clientApp.useUser()");
1566
- if (crud?.is_anonymous && options?.or !== "anonymous" && options?.or !== "anonymous-if-exists[deprecated]") {
1567
- crud = null;
1568
- }
1569
- if (crud === null) {
1640
+ const includeAnonymous = options?.or === "anonymous" || options?.or === "anonymous-if-exists[deprecated]";
1641
+ const includeRestricted = options?.includeRestricted === true || includeAnonymous;
1642
+ if (crud === null || crud.is_anonymous && !includeAnonymous || crud.is_restricted && !includeRestricted) {
1570
1643
  switch (options?.or) {
1571
1644
  case "redirect": {
1572
- runAsynchronously(this.redirectToSignIn({ replace: true }));
1645
+ if (!crud?.is_anonymous && crud?.is_restricted) {
1646
+ runAsynchronously(this.redirectToOnboarding({ replace: true }));
1647
+ } else {
1648
+ runAsynchronously(this.redirectToSignIn({ replace: true }));
1649
+ }
1573
1650
  suspend();
1574
1651
  throw new StackAssertionError("suspend should never return");
1575
1652
  }
@@ -1597,7 +1674,7 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1597
1674
  }, [crud, session, options?.or]);
1598
1675
  }
1599
1676
  _getTokenPartialUserFromSession(session, options) {
1600
- const accessToken = session.getAccessTokenIfNotExpiredYet(0);
1677
+ const accessToken = session.getAccessTokenIfNotExpiredYet(0, null);
1601
1678
  if (!accessToken) {
1602
1679
  return null;
1603
1680
  }
@@ -1610,7 +1687,9 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1610
1687
  primaryEmail: accessToken.payload.email,
1611
1688
  displayName: accessToken.payload.name,
1612
1689
  primaryEmailVerified: accessToken.payload.email_verified,
1613
- isAnonymous
1690
+ isAnonymous,
1691
+ isRestricted: accessToken.payload.is_restricted,
1692
+ restrictedReason: accessToken.payload.restricted_reason
1614
1693
  };
1615
1694
  }
1616
1695
  async _getPartialUserFromConvex(ctx) {
@@ -1623,7 +1702,9 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1623
1702
  displayName: auth.name ?? null,
1624
1703
  primaryEmail: auth.email ?? null,
1625
1704
  primaryEmailVerified: auth.email_verified,
1626
- isAnonymous: auth.is_anonymous
1705
+ isAnonymous: auth.is_anonymous,
1706
+ isRestricted: auth.is_restricted,
1707
+ restrictedReason: auth.restricted_reason ?? null
1627
1708
  };
1628
1709
  }
1629
1710
  async getPartialUser(options) {
@@ -1661,7 +1742,7 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1661
1742
  return async (args) => {
1662
1743
  const session = await this._getSession(options.tokenStore ?? this._tokenStoreInit);
1663
1744
  if (!args.forceRefreshToken) {
1664
- const tokens2 = await session.getOrFetchLikelyValidTokens(2e4);
1745
+ const tokens2 = await session.getOrFetchLikelyValidTokens(2e4, 75e3);
1665
1746
  return tokens2?.accessToken.token ?? null;
1666
1747
  }
1667
1748
  const tokens = await session.fetchNewTokens();
@@ -1670,7 +1751,7 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1670
1751
  }
1671
1752
  async getConvexHttpClientAuth(options) {
1672
1753
  const session = await this._getSession(options.tokenStore);
1673
- const tokens = await session.getOrFetchLikelyValidTokens(2e4);
1754
+ const tokens = await session.getOrFetchLikelyValidTokens(2e4, 75e3);
1674
1755
  return tokens?.accessToken.token ?? "";
1675
1756
  }
1676
1757
  async _updateClientUser(update, session) {
@@ -2017,11 +2098,44 @@ ${url}`);
2017
2098
  await user.signOut({ redirectUrl: options?.redirectUrl });
2018
2099
  }
2019
2100
  }
2101
+ async getAccessToken(options) {
2102
+ const user = await this.getUser({ tokenStore: options?.tokenStore ?? void 0 });
2103
+ if (user) {
2104
+ return await user.getAccessToken();
2105
+ }
2106
+ return null;
2107
+ }
2108
+ useAccessToken(options) {
2109
+ const user = this.useUser({ tokenStore: options?.tokenStore ?? void 0 });
2110
+ if (user) {
2111
+ return user.useAccessToken();
2112
+ }
2113
+ return null;
2114
+ }
2115
+ async getRefreshToken(options) {
2116
+ const user = await this.getUser({ tokenStore: options?.tokenStore ?? void 0 });
2117
+ if (user) {
2118
+ return await user.getRefreshToken();
2119
+ }
2120
+ return null;
2121
+ }
2122
+ useRefreshToken(options) {
2123
+ const user = this.useUser({ tokenStore: options?.tokenStore ?? void 0 });
2124
+ if (user) {
2125
+ return user.useRefreshToken();
2126
+ }
2127
+ return null;
2128
+ }
2020
2129
  async getAuthHeaders(options) {
2021
2130
  return {
2022
2131
  "x-stack-auth": JSON.stringify(await this.getAuthJson(options))
2023
2132
  };
2024
2133
  }
2134
+ useAuthHeaders(options) {
2135
+ return {
2136
+ "x-stack-auth": JSON.stringify(this.useAuthJson(options))
2137
+ };
2138
+ }
2025
2139
  async getAuthJson(options) {
2026
2140
  const user = await this.getUser({ tokenStore: options?.tokenStore ?? void 0 });
2027
2141
  if (user) {
@@ -2029,6 +2143,13 @@ ${url}`);
2029
2143
  }
2030
2144
  return { accessToken: null, refreshToken: null };
2031
2145
  }
2146
+ useAuthJson(options) {
2147
+ const user = this.useUser({ tokenStore: options?.tokenStore ?? void 0 });
2148
+ if (user) {
2149
+ return user.useAuthJson();
2150
+ }
2151
+ return { accessToken: null, refreshToken: null };
2152
+ }
2032
2153
  async getProject() {
2033
2154
  const crud = Result.orThrow(await this._currentProjectCache.getOrWait([], "write-only"));
2034
2155
  return this._clientProjectFromCrud(crud);
@@ -2065,6 +2186,7 @@ ${url}`);
2065
2186
  }
2066
2187
  async _refreshUser(session) {
2067
2188
  await this._refreshSession(session);
2189
+ session.suggestAccessTokenExpired();
2068
2190
  }
2069
2191
  async _refreshSession(session) {
2070
2192
  await this._currentUserCache.refresh([session]);