@hexclave/next 1.0.102 → 1.0.104

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 (169) hide show
  1. package/dist/{admin-app-impl-B--_O9fz.d.ts → admin-app-impl-Bplmg79y.d.ts} +17 -17
  2. package/dist/{admin-app-impl-B--_O9fz.d.ts.map → admin-app-impl-Bplmg79y.d.ts.map} +1 -1
  3. package/dist/clickmap/clickmap-core.d.ts +1 -1
  4. package/dist/clickmap/index.d.ts +1 -1
  5. package/dist/{client-app-CZjsVpWa.d.ts → client-app-D84Jo2In.d.ts} +10 -10
  6. package/dist/client-app-D84Jo2In.d.ts.map +1 -0
  7. package/dist/components/api-key-dialogs.d.ts +1 -1
  8. package/dist/components/api-key-dialogs.js +4 -4
  9. package/dist/components/credential-sign-in.js +3 -3
  10. package/dist/components/credential-sign-up.js +5 -5
  11. package/dist/components/elements/sidebar-layout.js +1 -1
  12. package/dist/components/elements/user-avatar.js +1 -1
  13. package/dist/components/magic-link-sign-in.js +5 -5
  14. package/dist/components/message-cards/no-auth-methods-message-card.js +2 -2
  15. package/dist/components/message-cards/predefined-message-card.js +1 -1
  16. package/dist/components/passkey-button.js +1 -1
  17. package/dist/components/profile-image-editor.js +1 -1
  18. package/dist/components/selected-team-switcher.d.ts +1 -1
  19. package/dist/components/team-icon.d.ts +1 -1
  20. package/dist/components/team-icon.js +1 -1
  21. package/dist/components/team-switcher.d.ts +1 -1
  22. package/dist/components/team-switcher.js +1 -1
  23. package/dist/components/user-button.js +1 -1
  24. package/dist/components-page/account-settings/editable-text.js +1 -1
  25. package/dist/components-page/account-settings/email-and-auth/emails-section.js +3 -3
  26. package/dist/components-page/account-settings/email-and-auth/password-section.js +3 -3
  27. package/dist/components-page/account-settings/payments/payments-page.d.ts +1 -1
  28. package/dist/components-page/account-settings/teams/leave-team-section.d.ts +1 -1
  29. package/dist/components-page/account-settings/teams/team-api-keys-section.d.ts +1 -1
  30. package/dist/components-page/account-settings/teams/team-creation-page.js +3 -3
  31. package/dist/components-page/account-settings/teams/team-display-name-section.d.ts +1 -1
  32. package/dist/components-page/account-settings/teams/team-member-invitation-section.d.ts +1 -1
  33. package/dist/components-page/account-settings/teams/team-member-invitation-section.js +4 -4
  34. package/dist/components-page/account-settings/teams/team-member-list-section.d.ts +1 -1
  35. package/dist/components-page/account-settings/teams/team-page.d.ts +1 -1
  36. package/dist/components-page/account-settings/teams/team-profile-image-section.d.ts +1 -1
  37. package/dist/components-page/account-settings/teams/team-profile-user-section.d.ts +1 -1
  38. package/dist/components-page/account-settings.js +3 -3
  39. package/dist/components-page/auth-page.js +1 -1
  40. package/dist/components-page/cli-auth-confirm.js +1 -1
  41. package/dist/components-page/forgot-password.js +5 -5
  42. package/dist/components-page/hexclave-handler-client.d.ts +1 -1
  43. package/dist/components-page/hexclave-handler-client.js +1 -1
  44. package/dist/components-page/hexclave-handler.d.ts +1 -1
  45. package/dist/components-page/mfa.js +3 -3
  46. package/dist/components-page/oauth-callback.js +1 -1
  47. package/dist/components-page/onboarding.js +4 -4
  48. package/dist/components-page/password-reset.js +8 -8
  49. package/dist/components-page/team-creation.js +5 -5
  50. package/dist/dev-tool/dev-tool-core.d.ts +1 -1
  51. package/dist/dev-tool/index.d.ts +1 -1
  52. package/dist/esm/components/api-key-dialogs.d.ts +1 -1
  53. package/dist/esm/components/api-key-dialogs.js +4 -4
  54. package/dist/esm/components/credential-sign-in.js +3 -3
  55. package/dist/esm/components/credential-sign-up.js +5 -5
  56. package/dist/esm/components/elements/sidebar-layout.js +1 -1
  57. package/dist/esm/components/elements/user-avatar.js +1 -1
  58. package/dist/esm/components/magic-link-sign-in.js +5 -5
  59. package/dist/esm/components/message-cards/no-auth-methods-message-card.js +2 -2
  60. package/dist/esm/components/message-cards/predefined-message-card.js +1 -1
  61. package/dist/esm/components/passkey-button.js +1 -1
  62. package/dist/esm/components/profile-image-editor.js +1 -1
  63. package/dist/esm/components/team-icon.js +1 -1
  64. package/dist/esm/components/team-switcher.js +1 -1
  65. package/dist/esm/components/user-button.js +1 -1
  66. package/dist/esm/components-page/account-settings/editable-text.js +1 -1
  67. package/dist/esm/components-page/account-settings/email-and-auth/emails-section.js +3 -3
  68. package/dist/esm/components-page/account-settings/email-and-auth/password-section.js +3 -3
  69. package/dist/esm/components-page/account-settings/teams/team-creation-page.js +3 -3
  70. package/dist/esm/components-page/account-settings/teams/team-member-invitation-section.js +4 -4
  71. package/dist/esm/components-page/account-settings.js +3 -3
  72. package/dist/esm/components-page/auth-page.js +1 -1
  73. package/dist/esm/components-page/cli-auth-confirm.js +1 -1
  74. package/dist/esm/components-page/forgot-password.js +5 -5
  75. package/dist/esm/components-page/hexclave-handler-client.js +1 -1
  76. package/dist/esm/components-page/mfa.js +3 -3
  77. package/dist/esm/components-page/oauth-callback.js +1 -1
  78. package/dist/esm/components-page/onboarding.js +4 -4
  79. package/dist/esm/components-page/password-reset.js +7 -7
  80. package/dist/esm/components-page/team-creation.js +5 -5
  81. package/dist/esm/generated/quetzal-translations.d.ts +2 -2
  82. package/dist/esm/lib/hexclave-app/apps/implementations/admin-app-impl.d.ts +4 -14
  83. package/dist/esm/lib/hexclave-app/apps/implementations/admin-app-impl.d.ts.map +1 -1
  84. package/dist/esm/lib/hexclave-app/apps/implementations/admin-app-impl.js +0 -87
  85. package/dist/esm/lib/hexclave-app/apps/implementations/admin-app-impl.js.map +1 -1
  86. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.cross-domain.test.js +22 -2
  87. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.cross-domain.test.js.map +1 -1
  88. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.d.ts +3 -3
  89. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.d.ts.map +1 -1
  90. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.js +1 -1
  91. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.js.map +1 -1
  92. package/dist/esm/lib/hexclave-app/apps/implementations/common.js +2 -2
  93. package/dist/esm/lib/hexclave-app/apps/implementations/redirect-page-urls.d.ts +1 -1
  94. package/dist/esm/lib/hexclave-app/apps/implementations/redirect-page-urls.d.ts.map +1 -1
  95. package/dist/esm/lib/hexclave-app/apps/implementations/redirect-page-urls.js +1 -1
  96. package/dist/esm/lib/hexclave-app/apps/implementations/redirect-page-urls.js.map +1 -1
  97. package/dist/esm/lib/hexclave-app/apps/implementations/redirect-page-urls.test.js +21 -1
  98. package/dist/esm/lib/hexclave-app/apps/implementations/redirect-page-urls.test.js.map +1 -1
  99. package/dist/esm/lib/hexclave-app/apps/implementations/server-app-impl.d.ts +11 -1
  100. package/dist/esm/lib/hexclave-app/apps/implementations/server-app-impl.d.ts.map +1 -1
  101. package/dist/esm/lib/hexclave-app/apps/implementations/server-app-impl.js +87 -0
  102. package/dist/esm/lib/hexclave-app/apps/implementations/server-app-impl.js.map +1 -1
  103. package/dist/esm/lib/hexclave-app/apps/interfaces/admin-app.d.ts +1 -11
  104. package/dist/esm/lib/hexclave-app/apps/interfaces/admin-app.d.ts.map +1 -1
  105. package/dist/esm/lib/hexclave-app/apps/interfaces/admin-app.js.map +1 -1
  106. package/dist/esm/lib/hexclave-app/apps/interfaces/server-app.d.ts +11 -1
  107. package/dist/esm/lib/hexclave-app/apps/interfaces/server-app.d.ts.map +1 -1
  108. package/dist/esm/lib/hexclave-app/apps/interfaces/server-app.js.map +1 -1
  109. package/dist/esm/lib/hexclave-app/index.d.ts +2 -1
  110. package/dist/esm/lib/hexclave-app/users/index.d.ts +1 -1
  111. package/dist/generated/quetzal-translations.d.ts +1 -1
  112. package/dist/{hexclave-provider-BlnLHwzv.d.ts → hexclave-provider-D2n_iIW3.d.ts} +3 -3
  113. package/dist/{hexclave-provider-BlnLHwzv.d.ts.map → hexclave-provider-D2n_iIW3.d.ts.map} +1 -1
  114. package/dist/{hooks-BLTs4rIm.d.ts → hooks-DNH1nVku.d.ts} +2 -2
  115. package/dist/{hooks-BLTs4rIm.d.ts.map → hooks-DNH1nVku.d.ts.map} +1 -1
  116. package/dist/{index-CnokyAXv.d.ts → index-CffsejeK.d.ts} +2 -2
  117. package/dist/{index-CnokyAXv.d.ts.map → index-CffsejeK.d.ts.map} +1 -1
  118. package/dist/index.d.ts +6 -5
  119. package/dist/lib/hexclave-app/apps/implementations/admin-app-impl.d.ts +1 -1
  120. package/dist/lib/hexclave-app/apps/implementations/admin-app-impl.js +0 -87
  121. package/dist/lib/hexclave-app/apps/implementations/admin-app-impl.js.map +1 -1
  122. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.cross-domain.test.js +22 -2
  123. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.cross-domain.test.js.map +1 -1
  124. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.d.ts +1 -1
  125. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.js +1 -1
  126. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.js.map +1 -1
  127. package/dist/lib/hexclave-app/apps/implementations/common.js +2 -2
  128. package/dist/lib/hexclave-app/apps/implementations/index.d.ts +1 -1
  129. package/dist/lib/hexclave-app/apps/implementations/redirect-page-urls.d.ts +1 -1
  130. package/dist/lib/hexclave-app/apps/implementations/redirect-page-urls.js +1 -1
  131. package/dist/lib/hexclave-app/apps/implementations/redirect-page-urls.js.map +1 -1
  132. package/dist/lib/hexclave-app/apps/implementations/redirect-page-urls.test.js +21 -1
  133. package/dist/lib/hexclave-app/apps/implementations/redirect-page-urls.test.js.map +1 -1
  134. package/dist/lib/hexclave-app/apps/implementations/server-app-impl.d.ts +1 -1
  135. package/dist/lib/hexclave-app/apps/implementations/server-app-impl.js +87 -0
  136. package/dist/lib/hexclave-app/apps/implementations/server-app-impl.js.map +1 -1
  137. package/dist/lib/hexclave-app/apps/index.d.ts +1 -1
  138. package/dist/lib/hexclave-app/apps/interfaces/admin-app.d.ts +2 -3
  139. package/dist/lib/hexclave-app/apps/interfaces/admin-app.js.map +1 -1
  140. package/dist/lib/hexclave-app/apps/interfaces/client-app.d.ts +1 -1
  141. package/dist/lib/hexclave-app/apps/interfaces/server-app.d.ts +3 -2
  142. package/dist/lib/hexclave-app/apps/interfaces/server-app.js.map +1 -1
  143. package/dist/lib/hexclave-app/index.d.ts +3 -2
  144. package/dist/lib/hexclave-app/projects/index.d.ts +1 -1
  145. package/dist/lib/hexclave-app/teams/index.d.ts +1 -1
  146. package/dist/lib/hexclave-app/users/index.d.ts +1 -1
  147. package/dist/lib/hooks.d.ts +1 -1
  148. package/dist/providers/hexclave-context.d.ts +1 -1
  149. package/dist/providers/hexclave-provider-client.d.ts +1 -1
  150. package/dist/providers/hexclave-provider.d.ts +1 -1
  151. package/dist/providers/translation-provider.d.ts +1 -1
  152. package/dist/pushed-config-error-overlay/index.d.ts +1 -1
  153. package/dist/{quetzal-translations-CwNB-iql.d.ts → quetzal-translations-CK45_4Dm.d.ts} +3 -3
  154. package/dist/{quetzal-translations-CwNB-iql.d.ts.map → quetzal-translations-CK45_4Dm.d.ts.map} +1 -1
  155. package/dist/{redirect-page-urls-BEWG0AtP.d.ts → redirect-page-urls-Jfs_-wyq.d.ts} +2 -2
  156. package/dist/{redirect-page-urls-BEWG0AtP.d.ts.map → redirect-page-urls-Jfs_-wyq.d.ts.map} +1 -1
  157. package/dist/{translation-provider-C0uPBd41.d.ts → translation-provider-DQ3BJepJ.d.ts} +2 -2
  158. package/dist/{translation-provider-C0uPBd41.d.ts.map → translation-provider-DQ3BJepJ.d.ts.map} +1 -1
  159. package/package.json +4 -4
  160. package/src/lib/hexclave-app/apps/implementations/admin-app-impl.ts +0 -100
  161. package/src/lib/hexclave-app/apps/implementations/client-app-impl.cross-domain.test.ts +31 -2
  162. package/src/lib/hexclave-app/apps/implementations/client-app-impl.ts +3 -1
  163. package/src/lib/hexclave-app/apps/implementations/redirect-page-urls.test.ts +24 -1
  164. package/src/lib/hexclave-app/apps/implementations/redirect-page-urls.ts +2 -2
  165. package/src/lib/hexclave-app/apps/implementations/server-app-impl.ts +100 -0
  166. package/src/lib/hexclave-app/apps/interfaces/admin-app.ts +0 -9
  167. package/src/lib/hexclave-app/apps/interfaces/server-app.ts +11 -0
  168. package/src/lib/hexclave-app/index.ts +10 -0
  169. package/dist/client-app-CZjsVpWa.d.ts.map +0 -1
@@ -15,8 +15,8 @@ import { envVars } from "../../../../generated/env.js";
15
15
  import { suspendIfSsr } from "../../../../utils/react.js";
16
16
  import { resolveHandlerUrls } from "../../url-targets.js";
17
17
  //#region src/lib/hexclave-app/apps/implementations/common.ts
18
- const clientVersion = "js @hexclave/next@1.0.102";
19
- if ("js @hexclave/next@1.0.102".startsWith("STACK_COMPILE_TIME"));
18
+ const clientVersion = "js @hexclave/next@1.0.104";
19
+ if ("js @hexclave/next@1.0.104".startsWith("STACK_COMPILE_TIME"));
20
20
  const replaceHexclavePortPrefix = (input) => {
21
21
  if (!input) return input;
22
22
  const prefix = envVars.HEXCLAVE_PORT_PREFIX;
@@ -27,7 +27,7 @@ declare function planRedirectToHandler(options: {
27
27
  rawHandlerUrl: string;
28
28
  noRedirectBack: boolean;
29
29
  currentUrl: URL | null;
30
- localOAuthCallbackUrl: string;
30
+ getLocalOAuthCallbackUrl: () => string;
31
31
  rawHomeUrl: string;
32
32
  getCrossDomainHandoffParams: (currentUrl: URL) => Promise<CrossDomainHandoffParams>;
33
33
  }): Promise<RedirectToHandlerPlan>;
@@ -1 +1 @@
1
- {"version":3,"file":"redirect-page-urls.d.ts","names":[],"sources":["../../../../../../src/lib/hexclave-app/apps/implementations/redirect-page-urls.ts"],"mappings":";;;cAQa,0BAAA;EAAA;;;;;KAqBD,wBAAA;EACV,KAAA;EACA,aAAa;AAAA;AAAA,iBAGC,yCAAA,CAA0C,UAAA,EAAY,GAAA,GAAM,wBAAwB;AAAA,KA0K/F,qBAAA;EACC,IAAA;EAAkB,GAAA;AAAA;EAEpB,IAAA;EACA,WAAA;EACA,KAAA;EACA,aAAA;EACA,wBAAA;AAAA;AAAA,iBA4CkB,qBAAA,CAAsB,OAAA;EAC1C,WAAA,QAAmB,WAAA;EACnB,aAAA;EACA,cAAA;EACA,UAAA,EAAY,GAAA;EACZ,qBAAA;EACA,UAAA;EACA,2BAAA,GAA8B,UAAA,EAAY,GAAA,KAAQ,OAAA,CAAQ,wBAAA;AAAA,IACxD,OAAA,CAAQ,qBAAA"}
1
+ {"version":3,"file":"redirect-page-urls.d.ts","names":[],"sources":["../../../../../../src/lib/hexclave-app/apps/implementations/redirect-page-urls.ts"],"mappings":";;;cAQa,0BAAA;EAAA;;;;;KAqBD,wBAAA;EACV,KAAA;EACA,aAAa;AAAA;AAAA,iBAGC,yCAAA,CAA0C,UAAA,EAAY,GAAA,GAAM,wBAAwB;AAAA,KA0K/F,qBAAA;EACC,IAAA;EAAkB,GAAA;AAAA;EAEpB,IAAA;EACA,WAAA;EACA,KAAA;EACA,aAAA;EACA,wBAAA;AAAA;AAAA,iBA4CkB,qBAAA,CAAsB,OAAA;EAC1C,WAAA,QAAmB,WAAA;EACnB,aAAA;EACA,cAAA;EACA,UAAA,EAAY,GAAA;EACZ,wBAAA;EACA,UAAA;EACA,2BAAA,GAA8B,UAAA,EAAY,GAAA,KAAQ,OAAA,CAAQ,wBAAA;AAAA,IACxD,OAAA,CAAQ,qBAAA"}
@@ -211,7 +211,7 @@ async function planRedirectToHandler(options) {
211
211
  handlerName: options.handlerName,
212
212
  rawHandlerUrl: options.rawHandlerUrl,
213
213
  currentUrl: options.currentUrl,
214
- localOAuthCallbackUrl: options.localOAuthCallbackUrl,
214
+ localOAuthCallbackUrl: options.getLocalOAuthCallbackUrl(),
215
215
  getCrossDomainHandoffParams: options.getCrossDomainHandoffParams,
216
216
  noRedirectBack: options.noRedirectBack,
217
217
  afterCallbackRedirectUrlOverride
@@ -1 +1 @@
1
- {"version":3,"file":"redirect-page-urls.js","names":[],"sources":["../../../../../../src/lib/hexclave-app/apps/implementations/redirect-page-urls.ts"],"sourcesContent":["\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY UNLESS YOU ALSO EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\nimport { HexclaveAssertionError } from \"@hexclave/shared/dist/utils/errors\";\nimport { getRelativePart } from \"@hexclave/shared/dist/utils/urls\";\nimport { HandlerUrls } from \"../../common\";\n\nexport const crossDomainAuthQueryParams = {\n marker: \"hexclave_cross_domain_auth\",\n state: \"hexclave_cross_domain_state\",\n codeChallenge: \"hexclave_cross_domain_code_challenge\",\n afterCallbackRedirectUrl: \"hexclave_cross_domain_after_callback_redirect_url\",\n} as const;\n\ntype CrossDomainAuthQueryParamKey = keyof typeof crossDomainAuthQueryParams;\n\nfunction getCrossDomainParam(params: URLSearchParams, key: CrossDomainAuthQueryParamKey): string | null {\n return params.get(crossDomainAuthQueryParams[key]);\n}\n\nfunction hasCrossDomainParam(params: URLSearchParams, key: CrossDomainAuthQueryParamKey): boolean {\n return params.has(crossDomainAuthQueryParams[key]);\n}\n\nfunction setCrossDomainParam(params: URLSearchParams, key: CrossDomainAuthQueryParamKey, value: string): void {\n params.set(crossDomainAuthQueryParams[key], value);\n}\n\nexport type CrossDomainHandoffParams = {\n state: string,\n codeChallenge: string,\n};\n\nexport function getCrossDomainHandoffParamsFromCurrentUrl(currentUrl: URL): CrossDomainHandoffParams | null {\n const state = getCrossDomainParam(currentUrl.searchParams, \"state\");\n const codeChallenge = getCrossDomainParam(currentUrl.searchParams, \"codeChallenge\");\n if (state == null || codeChallenge == null) {\n return null;\n }\n return { state, codeChallenge };\n}\n\ntype RedirectBackAwareHandlerName = \"signIn\" | \"signUp\" | \"onboarding\" | \"signOut\";\ntype ContinuationAwareHandlerName = \"forgotPassword\" | \"passwordReset\";\ntype HandlerRedirectPolicy = \"none\" | \"redirect-back-aware\" | \"continuation-aware\" | \"after-auth-return\";\n\ntype CrossDomainHandoffParamsMaybeMissing = {\n state: string | null,\n codeChallenge: string | null,\n afterCallbackRedirectUrl: string | null,\n};\n\nfunction isRedirectBackAwareHandlerName(handlerName: keyof HandlerUrls): handlerName is RedirectBackAwareHandlerName {\n return handlerName === \"signIn\"\n || handlerName === \"signUp\"\n || handlerName === \"onboarding\"\n || handlerName === \"signOut\";\n}\n\nfunction isContinuationAwareHandlerName(handlerName: keyof HandlerUrls): handlerName is ContinuationAwareHandlerName {\n return handlerName === \"forgotPassword\" || handlerName === \"passwordReset\";\n}\n\nfunction hasCrossDomainHandoffParams(url: URL): boolean {\n return (\n hasCrossDomainParam(url.searchParams, \"state\")\n && hasCrossDomainParam(url.searchParams, \"codeChallenge\")\n && hasCrossDomainParam(url.searchParams, \"afterCallbackRedirectUrl\")\n );\n}\n\nfunction buildCrossDomainAuthCallbackUrl(options: {\n currentUrl: URL,\n localOAuthCallbackUrl: string,\n state?: string,\n codeChallenge?: string,\n afterCallbackRedirectUrl?: string,\n}): URL {\n const localOAuthCallbackUrl = new URL(options.localOAuthCallbackUrl, options.currentUrl);\n if (localOAuthCallbackUrl.origin !== options.currentUrl.origin) {\n throw new HexclaveAssertionError(\"Cross-domain auth callback URL must stay on the current origin\", {\n localOAuthCallbackUrl: localOAuthCallbackUrl.toString(),\n currentUrl: options.currentUrl.toString(),\n });\n }\n setCrossDomainParam(localOAuthCallbackUrl.searchParams, \"marker\", \"1\");\n if (options.state != null) {\n setCrossDomainParam(localOAuthCallbackUrl.searchParams, \"state\", options.state);\n }\n if (options.codeChallenge != null) {\n setCrossDomainParam(localOAuthCallbackUrl.searchParams, \"codeChallenge\", options.codeChallenge);\n }\n if (options.afterCallbackRedirectUrl != null) {\n setCrossDomainParam(localOAuthCallbackUrl.searchParams, \"afterCallbackRedirectUrl\", options.afterCallbackRedirectUrl);\n }\n return localOAuthCallbackUrl;\n}\n\nfunction buildRedirectBackAwareHandlerUrl(options: {\n handlerName: RedirectBackAwareHandlerName,\n rawHandlerUrl: string,\n currentUrl: URL,\n crossDomainHandoffParams: CrossDomainHandoffParams | null,\n localOAuthCallbackUrl: string,\n noRedirectBack: boolean,\n afterCallbackRedirectUrlOverride: string | null,\n}): string {\n const nextUrl = new URL(options.rawHandlerUrl, options.currentUrl);\n // Preserve after_auth_return_to verbatim (not a rebranded param).\n const currentAfterAuthReturnTo = options.currentUrl.searchParams.get(\"after_auth_return_to\");\n if (!options.noRedirectBack && currentAfterAuthReturnTo != null && !nextUrl.searchParams.has(\"after_auth_return_to\")) {\n nextUrl.searchParams.set(\"after_auth_return_to\", currentAfterAuthReturnTo);\n }\n for (const preservedParam of [\"state\", \"codeChallenge\", \"afterCallbackRedirectUrl\"] as const) {\n if (options.noRedirectBack && preservedParam === \"afterCallbackRedirectUrl\") {\n continue;\n }\n const currentValue = getCrossDomainParam(options.currentUrl.searchParams, preservedParam);\n if (currentValue != null && !hasCrossDomainParam(nextUrl.searchParams, preservedParam)) {\n setCrossDomainParam(nextUrl.searchParams, preservedParam, currentValue);\n }\n }\n\n if (options.handlerName === \"signOut\") {\n if (!nextUrl.searchParams.has(\"after_auth_return_to\")) {\n if (options.currentUrl.protocol === nextUrl.protocol && options.currentUrl.host === nextUrl.host) {\n nextUrl.searchParams.set(\"after_auth_return_to\", getRelativePart(options.currentUrl));\n } else {\n nextUrl.searchParams.set(\"after_auth_return_to\", options.currentUrl.toString());\n }\n }\n return nextUrl.origin === options.currentUrl.origin ? getRelativePart(nextUrl) : nextUrl.toString();\n }\n\n const isCrossDomainHandlerRedirect = options.currentUrl.origin !== nextUrl.origin;\n if (isCrossDomainHandlerRedirect) {\n if (!hasCrossDomainHandoffParams(nextUrl)) {\n const inheritedAfterAuthReturnTo = options.currentUrl.searchParams.get(\"after_auth_return_to\");\n const afterCallbackRedirectUrl = options.afterCallbackRedirectUrlOverride ?? (\n inheritedAfterAuthReturnTo\n ? new URL(inheritedAfterAuthReturnTo, options.currentUrl).toString()\n : options.currentUrl.toString()\n );\n const handoffParams = options.crossDomainHandoffParams\n ?? getCrossDomainHandoffParamsFromCurrentUrl(options.currentUrl);\n const callbackUrl = buildCrossDomainAuthCallbackUrl({\n currentUrl: options.currentUrl,\n localOAuthCallbackUrl: options.localOAuthCallbackUrl,\n state: handoffParams?.state,\n codeChallenge: handoffParams?.codeChallenge,\n afterCallbackRedirectUrl,\n });\n\n nextUrl.searchParams.set(\"after_auth_return_to\", callbackUrl.toString());\n setCrossDomainParam(nextUrl.searchParams, \"afterCallbackRedirectUrl\", afterCallbackRedirectUrl);\n if (handoffParams != null) {\n setCrossDomainParam(nextUrl.searchParams, \"state\", handoffParams.state);\n setCrossDomainParam(nextUrl.searchParams, \"codeChallenge\", handoffParams.codeChallenge);\n }\n }\n } else if (!options.noRedirectBack && options.currentUrl.protocol === nextUrl.protocol && options.currentUrl.host === nextUrl.host && !nextUrl.searchParams.has(\"after_auth_return_to\")) {\n nextUrl.searchParams.set(\"after_auth_return_to\", getRelativePart(options.currentUrl));\n }\n\n return nextUrl.origin === options.currentUrl.origin ? getRelativePart(nextUrl) : nextUrl.toString();\n}\n\n/**\n * Carries an auth flow's existing return state without ever making the current page the return\n * target. This distinction is important for password flows: forgot-password and password-reset\n * are continuation pages, not destinations customers should return to after signing in.\n */\nfunction buildContinuationAwareHandlerUrl(options: {\n rawHandlerUrl: string,\n currentUrl: URL,\n}): string {\n const nextUrl = new URL(options.rawHandlerUrl, options.currentUrl);\n const inheritedAfterAuthReturnTo = options.currentUrl.searchParams.get(\"after_auth_return_to\");\n if (inheritedAfterAuthReturnTo != null && !nextUrl.searchParams.has(\"after_auth_return_to\")) {\n nextUrl.searchParams.set(\"after_auth_return_to\", inheritedAfterAuthReturnTo);\n }\n for (const preservedParam of [\"state\", \"codeChallenge\", \"afterCallbackRedirectUrl\"] as const) {\n const currentValue = getCrossDomainParam(options.currentUrl.searchParams, preservedParam);\n if (currentValue != null && !hasCrossDomainParam(nextUrl.searchParams, preservedParam)) {\n setCrossDomainParam(nextUrl.searchParams, preservedParam, currentValue);\n }\n }\n return nextUrl.origin === options.currentUrl.origin ? getRelativePart(nextUrl) : nextUrl.toString();\n}\n\nfunction getHandlerRedirectPolicy(handlerName: keyof HandlerUrls): HandlerRedirectPolicy {\n if (handlerName === \"afterSignIn\" || handlerName === \"afterSignUp\") {\n return \"after-auth-return\";\n }\n if (isRedirectBackAwareHandlerName(handlerName)) {\n return \"redirect-back-aware\";\n }\n if (isContinuationAwareHandlerName(handlerName)) {\n return \"continuation-aware\";\n }\n return \"none\";\n}\n\ntype RedirectToHandlerPlan =\n | { type: \"redirect\", url: string }\n | {\n type: \"cross-domain-authorize\",\n redirectUri: string,\n state: string,\n codeChallenge: string,\n afterCallbackRedirectUrl: string,\n };\n\n\nasync function resolveRedirectBackAwareHandlerUrlForRedirect(options: {\n handlerName: RedirectBackAwareHandlerName,\n rawHandlerUrl: string,\n currentUrl: URL,\n localOAuthCallbackUrl: string,\n getCrossDomainHandoffParams: (currentUrl: URL) => Promise<CrossDomainHandoffParams>,\n noRedirectBack: boolean,\n afterCallbackRedirectUrlOverride: string | null,\n}): Promise<string> {\n const initial = buildRedirectBackAwareHandlerUrl({\n handlerName: options.handlerName,\n rawHandlerUrl: options.rawHandlerUrl,\n currentUrl: options.currentUrl,\n crossDomainHandoffParams: null,\n localOAuthCallbackUrl: options.localOAuthCallbackUrl,\n noRedirectBack: options.noRedirectBack,\n afterCallbackRedirectUrlOverride: options.afterCallbackRedirectUrlOverride,\n });\n if (options.handlerName === \"signOut\") {\n return initial;\n }\n\n const initialTarget = new URL(initial, options.currentUrl);\n const isCrossDomainHandlerRedirect = options.currentUrl.origin !== initialTarget.origin;\n if (!isCrossDomainHandlerRedirect || hasCrossDomainHandoffParams(initialTarget)) {\n return initial;\n }\n\n const crossDomainHandoffParams = await options.getCrossDomainHandoffParams(options.currentUrl);\n return buildRedirectBackAwareHandlerUrl({\n handlerName: options.handlerName,\n rawHandlerUrl: options.rawHandlerUrl,\n currentUrl: options.currentUrl,\n crossDomainHandoffParams,\n localOAuthCallbackUrl: options.localOAuthCallbackUrl,\n noRedirectBack: options.noRedirectBack,\n afterCallbackRedirectUrlOverride: options.afterCallbackRedirectUrlOverride,\n });\n}\n\nexport async function planRedirectToHandler(options: {\n handlerName: keyof HandlerUrls,\n rawHandlerUrl: string,\n noRedirectBack: boolean,\n currentUrl: URL | null,\n localOAuthCallbackUrl: string,\n rawHomeUrl: string,\n getCrossDomainHandoffParams: (currentUrl: URL) => Promise<CrossDomainHandoffParams>,\n}): Promise<RedirectToHandlerPlan> {\n if (options.currentUrl == null) {\n return { type: \"redirect\", url: options.rawHandlerUrl };\n }\n\n const policy = getHandlerRedirectPolicy(options.handlerName);\n if (options.noRedirectBack) {\n // Sign-in uses noRedirectBack from password-reset pages to avoid capturing the reset page.\n // Same-domain sign-in must still carry an already-inherited continuation. Cross-domain\n // sign-in falls through to the redirect-back-aware planner below because it needs to return\n // through the source app's callback before continuing to home.\n if (options.handlerName === \"signIn\") {\n const signInTarget = new URL(options.rawHandlerUrl, options.currentUrl);\n if (signInTarget.origin === options.currentUrl.origin) {\n return {\n type: \"redirect\",\n url: buildContinuationAwareHandlerUrl({\n rawHandlerUrl: options.rawHandlerUrl,\n currentUrl: options.currentUrl,\n }),\n };\n }\n } else {\n // Other handlers retain the historical noRedirectBack behavior, including\n // afterSignIn/afterSignUp ignoring all return state.\n return {\n type: \"redirect\",\n url: options.rawHandlerUrl,\n };\n }\n }\n if (policy === \"none\") {\n return { type: \"redirect\", url: options.rawHandlerUrl };\n }\n if (policy === \"continuation-aware\") {\n return {\n type: \"redirect\",\n url: buildContinuationAwareHandlerUrl({\n rawHandlerUrl: options.rawHandlerUrl,\n currentUrl: options.currentUrl,\n }),\n };\n }\n\n if (policy === \"after-auth-return\") {\n if (options.noRedirectBack) {\n return { type: \"redirect\", url: options.rawHandlerUrl };\n }\n const redirectBackUrl = options.currentUrl.searchParams.get(\"after_auth_return_to\");\n if (redirectBackUrl == null) {\n return { type: \"redirect\", url: options.rawHandlerUrl };\n }\n const redirectBackTarget = new URL(redirectBackUrl, options.currentUrl);\n const crossDomainHandoff = getCrossDomainHandoffForRedirect({\n currentUrl: options.currentUrl,\n redirectBackTarget,\n });\n if (crossDomainHandoff == null) {\n return { type: \"redirect\", url: redirectBackUrl };\n }\n let state = crossDomainHandoff.handoffParams.state;\n let codeChallenge = crossDomainHandoff.handoffParams.codeChallenge;\n let afterCallbackRedirectUrl = crossDomainHandoff.handoffParams.afterCallbackRedirectUrl;\n if (state == null || codeChallenge == null) {\n const generatedHandoffParams = await options.getCrossDomainHandoffParams(options.currentUrl);\n state ??= generatedHandoffParams.state;\n codeChallenge ??= generatedHandoffParams.codeChallenge;\n }\n afterCallbackRedirectUrl ??= options.currentUrl.toString();\n return {\n type: \"cross-domain-authorize\",\n redirectUri: crossDomainHandoff.redirectBackTarget.toString(),\n state,\n codeChallenge,\n afterCallbackRedirectUrl,\n };\n }\n\n if (\n options.handlerName !== \"signIn\"\n && options.handlerName !== \"signUp\"\n && options.handlerName !== \"onboarding\"\n && options.handlerName !== \"signOut\"\n ) {\n throw new HexclaveAssertionError(\"Unexpected redirect-back-aware handler policy mismatch\", {\n handlerName: options.handlerName,\n policy,\n });\n }\n\n // noRedirectBack suppresses the initiating deep link, not the return journey. Cross-domain auth\n // still needs to return through the source app's callback, but its final destination is home.\n const afterCallbackRedirectUrlOverride = options.noRedirectBack\n ? new URL(options.rawHomeUrl, options.currentUrl).toString()\n : null;\n\n return {\n type: \"redirect\",\n url: await resolveRedirectBackAwareHandlerUrlForRedirect({\n handlerName: options.handlerName,\n rawHandlerUrl: options.rawHandlerUrl,\n currentUrl: options.currentUrl,\n localOAuthCallbackUrl: options.localOAuthCallbackUrl,\n getCrossDomainHandoffParams: options.getCrossDomainHandoffParams,\n noRedirectBack: options.noRedirectBack,\n afterCallbackRedirectUrlOverride,\n }),\n };\n}\n\nfunction readCrossDomainHandoffParams(currentUrl: URL, redirectBackTarget: URL): CrossDomainHandoffParamsMaybeMissing {\n // Hexclave rebrand: accept either param name from both URLs.\n const state = getCrossDomainParam(currentUrl.searchParams, \"state\")\n ?? getCrossDomainParam(redirectBackTarget.searchParams, \"state\");\n const codeChallenge = getCrossDomainParam(currentUrl.searchParams, \"codeChallenge\")\n ?? getCrossDomainParam(redirectBackTarget.searchParams, \"codeChallenge\");\n const afterCallbackRedirectUrl = getCrossDomainParam(currentUrl.searchParams, \"afterCallbackRedirectUrl\")\n ?? getCrossDomainParam(redirectBackTarget.searchParams, \"afterCallbackRedirectUrl\");\n return {\n state,\n codeChallenge,\n afterCallbackRedirectUrl,\n };\n}\n\nfunction resolveCrossDomainRedirectBackTarget(options: {\n currentUrl: URL,\n redirectBackTarget: URL,\n handoffParams: CrossDomainHandoffParamsMaybeMissing,\n}): URL | null {\n if (options.redirectBackTarget.origin !== options.currentUrl.origin) {\n return options.redirectBackTarget;\n }\n if (\n options.handoffParams.state == null\n || options.handoffParams.codeChallenge == null\n || options.handoffParams.afterCallbackRedirectUrl == null\n ) {\n return null;\n }\n const afterCallbackRedirectTarget = new URL(options.handoffParams.afterCallbackRedirectUrl, options.currentUrl);\n if (afterCallbackRedirectTarget.origin === options.currentUrl.origin) {\n return null;\n }\n return new URL(\n `${options.redirectBackTarget.pathname}${options.redirectBackTarget.search}${options.redirectBackTarget.hash}`,\n afterCallbackRedirectTarget.origin,\n );\n}\n\nfunction getCrossDomainHandoffForRedirect(options: {\n currentUrl: URL,\n redirectBackTarget: URL,\n}): {\n redirectBackTarget: URL,\n handoffParams: CrossDomainHandoffParamsMaybeMissing,\n} | null {\n const handoffParams = readCrossDomainHandoffParams(options.currentUrl, options.redirectBackTarget);\n const crossDomainRedirectBackTarget = resolveCrossDomainRedirectBackTarget({\n currentUrl: options.currentUrl,\n redirectBackTarget: options.redirectBackTarget,\n handoffParams,\n });\n if (crossDomainRedirectBackTarget == null) {\n return null;\n }\n return {\n redirectBackTarget: crossDomainRedirectBackTarget,\n handoffParams,\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"redirect-page-urls.js","names":[],"sources":["../../../../../../src/lib/hexclave-app/apps/implementations/redirect-page-urls.ts"],"sourcesContent":["\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY UNLESS YOU ALSO EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\nimport { HexclaveAssertionError } from \"@hexclave/shared/dist/utils/errors\";\nimport { getRelativePart } from \"@hexclave/shared/dist/utils/urls\";\nimport { HandlerUrls } from \"../../common\";\n\nexport const crossDomainAuthQueryParams = {\n marker: \"hexclave_cross_domain_auth\",\n state: \"hexclave_cross_domain_state\",\n codeChallenge: \"hexclave_cross_domain_code_challenge\",\n afterCallbackRedirectUrl: \"hexclave_cross_domain_after_callback_redirect_url\",\n} as const;\n\ntype CrossDomainAuthQueryParamKey = keyof typeof crossDomainAuthQueryParams;\n\nfunction getCrossDomainParam(params: URLSearchParams, key: CrossDomainAuthQueryParamKey): string | null {\n return params.get(crossDomainAuthQueryParams[key]);\n}\n\nfunction hasCrossDomainParam(params: URLSearchParams, key: CrossDomainAuthQueryParamKey): boolean {\n return params.has(crossDomainAuthQueryParams[key]);\n}\n\nfunction setCrossDomainParam(params: URLSearchParams, key: CrossDomainAuthQueryParamKey, value: string): void {\n params.set(crossDomainAuthQueryParams[key], value);\n}\n\nexport type CrossDomainHandoffParams = {\n state: string,\n codeChallenge: string,\n};\n\nexport function getCrossDomainHandoffParamsFromCurrentUrl(currentUrl: URL): CrossDomainHandoffParams | null {\n const state = getCrossDomainParam(currentUrl.searchParams, \"state\");\n const codeChallenge = getCrossDomainParam(currentUrl.searchParams, \"codeChallenge\");\n if (state == null || codeChallenge == null) {\n return null;\n }\n return { state, codeChallenge };\n}\n\ntype RedirectBackAwareHandlerName = \"signIn\" | \"signUp\" | \"onboarding\" | \"signOut\";\ntype ContinuationAwareHandlerName = \"forgotPassword\" | \"passwordReset\";\ntype HandlerRedirectPolicy = \"none\" | \"redirect-back-aware\" | \"continuation-aware\" | \"after-auth-return\";\n\ntype CrossDomainHandoffParamsMaybeMissing = {\n state: string | null,\n codeChallenge: string | null,\n afterCallbackRedirectUrl: string | null,\n};\n\nfunction isRedirectBackAwareHandlerName(handlerName: keyof HandlerUrls): handlerName is RedirectBackAwareHandlerName {\n return handlerName === \"signIn\"\n || handlerName === \"signUp\"\n || handlerName === \"onboarding\"\n || handlerName === \"signOut\";\n}\n\nfunction isContinuationAwareHandlerName(handlerName: keyof HandlerUrls): handlerName is ContinuationAwareHandlerName {\n return handlerName === \"forgotPassword\" || handlerName === \"passwordReset\";\n}\n\nfunction hasCrossDomainHandoffParams(url: URL): boolean {\n return (\n hasCrossDomainParam(url.searchParams, \"state\")\n && hasCrossDomainParam(url.searchParams, \"codeChallenge\")\n && hasCrossDomainParam(url.searchParams, \"afterCallbackRedirectUrl\")\n );\n}\n\nfunction buildCrossDomainAuthCallbackUrl(options: {\n currentUrl: URL,\n localOAuthCallbackUrl: string,\n state?: string,\n codeChallenge?: string,\n afterCallbackRedirectUrl?: string,\n}): URL {\n const localOAuthCallbackUrl = new URL(options.localOAuthCallbackUrl, options.currentUrl);\n if (localOAuthCallbackUrl.origin !== options.currentUrl.origin) {\n throw new HexclaveAssertionError(\"Cross-domain auth callback URL must stay on the current origin\", {\n localOAuthCallbackUrl: localOAuthCallbackUrl.toString(),\n currentUrl: options.currentUrl.toString(),\n });\n }\n setCrossDomainParam(localOAuthCallbackUrl.searchParams, \"marker\", \"1\");\n if (options.state != null) {\n setCrossDomainParam(localOAuthCallbackUrl.searchParams, \"state\", options.state);\n }\n if (options.codeChallenge != null) {\n setCrossDomainParam(localOAuthCallbackUrl.searchParams, \"codeChallenge\", options.codeChallenge);\n }\n if (options.afterCallbackRedirectUrl != null) {\n setCrossDomainParam(localOAuthCallbackUrl.searchParams, \"afterCallbackRedirectUrl\", options.afterCallbackRedirectUrl);\n }\n return localOAuthCallbackUrl;\n}\n\nfunction buildRedirectBackAwareHandlerUrl(options: {\n handlerName: RedirectBackAwareHandlerName,\n rawHandlerUrl: string,\n currentUrl: URL,\n crossDomainHandoffParams: CrossDomainHandoffParams | null,\n localOAuthCallbackUrl: string,\n noRedirectBack: boolean,\n afterCallbackRedirectUrlOverride: string | null,\n}): string {\n const nextUrl = new URL(options.rawHandlerUrl, options.currentUrl);\n // Preserve after_auth_return_to verbatim (not a rebranded param).\n const currentAfterAuthReturnTo = options.currentUrl.searchParams.get(\"after_auth_return_to\");\n if (!options.noRedirectBack && currentAfterAuthReturnTo != null && !nextUrl.searchParams.has(\"after_auth_return_to\")) {\n nextUrl.searchParams.set(\"after_auth_return_to\", currentAfterAuthReturnTo);\n }\n for (const preservedParam of [\"state\", \"codeChallenge\", \"afterCallbackRedirectUrl\"] as const) {\n if (options.noRedirectBack && preservedParam === \"afterCallbackRedirectUrl\") {\n continue;\n }\n const currentValue = getCrossDomainParam(options.currentUrl.searchParams, preservedParam);\n if (currentValue != null && !hasCrossDomainParam(nextUrl.searchParams, preservedParam)) {\n setCrossDomainParam(nextUrl.searchParams, preservedParam, currentValue);\n }\n }\n\n if (options.handlerName === \"signOut\") {\n if (!nextUrl.searchParams.has(\"after_auth_return_to\")) {\n if (options.currentUrl.protocol === nextUrl.protocol && options.currentUrl.host === nextUrl.host) {\n nextUrl.searchParams.set(\"after_auth_return_to\", getRelativePart(options.currentUrl));\n } else {\n nextUrl.searchParams.set(\"after_auth_return_to\", options.currentUrl.toString());\n }\n }\n return nextUrl.origin === options.currentUrl.origin ? getRelativePart(nextUrl) : nextUrl.toString();\n }\n\n const isCrossDomainHandlerRedirect = options.currentUrl.origin !== nextUrl.origin;\n if (isCrossDomainHandlerRedirect) {\n if (!hasCrossDomainHandoffParams(nextUrl)) {\n const inheritedAfterAuthReturnTo = options.currentUrl.searchParams.get(\"after_auth_return_to\");\n const afterCallbackRedirectUrl = options.afterCallbackRedirectUrlOverride ?? (\n inheritedAfterAuthReturnTo\n ? new URL(inheritedAfterAuthReturnTo, options.currentUrl).toString()\n : options.currentUrl.toString()\n );\n const handoffParams = options.crossDomainHandoffParams\n ?? getCrossDomainHandoffParamsFromCurrentUrl(options.currentUrl);\n const callbackUrl = buildCrossDomainAuthCallbackUrl({\n currentUrl: options.currentUrl,\n localOAuthCallbackUrl: options.localOAuthCallbackUrl,\n state: handoffParams?.state,\n codeChallenge: handoffParams?.codeChallenge,\n afterCallbackRedirectUrl,\n });\n\n nextUrl.searchParams.set(\"after_auth_return_to\", callbackUrl.toString());\n setCrossDomainParam(nextUrl.searchParams, \"afterCallbackRedirectUrl\", afterCallbackRedirectUrl);\n if (handoffParams != null) {\n setCrossDomainParam(nextUrl.searchParams, \"state\", handoffParams.state);\n setCrossDomainParam(nextUrl.searchParams, \"codeChallenge\", handoffParams.codeChallenge);\n }\n }\n } else if (!options.noRedirectBack && options.currentUrl.protocol === nextUrl.protocol && options.currentUrl.host === nextUrl.host && !nextUrl.searchParams.has(\"after_auth_return_to\")) {\n nextUrl.searchParams.set(\"after_auth_return_to\", getRelativePart(options.currentUrl));\n }\n\n return nextUrl.origin === options.currentUrl.origin ? getRelativePart(nextUrl) : nextUrl.toString();\n}\n\n/**\n * Carries an auth flow's existing return state without ever making the current page the return\n * target. This distinction is important for password flows: forgot-password and password-reset\n * are continuation pages, not destinations customers should return to after signing in.\n */\nfunction buildContinuationAwareHandlerUrl(options: {\n rawHandlerUrl: string,\n currentUrl: URL,\n}): string {\n const nextUrl = new URL(options.rawHandlerUrl, options.currentUrl);\n const inheritedAfterAuthReturnTo = options.currentUrl.searchParams.get(\"after_auth_return_to\");\n if (inheritedAfterAuthReturnTo != null && !nextUrl.searchParams.has(\"after_auth_return_to\")) {\n nextUrl.searchParams.set(\"after_auth_return_to\", inheritedAfterAuthReturnTo);\n }\n for (const preservedParam of [\"state\", \"codeChallenge\", \"afterCallbackRedirectUrl\"] as const) {\n const currentValue = getCrossDomainParam(options.currentUrl.searchParams, preservedParam);\n if (currentValue != null && !hasCrossDomainParam(nextUrl.searchParams, preservedParam)) {\n setCrossDomainParam(nextUrl.searchParams, preservedParam, currentValue);\n }\n }\n return nextUrl.origin === options.currentUrl.origin ? getRelativePart(nextUrl) : nextUrl.toString();\n}\n\nfunction getHandlerRedirectPolicy(handlerName: keyof HandlerUrls): HandlerRedirectPolicy {\n if (handlerName === \"afterSignIn\" || handlerName === \"afterSignUp\") {\n return \"after-auth-return\";\n }\n if (isRedirectBackAwareHandlerName(handlerName)) {\n return \"redirect-back-aware\";\n }\n if (isContinuationAwareHandlerName(handlerName)) {\n return \"continuation-aware\";\n }\n return \"none\";\n}\n\ntype RedirectToHandlerPlan =\n | { type: \"redirect\", url: string }\n | {\n type: \"cross-domain-authorize\",\n redirectUri: string,\n state: string,\n codeChallenge: string,\n afterCallbackRedirectUrl: string,\n };\n\n\nasync function resolveRedirectBackAwareHandlerUrlForRedirect(options: {\n handlerName: RedirectBackAwareHandlerName,\n rawHandlerUrl: string,\n currentUrl: URL,\n localOAuthCallbackUrl: string,\n getCrossDomainHandoffParams: (currentUrl: URL) => Promise<CrossDomainHandoffParams>,\n noRedirectBack: boolean,\n afterCallbackRedirectUrlOverride: string | null,\n}): Promise<string> {\n const initial = buildRedirectBackAwareHandlerUrl({\n handlerName: options.handlerName,\n rawHandlerUrl: options.rawHandlerUrl,\n currentUrl: options.currentUrl,\n crossDomainHandoffParams: null,\n localOAuthCallbackUrl: options.localOAuthCallbackUrl,\n noRedirectBack: options.noRedirectBack,\n afterCallbackRedirectUrlOverride: options.afterCallbackRedirectUrlOverride,\n });\n if (options.handlerName === \"signOut\") {\n return initial;\n }\n\n const initialTarget = new URL(initial, options.currentUrl);\n const isCrossDomainHandlerRedirect = options.currentUrl.origin !== initialTarget.origin;\n if (!isCrossDomainHandlerRedirect || hasCrossDomainHandoffParams(initialTarget)) {\n return initial;\n }\n\n const crossDomainHandoffParams = await options.getCrossDomainHandoffParams(options.currentUrl);\n return buildRedirectBackAwareHandlerUrl({\n handlerName: options.handlerName,\n rawHandlerUrl: options.rawHandlerUrl,\n currentUrl: options.currentUrl,\n crossDomainHandoffParams,\n localOAuthCallbackUrl: options.localOAuthCallbackUrl,\n noRedirectBack: options.noRedirectBack,\n afterCallbackRedirectUrlOverride: options.afterCallbackRedirectUrlOverride,\n });\n}\n\nexport async function planRedirectToHandler(options: {\n handlerName: keyof HandlerUrls,\n rawHandlerUrl: string,\n noRedirectBack: boolean,\n currentUrl: URL | null,\n getLocalOAuthCallbackUrl: () => string,\n rawHomeUrl: string,\n getCrossDomainHandoffParams: (currentUrl: URL) => Promise<CrossDomainHandoffParams>,\n}): Promise<RedirectToHandlerPlan> {\n if (options.currentUrl == null) {\n return { type: \"redirect\", url: options.rawHandlerUrl };\n }\n\n const policy = getHandlerRedirectPolicy(options.handlerName);\n if (options.noRedirectBack) {\n // Sign-in uses noRedirectBack from password-reset pages to avoid capturing the reset page.\n // Same-domain sign-in must still carry an already-inherited continuation. Cross-domain\n // sign-in falls through to the redirect-back-aware planner below because it needs to return\n // through the source app's callback before continuing to home.\n if (options.handlerName === \"signIn\") {\n const signInTarget = new URL(options.rawHandlerUrl, options.currentUrl);\n if (signInTarget.origin === options.currentUrl.origin) {\n return {\n type: \"redirect\",\n url: buildContinuationAwareHandlerUrl({\n rawHandlerUrl: options.rawHandlerUrl,\n currentUrl: options.currentUrl,\n }),\n };\n }\n } else {\n // Other handlers retain the historical noRedirectBack behavior, including\n // afterSignIn/afterSignUp ignoring all return state.\n return {\n type: \"redirect\",\n url: options.rawHandlerUrl,\n };\n }\n }\n if (policy === \"none\") {\n return { type: \"redirect\", url: options.rawHandlerUrl };\n }\n if (policy === \"continuation-aware\") {\n return {\n type: \"redirect\",\n url: buildContinuationAwareHandlerUrl({\n rawHandlerUrl: options.rawHandlerUrl,\n currentUrl: options.currentUrl,\n }),\n };\n }\n\n if (policy === \"after-auth-return\") {\n if (options.noRedirectBack) {\n return { type: \"redirect\", url: options.rawHandlerUrl };\n }\n const redirectBackUrl = options.currentUrl.searchParams.get(\"after_auth_return_to\");\n if (redirectBackUrl == null) {\n return { type: \"redirect\", url: options.rawHandlerUrl };\n }\n const redirectBackTarget = new URL(redirectBackUrl, options.currentUrl);\n const crossDomainHandoff = getCrossDomainHandoffForRedirect({\n currentUrl: options.currentUrl,\n redirectBackTarget,\n });\n if (crossDomainHandoff == null) {\n return { type: \"redirect\", url: redirectBackUrl };\n }\n let state = crossDomainHandoff.handoffParams.state;\n let codeChallenge = crossDomainHandoff.handoffParams.codeChallenge;\n let afterCallbackRedirectUrl = crossDomainHandoff.handoffParams.afterCallbackRedirectUrl;\n if (state == null || codeChallenge == null) {\n const generatedHandoffParams = await options.getCrossDomainHandoffParams(options.currentUrl);\n state ??= generatedHandoffParams.state;\n codeChallenge ??= generatedHandoffParams.codeChallenge;\n }\n afterCallbackRedirectUrl ??= options.currentUrl.toString();\n return {\n type: \"cross-domain-authorize\",\n redirectUri: crossDomainHandoff.redirectBackTarget.toString(),\n state,\n codeChallenge,\n afterCallbackRedirectUrl,\n };\n }\n\n if (\n options.handlerName !== \"signIn\"\n && options.handlerName !== \"signUp\"\n && options.handlerName !== \"onboarding\"\n && options.handlerName !== \"signOut\"\n ) {\n throw new HexclaveAssertionError(\"Unexpected redirect-back-aware handler policy mismatch\", {\n handlerName: options.handlerName,\n policy,\n });\n }\n\n // noRedirectBack suppresses the initiating deep link, not the return journey. Cross-domain auth\n // still needs to return through the source app's callback, but its final destination is home.\n const afterCallbackRedirectUrlOverride = options.noRedirectBack\n ? new URL(options.rawHomeUrl, options.currentUrl).toString()\n : null;\n\n return {\n type: \"redirect\",\n url: await resolveRedirectBackAwareHandlerUrlForRedirect({\n handlerName: options.handlerName,\n rawHandlerUrl: options.rawHandlerUrl,\n currentUrl: options.currentUrl,\n localOAuthCallbackUrl: options.getLocalOAuthCallbackUrl(),\n getCrossDomainHandoffParams: options.getCrossDomainHandoffParams,\n noRedirectBack: options.noRedirectBack,\n afterCallbackRedirectUrlOverride,\n }),\n };\n}\n\nfunction readCrossDomainHandoffParams(currentUrl: URL, redirectBackTarget: URL): CrossDomainHandoffParamsMaybeMissing {\n // Hexclave rebrand: accept either param name from both URLs.\n const state = getCrossDomainParam(currentUrl.searchParams, \"state\")\n ?? getCrossDomainParam(redirectBackTarget.searchParams, \"state\");\n const codeChallenge = getCrossDomainParam(currentUrl.searchParams, \"codeChallenge\")\n ?? getCrossDomainParam(redirectBackTarget.searchParams, \"codeChallenge\");\n const afterCallbackRedirectUrl = getCrossDomainParam(currentUrl.searchParams, \"afterCallbackRedirectUrl\")\n ?? getCrossDomainParam(redirectBackTarget.searchParams, \"afterCallbackRedirectUrl\");\n return {\n state,\n codeChallenge,\n afterCallbackRedirectUrl,\n };\n}\n\nfunction resolveCrossDomainRedirectBackTarget(options: {\n currentUrl: URL,\n redirectBackTarget: URL,\n handoffParams: CrossDomainHandoffParamsMaybeMissing,\n}): URL | null {\n if (options.redirectBackTarget.origin !== options.currentUrl.origin) {\n return options.redirectBackTarget;\n }\n if (\n options.handoffParams.state == null\n || options.handoffParams.codeChallenge == null\n || options.handoffParams.afterCallbackRedirectUrl == null\n ) {\n return null;\n }\n const afterCallbackRedirectTarget = new URL(options.handoffParams.afterCallbackRedirectUrl, options.currentUrl);\n if (afterCallbackRedirectTarget.origin === options.currentUrl.origin) {\n return null;\n }\n return new URL(\n `${options.redirectBackTarget.pathname}${options.redirectBackTarget.search}${options.redirectBackTarget.hash}`,\n afterCallbackRedirectTarget.origin,\n );\n}\n\nfunction getCrossDomainHandoffForRedirect(options: {\n currentUrl: URL,\n redirectBackTarget: URL,\n}): {\n redirectBackTarget: URL,\n handoffParams: CrossDomainHandoffParamsMaybeMissing,\n} | null {\n const handoffParams = readCrossDomainHandoffParams(options.currentUrl, options.redirectBackTarget);\n const crossDomainRedirectBackTarget = resolveCrossDomainRedirectBackTarget({\n currentUrl: options.currentUrl,\n redirectBackTarget: options.redirectBackTarget,\n handoffParams,\n });\n if (crossDomainRedirectBackTarget == null) {\n return null;\n }\n return {\n redirectBackTarget: crossDomainRedirectBackTarget,\n handoffParams,\n };\n}\n"],"mappings":"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"}
@@ -6,7 +6,7 @@ async function plan(options) {
6
6
  return await planRedirectToHandler({
7
7
  ...options,
8
8
  noRedirectBack: options.noRedirectBack === true,
9
- localOAuthCallbackUrl,
9
+ getLocalOAuthCallbackUrl: () => localOAuthCallbackUrl,
10
10
  rawHomeUrl: "/",
11
11
  getCrossDomainHandoffParams: async () => {
12
12
  throw new Error("Continuation-only redirects must not mint a new cross-domain handoff");
@@ -23,6 +23,26 @@ function expectContinuation(url, expectedReturnTo) {
23
23
  expect(url.searchParams.get(crossDomainAuthQueryParams.codeChallenge)).toBe("outer-challenge");
24
24
  expect(url.searchParams.get(crossDomainAuthQueryParams.afterCallbackRedirectUrl)).toBe("https://customer.example.test/dashboard");
25
25
  }
26
+ describe("server-side redirect planning", () => {
27
+ it("does not resolve a browser-only callback URL without a current URL", async () => {
28
+ expect(await planRedirectToHandler({
29
+ handlerName: "signIn",
30
+ rawHandlerUrl: "https://hosted.example.test/handler/sign-in",
31
+ noRedirectBack: false,
32
+ currentUrl: null,
33
+ getLocalOAuthCallbackUrl: () => {
34
+ throw new Error("Server-side redirect planning must not resolve the browser callback URL");
35
+ },
36
+ rawHomeUrl: "/",
37
+ getCrossDomainHandoffParams: async () => {
38
+ throw new Error("Server-side redirect planning must not mint cross-domain handoff parameters");
39
+ }
40
+ })).toEqual({
41
+ type: "redirect",
42
+ url: "https://hosted.example.test/handler/sign-in"
43
+ });
44
+ });
45
+ });
26
46
  describe("password-flow redirect continuation", () => {
27
47
  it("carries the complete customer return state through forgot-password and a reset-email new tab", async () => {
28
48
  const customerReturnTo = "https://customer.example.test/handler/oauth-callback?hexclave_cross_domain_auth=1";
@@ -1 +1 @@
1
- {"version":3,"file":"redirect-page-urls.test.js","names":[],"sources":["../../../../../../src/lib/hexclave-app/apps/implementations/redirect-page-urls.test.ts"],"sourcesContent":["\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY UNLESS YOU ALSO EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\nimport { describe, expect, it } from \"vitest\";\nimport { crossDomainAuthQueryParams, planRedirectToHandler } from \"./redirect-page-urls\";\n\nconst localOAuthCallbackUrl = \"https://hosted.example.test/handler/oauth-callback\";\n\nasync function plan(options: {\n handlerName: \"signIn\" | \"forgotPassword\" | \"passwordReset\" | \"afterSignIn\" | \"afterSignUp\",\n rawHandlerUrl: string,\n currentUrl: URL,\n noRedirectBack?: boolean,\n}) {\n return await planRedirectToHandler({\n ...options,\n noRedirectBack: options.noRedirectBack === true,\n localOAuthCallbackUrl,\n rawHomeUrl: \"/\",\n getCrossDomainHandoffParams: async () => {\n throw new Error(\"Continuation-only redirects must not mint a new cross-domain handoff\");\n },\n });\n}\n\nfunction expectRedirectUrl(planResult: Awaited<ReturnType<typeof plan>>, baseUrl: URL): URL {\n if (planResult.type !== \"redirect\") {\n throw new Error(\"Expected a direct redirect plan\");\n }\n return new URL(planResult.url, baseUrl);\n}\n\nfunction expectContinuation(url: URL, expectedReturnTo: string): void {\n expect(url.searchParams.get(\"after_auth_return_to\")).toBe(expectedReturnTo);\n expect(url.searchParams.get(crossDomainAuthQueryParams.state)).toBe(\"outer-state\");\n expect(url.searchParams.get(crossDomainAuthQueryParams.codeChallenge)).toBe(\"outer-challenge\");\n expect(url.searchParams.get(crossDomainAuthQueryParams.afterCallbackRedirectUrl)).toBe(\"https://customer.example.test/dashboard\");\n}\n\ndescribe(\"password-flow redirect continuation\", () => {\n it(\"carries the complete customer return state through forgot-password and a reset-email new tab\", async () => {\n const customerReturnTo = \"https://customer.example.test/handler/oauth-callback?hexclave_cross_domain_auth=1\";\n const signInUrl = new URL(\"https://hosted.example.test/handler/sign-in\");\n signInUrl.searchParams.set(\"after_auth_return_to\", customerReturnTo);\n signInUrl.searchParams.set(crossDomainAuthQueryParams.state, \"outer-state\");\n signInUrl.searchParams.set(crossDomainAuthQueryParams.codeChallenge, \"outer-challenge\");\n signInUrl.searchParams.set(crossDomainAuthQueryParams.afterCallbackRedirectUrl, \"https://customer.example.test/dashboard\");\n\n const forgotPlan = await plan({\n handlerName: \"forgotPassword\",\n rawHandlerUrl: \"/handler/forgot-password\",\n currentUrl: signInUrl,\n });\n const forgotUrl = expectRedirectUrl(forgotPlan, signInUrl);\n expectContinuation(forgotUrl, customerReturnTo);\n\n const callbackPlan = await plan({\n handlerName: \"passwordReset\",\n rawHandlerUrl: \"/handler/password-reset\",\n currentUrl: forgotUrl,\n });\n const resetEmailCallbackUrl = expectRedirectUrl(callbackPlan, forgotUrl);\n expectContinuation(resetEmailCallbackUrl, customerReturnTo);\n\n // Model opening the callback in a new tab: only URL state is available.\n resetEmailCallbackUrl.searchParams.set(\"code\", \"reset-code\");\n const signInPlan = await plan({\n handlerName: \"signIn\",\n rawHandlerUrl: \"/handler/sign-in\",\n currentUrl: resetEmailCallbackUrl,\n noRedirectBack: true,\n });\n const finalSignInUrl = expectRedirectUrl(signInPlan, resetEmailCallbackUrl);\n expectContinuation(finalSignInUrl, customerReturnTo);\n expect(finalSignInUrl.searchParams.has(\"code\")).toBe(false);\n });\n\n it.each([\n [\"forgotPassword\", \"/handler/forgot-password\"],\n [\"passwordReset\", \"/handler/password-reset\"],\n ] as const)(\"never synthesizes the current %s page as a return target\", async (handlerName, rawHandlerUrl) => {\n const currentUrl = new URL(`https://hosted.example.test${rawHandlerUrl}?code=reset-code`);\n const result = expectRedirectUrl(await plan({\n handlerName,\n rawHandlerUrl,\n currentUrl,\n }), currentUrl);\n\n expect(result.searchParams.has(\"after_auth_return_to\")).toBe(false);\n expect(result.searchParams.has(\"code\")).toBe(false);\n });\n\n it(\"makes sign-in noRedirectBack suppress capture while preserving only inherited state\", async () => {\n const resetUrlWithoutContinuation = new URL(\"https://hosted.example.test/handler/password-reset?code=reset-code\");\n const result = expectRedirectUrl(await plan({\n handlerName: \"signIn\",\n rawHandlerUrl: \"/handler/sign-in\",\n currentUrl: resetUrlWithoutContinuation,\n noRedirectBack: true,\n }), resetUrlWithoutContinuation);\n\n expect(result.toString()).toBe(\"https://hosted.example.test/handler/sign-in\");\n });\n\n it.each([\"afterSignIn\", \"afterSignUp\"] as const)(\n \"keeps existing %s noRedirectBack semantics\",\n async (handlerName) => {\n const currentUrl = new URL(\"https://hosted.example.test/handler/sign-in?after_auth_return_to=%2Fcustomer\");\n const result = expectRedirectUrl(await plan({\n handlerName,\n rawHandlerUrl: \"/default-after-auth\",\n currentUrl,\n noRedirectBack: true,\n }), currentUrl);\n\n expect(result.toString()).toBe(\"https://hosted.example.test/default-after-auth\");\n },\n );\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"redirect-page-urls.test.js","names":[],"sources":["../../../../../../src/lib/hexclave-app/apps/implementations/redirect-page-urls.test.ts"],"sourcesContent":["\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY UNLESS YOU ALSO EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\nimport { describe, expect, it } from \"vitest\";\nimport { crossDomainAuthQueryParams, planRedirectToHandler } from \"./redirect-page-urls\";\n\nconst localOAuthCallbackUrl = \"https://hosted.example.test/handler/oauth-callback\";\n\nasync function plan(options: {\n handlerName: \"signIn\" | \"forgotPassword\" | \"passwordReset\" | \"afterSignIn\" | \"afterSignUp\",\n rawHandlerUrl: string,\n currentUrl: URL,\n noRedirectBack?: boolean,\n}) {\n return await planRedirectToHandler({\n ...options,\n noRedirectBack: options.noRedirectBack === true,\n getLocalOAuthCallbackUrl: () => localOAuthCallbackUrl,\n rawHomeUrl: \"/\",\n getCrossDomainHandoffParams: async () => {\n throw new Error(\"Continuation-only redirects must not mint a new cross-domain handoff\");\n },\n });\n}\n\nfunction expectRedirectUrl(planResult: Awaited<ReturnType<typeof plan>>, baseUrl: URL): URL {\n if (planResult.type !== \"redirect\") {\n throw new Error(\"Expected a direct redirect plan\");\n }\n return new URL(planResult.url, baseUrl);\n}\n\nfunction expectContinuation(url: URL, expectedReturnTo: string): void {\n expect(url.searchParams.get(\"after_auth_return_to\")).toBe(expectedReturnTo);\n expect(url.searchParams.get(crossDomainAuthQueryParams.state)).toBe(\"outer-state\");\n expect(url.searchParams.get(crossDomainAuthQueryParams.codeChallenge)).toBe(\"outer-challenge\");\n expect(url.searchParams.get(crossDomainAuthQueryParams.afterCallbackRedirectUrl)).toBe(\"https://customer.example.test/dashboard\");\n}\n\ndescribe(\"server-side redirect planning\", () => {\n it(\"does not resolve a browser-only callback URL without a current URL\", async () => {\n const result = await planRedirectToHandler({\n handlerName: \"signIn\",\n rawHandlerUrl: \"https://hosted.example.test/handler/sign-in\",\n noRedirectBack: false,\n currentUrl: null,\n getLocalOAuthCallbackUrl: () => {\n throw new Error(\"Server-side redirect planning must not resolve the browser callback URL\");\n },\n rawHomeUrl: \"/\",\n getCrossDomainHandoffParams: async () => {\n throw new Error(\"Server-side redirect planning must not mint cross-domain handoff parameters\");\n },\n });\n\n expect(result).toEqual({\n type: \"redirect\",\n url: \"https://hosted.example.test/handler/sign-in\",\n });\n });\n});\n\ndescribe(\"password-flow redirect continuation\", () => {\n it(\"carries the complete customer return state through forgot-password and a reset-email new tab\", async () => {\n const customerReturnTo = \"https://customer.example.test/handler/oauth-callback?hexclave_cross_domain_auth=1\";\n const signInUrl = new URL(\"https://hosted.example.test/handler/sign-in\");\n signInUrl.searchParams.set(\"after_auth_return_to\", customerReturnTo);\n signInUrl.searchParams.set(crossDomainAuthQueryParams.state, \"outer-state\");\n signInUrl.searchParams.set(crossDomainAuthQueryParams.codeChallenge, \"outer-challenge\");\n signInUrl.searchParams.set(crossDomainAuthQueryParams.afterCallbackRedirectUrl, \"https://customer.example.test/dashboard\");\n\n const forgotPlan = await plan({\n handlerName: \"forgotPassword\",\n rawHandlerUrl: \"/handler/forgot-password\",\n currentUrl: signInUrl,\n });\n const forgotUrl = expectRedirectUrl(forgotPlan, signInUrl);\n expectContinuation(forgotUrl, customerReturnTo);\n\n const callbackPlan = await plan({\n handlerName: \"passwordReset\",\n rawHandlerUrl: \"/handler/password-reset\",\n currentUrl: forgotUrl,\n });\n const resetEmailCallbackUrl = expectRedirectUrl(callbackPlan, forgotUrl);\n expectContinuation(resetEmailCallbackUrl, customerReturnTo);\n\n // Model opening the callback in a new tab: only URL state is available.\n resetEmailCallbackUrl.searchParams.set(\"code\", \"reset-code\");\n const signInPlan = await plan({\n handlerName: \"signIn\",\n rawHandlerUrl: \"/handler/sign-in\",\n currentUrl: resetEmailCallbackUrl,\n noRedirectBack: true,\n });\n const finalSignInUrl = expectRedirectUrl(signInPlan, resetEmailCallbackUrl);\n expectContinuation(finalSignInUrl, customerReturnTo);\n expect(finalSignInUrl.searchParams.has(\"code\")).toBe(false);\n });\n\n it.each([\n [\"forgotPassword\", \"/handler/forgot-password\"],\n [\"passwordReset\", \"/handler/password-reset\"],\n ] as const)(\"never synthesizes the current %s page as a return target\", async (handlerName, rawHandlerUrl) => {\n const currentUrl = new URL(`https://hosted.example.test${rawHandlerUrl}?code=reset-code`);\n const result = expectRedirectUrl(await plan({\n handlerName,\n rawHandlerUrl,\n currentUrl,\n }), currentUrl);\n\n expect(result.searchParams.has(\"after_auth_return_to\")).toBe(false);\n expect(result.searchParams.has(\"code\")).toBe(false);\n });\n\n it(\"makes sign-in noRedirectBack suppress capture while preserving only inherited state\", async () => {\n const resetUrlWithoutContinuation = new URL(\"https://hosted.example.test/handler/password-reset?code=reset-code\");\n const result = expectRedirectUrl(await plan({\n handlerName: \"signIn\",\n rawHandlerUrl: \"/handler/sign-in\",\n currentUrl: resetUrlWithoutContinuation,\n noRedirectBack: true,\n }), resetUrlWithoutContinuation);\n\n expect(result.toString()).toBe(\"https://hosted.example.test/handler/sign-in\");\n });\n\n it.each([\"afterSignIn\", \"afterSignUp\"] as const)(\n \"keeps existing %s noRedirectBack semantics\",\n async (handlerName) => {\n const currentUrl = new URL(\"https://hosted.example.test/handler/sign-in?after_auth_return_to=%2Fcustomer\");\n const result = expectRedirectUrl(await plan({\n handlerName,\n rawHandlerUrl: \"/default-after-auth\",\n currentUrl,\n noRedirectBack: true,\n }), currentUrl);\n\n expect(result.toString()).toBe(\"https://hosted.example.test/default-after-auth\");\n },\n );\n});\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
- import { HexclaveServerInterface, KnownErrors } from "@hexclave/shared";
2
1
  import * as yup from "yup";
2
+ import { HexclaveServerInterface, KnownErrors } from "@hexclave/shared";
3
3
  import { Result } from "@hexclave/shared/dist/utils/results";
4
4
  import { ConvexCtx, GetCurrentUserOptions } from "../../common.js";
5
5
  import { AdminProjectPermissionDefinition, AdminTeamPermission, AdminTeamPermissionDefinition } from "../../permissions/index.js";
@@ -24,6 +24,8 @@ import { OAuthConnection } from "../../connected-accounts/index.js";
24
24
  import { Customer, CustomerProductsList, CustomerProductsRequestOptions, InlineProduct, ServerItem } from "../../customers/index.js";
25
25
  import { NotificationCategory } from "../../notification-categories/index.js";
26
26
  import { AnalyticsQueryOptions, AnalyticsQueryResponse } from "@hexclave/shared/dist/interface/crud/analytics";
27
+ import { AdminGetSessionReplayChunkEventsResponse } from "@hexclave/shared/dist/interface/crud/session-replays";
28
+ import { AdminSessionReplay, ListSessionReplayChunksOptions, ListSessionReplayChunksResult, ListSessionReplaysOptions, ListSessionReplaysResult, SessionReplayAllEventsResult } from "../../session-replays/index.js";
27
29
  import { DataVaultStore } from "../../data-vault/index.js";
28
30
  import { EmailDeliveryInfo, SendEmailOptions } from "../../email/index.js";
29
31
  import { StackServerAppConstructorOptions } from "../interfaces/server-app.js";
@@ -262,6 +264,14 @@ declare class _HexclaveServerAppImplIncomplete<HasTokenStore extends boolean, Pr
262
264
  useEmailDeliveryStats(): EmailDeliveryInfo;
263
265
  activateEmailCapacityBoost(): Promise<void>;
264
266
  queryAnalytics(options: AnalyticsQueryOptions): Promise<AnalyticsQueryResponse>;
267
+ listSessionReplays(options?: ListSessionReplaysOptions): Promise<ListSessionReplaysResult>;
268
+ getSessionReplay(sessionReplayId: string): Promise<AdminSessionReplay>;
269
+ listSessionReplayChunks(sessionReplayId: string, options?: ListSessionReplayChunksOptions): Promise<ListSessionReplayChunksResult>;
270
+ getSessionReplayChunkEvents(sessionReplayId: string, chunkId: string): Promise<AdminGetSessionReplayChunkEventsResponse>;
271
+ getSessionReplayEvents(sessionReplayId: string, options?: {
272
+ offset?: number;
273
+ limit?: number;
274
+ }): Promise<SessionReplayAllEventsResult>;
265
275
  protected _refreshSession(session: InternalSession): Promise<void>;
266
276
  protected _refreshUsers(): Promise<void>;
267
277
  createOAuthProvider(options: {
@@ -1 +1 @@
1
- {"version":3,"file":"server-app-impl.d.ts","names":[],"sources":["../../../../../../src/lib/hexclave-app/apps/implementations/server-app-impl.ts"],"mappings":"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"}
1
+ {"version":3,"file":"server-app-impl.d.ts","names":[],"sources":["../../../../../../src/lib/hexclave-app/apps/implementations/server-app-impl.ts"],"mappings":"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"}
@@ -1386,6 +1386,93 @@ var _HexclaveServerAppImplIncomplete = class extends _HexclaveClientAppImplIncom
1386
1386
  async queryAnalytics(options) {
1387
1387
  return await this._interface.queryAnalytics(options);
1388
1388
  }
1389
+ async listSessionReplays(options) {
1390
+ const response = await this._interface.listSessionReplays({
1391
+ cursor: options?.cursor,
1392
+ limit: options?.limit,
1393
+ user_ids: options?.userIds,
1394
+ team_ids: options?.teamIds,
1395
+ duration_ms_min: options?.durationMsMin,
1396
+ duration_ms_max: options?.durationMsMax,
1397
+ last_event_at_from_millis: options?.lastEventAtFromMillis,
1398
+ last_event_at_to_millis: options?.lastEventAtToMillis,
1399
+ click_count_min: options?.clickCountMin
1400
+ });
1401
+ return {
1402
+ items: response.items.map((r) => ({
1403
+ id: r.id,
1404
+ refreshTokenId: r.refresh_token_id,
1405
+ projectUser: {
1406
+ id: r.project_user.id,
1407
+ displayName: r.project_user.display_name,
1408
+ primaryEmail: r.project_user.primary_email
1409
+ },
1410
+ startedAt: new Date(r.started_at_millis),
1411
+ lastEventAt: new Date(r.last_event_at_millis),
1412
+ chunkCount: r.chunk_count,
1413
+ eventCount: r.event_count
1414
+ })),
1415
+ nextCursor: response.pagination.next_cursor
1416
+ };
1417
+ }
1418
+ async getSessionReplay(sessionReplayId) {
1419
+ const response = await this._interface.getSessionReplay(sessionReplayId);
1420
+ return {
1421
+ id: response.id,
1422
+ refreshTokenId: response.refresh_token_id,
1423
+ projectUser: {
1424
+ id: response.project_user.id,
1425
+ displayName: response.project_user.display_name,
1426
+ primaryEmail: response.project_user.primary_email
1427
+ },
1428
+ startedAt: new Date(response.started_at_millis),
1429
+ lastEventAt: new Date(response.last_event_at_millis),
1430
+ chunkCount: response.chunk_count,
1431
+ eventCount: response.event_count
1432
+ };
1433
+ }
1434
+ async listSessionReplayChunks(sessionReplayId, options) {
1435
+ const response = await this._interface.listSessionReplayChunks(sessionReplayId, {
1436
+ cursor: options?.cursor,
1437
+ limit: options?.limit
1438
+ });
1439
+ return {
1440
+ items: response.items.map((c) => ({
1441
+ id: c.id,
1442
+ batchId: c.batch_id,
1443
+ sessionReplaySegmentId: c.session_replay_segment_id,
1444
+ browserSessionId: c.browser_session_id,
1445
+ eventCount: c.event_count,
1446
+ byteLength: c.byte_length,
1447
+ firstEventAt: new Date(c.first_event_at_millis),
1448
+ lastEventAt: new Date(c.last_event_at_millis),
1449
+ createdAt: new Date(c.created_at_millis)
1450
+ })),
1451
+ nextCursor: response.pagination.next_cursor
1452
+ };
1453
+ }
1454
+ async getSessionReplayChunkEvents(sessionReplayId, chunkId) {
1455
+ return await this._interface.getSessionReplayChunkEvents(sessionReplayId, chunkId);
1456
+ }
1457
+ async getSessionReplayEvents(sessionReplayId, options) {
1458
+ const response = await this._interface.getSessionReplayEvents(sessionReplayId, options);
1459
+ return {
1460
+ chunks: response.chunks.map((c) => ({
1461
+ id: c.id,
1462
+ batchId: c.batch_id,
1463
+ sessionReplaySegmentId: c.session_replay_segment_id,
1464
+ eventCount: c.event_count,
1465
+ byteLength: c.byte_length,
1466
+ firstEventAt: new Date(c.first_event_at_millis),
1467
+ lastEventAt: new Date(c.last_event_at_millis),
1468
+ createdAt: new Date(c.created_at_millis)
1469
+ })),
1470
+ chunkEvents: response.chunk_events.map((ce) => ({
1471
+ chunkId: ce.chunk_id,
1472
+ events: ce.events
1473
+ }))
1474
+ };
1475
+ }
1389
1476
  async _refreshSession(session) {
1390
1477
  await Promise.all([super._refreshUser(session), this._currentServerUserCache.refresh([session])]);
1391
1478
  }