@stackframe/react 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 +4 -3
  62. package/CHANGELOG.md +0 -2072
@@ -971,22 +971,65 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
971
971
  _internalSession: session,
972
972
  currentSession: {
973
973
  async getTokens() {
974
- const tokens = await session.getOrFetchLikelyValidTokens(2e4);
974
+ const tokens = await session.getOrFetchLikelyValidTokens(2e4, 75e3);
975
975
  return {
976
976
  accessToken: tokens?.accessToken.token ?? null,
977
977
  refreshToken: tokens?.refreshToken?.token ?? null
978
978
  };
979
+ },
980
+ useTokens() {
981
+ const [_, setCounter] = import_react2.default.useState(0);
982
+ import_react2.default.useEffect(() => {
983
+ const { unsubscribe: unsubscribeRefresh } = session.startRefreshingAccessToken(3e4, 6e4);
984
+ const { unsubscribe: unsubscribeInvalidate } = session.onInvalidate(() => setCounter((c) => c + 1));
985
+ const { unsubscribe: unsubscribeAccessTokenChange } = session.onAccessTokenChange(() => setCounter((c) => c + 1));
986
+ return () => {
987
+ unsubscribeRefresh();
988
+ unsubscribeInvalidate();
989
+ unsubscribeAccessTokenChange();
990
+ };
991
+ }, []);
992
+ let accessToken = session.isKnownToBeInvalid() ? null : session.getAccessTokenIfNotExpiredYet(2e4, 75e3);
993
+ if (accessToken === null) {
994
+ accessToken = (0, import_react.use)(session.getOrFetchLikelyValidTokens(2e4, 75e3))?.accessToken ?? null;
995
+ }
996
+ return {
997
+ accessToken: accessToken?.token ?? null,
998
+ refreshToken: session.getRefreshToken()?.token ?? null
999
+ };
979
1000
  }
980
1001
  },
1002
+ async getAccessToken() {
1003
+ const tokens = await this.currentSession.getTokens();
1004
+ return tokens.accessToken;
1005
+ },
1006
+ useAccessToken() {
1007
+ return this.currentSession.useTokens().accessToken;
1008
+ },
1009
+ async getRefreshToken() {
1010
+ const tokens = await this.currentSession.getTokens();
1011
+ return tokens.refreshToken;
1012
+ },
1013
+ useRefreshToken() {
1014
+ return this.currentSession.useTokens().refreshToken;
1015
+ },
981
1016
  async getAuthHeaders() {
982
1017
  return {
983
1018
  "x-stack-auth": JSON.stringify(await this.getAuthJson())
984
1019
  };
985
1020
  },
1021
+ useAuthHeaders() {
1022
+ return {
1023
+ "x-stack-auth": JSON.stringify(this.useAuthJson())
1024
+ };
1025
+ },
986
1026
  async getAuthJson() {
987
1027
  const tokens = await this.currentSession.getTokens();
988
1028
  return tokens;
989
1029
  },
1030
+ useAuthJson() {
1031
+ return this.currentSession.useTokens();
1032
+ },
990
1033
  signOut(options) {
991
1034
  return app._signOut(session, options);
992
1035
  }
@@ -1027,6 +1070,8 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1027
1070
  passkeyAuthEnabled: crud.passkey_auth_enabled,
1028
1071
  isMultiFactorRequired: crud.requires_totp_mfa,
1029
1072
  isAnonymous: crud.is_anonymous,
1073
+ isRestricted: crud.is_restricted,
1074
+ restrictedReason: crud.restricted_reason,
1030
1075
  toClientJson() {
1031
1076
  return crud;
1032
1077
  }
@@ -1057,7 +1102,7 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1057
1102
  return this.update({ clientMetadata: metadata });
1058
1103
  },
1059
1104
  async setSelectedTeam(team) {
1060
- await this.update({ selectedTeamId: team?.id ?? null });
1105
+ await this.update({ selectedTeamId: typeof team === "string" ? team : team?.id ?? null });
1061
1106
  },
1062
1107
  getConnectedAccount,
1063
1108
  useConnectedAccount,
@@ -1337,6 +1382,25 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1337
1382
  const response = import_results.Result.orThrow(await this._customProductsCache.getOrWait([session, options.customCustomerId, options.cursor ?? null, options.limit ?? null], "write-only"));
1338
1383
  return this._customerProductsFromResponse(response);
1339
1384
  }
1385
+ async cancelSubscription(options) {
1386
+ const session = await this._getSession();
1387
+ const user = await this.getUser();
1388
+ if (!user) {
1389
+ throw new import_stack_shared.KnownErrors.UserAuthenticationRequired();
1390
+ }
1391
+ const customerType = "teamId" in options ? "team" : "user";
1392
+ const customerId = "teamId" in options ? options.teamId : user.id;
1393
+ await this._interface.cancelSubscription({
1394
+ customer_type: customerType,
1395
+ customer_id: customerId,
1396
+ product_id: options.productId
1397
+ }, session);
1398
+ if (customerType === "user") {
1399
+ await this._userProductsCache.invalidateWhere(([cachedSession, userId]) => cachedSession === session && userId === customerId);
1400
+ } else {
1401
+ await this._teamProductsCache.invalidateWhere(([cachedSession, teamId]) => cachedSession === session && teamId === customerId);
1402
+ }
1403
+ }
1340
1404
  useProducts(options) {
1341
1405
  const session = this._useSession();
1342
1406
  const cache = "userId" in options ? this._userProductsCache : "teamId" in options ? this._teamProductsCache : this._customProductsCache;
@@ -1346,15 +1410,13 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1346
1410
  return this._customerProductsFromResponse(response);
1347
1411
  }
1348
1412
  _currentUserFromCrud(crud, session) {
1349
- const currentUser = {
1413
+ const currentUser = (0, import_users.withUserDestructureGuard)({
1350
1414
  ...this._createBaseUser(crud),
1351
1415
  ...this._createAuth(session),
1352
1416
  ...this._createUserExtraFromCurrent(crud, session),
1353
1417
  ...this._isInternalProject() ? this._createInternalUserExtra(session) : {},
1354
1418
  ...this._createCustomer(crud.id, "user", session)
1355
- };
1356
- (0, import_users.attachUserDestructureGuard)(currentUser);
1357
- Object.freeze(currentUser);
1419
+ });
1358
1420
  return currentUser;
1359
1421
  }
1360
1422
  _clientSessionFromCrud(crud) {
@@ -1437,7 +1499,7 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1437
1499
  const queryParams = new URLSearchParams(window.location.search);
1438
1500
  url = queryParams.get("after_auth_return_to") || url;
1439
1501
  }
1440
- } else if (handlerName === "signIn" || handlerName === "signUp") {
1502
+ } else if (handlerName === "signIn" || handlerName === "signUp" || handlerName === "onboarding") {
1441
1503
  if (isReactServer || typeof window === "undefined") {
1442
1504
  } else {
1443
1505
  const currentUrl = new URL(window.location.href);
@@ -1486,6 +1548,9 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1486
1548
  async redirectToAfterSignUp(options) {
1487
1549
  return await this._redirectToHandler("afterSignUp", options);
1488
1550
  }
1551
+ async redirectToOnboarding(options) {
1552
+ return await this._redirectToHandler("onboarding", options);
1553
+ }
1489
1554
  async redirectToAfterSignOut(options) {
1490
1555
  return await this._redirectToHandler("afterSignOut", options);
1491
1556
  }
@@ -1551,16 +1616,22 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1551
1616
  return result;
1552
1617
  }
1553
1618
  async getUser(options) {
1619
+ if (options?.or === "anonymous" && options.includeRestricted === false) {
1620
+ throw new Error("Cannot use { or: 'anonymous' } with { includeRestricted: false }. Anonymous users implicitly include restricted users.");
1621
+ }
1554
1622
  this._ensurePersistentTokenStore(options?.tokenStore);
1555
1623
  const session = await this._getSession(options?.tokenStore);
1556
1624
  let crud = import_results.Result.orThrow(await this._currentUserCache.getOrWait([session], "write-only"));
1557
- if (crud?.is_anonymous && options?.or !== "anonymous" && options?.or !== "anonymous-if-exists[deprecated]") {
1558
- crud = null;
1559
- }
1560
- if (crud === null) {
1625
+ const includeAnonymous = options?.or === "anonymous" || options?.or === "anonymous-if-exists[deprecated]";
1626
+ const includeRestricted = options?.includeRestricted === true || includeAnonymous;
1627
+ if (crud === null || crud.is_anonymous && !includeAnonymous || crud.is_restricted && !includeRestricted) {
1561
1628
  switch (options?.or) {
1562
1629
  case "redirect": {
1563
- await this.redirectToSignIn({ replace: true });
1630
+ if (!crud?.is_anonymous && crud?.is_restricted) {
1631
+ await this.redirectToOnboarding({ replace: true });
1632
+ } else {
1633
+ await this.redirectToSignIn({ replace: true });
1634
+ }
1564
1635
  break;
1565
1636
  }
1566
1637
  case "throw": {
@@ -1568,7 +1639,7 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1568
1639
  }
1569
1640
  case "anonymous": {
1570
1641
  const tokens = await this._signUpAnonymously();
1571
- return await this.getUser({ tokenStore: tokens, or: "anonymous-if-exists[deprecated]" }) ?? (0, import_errors.throwErr)("Something went wrong while signing up anonymously");
1642
+ return await this.getUser({ tokenStore: tokens, or: "anonymous-if-exists[deprecated]", includeRestricted: true }) ?? (0, import_errors.throwErr)("Something went wrong while signing up anonymously");
1572
1643
  }
1573
1644
  case void 0:
1574
1645
  case "anonymous-if-exists[deprecated]":
@@ -1580,16 +1651,22 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1580
1651
  return crud && this._currentUserFromCrud(crud, session);
1581
1652
  }
1582
1653
  useUser(options) {
1654
+ if (options?.or === "anonymous" && options.includeRestricted === false) {
1655
+ throw new Error("Cannot use { or: 'anonymous' } with { includeRestricted: false }. Anonymous users implicitly include restricted users.");
1656
+ }
1583
1657
  this._ensurePersistentTokenStore(options?.tokenStore);
1584
1658
  const session = this._useSession(options?.tokenStore);
1585
1659
  let crud = (0, import_common3.useAsyncCache)(this._currentUserCache, [session], "clientApp.useUser()");
1586
- if (crud?.is_anonymous && options?.or !== "anonymous" && options?.or !== "anonymous-if-exists[deprecated]") {
1587
- crud = null;
1588
- }
1589
- if (crud === null) {
1660
+ const includeAnonymous = options?.or === "anonymous" || options?.or === "anonymous-if-exists[deprecated]";
1661
+ const includeRestricted = options?.includeRestricted === true || includeAnonymous;
1662
+ if (crud === null || crud.is_anonymous && !includeAnonymous || crud.is_restricted && !includeRestricted) {
1590
1663
  switch (options?.or) {
1591
1664
  case "redirect": {
1592
- (0, import_promises.runAsynchronously)(this.redirectToSignIn({ replace: true }));
1665
+ if (!crud?.is_anonymous && crud?.is_restricted) {
1666
+ (0, import_promises.runAsynchronously)(this.redirectToOnboarding({ replace: true }));
1667
+ } else {
1668
+ (0, import_promises.runAsynchronously)(this.redirectToSignIn({ replace: true }));
1669
+ }
1593
1670
  (0, import_react.suspend)();
1594
1671
  throw new import_errors.StackAssertionError("suspend should never return");
1595
1672
  }
@@ -1617,7 +1694,7 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1617
1694
  }, [crud, session, options?.or]);
1618
1695
  }
1619
1696
  _getTokenPartialUserFromSession(session, options) {
1620
- const accessToken = session.getAccessTokenIfNotExpiredYet(0);
1697
+ const accessToken = session.getAccessTokenIfNotExpiredYet(0, null);
1621
1698
  if (!accessToken) {
1622
1699
  return null;
1623
1700
  }
@@ -1630,7 +1707,9 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1630
1707
  primaryEmail: accessToken.payload.email,
1631
1708
  displayName: accessToken.payload.name,
1632
1709
  primaryEmailVerified: accessToken.payload.email_verified,
1633
- isAnonymous
1710
+ isAnonymous,
1711
+ isRestricted: accessToken.payload.is_restricted,
1712
+ restrictedReason: accessToken.payload.restricted_reason
1634
1713
  };
1635
1714
  }
1636
1715
  async _getPartialUserFromConvex(ctx) {
@@ -1643,7 +1722,9 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1643
1722
  displayName: auth.name ?? null,
1644
1723
  primaryEmail: auth.email ?? null,
1645
1724
  primaryEmailVerified: auth.email_verified,
1646
- isAnonymous: auth.is_anonymous
1725
+ isAnonymous: auth.is_anonymous,
1726
+ isRestricted: auth.is_restricted,
1727
+ restrictedReason: auth.restricted_reason ?? null
1647
1728
  };
1648
1729
  }
1649
1730
  async getPartialUser(options) {
@@ -1681,7 +1762,7 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1681
1762
  return async (args) => {
1682
1763
  const session = await this._getSession(options.tokenStore ?? this._tokenStoreInit);
1683
1764
  if (!args.forceRefreshToken) {
1684
- const tokens2 = await session.getOrFetchLikelyValidTokens(2e4);
1765
+ const tokens2 = await session.getOrFetchLikelyValidTokens(2e4, 75e3);
1685
1766
  return tokens2?.accessToken.token ?? null;
1686
1767
  }
1687
1768
  const tokens = await session.fetchNewTokens();
@@ -1690,7 +1771,7 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1690
1771
  }
1691
1772
  async getConvexHttpClientAuth(options) {
1692
1773
  const session = await this._getSession(options.tokenStore);
1693
- const tokens = await session.getOrFetchLikelyValidTokens(2e4);
1774
+ const tokens = await session.getOrFetchLikelyValidTokens(2e4, 75e3);
1694
1775
  return tokens?.accessToken.token ?? "";
1695
1776
  }
1696
1777
  async _updateClientUser(update, session) {
@@ -2037,11 +2118,44 @@ ${url}`);
2037
2118
  await user.signOut({ redirectUrl: options?.redirectUrl });
2038
2119
  }
2039
2120
  }
2121
+ async getAccessToken(options) {
2122
+ const user = await this.getUser({ tokenStore: options?.tokenStore ?? void 0 });
2123
+ if (user) {
2124
+ return await user.getAccessToken();
2125
+ }
2126
+ return null;
2127
+ }
2128
+ useAccessToken(options) {
2129
+ const user = this.useUser({ tokenStore: options?.tokenStore ?? void 0 });
2130
+ if (user) {
2131
+ return user.useAccessToken();
2132
+ }
2133
+ return null;
2134
+ }
2135
+ async getRefreshToken(options) {
2136
+ const user = await this.getUser({ tokenStore: options?.tokenStore ?? void 0 });
2137
+ if (user) {
2138
+ return await user.getRefreshToken();
2139
+ }
2140
+ return null;
2141
+ }
2142
+ useRefreshToken(options) {
2143
+ const user = this.useUser({ tokenStore: options?.tokenStore ?? void 0 });
2144
+ if (user) {
2145
+ return user.useRefreshToken();
2146
+ }
2147
+ return null;
2148
+ }
2040
2149
  async getAuthHeaders(options) {
2041
2150
  return {
2042
2151
  "x-stack-auth": JSON.stringify(await this.getAuthJson(options))
2043
2152
  };
2044
2153
  }
2154
+ useAuthHeaders(options) {
2155
+ return {
2156
+ "x-stack-auth": JSON.stringify(this.useAuthJson(options))
2157
+ };
2158
+ }
2045
2159
  async getAuthJson(options) {
2046
2160
  const user = await this.getUser({ tokenStore: options?.tokenStore ?? void 0 });
2047
2161
  if (user) {
@@ -2049,6 +2163,13 @@ ${url}`);
2049
2163
  }
2050
2164
  return { accessToken: null, refreshToken: null };
2051
2165
  }
2166
+ useAuthJson(options) {
2167
+ const user = this.useUser({ tokenStore: options?.tokenStore ?? void 0 });
2168
+ if (user) {
2169
+ return user.useAuthJson();
2170
+ }
2171
+ return { accessToken: null, refreshToken: null };
2172
+ }
2052
2173
  async getProject() {
2053
2174
  const crud = import_results.Result.orThrow(await this._currentProjectCache.getOrWait([], "write-only"));
2054
2175
  return this._clientProjectFromCrud(crud);
@@ -2085,6 +2206,7 @@ ${url}`);
2085
2206
  }
2086
2207
  async _refreshUser(session) {
2087
2208
  await this._refreshSession(session);
2209
+ session.suggestAccessTokenExpired();
2088
2210
  }
2089
2211
  async _refreshSession(session) {
2090
2212
  await this._currentUserCache.refresh([session]);