@hexclave/tanstack-start 1.0.5 → 1.0.6

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 (102) hide show
  1. package/dist/components-page/account-settings/payments/payments-panel.js +3 -3
  2. package/dist/components-page/account-settings/payments/payments-panel.js.map +1 -1
  3. package/dist/components-page/account-settings/teams/team-api-keys-section.js +1 -1
  4. package/dist/components-page/hexclave-handler-client.d.ts +13 -1
  5. package/dist/components-page/hexclave-handler-client.d.ts.map +1 -1
  6. package/dist/components-page/hexclave-handler-client.js +44 -9
  7. package/dist/components-page/hexclave-handler-client.js.map +1 -1
  8. package/dist/components-page/hexclave-handler-client.test.d.ts +1 -0
  9. package/dist/components-page/hexclave-handler-client.test.js +51 -0
  10. package/dist/components-page/hexclave-handler-client.test.js.map +1 -0
  11. package/dist/dev-tool/dev-tool-core.js +2 -2
  12. package/dist/dev-tool/dev-tool-core.js.map +1 -1
  13. package/dist/esm/components-page/account-settings/payments/payments-panel.js +2 -2
  14. package/dist/esm/components-page/account-settings/payments/payments-panel.js.map +1 -1
  15. package/dist/esm/components-page/account-settings/teams/team-api-keys-section.js +1 -1
  16. package/dist/esm/components-page/hexclave-handler-client.d.ts +12 -1
  17. package/dist/esm/components-page/hexclave-handler-client.d.ts.map +1 -1
  18. package/dist/esm/components-page/hexclave-handler-client.js +46 -12
  19. package/dist/esm/components-page/hexclave-handler-client.js.map +1 -1
  20. package/dist/esm/components-page/hexclave-handler-client.test.d.ts +1 -0
  21. package/dist/esm/components-page/hexclave-handler-client.test.js +51 -0
  22. package/dist/esm/components-page/hexclave-handler-client.test.js.map +1 -0
  23. package/dist/esm/dev-tool/dev-tool-core.js +2 -2
  24. package/dist/esm/dev-tool/dev-tool-core.js.map +1 -1
  25. package/dist/esm/generated/env.d.ts +26 -0
  26. package/dist/esm/{lib → generated}/env.d.ts.map +1 -1
  27. package/dist/esm/generated/env.js +67 -0
  28. package/dist/esm/generated/env.js.map +1 -0
  29. package/dist/esm/generated/quetzal-translations.d.ts +2 -2
  30. package/dist/esm/global.d.ts +8 -1
  31. package/dist/esm/global.d.ts.map +1 -0
  32. package/dist/esm/lib/auth.js +1 -1
  33. package/dist/esm/lib/cookie.d.ts +0 -8
  34. package/dist/esm/lib/cookie.d.ts.map +1 -1
  35. package/dist/esm/lib/cookie.js +2 -2
  36. package/dist/esm/lib/cookie.js.map +1 -1
  37. package/dist/esm/lib/hexclave-app/apps/implementations/admin-app-impl.d.ts.map +1 -1
  38. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.cross-domain.test.js +263 -3
  39. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.cross-domain.test.js.map +1 -1
  40. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.d.ts +3 -1
  41. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.d.ts.map +1 -1
  42. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.js +54 -27
  43. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.js.map +1 -1
  44. package/dist/esm/lib/hexclave-app/apps/implementations/common.d.ts +8 -8
  45. package/dist/esm/lib/hexclave-app/apps/implementations/common.d.ts.map +1 -1
  46. package/dist/esm/lib/hexclave-app/apps/implementations/common.js +29 -15
  47. package/dist/esm/lib/hexclave-app/apps/implementations/common.js.map +1 -1
  48. package/dist/esm/lib/hexclave-app/apps/implementations/server-app-impl.js +1 -1
  49. package/dist/esm/lib/hexclave-app/url-targets.d.ts.map +1 -1
  50. package/dist/esm/lib/hexclave-app/url-targets.js +25 -11
  51. package/dist/esm/lib/hexclave-app/url-targets.js.map +1 -1
  52. package/dist/esm/lib/hexclave-app/url-targets.test.js +12 -0
  53. package/dist/esm/lib/hexclave-app/url-targets.test.js.map +1 -1
  54. package/dist/generated/env.d.ts +26 -0
  55. package/dist/{lib → generated}/env.d.ts.map +1 -1
  56. package/dist/generated/env.js +69 -0
  57. package/dist/generated/env.js.map +1 -0
  58. package/dist/generated/quetzal-translations.d.ts +2 -2
  59. package/dist/global.d.ts +8 -1
  60. package/dist/global.d.ts.map +1 -0
  61. package/dist/lib/auth.js +1 -1
  62. package/dist/lib/cookie.d.ts +0 -8
  63. package/dist/lib/cookie.d.ts.map +1 -1
  64. package/dist/lib/cookie.js +2 -2
  65. package/dist/lib/cookie.js.map +1 -1
  66. package/dist/lib/hexclave-app/apps/implementations/admin-app-impl.d.ts.map +1 -1
  67. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.cross-domain.test.js +263 -3
  68. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.cross-domain.test.js.map +1 -1
  69. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.d.ts +3 -1
  70. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.d.ts.map +1 -1
  71. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.js +53 -26
  72. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.js.map +1 -1
  73. package/dist/lib/hexclave-app/apps/implementations/common.d.ts +8 -8
  74. package/dist/lib/hexclave-app/apps/implementations/common.d.ts.map +1 -1
  75. package/dist/lib/hexclave-app/apps/implementations/common.js +29 -15
  76. package/dist/lib/hexclave-app/apps/implementations/common.js.map +1 -1
  77. package/dist/lib/hexclave-app/apps/implementations/server-app-impl.js +1 -1
  78. package/dist/lib/hexclave-app/url-targets.d.ts.map +1 -1
  79. package/dist/lib/hexclave-app/url-targets.js +25 -11
  80. package/dist/lib/hexclave-app/url-targets.js.map +1 -1
  81. package/dist/lib/hexclave-app/url-targets.test.js +12 -0
  82. package/dist/lib/hexclave-app/url-targets.test.js.map +1 -1
  83. package/package.json +8 -6
  84. package/src/components-page/account-settings/payments/payments-panel.tsx +2 -2
  85. package/src/components-page/hexclave-handler-client.test.tsx +64 -0
  86. package/src/components-page/hexclave-handler-client.tsx +51 -12
  87. package/src/dev-tool/dev-tool-core.ts +2 -2
  88. package/src/generated/.gitignore +1 -1
  89. package/src/global.d.ts +8 -1
  90. package/src/lib/cookie.ts +2 -15
  91. package/src/lib/hexclave-app/apps/implementations/client-app-impl.cross-domain.test.ts +316 -3
  92. package/src/lib/hexclave-app/apps/implementations/client-app-impl.ts +69 -25
  93. package/src/lib/hexclave-app/apps/implementations/common.ts +34 -14
  94. package/src/lib/hexclave-app/url-targets.test.ts +17 -0
  95. package/src/lib/hexclave-app/url-targets.ts +25 -7
  96. package/dist/esm/lib/env.d.ts +0 -42
  97. package/dist/esm/lib/env.js +0 -93
  98. package/dist/esm/lib/env.js.map +0 -1
  99. package/dist/lib/env.d.ts +0 -42
  100. package/dist/lib/env.js +0 -95
  101. package/dist/lib/env.js.map +0 -1
  102. package/src/lib/env.ts +0 -93
@@ -4,9 +4,9 @@ import React, { useCallback, useMemo } from "react";
4
4
  import { HexclaveClientInterface, KnownErrors } from "@hexclave/shared";
5
5
  import { suspend, suspendIfSsr, use } from "@hexclave/shared/dist/utils/react";
6
6
  import { deepPlainEquals, omit } from "@hexclave/shared/dist/utils/objects";
7
- import { createUrlIfValid, isRelative } from "@hexclave/shared/dist/utils/urls";
8
- import { deindent, mergeScopeStrings } from "@hexclave/shared/dist/utils/strings";
7
+ import { createUrlIfValid, getRelativePart, isRelative } from "@hexclave/shared/dist/utils/urls";
9
8
  import { Result } from "@hexclave/shared/dist/utils/results";
9
+ import { deindent, mergeScopeStrings } from "@hexclave/shared/dist/utils/strings";
10
10
  import { isBrowserLike } from "@hexclave/shared/dist/utils/env";
11
11
  import * as tanstackStartServerContext from "@hexclave/tanstack-start/tanstack-start-server-context";
12
12
  import { clientVersion, createCache, createCacheBySession, createEmptyTokenStore, getAnalyticsBaseUrl, getDefaultExtraRequestHeaders, getDefaultProjectId, getDefaultPublishableClientKey, getUrls, resolveApiUrls, resolveConstructorOptions, useAsyncCache } from "./common.js";
@@ -14,11 +14,11 @@ import { getTrustedParentDomain, validateRedirectUrl } from "@hexclave/shared/di
14
14
  import { decodeBase32, decodeBase64, encodeBase32, encodeBase64 } from "@hexclave/shared/dist/utils/bytes";
15
15
  import { hexclaveAppInternalsSymbol } from "../../common.js";
16
16
  import { adminProjectCreateOptionsToCrud } from "../../projects/index.js";
17
- import { WebAuthnError, startAuthentication, startRegistration } from "@simplewebauthn/browser";
18
17
  import { InternalSession } from "@hexclave/shared/dist/sessions";
18
+ import { Store, storeLock } from "@hexclave/shared/dist/utils/stores";
19
+ import { WebAuthnError, startAuthentication, startRegistration } from "@simplewebauthn/browser";
19
20
  import { parseJson } from "@hexclave/shared/dist/utils/json";
20
21
  import { DependenciesMap } from "@hexclave/shared/dist/utils/maps";
21
- import { Store, storeLock } from "@hexclave/shared/dist/utils/stores";
22
22
  import { BotChallengeExecutionFailedError, BotChallengeUserCancelledError, withBotChallengeFlow } from "@hexclave/shared/dist/utils/turnstile-flow";
23
23
  import { generateUuid } from "@hexclave/shared/dist/utils/uuids";
24
24
  import * as TanStackRouter from "@tanstack/react-router";
@@ -26,7 +26,7 @@ import * as cookie from "cookie";
26
26
  import { constructRedirectUrl } from "../../../../utils/url.js";
27
27
  import { callOAuthCallback, getNewOAuthProviderOrScopeUrl } from "../../../auth.js";
28
28
  import { createBrowserCookieHelper, createCookieHelper, createPlaceholderCookieHelper, deleteCookie, deleteCookieClient, getCookieClient, isSecure, saveVerifierAndState, setOrDeleteCookie, setOrDeleteCookieClient } from "../../../cookie.js";
29
- import { envVars } from "../../../env.js";
29
+ import { envVars } from "../../../../generated/env.js";
30
30
  import { apiKeyCreationOptionsToCrud } from "../../api-keys/index.js";
31
31
  import { contactChannelCreateOptionsToCrud, contactChannelUpdateOptionsToCrud } from "../../contact-channels/index.js";
32
32
  import { teamCreateOptionsToCrud, teamUpdateOptionsToCrud } from "../../teams/index.js";
@@ -503,15 +503,15 @@ var _HexclaveClientAppImplIncomplete = class _HexclaveClientAppImplIncomplete {
503
503
  for (const param of oauthCallbackResponseQueryParams) currentUrl.searchParams.delete(param);
504
504
  return currentUrl.toString();
505
505
  }
506
- async _getCurrentRefreshTokenIdIfSignedIn(options) {
507
- const tokens = await (await this._getSession(options?.overrideTokenStoreInit, options)).getOrFetchLikelyValidTokens(0, null);
506
+ async _fetchCurrentRefreshTokenIdIfSignedIn(options) {
507
+ const tokens = await (await this._getSession(options?.overrideTokenStoreInit, options)).fetchNewTokens();
508
508
  if (tokens?.refreshToken == null) return null;
509
509
  return tokens.accessToken.payload.refresh_token_id;
510
510
  }
511
511
  async _addNestedCrossDomainAuthParamsToRedirectUrl(options) {
512
512
  const targetUrl = new URL(options.url, options.currentUrl);
513
513
  if (targetUrl.origin === options.currentUrl.origin) return options.url;
514
- const refreshTokenId = await this._getCurrentRefreshTokenIdIfSignedIn({
514
+ const refreshTokenId = await this._fetchCurrentRefreshTokenIdIfSignedIn({
515
515
  awaitPendingAuthResolutions: options.awaitPendingAuthResolutions,
516
516
  overrideTokenStoreInit: options.overrideTokenStoreInit
517
517
  });
@@ -542,7 +542,7 @@ var _HexclaveClientAppImplIncomplete = class _HexclaveClientAppImplIncomplete {
542
542
  const afterCallbackRedirectUrlString = currentUrl.searchParams.get(nestedCrossDomainAuthQueryParams.afterCallbackRedirectUrl);
543
543
  const afterCallbackRedirectUrl = afterCallbackRedirectUrlString == null ? redirectUriUrl : new URL(afterCallbackRedirectUrlString, redirectUriUrl);
544
544
  if (!await this._isTrusted(afterCallbackRedirectUrl.toString())) throw new Error(`Nested cross-domain auth after-callback redirect URL ${afterCallbackRedirectUrlString} is not trusted.`);
545
- if (await this._getCurrentRefreshTokenIdIfSignedIn({ awaitPendingAuthResolutions: false }) !== refreshTokenId) throw new Error("Nested cross-domain auth source session does not match the requested refresh token ID.");
545
+ if (await this._fetchCurrentRefreshTokenIdIfSignedIn({ awaitPendingAuthResolutions: false }) !== refreshTokenId) throw new Error("Nested cross-domain auth source session does not match the requested refresh token ID.");
546
546
  await this._redirectTo({
547
547
  url: await this._createCrossDomainAuthRedirectUrl({
548
548
  redirectUri: redirectUriUrl.toString(),
@@ -555,7 +555,9 @@ var _HexclaveClientAppImplIncomplete = class _HexclaveClientAppImplIncomplete {
555
555
  });
556
556
  return true;
557
557
  }
558
- if (await this._getCurrentRefreshTokenIdIfSignedIn({ awaitPendingAuthResolutions: false }) === refreshTokenId) return false;
558
+ const currentRefreshTokenId = await this._fetchCurrentRefreshTokenIdIfSignedIn({ awaitPendingAuthResolutions: false });
559
+ if (currentRefreshTokenId === refreshTokenId) return false;
560
+ if (currentRefreshTokenId != null) (await this._getSession(void 0, { awaitPendingAuthResolutions: false })).markInvalid();
559
561
  const callbackUrlString = currentUrl.searchParams.get(nestedCrossDomainAuthQueryParams.callbackUrl);
560
562
  if (callbackUrlString == null) throw new HexclaveAssertionError("Nested cross-domain auth URL is missing callback URL");
561
563
  if (isRelative(callbackUrlString)) throw new Error("Nested cross-domain auth callback URL must be absolute.");
@@ -708,6 +710,13 @@ var _HexclaveClientAppImplIncomplete = class _HexclaveClientAppImplIncomplete {
708
710
  accessToken
709
711
  };
710
712
  }
713
+ _getCurrentBrowserCookieTokenStoreValue(old) {
714
+ const tokens = this._getTokensFromCookies(this._getAllBrowserCookies());
715
+ return {
716
+ refreshToken: tokens.refreshToken,
717
+ accessToken: tokens.accessToken ?? (old?.refreshToken === tokens.refreshToken ? old.accessToken : null)
718
+ };
719
+ }
711
720
  get _accessTokenCookieName() {
712
721
  return `hexclave-access`;
713
722
  }
@@ -812,19 +821,12 @@ var _HexclaveClientAppImplIncomplete = class _HexclaveClientAppImplIncomplete {
812
821
  _getBrowserCookieTokenStore() {
813
822
  if (!isBrowserLike()) throw new Error("Cannot use cookie token store on the server!");
814
823
  if (this._storedBrowserCookieTokenStore === null) {
815
- const getCurrentValue = (old) => {
816
- const tokens = this._getTokensFromCookies(this._getAllBrowserCookies());
817
- return {
818
- refreshToken: tokens.refreshToken,
819
- accessToken: tokens.accessToken ?? (old?.refreshToken === tokens.refreshToken ? old.accessToken : null)
820
- };
821
- };
822
- this._storedBrowserCookieTokenStore = new Store(getCurrentValue(null));
824
+ this._storedBrowserCookieTokenStore = new Store(this._getCurrentBrowserCookieTokenStoreValue(null));
823
825
  let hasSucceededInWriting = true;
824
826
  setInterval(() => {
825
827
  if (hasSucceededInWriting) {
826
828
  const oldValue = this._storedBrowserCookieTokenStore.get();
827
- const currentValue = getCurrentValue(oldValue);
829
+ const currentValue = this._getCurrentBrowserCookieTokenStoreValue(oldValue);
828
830
  if (!deepPlainEquals(currentValue, oldValue)) this._storedBrowserCookieTokenStore.set(currentValue);
829
831
  }
830
832
  }, 100);
@@ -850,6 +852,10 @@ var _HexclaveClientAppImplIncomplete = class _HexclaveClientAppImplIncomplete {
850
852
  else throw e;
851
853
  }
852
854
  });
855
+ } else {
856
+ const oldValue = this._storedBrowserCookieTokenStore.get();
857
+ const currentValue = this._getCurrentBrowserCookieTokenStoreValue(oldValue);
858
+ if (!deepPlainEquals(currentValue, oldValue)) this._storedBrowserCookieTokenStore.set(currentValue);
853
859
  }
854
860
  return this._storedBrowserCookieTokenStore;
855
861
  }
@@ -947,17 +953,17 @@ var _HexclaveClientAppImplIncomplete = class _HexclaveClientAppImplIncomplete {
947
953
  accessToken: tokenObj.accessToken
948
954
  });
949
955
  session.onAccessTokenChange((newAccessToken) => {
950
- tokenStore.update((old) => ({
956
+ tokenStore.update((old) => InternalSession.calculateSessionKey(old) === sessionKey ? {
951
957
  ...old,
952
958
  accessToken: newAccessToken?.token ?? null
953
- }));
959
+ } : old);
954
960
  });
955
961
  session.onInvalidate(() => {
956
- tokenStore.update((old) => ({
962
+ tokenStore.update((old) => InternalSession.calculateSessionKey(old) === sessionKey ? {
957
963
  ...old,
958
964
  accessToken: null,
959
965
  refreshToken: null
960
- }));
966
+ } : old);
961
967
  });
962
968
  let sessionsBySessionKey = this._sessionsByTokenStoreAndSessionKey.get(tokenStore) ?? /* @__PURE__ */ new Map();
963
969
  this._sessionsByTokenStoreAndSessionKey.set(tokenStore, sessionsBySessionKey);
@@ -1906,17 +1912,17 @@ var _HexclaveClientAppImplIncomplete = class _HexclaveClientAppImplIncomplete {
1906
1912
  }
1907
1913
  _getBotChallengeSiteKeys() {
1908
1914
  if (!isBrowserLike()) return null;
1909
- const visibleSiteKey = envVars.NEXT_PUBLIC_STACK_BOT_CHALLENGE_SITE_KEY;
1915
+ const visibleSiteKey = envVars.HEXCLAVE_BOT_CHALLENGE_SITE_KEY;
1910
1916
  if (!visibleSiteKey) {
1911
1917
  if (!this._botChallengeSiteKeysWarned) {
1912
1918
  this._botChallengeSiteKeysWarned = true;
1913
- console.warn("[stack-auth] NEXT_PUBLIC_STACK_BOT_CHALLENGE_SITE_KEY is not set — bot challenge fraud protection is disabled. Set the env variable to enable it.");
1919
+ console.warn("[stack-auth] HEXCLAVE_BOT_CHALLENGE_SITE_KEY is not set — bot challenge fraud protection is disabled. Set the env variable to enable it.");
1914
1920
  }
1915
1921
  return null;
1916
1922
  }
1917
1923
  return {
1918
1924
  visibleSiteKey,
1919
- invisibleSiteKey: envVars.NEXT_PUBLIC_STACK_BOT_CHALLENGE_INVISIBLE_SITE_KEY ?? visibleSiteKey
1925
+ invisibleSiteKey: envVars.HEXCLAVE_BOT_CHALLENGE_INVISIBLE_SITE_KEY ?? visibleSiteKey
1920
1926
  };
1921
1927
  }
1922
1928
  _getBotChallengeFlowFailure(error) {
@@ -2038,6 +2044,7 @@ var _HexclaveClientAppImplIncomplete = class _HexclaveClientAppImplIncomplete {
2038
2044
  }
2039
2045
  async _createCrossDomainAuthRedirectUrl(options) {
2040
2046
  const session = await this._getSession(options.overrideTokenStoreInit, { awaitPendingAuthResolutions: options.awaitPendingAuthResolutions });
2047
+ await session.fetchNewTokens();
2041
2048
  const response = await this._interface.sendClientRequest("/auth/oauth/cross-domain/authorize", {
2042
2049
  method: "POST",
2043
2050
  headers: { "Content-Type": "application/json" },
@@ -2147,6 +2154,8 @@ var _HexclaveClientAppImplIncomplete = class _HexclaveClientAppImplIncomplete {
2147
2154
  return await this._redirectToHandler("signUp", options);
2148
2155
  }
2149
2156
  async redirectToSignOut(options) {
2157
+ const configuredSignOutTarget = this._urlOptions.signOut ?? this._urlOptions.default;
2158
+ if (typeof configuredSignOutTarget !== "string" && configuredSignOutTarget?.type === "hosted") return await this.signOut();
2150
2159
  return await this._redirectToHandler("signOut", options);
2151
2160
  }
2152
2161
  async redirectToEmailVerification(options) {
@@ -2684,9 +2693,27 @@ var _HexclaveClientAppImplIncomplete = class _HexclaveClientAppImplIncomplete {
2684
2693
  url: options.redirectUrl,
2685
2694
  replace: true
2686
2695
  });
2687
- else await this.redirectToAfterSignOut();
2696
+ else await this._redirectToDefaultAfterSignOut();
2688
2697
  });
2689
2698
  }
2699
+ async _redirectToDefaultAfterSignOut() {
2700
+ if (this._urlOptions.afterSignOut != null) {
2701
+ await this.redirectToAfterSignOut({ replace: true });
2702
+ return;
2703
+ }
2704
+ if (this._urlOptions.home != null) {
2705
+ await this.redirectToHome({ replace: true });
2706
+ return;
2707
+ }
2708
+ if (this._urlOptions.default?.type === "hosted" && typeof window !== "undefined") {
2709
+ await this._redirectTo({
2710
+ url: getRelativePart(new URL(window.location.href)),
2711
+ replace: true
2712
+ });
2713
+ return;
2714
+ }
2715
+ await this.redirectToAfterSignOut({ replace: true });
2716
+ }
2690
2717
  async signOut(options) {
2691
2718
  const user = await this.getUser({ tokenStore: options?.tokenStore ?? void 0 });
2692
2719
  if (user) await user.signOut({ redirectUrl: options?.redirectUrl });