@volr/react-ui 0.1.125 → 0.1.126

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.
package/dist/index.cjs CHANGED
@@ -2162,7 +2162,12 @@ function PasskeyEnrollView({
2162
2162
  }
2163
2163
  if (migrationInfo.needsMigration && migrationInfo.sourcePasskey) {
2164
2164
  const handleMigration = async () => {
2165
- await handleEnroll();
2165
+ const targetOrigin = typeof window !== "undefined" ? window.location.origin : "";
2166
+ const sourceRpId = migrationInfo.sourcePasskey.rpId;
2167
+ const sourceOrigin = sourceRpId === "localhost" ? "http://localhost" : `https://${sourceRpId}`;
2168
+ const url = new URL(sourceOrigin);
2169
+ url.searchParams.set("volr_migrate_to", targetOrigin);
2170
+ window.open(url.toString(), "_blank", "noopener,noreferrer");
2166
2171
  };
2167
2172
  return /* @__PURE__ */ jsxRuntime.jsx(
2168
2173
  PasskeyMigrationView,
@@ -6803,6 +6808,13 @@ function VolrUIProviderInner({
6803
6808
  keyStorageType
6804
6809
  },
6805
6810
  children: /* @__PURE__ */ jsxRuntime.jsxs(VolrModalProvider, { children: [
6811
+ /* @__PURE__ */ jsxRuntime.jsx(
6812
+ MigrationCoordinator,
6813
+ {
6814
+ onShowOnboarding: () => setShowOnboarding(true),
6815
+ onHideOnboarding: () => setShowOnboarding(false)
6816
+ }
6817
+ ),
6806
6818
  /* @__PURE__ */ jsxRuntime.jsx(
6807
6819
  OAuthCallbackHandler,
6808
6820
  {
@@ -6845,6 +6857,130 @@ function VolrUIProviderInner({
6845
6857
  }
6846
6858
  ) }) });
6847
6859
  }
6860
+ function normalizeOrigin(input) {
6861
+ try {
6862
+ const u = new URL(input);
6863
+ return `${u.protocol}//${u.host}`;
6864
+ } catch {
6865
+ return input;
6866
+ }
6867
+ }
6868
+ function MigrationCoordinator({
6869
+ onShowOnboarding,
6870
+ onHideOnboarding
6871
+ }) {
6872
+ const { user, setUser } = react.useVolrContext();
6873
+ const { client } = react.useInternalAuth();
6874
+ const [running, setRunning] = React13.useState(false);
6875
+ React13.useEffect(() => {
6876
+ if (typeof window === "undefined") return;
6877
+ const handler = (event) => {
6878
+ const data = event.data;
6879
+ if (data?.type === "VOLR_MIGRATION_DONE") {
6880
+ client.refreshSession().then((u) => u && setUser(u)).catch(() => void 0);
6881
+ onHideOnboarding();
6882
+ }
6883
+ };
6884
+ window.addEventListener("message", handler);
6885
+ return () => window.removeEventListener("message", handler);
6886
+ }, [client, setUser, onHideOnboarding]);
6887
+ React13.useEffect(() => {
6888
+ if (typeof window === "undefined") return;
6889
+ if (running) return;
6890
+ const params = new URLSearchParams(window.location.search);
6891
+ const migrationToken = params.get("migration_token");
6892
+ const sourceOriginParam = params.get("source_origin");
6893
+ const isTargetPopup = Boolean(migrationToken && sourceOriginParam);
6894
+ const migrateTo = params.get("volr_migrate_to");
6895
+ const isSourceFlow = Boolean(migrateTo);
6896
+ if (!isTargetPopup && !isSourceFlow) {
6897
+ return;
6898
+ }
6899
+ const run = async () => {
6900
+ setRunning(true);
6901
+ try {
6902
+ if (isTargetPopup) {
6903
+ const sourceOrigin2 = normalizeOrigin(sourceOriginParam);
6904
+ const token2 = migrationToken;
6905
+ const refreshedUser2 = await client.refreshSession();
6906
+ const effectiveUser2 = refreshedUser2 ?? user;
6907
+ if (refreshedUser2) setUser(refreshedUser2);
6908
+ if (!effectiveUser2?.id || !effectiveUser2?.projectId) {
6909
+ throw new Error(
6910
+ "Migration requires an active session on the target site. Please log in first."
6911
+ );
6912
+ }
6913
+ const { requestSeedFromOpener } = await import('@volr/react');
6914
+ const seed = await requestSeedFromOpener(sourceOrigin2, token2);
6915
+ await react.completeMigration({
6916
+ client,
6917
+ userId: seed.userId,
6918
+ projectId: seed.projectId,
6919
+ migrationToken: token2,
6920
+ masterSeed: seed.masterSeed,
6921
+ rpName: effectiveUser2.projectName ?? "Volr",
6922
+ userEmail: effectiveUser2.email ?? null
6923
+ });
6924
+ try {
6925
+ window.opener?.postMessage({ type: "VOLR_MIGRATION_DONE" }, "*");
6926
+ } catch {
6927
+ }
6928
+ window.close();
6929
+ return;
6930
+ }
6931
+ const targetOrigin = normalizeOrigin(migrateTo);
6932
+ const sourceOrigin = window.location.origin;
6933
+ const refreshedUser = await client.refreshSession();
6934
+ const effectiveUser = refreshedUser ?? user;
6935
+ if (refreshedUser) setUser(refreshedUser);
6936
+ if (!effectiveUser?.id || !effectiveUser?.projectId) {
6937
+ throw new Error(
6938
+ "Migration requires an active session on the source site. Please log in first."
6939
+ );
6940
+ }
6941
+ const currentRpId = getCurrentRpId();
6942
+ const sourcePasskey = effectiveUser.registeredPasskeys?.find((p) => p?.rpId === currentRpId) ?? null;
6943
+ if (!sourcePasskey?.credentialId || !sourcePasskey?.blobUrl || !sourcePasskey?.prfInput) {
6944
+ throw new Error(
6945
+ `No passkey registered for source rpId=${currentRpId}. Cannot migrate from this site.`
6946
+ );
6947
+ }
6948
+ const token = await react.requestMigration({ client, targetOrigin });
6949
+ const entropy = await react.decryptEntropyForMigration({
6950
+ client,
6951
+ userId: effectiveUser.id,
6952
+ blobUrl: sourcePasskey.blobUrl,
6953
+ prfInput: sourcePasskey.prfInput,
6954
+ credentialId: sourcePasskey.credentialId,
6955
+ rpName: effectiveUser.projectName ?? "Volr"
6956
+ });
6957
+ const cleanup = react.listenForSeedRequests(
6958
+ [targetOrigin],
6959
+ async () => entropy,
6960
+ () => ({ userId: effectiveUser.id, projectId: effectiveUser.projectId })
6961
+ );
6962
+ const url = new URL(targetOrigin);
6963
+ url.searchParams.set("migration_token", token.migrationToken);
6964
+ url.searchParams.set("source_origin", sourceOrigin);
6965
+ window.open(
6966
+ url.toString(),
6967
+ "volr_migration",
6968
+ "width=500,height=650,left=100,top=100,popup=1"
6969
+ );
6970
+ onShowOnboarding();
6971
+ setTimeout(() => cleanup(), 2 * 60 * 1e3);
6972
+ return;
6973
+ } finally {
6974
+ setRunning(false);
6975
+ }
6976
+ };
6977
+ run().catch((e) => {
6978
+ console.error("[MigrationCoordinator] failed:", e);
6979
+ setRunning(false);
6980
+ });
6981
+ }, [client, user, setUser, running, onShowOnboarding, onHideOnboarding]);
6982
+ return null;
6983
+ }
6848
6984
  function AccountModalPortal() {
6849
6985
  const { isOpen, mode, close } = useVolrModal();
6850
6986
  const [portalRoot, setPortalRoot] = React13.useState(null);