@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
@@ -9,7 +9,7 @@ import { parseJson } from "@stackframe/stack-shared/dist/utils/json";
9
9
  import { DependenciesMap } from "@stackframe/stack-shared/dist/utils/maps";
10
10
  import { deepPlainEquals, omit } from "@stackframe/stack-shared/dist/utils/objects";
11
11
  import { neverResolve, runAsynchronously, wait } from "@stackframe/stack-shared/dist/utils/promises";
12
- import { suspend, suspendIfSsr } from "@stackframe/stack-shared/dist/utils/react";
12
+ import { suspend, suspendIfSsr, use } from "@stackframe/stack-shared/dist/utils/react";
13
13
  import { Result } from "@stackframe/stack-shared/dist/utils/results";
14
14
  import { Store, storeLock } from "@stackframe/stack-shared/dist/utils/stores";
15
15
  import { deindent, mergeScopeStrings } from "@stackframe/stack-shared/dist/utils/strings";
@@ -25,7 +25,7 @@ import { stackAppInternalsSymbol } from "../../common.js";
25
25
  import { contactChannelCreateOptionsToCrud, contactChannelUpdateOptionsToCrud } from "../../contact-channels/index.js";
26
26
  import { adminProjectCreateOptionsToCrud } from "../../projects/index.js";
27
27
  import { teamCreateOptionsToCrud, teamUpdateOptionsToCrud } from "../../teams/index.js";
28
- import { attachUserDestructureGuard, userUpdateOptionsToCrud } from "../../users/index.js";
28
+ import { userUpdateOptionsToCrud, withUserDestructureGuard } from "../../users/index.js";
29
29
  import { clientVersion, createCache, createCacheBySession, createEmptyTokenStore, getBaseUrl, getDefaultExtraRequestHeaders, getDefaultProjectId, getDefaultPublishableClientKey, getUrls, resolveConstructorOptions } from "./common.js";
30
30
  import { useAsyncCache } from "./common.js";
31
31
  var isReactServer = false;
@@ -937,22 +937,65 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
937
937
  _internalSession: session,
938
938
  currentSession: {
939
939
  async getTokens() {
940
- const tokens = await session.getOrFetchLikelyValidTokens(2e4);
940
+ const tokens = await session.getOrFetchLikelyValidTokens(2e4, 75e3);
941
941
  return {
942
942
  accessToken: tokens?.accessToken.token ?? null,
943
943
  refreshToken: tokens?.refreshToken?.token ?? null
944
944
  };
945
+ },
946
+ useTokens() {
947
+ const [_, setCounter] = React.useState(0);
948
+ React.useEffect(() => {
949
+ const { unsubscribe: unsubscribeRefresh } = session.startRefreshingAccessToken(3e4, 6e4);
950
+ const { unsubscribe: unsubscribeInvalidate } = session.onInvalidate(() => setCounter((c) => c + 1));
951
+ const { unsubscribe: unsubscribeAccessTokenChange } = session.onAccessTokenChange(() => setCounter((c) => c + 1));
952
+ return () => {
953
+ unsubscribeRefresh();
954
+ unsubscribeInvalidate();
955
+ unsubscribeAccessTokenChange();
956
+ };
957
+ }, []);
958
+ let accessToken = session.isKnownToBeInvalid() ? null : session.getAccessTokenIfNotExpiredYet(2e4, 75e3);
959
+ if (accessToken === null) {
960
+ accessToken = use(session.getOrFetchLikelyValidTokens(2e4, 75e3))?.accessToken ?? null;
961
+ }
962
+ return {
963
+ accessToken: accessToken?.token ?? null,
964
+ refreshToken: session.getRefreshToken()?.token ?? null
965
+ };
945
966
  }
946
967
  },
968
+ async getAccessToken() {
969
+ const tokens = await this.currentSession.getTokens();
970
+ return tokens.accessToken;
971
+ },
972
+ useAccessToken() {
973
+ return this.currentSession.useTokens().accessToken;
974
+ },
975
+ async getRefreshToken() {
976
+ const tokens = await this.currentSession.getTokens();
977
+ return tokens.refreshToken;
978
+ },
979
+ useRefreshToken() {
980
+ return this.currentSession.useTokens().refreshToken;
981
+ },
947
982
  async getAuthHeaders() {
948
983
  return {
949
984
  "x-stack-auth": JSON.stringify(await this.getAuthJson())
950
985
  };
951
986
  },
987
+ useAuthHeaders() {
988
+ return {
989
+ "x-stack-auth": JSON.stringify(this.useAuthJson())
990
+ };
991
+ },
952
992
  async getAuthJson() {
953
993
  const tokens = await this.currentSession.getTokens();
954
994
  return tokens;
955
995
  },
996
+ useAuthJson() {
997
+ return this.currentSession.useTokens();
998
+ },
956
999
  signOut(options) {
957
1000
  return app._signOut(session, options);
958
1001
  }
@@ -993,6 +1036,8 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
993
1036
  passkeyAuthEnabled: crud.passkey_auth_enabled,
994
1037
  isMultiFactorRequired: crud.requires_totp_mfa,
995
1038
  isAnonymous: crud.is_anonymous,
1039
+ isRestricted: crud.is_restricted,
1040
+ restrictedReason: crud.restricted_reason,
996
1041
  toClientJson() {
997
1042
  return crud;
998
1043
  }
@@ -1023,7 +1068,7 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1023
1068
  return this.update({ clientMetadata: metadata });
1024
1069
  },
1025
1070
  async setSelectedTeam(team) {
1026
- await this.update({ selectedTeamId: team?.id ?? null });
1071
+ await this.update({ selectedTeamId: typeof team === "string" ? team : team?.id ?? null });
1027
1072
  },
1028
1073
  getConnectedAccount,
1029
1074
  useConnectedAccount,
@@ -1303,6 +1348,25 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1303
1348
  const response = Result.orThrow(await this._customProductsCache.getOrWait([session, options.customCustomerId, options.cursor ?? null, options.limit ?? null], "write-only"));
1304
1349
  return this._customerProductsFromResponse(response);
1305
1350
  }
1351
+ async cancelSubscription(options) {
1352
+ const session = await this._getSession();
1353
+ const user = await this.getUser();
1354
+ if (!user) {
1355
+ throw new KnownErrors.UserAuthenticationRequired();
1356
+ }
1357
+ const customerType = "teamId" in options ? "team" : "user";
1358
+ const customerId = "teamId" in options ? options.teamId : user.id;
1359
+ await this._interface.cancelSubscription({
1360
+ customer_type: customerType,
1361
+ customer_id: customerId,
1362
+ product_id: options.productId
1363
+ }, session);
1364
+ if (customerType === "user") {
1365
+ await this._userProductsCache.invalidateWhere(([cachedSession, userId]) => cachedSession === session && userId === customerId);
1366
+ } else {
1367
+ await this._teamProductsCache.invalidateWhere(([cachedSession, teamId]) => cachedSession === session && teamId === customerId);
1368
+ }
1369
+ }
1306
1370
  useProducts(options) {
1307
1371
  const session = this._useSession();
1308
1372
  const cache = "userId" in options ? this._userProductsCache : "teamId" in options ? this._teamProductsCache : this._customProductsCache;
@@ -1312,15 +1376,13 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1312
1376
  return this._customerProductsFromResponse(response);
1313
1377
  }
1314
1378
  _currentUserFromCrud(crud, session) {
1315
- const currentUser = {
1379
+ const currentUser = withUserDestructureGuard({
1316
1380
  ...this._createBaseUser(crud),
1317
1381
  ...this._createAuth(session),
1318
1382
  ...this._createUserExtraFromCurrent(crud, session),
1319
1383
  ...this._isInternalProject() ? this._createInternalUserExtra(session) : {},
1320
1384
  ...this._createCustomer(crud.id, "user", session)
1321
- };
1322
- attachUserDestructureGuard(currentUser);
1323
- Object.freeze(currentUser);
1385
+ });
1324
1386
  return currentUser;
1325
1387
  }
1326
1388
  _clientSessionFromCrud(crud) {
@@ -1403,7 +1465,7 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1403
1465
  const queryParams = new URLSearchParams(window.location.search);
1404
1466
  url = queryParams.get("after_auth_return_to") || url;
1405
1467
  }
1406
- } else if (handlerName === "signIn" || handlerName === "signUp") {
1468
+ } else if (handlerName === "signIn" || handlerName === "signUp" || handlerName === "onboarding") {
1407
1469
  if (isReactServer || typeof window === "undefined") {
1408
1470
  } else {
1409
1471
  const currentUrl = new URL(window.location.href);
@@ -1452,6 +1514,9 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1452
1514
  async redirectToAfterSignUp(options) {
1453
1515
  return await this._redirectToHandler("afterSignUp", options);
1454
1516
  }
1517
+ async redirectToOnboarding(options) {
1518
+ return await this._redirectToHandler("onboarding", options);
1519
+ }
1455
1520
  async redirectToAfterSignOut(options) {
1456
1521
  return await this._redirectToHandler("afterSignOut", options);
1457
1522
  }
@@ -1517,16 +1582,22 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1517
1582
  return result;
1518
1583
  }
1519
1584
  async getUser(options) {
1585
+ if (options?.or === "anonymous" && options.includeRestricted === false) {
1586
+ throw new Error("Cannot use { or: 'anonymous' } with { includeRestricted: false }. Anonymous users implicitly include restricted users.");
1587
+ }
1520
1588
  this._ensurePersistentTokenStore(options?.tokenStore);
1521
1589
  const session = await this._getSession(options?.tokenStore);
1522
1590
  let crud = Result.orThrow(await this._currentUserCache.getOrWait([session], "write-only"));
1523
- if (crud?.is_anonymous && options?.or !== "anonymous" && options?.or !== "anonymous-if-exists[deprecated]") {
1524
- crud = null;
1525
- }
1526
- if (crud === null) {
1591
+ const includeAnonymous = options?.or === "anonymous" || options?.or === "anonymous-if-exists[deprecated]";
1592
+ const includeRestricted = options?.includeRestricted === true || includeAnonymous;
1593
+ if (crud === null || crud.is_anonymous && !includeAnonymous || crud.is_restricted && !includeRestricted) {
1527
1594
  switch (options?.or) {
1528
1595
  case "redirect": {
1529
- await this.redirectToSignIn({ replace: true });
1596
+ if (!crud?.is_anonymous && crud?.is_restricted) {
1597
+ await this.redirectToOnboarding({ replace: true });
1598
+ } else {
1599
+ await this.redirectToSignIn({ replace: true });
1600
+ }
1530
1601
  break;
1531
1602
  }
1532
1603
  case "throw": {
@@ -1534,7 +1605,7 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1534
1605
  }
1535
1606
  case "anonymous": {
1536
1607
  const tokens = await this._signUpAnonymously();
1537
- return await this.getUser({ tokenStore: tokens, or: "anonymous-if-exists[deprecated]" }) ?? throwErr("Something went wrong while signing up anonymously");
1608
+ return await this.getUser({ tokenStore: tokens, or: "anonymous-if-exists[deprecated]", includeRestricted: true }) ?? throwErr("Something went wrong while signing up anonymously");
1538
1609
  }
1539
1610
  case void 0:
1540
1611
  case "anonymous-if-exists[deprecated]":
@@ -1546,16 +1617,22 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1546
1617
  return crud && this._currentUserFromCrud(crud, session);
1547
1618
  }
1548
1619
  useUser(options) {
1620
+ if (options?.or === "anonymous" && options.includeRestricted === false) {
1621
+ throw new Error("Cannot use { or: 'anonymous' } with { includeRestricted: false }. Anonymous users implicitly include restricted users.");
1622
+ }
1549
1623
  this._ensurePersistentTokenStore(options?.tokenStore);
1550
1624
  const session = this._useSession(options?.tokenStore);
1551
1625
  let crud = useAsyncCache(this._currentUserCache, [session], "clientApp.useUser()");
1552
- if (crud?.is_anonymous && options?.or !== "anonymous" && options?.or !== "anonymous-if-exists[deprecated]") {
1553
- crud = null;
1554
- }
1555
- if (crud === null) {
1626
+ const includeAnonymous = options?.or === "anonymous" || options?.or === "anonymous-if-exists[deprecated]";
1627
+ const includeRestricted = options?.includeRestricted === true || includeAnonymous;
1628
+ if (crud === null || crud.is_anonymous && !includeAnonymous || crud.is_restricted && !includeRestricted) {
1556
1629
  switch (options?.or) {
1557
1630
  case "redirect": {
1558
- runAsynchronously(this.redirectToSignIn({ replace: true }));
1631
+ if (!crud?.is_anonymous && crud?.is_restricted) {
1632
+ runAsynchronously(this.redirectToOnboarding({ replace: true }));
1633
+ } else {
1634
+ runAsynchronously(this.redirectToSignIn({ replace: true }));
1635
+ }
1559
1636
  suspend();
1560
1637
  throw new StackAssertionError("suspend should never return");
1561
1638
  }
@@ -1583,7 +1660,7 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1583
1660
  }, [crud, session, options?.or]);
1584
1661
  }
1585
1662
  _getTokenPartialUserFromSession(session, options) {
1586
- const accessToken = session.getAccessTokenIfNotExpiredYet(0);
1663
+ const accessToken = session.getAccessTokenIfNotExpiredYet(0, null);
1587
1664
  if (!accessToken) {
1588
1665
  return null;
1589
1666
  }
@@ -1596,7 +1673,9 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1596
1673
  primaryEmail: accessToken.payload.email,
1597
1674
  displayName: accessToken.payload.name,
1598
1675
  primaryEmailVerified: accessToken.payload.email_verified,
1599
- isAnonymous
1676
+ isAnonymous,
1677
+ isRestricted: accessToken.payload.is_restricted,
1678
+ restrictedReason: accessToken.payload.restricted_reason
1600
1679
  };
1601
1680
  }
1602
1681
  async _getPartialUserFromConvex(ctx) {
@@ -1609,7 +1688,9 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1609
1688
  displayName: auth.name ?? null,
1610
1689
  primaryEmail: auth.email ?? null,
1611
1690
  primaryEmailVerified: auth.email_verified,
1612
- isAnonymous: auth.is_anonymous
1691
+ isAnonymous: auth.is_anonymous,
1692
+ isRestricted: auth.is_restricted,
1693
+ restrictedReason: auth.restricted_reason ?? null
1613
1694
  };
1614
1695
  }
1615
1696
  async getPartialUser(options) {
@@ -1647,7 +1728,7 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1647
1728
  return async (args) => {
1648
1729
  const session = await this._getSession(options.tokenStore ?? this._tokenStoreInit);
1649
1730
  if (!args.forceRefreshToken) {
1650
- const tokens2 = await session.getOrFetchLikelyValidTokens(2e4);
1731
+ const tokens2 = await session.getOrFetchLikelyValidTokens(2e4, 75e3);
1651
1732
  return tokens2?.accessToken.token ?? null;
1652
1733
  }
1653
1734
  const tokens = await session.fetchNewTokens();
@@ -1656,7 +1737,7 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1656
1737
  }
1657
1738
  async getConvexHttpClientAuth(options) {
1658
1739
  const session = await this._getSession(options.tokenStore);
1659
- const tokens = await session.getOrFetchLikelyValidTokens(2e4);
1740
+ const tokens = await session.getOrFetchLikelyValidTokens(2e4, 75e3);
1660
1741
  return tokens?.accessToken.token ?? "";
1661
1742
  }
1662
1743
  async _updateClientUser(update, session) {
@@ -2003,11 +2084,44 @@ ${url}`);
2003
2084
  await user.signOut({ redirectUrl: options?.redirectUrl });
2004
2085
  }
2005
2086
  }
2087
+ async getAccessToken(options) {
2088
+ const user = await this.getUser({ tokenStore: options?.tokenStore ?? void 0 });
2089
+ if (user) {
2090
+ return await user.getAccessToken();
2091
+ }
2092
+ return null;
2093
+ }
2094
+ useAccessToken(options) {
2095
+ const user = this.useUser({ tokenStore: options?.tokenStore ?? void 0 });
2096
+ if (user) {
2097
+ return user.useAccessToken();
2098
+ }
2099
+ return null;
2100
+ }
2101
+ async getRefreshToken(options) {
2102
+ const user = await this.getUser({ tokenStore: options?.tokenStore ?? void 0 });
2103
+ if (user) {
2104
+ return await user.getRefreshToken();
2105
+ }
2106
+ return null;
2107
+ }
2108
+ useRefreshToken(options) {
2109
+ const user = this.useUser({ tokenStore: options?.tokenStore ?? void 0 });
2110
+ if (user) {
2111
+ return user.useRefreshToken();
2112
+ }
2113
+ return null;
2114
+ }
2006
2115
  async getAuthHeaders(options) {
2007
2116
  return {
2008
2117
  "x-stack-auth": JSON.stringify(await this.getAuthJson(options))
2009
2118
  };
2010
2119
  }
2120
+ useAuthHeaders(options) {
2121
+ return {
2122
+ "x-stack-auth": JSON.stringify(this.useAuthJson(options))
2123
+ };
2124
+ }
2011
2125
  async getAuthJson(options) {
2012
2126
  const user = await this.getUser({ tokenStore: options?.tokenStore ?? void 0 });
2013
2127
  if (user) {
@@ -2015,6 +2129,13 @@ ${url}`);
2015
2129
  }
2016
2130
  return { accessToken: null, refreshToken: null };
2017
2131
  }
2132
+ useAuthJson(options) {
2133
+ const user = this.useUser({ tokenStore: options?.tokenStore ?? void 0 });
2134
+ if (user) {
2135
+ return user.useAuthJson();
2136
+ }
2137
+ return { accessToken: null, refreshToken: null };
2138
+ }
2018
2139
  async getProject() {
2019
2140
  const crud = Result.orThrow(await this._currentProjectCache.getOrWait([], "write-only"));
2020
2141
  return this._clientProjectFromCrud(crud);
@@ -2051,6 +2172,7 @@ ${url}`);
2051
2172
  }
2052
2173
  async _refreshUser(session) {
2053
2174
  await this._refreshSession(session);
2175
+ session.suggestAccessTokenExpired();
2054
2176
  }
2055
2177
  async _refreshSession(session) {
2056
2178
  await this._currentUserCache.refresh([session]);