@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
@@ -980,22 +980,65 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
980
980
  _internalSession: session,
981
981
  currentSession: {
982
982
  async getTokens() {
983
- const tokens = await session.getOrFetchLikelyValidTokens(2e4);
983
+ const tokens = await session.getOrFetchLikelyValidTokens(2e4, 75e3);
984
984
  return {
985
985
  accessToken: tokens?.accessToken.token ?? null,
986
986
  refreshToken: tokens?.refreshToken?.token ?? null
987
987
  };
988
+ },
989
+ useTokens() {
990
+ const [_, setCounter] = import_react2.default.useState(0);
991
+ import_react2.default.useEffect(() => {
992
+ const { unsubscribe: unsubscribeRefresh } = session.startRefreshingAccessToken(3e4, 6e4);
993
+ const { unsubscribe: unsubscribeInvalidate } = session.onInvalidate(() => setCounter((c) => c + 1));
994
+ const { unsubscribe: unsubscribeAccessTokenChange } = session.onAccessTokenChange(() => setCounter((c) => c + 1));
995
+ return () => {
996
+ unsubscribeRefresh();
997
+ unsubscribeInvalidate();
998
+ unsubscribeAccessTokenChange();
999
+ };
1000
+ }, []);
1001
+ let accessToken = session.isKnownToBeInvalid() ? null : session.getAccessTokenIfNotExpiredYet(2e4, 75e3);
1002
+ if (accessToken === null) {
1003
+ accessToken = (0, import_react.use)(session.getOrFetchLikelyValidTokens(2e4, 75e3))?.accessToken ?? null;
1004
+ }
1005
+ return {
1006
+ accessToken: accessToken?.token ?? null,
1007
+ refreshToken: session.getRefreshToken()?.token ?? null
1008
+ };
988
1009
  }
989
1010
  },
1011
+ async getAccessToken() {
1012
+ const tokens = await this.currentSession.getTokens();
1013
+ return tokens.accessToken;
1014
+ },
1015
+ useAccessToken() {
1016
+ return this.currentSession.useTokens().accessToken;
1017
+ },
1018
+ async getRefreshToken() {
1019
+ const tokens = await this.currentSession.getTokens();
1020
+ return tokens.refreshToken;
1021
+ },
1022
+ useRefreshToken() {
1023
+ return this.currentSession.useTokens().refreshToken;
1024
+ },
990
1025
  async getAuthHeaders() {
991
1026
  return {
992
1027
  "x-stack-auth": JSON.stringify(await this.getAuthJson())
993
1028
  };
994
1029
  },
1030
+ useAuthHeaders() {
1031
+ return {
1032
+ "x-stack-auth": JSON.stringify(this.useAuthJson())
1033
+ };
1034
+ },
995
1035
  async getAuthJson() {
996
1036
  const tokens = await this.currentSession.getTokens();
997
1037
  return tokens;
998
1038
  },
1039
+ useAuthJson() {
1040
+ return this.currentSession.useTokens();
1041
+ },
999
1042
  signOut(options) {
1000
1043
  return app._signOut(session, options);
1001
1044
  }
@@ -1036,6 +1079,8 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1036
1079
  passkeyAuthEnabled: crud.passkey_auth_enabled,
1037
1080
  isMultiFactorRequired: crud.requires_totp_mfa,
1038
1081
  isAnonymous: crud.is_anonymous,
1082
+ isRestricted: crud.is_restricted,
1083
+ restrictedReason: crud.restricted_reason,
1039
1084
  toClientJson() {
1040
1085
  return crud;
1041
1086
  }
@@ -1066,7 +1111,7 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1066
1111
  return this.update({ clientMetadata: metadata });
1067
1112
  },
1068
1113
  async setSelectedTeam(team) {
1069
- await this.update({ selectedTeamId: team?.id ?? null });
1114
+ await this.update({ selectedTeamId: typeof team === "string" ? team : team?.id ?? null });
1070
1115
  },
1071
1116
  getConnectedAccount,
1072
1117
  useConnectedAccount,
@@ -1346,6 +1391,25 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1346
1391
  const response = import_results.Result.orThrow(await this._customProductsCache.getOrWait([session, options.customCustomerId, options.cursor ?? null, options.limit ?? null], "write-only"));
1347
1392
  return this._customerProductsFromResponse(response);
1348
1393
  }
1394
+ async cancelSubscription(options) {
1395
+ const session = await this._getSession();
1396
+ const user = await this.getUser();
1397
+ if (!user) {
1398
+ throw new import_stack_shared.KnownErrors.UserAuthenticationRequired();
1399
+ }
1400
+ const customerType = "teamId" in options ? "team" : "user";
1401
+ const customerId = "teamId" in options ? options.teamId : user.id;
1402
+ await this._interface.cancelSubscription({
1403
+ customer_type: customerType,
1404
+ customer_id: customerId,
1405
+ product_id: options.productId
1406
+ }, session);
1407
+ if (customerType === "user") {
1408
+ await this._userProductsCache.invalidateWhere(([cachedSession, userId]) => cachedSession === session && userId === customerId);
1409
+ } else {
1410
+ await this._teamProductsCache.invalidateWhere(([cachedSession, teamId]) => cachedSession === session && teamId === customerId);
1411
+ }
1412
+ }
1349
1413
  useProducts(options) {
1350
1414
  const session = this._useSession();
1351
1415
  const cache = "userId" in options ? this._userProductsCache : "teamId" in options ? this._teamProductsCache : this._customProductsCache;
@@ -1355,15 +1419,13 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1355
1419
  return this._customerProductsFromResponse(response);
1356
1420
  }
1357
1421
  _currentUserFromCrud(crud, session) {
1358
- const currentUser = {
1422
+ const currentUser = (0, import_users.withUserDestructureGuard)({
1359
1423
  ...this._createBaseUser(crud),
1360
1424
  ...this._createAuth(session),
1361
1425
  ...this._createUserExtraFromCurrent(crud, session),
1362
1426
  ...this._isInternalProject() ? this._createInternalUserExtra(session) : {},
1363
1427
  ...this._createCustomer(crud.id, "user", session)
1364
- };
1365
- (0, import_users.attachUserDestructureGuard)(currentUser);
1366
- Object.freeze(currentUser);
1428
+ });
1367
1429
  return currentUser;
1368
1430
  }
1369
1431
  _clientSessionFromCrud(crud) {
@@ -1451,7 +1513,7 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1451
1513
  const queryParams = new URLSearchParams(window.location.search);
1452
1514
  url = queryParams.get("after_auth_return_to") || url;
1453
1515
  }
1454
- } else if (handlerName === "signIn" || handlerName === "signUp") {
1516
+ } else if (handlerName === "signIn" || handlerName === "signUp" || handlerName === "onboarding") {
1455
1517
  if (isReactServer2 || typeof window === "undefined") {
1456
1518
  } else {
1457
1519
  const currentUrl = new URL(window.location.href);
@@ -1500,6 +1562,9 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1500
1562
  async redirectToAfterSignUp(options) {
1501
1563
  return await this._redirectToHandler("afterSignUp", options);
1502
1564
  }
1565
+ async redirectToOnboarding(options) {
1566
+ return await this._redirectToHandler("onboarding", options);
1567
+ }
1503
1568
  async redirectToAfterSignOut(options) {
1504
1569
  return await this._redirectToHandler("afterSignOut", options);
1505
1570
  }
@@ -1565,16 +1630,22 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1565
1630
  return result;
1566
1631
  }
1567
1632
  async getUser(options) {
1633
+ if (options?.or === "anonymous" && options.includeRestricted === false) {
1634
+ throw new Error("Cannot use { or: 'anonymous' } with { includeRestricted: false }. Anonymous users implicitly include restricted users.");
1635
+ }
1568
1636
  this._ensurePersistentTokenStore(options?.tokenStore);
1569
1637
  const session = await this._getSession(options?.tokenStore);
1570
1638
  let crud = import_results.Result.orThrow(await this._currentUserCache.getOrWait([session], "write-only"));
1571
- if (crud?.is_anonymous && options?.or !== "anonymous" && options?.or !== "anonymous-if-exists[deprecated]") {
1572
- crud = null;
1573
- }
1574
- if (crud === null) {
1639
+ const includeAnonymous = options?.or === "anonymous" || options?.or === "anonymous-if-exists[deprecated]";
1640
+ const includeRestricted = options?.includeRestricted === true || includeAnonymous;
1641
+ if (crud === null || crud.is_anonymous && !includeAnonymous || crud.is_restricted && !includeRestricted) {
1575
1642
  switch (options?.or) {
1576
1643
  case "redirect": {
1577
- await this.redirectToSignIn({ replace: true });
1644
+ if (!crud?.is_anonymous && crud?.is_restricted) {
1645
+ await this.redirectToOnboarding({ replace: true });
1646
+ } else {
1647
+ await this.redirectToSignIn({ replace: true });
1648
+ }
1578
1649
  break;
1579
1650
  }
1580
1651
  case "throw": {
@@ -1582,7 +1653,7 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1582
1653
  }
1583
1654
  case "anonymous": {
1584
1655
  const tokens = await this._signUpAnonymously();
1585
- return await this.getUser({ tokenStore: tokens, or: "anonymous-if-exists[deprecated]" }) ?? (0, import_errors.throwErr)("Something went wrong while signing up anonymously");
1656
+ return await this.getUser({ tokenStore: tokens, or: "anonymous-if-exists[deprecated]", includeRestricted: true }) ?? (0, import_errors.throwErr)("Something went wrong while signing up anonymously");
1586
1657
  }
1587
1658
  case void 0:
1588
1659
  case "anonymous-if-exists[deprecated]":
@@ -1594,16 +1665,22 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1594
1665
  return crud && this._currentUserFromCrud(crud, session);
1595
1666
  }
1596
1667
  useUser(options) {
1668
+ if (options?.or === "anonymous" && options.includeRestricted === false) {
1669
+ throw new Error("Cannot use { or: 'anonymous' } with { includeRestricted: false }. Anonymous users implicitly include restricted users.");
1670
+ }
1597
1671
  this._ensurePersistentTokenStore(options?.tokenStore);
1598
1672
  const session = this._useSession(options?.tokenStore);
1599
1673
  let crud = (0, import_common3.useAsyncCache)(this._currentUserCache, [session], "clientApp.useUser()");
1600
- if (crud?.is_anonymous && options?.or !== "anonymous" && options?.or !== "anonymous-if-exists[deprecated]") {
1601
- crud = null;
1602
- }
1603
- if (crud === null) {
1674
+ const includeAnonymous = options?.or === "anonymous" || options?.or === "anonymous-if-exists[deprecated]";
1675
+ const includeRestricted = options?.includeRestricted === true || includeAnonymous;
1676
+ if (crud === null || crud.is_anonymous && !includeAnonymous || crud.is_restricted && !includeRestricted) {
1604
1677
  switch (options?.or) {
1605
1678
  case "redirect": {
1606
- (0, import_promises.runAsynchronously)(this.redirectToSignIn({ replace: true }));
1679
+ if (!crud?.is_anonymous && crud?.is_restricted) {
1680
+ (0, import_promises.runAsynchronously)(this.redirectToOnboarding({ replace: true }));
1681
+ } else {
1682
+ (0, import_promises.runAsynchronously)(this.redirectToSignIn({ replace: true }));
1683
+ }
1607
1684
  (0, import_react.suspend)();
1608
1685
  throw new import_errors.StackAssertionError("suspend should never return");
1609
1686
  }
@@ -1631,7 +1708,7 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1631
1708
  }, [crud, session, options?.or]);
1632
1709
  }
1633
1710
  _getTokenPartialUserFromSession(session, options) {
1634
- const accessToken = session.getAccessTokenIfNotExpiredYet(0);
1711
+ const accessToken = session.getAccessTokenIfNotExpiredYet(0, null);
1635
1712
  if (!accessToken) {
1636
1713
  return null;
1637
1714
  }
@@ -1644,7 +1721,9 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1644
1721
  primaryEmail: accessToken.payload.email,
1645
1722
  displayName: accessToken.payload.name,
1646
1723
  primaryEmailVerified: accessToken.payload.email_verified,
1647
- isAnonymous
1724
+ isAnonymous,
1725
+ isRestricted: accessToken.payload.is_restricted,
1726
+ restrictedReason: accessToken.payload.restricted_reason
1648
1727
  };
1649
1728
  }
1650
1729
  async _getPartialUserFromConvex(ctx) {
@@ -1657,7 +1736,9 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1657
1736
  displayName: auth.name ?? null,
1658
1737
  primaryEmail: auth.email ?? null,
1659
1738
  primaryEmailVerified: auth.email_verified,
1660
- isAnonymous: auth.is_anonymous
1739
+ isAnonymous: auth.is_anonymous,
1740
+ isRestricted: auth.is_restricted,
1741
+ restrictedReason: auth.restricted_reason ?? null
1661
1742
  };
1662
1743
  }
1663
1744
  async getPartialUser(options) {
@@ -1695,7 +1776,7 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1695
1776
  return async (args) => {
1696
1777
  const session = await this._getSession(options.tokenStore ?? this._tokenStoreInit);
1697
1778
  if (!args.forceRefreshToken) {
1698
- const tokens2 = await session.getOrFetchLikelyValidTokens(2e4);
1779
+ const tokens2 = await session.getOrFetchLikelyValidTokens(2e4, 75e3);
1699
1780
  return tokens2?.accessToken.token ?? null;
1700
1781
  }
1701
1782
  const tokens = await session.fetchNewTokens();
@@ -1704,7 +1785,7 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1704
1785
  }
1705
1786
  async getConvexHttpClientAuth(options) {
1706
1787
  const session = await this._getSession(options.tokenStore);
1707
- const tokens = await session.getOrFetchLikelyValidTokens(2e4);
1788
+ const tokens = await session.getOrFetchLikelyValidTokens(2e4, 75e3);
1708
1789
  return tokens?.accessToken.token ?? "";
1709
1790
  }
1710
1791
  async _updateClientUser(update, session) {
@@ -2051,11 +2132,44 @@ ${url}`);
2051
2132
  await user.signOut({ redirectUrl: options?.redirectUrl });
2052
2133
  }
2053
2134
  }
2135
+ async getAccessToken(options) {
2136
+ const user = await this.getUser({ tokenStore: options?.tokenStore ?? void 0 });
2137
+ if (user) {
2138
+ return await user.getAccessToken();
2139
+ }
2140
+ return null;
2141
+ }
2142
+ useAccessToken(options) {
2143
+ const user = this.useUser({ tokenStore: options?.tokenStore ?? void 0 });
2144
+ if (user) {
2145
+ return user.useAccessToken();
2146
+ }
2147
+ return null;
2148
+ }
2149
+ async getRefreshToken(options) {
2150
+ const user = await this.getUser({ tokenStore: options?.tokenStore ?? void 0 });
2151
+ if (user) {
2152
+ return await user.getRefreshToken();
2153
+ }
2154
+ return null;
2155
+ }
2156
+ useRefreshToken(options) {
2157
+ const user = this.useUser({ tokenStore: options?.tokenStore ?? void 0 });
2158
+ if (user) {
2159
+ return user.useRefreshToken();
2160
+ }
2161
+ return null;
2162
+ }
2054
2163
  async getAuthHeaders(options) {
2055
2164
  return {
2056
2165
  "x-stack-auth": JSON.stringify(await this.getAuthJson(options))
2057
2166
  };
2058
2167
  }
2168
+ useAuthHeaders(options) {
2169
+ return {
2170
+ "x-stack-auth": JSON.stringify(this.useAuthJson(options))
2171
+ };
2172
+ }
2059
2173
  async getAuthJson(options) {
2060
2174
  const user = await this.getUser({ tokenStore: options?.tokenStore ?? void 0 });
2061
2175
  if (user) {
@@ -2063,6 +2177,13 @@ ${url}`);
2063
2177
  }
2064
2178
  return { accessToken: null, refreshToken: null };
2065
2179
  }
2180
+ useAuthJson(options) {
2181
+ const user = this.useUser({ tokenStore: options?.tokenStore ?? void 0 });
2182
+ if (user) {
2183
+ return user.useAuthJson();
2184
+ }
2185
+ return { accessToken: null, refreshToken: null };
2186
+ }
2066
2187
  async getProject() {
2067
2188
  const crud = import_results.Result.orThrow(await this._currentProjectCache.getOrWait([], "write-only"));
2068
2189
  return this._clientProjectFromCrud(crud);
@@ -2099,6 +2220,7 @@ ${url}`);
2099
2220
  }
2100
2221
  async _refreshUser(session) {
2101
2222
  await this._refreshSession(session);
2223
+ session.suggestAccessTokenExpired();
2102
2224
  }
2103
2225
  async _refreshSession(session) {
2104
2226
  await this._currentUserCache.refresh([session]);