@unhingged/vizu-core 0.1.5 → 0.1.7

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
@@ -389,11 +389,59 @@ var CloudStorageAdapter = class {
389
389
  this.apiUrl = (opts.apiUrl ?? DEFAULT_API_URL).replace(/\/$/, "");
390
390
  this.autoSignIn = opts.autoSignIn !== false;
391
391
  this.onAuthChanged = opts.onAuthChanged;
392
- this.cachedToken = this.readStoredToken();
392
+ const fromHash = this.readHashToken();
393
+ if (fromHash) {
394
+ this.cachedToken = fromHash;
395
+ this.writeStoredToken(fromHash);
396
+ } else {
397
+ this.cachedToken = this.readStoredToken();
398
+ }
393
399
  if (this.cachedToken && !this.isExpired(this.cachedToken)) {
394
400
  this.fireAuthChanged(this.cachedToken);
395
401
  }
396
402
  }
403
+ /**
404
+ * Pull a token out of the URL fragment if /connect just redirected us
405
+ * back here. Strips the fragment on success so the token doesn't sit
406
+ * in browser history or get shared if the user copies the URL.
407
+ *
408
+ * The fragment is base64-encoded JSON with compact keys; see
409
+ * apps/landing/app/connect/RedirectComplete.tsx for the producer side.
410
+ */
411
+ readHashToken() {
412
+ if (typeof window === "undefined") return null;
413
+ const hash = window.location.hash;
414
+ if (!hash || hash.length < 2) return null;
415
+ const params = new URLSearchParams(hash.slice(1));
416
+ const payload = params.get("vizu_auth");
417
+ if (!payload) return null;
418
+ try {
419
+ const json = JSON.parse(atob(payload));
420
+ if (!json.t || !json.e || !json.u || !json.w) return null;
421
+ if (json.w !== this.workspace) return null;
422
+ const stored = {
423
+ token: json.t,
424
+ expiresAt: json.e,
425
+ userId: json.u,
426
+ user: typeof json.n === "string" ? {
427
+ id: json.u,
428
+ name: json.n,
429
+ avatarUrl: typeof json.a === "string" ? json.a : void 0
430
+ } : null
431
+ };
432
+ params.delete("vizu_auth");
433
+ const remaining = params.toString();
434
+ const newHash = remaining ? `#${remaining}` : "";
435
+ try {
436
+ const newUrl = window.location.pathname + window.location.search + newHash;
437
+ window.history.replaceState(null, "", newUrl);
438
+ } catch {
439
+ }
440
+ return stored;
441
+ } catch {
442
+ return null;
443
+ }
444
+ }
397
445
  /**
398
446
  * Open the sign-in popup right now (or no-op if a valid token is
399
447
  * cached). Vizu calls this on enable() so the user signs in BEFORE
@@ -662,12 +710,19 @@ var CloudStorageAdapter = class {
662
710
  `width=${POPUP_WIDTH},height=${POPUP_HEIGHT},left=${left},top=${top},noopener=no,popup=yes`
663
711
  );
664
712
  if (!popup) {
665
- return reject(
666
- makeAuthError(
667
- "popup_blocked",
668
- "Sign-in popup was blocked by the browser. Allow popups for this site and try again."
669
- )
670
- );
713
+ try {
714
+ const returnTo = window.location.href;
715
+ const redirectUrl = this.apiUrl + "/connect?workspace=" + encodeURIComponent(this.workspace) + "&origin=" + encodeURIComponent(hostOrigin) + "&return_to=" + encodeURIComponent(returnTo);
716
+ window.location.assign(redirectUrl);
717
+ return;
718
+ } catch (err) {
719
+ return reject(
720
+ makeAuthError(
721
+ "popup_blocked",
722
+ "Sign-in popup was blocked and redirect fallback failed: " + (err instanceof Error ? err.message : String(err))
723
+ )
724
+ );
725
+ }
671
726
  }
672
727
  let resolved = false;
673
728
  const onMessage = (e) => {
@@ -3161,7 +3216,16 @@ var Vizu = class {
3161
3216
  }
3162
3217
  if (matches(e, this.parsedShortcut)) {
3163
3218
  e.preventDefault();
3219
+ const wasEnabled = this.enabled;
3164
3220
  this.toggle();
3221
+ if (!wasEnabled && this.enabled && this.storage instanceof CloudStorageAdapter) {
3222
+ void this.storage.preflightAuth().catch((err) => {
3223
+ if (err?.code === "auth_canceled" || err?.code === "popup_blocked") return;
3224
+ if (typeof console !== "undefined") {
3225
+ console.warn("[vizu] preflight auth failed:", err);
3226
+ }
3227
+ });
3228
+ }
3165
3229
  }
3166
3230
  };
3167
3231
  /* ===== Reposition on scroll/resize ===== */
@@ -3250,14 +3314,6 @@ var Vizu = class {
3250
3314
  this.enabled = true;
3251
3315
  this.bus.emit("enabled", {});
3252
3316
  this.deferred(() => this.mount());
3253
- if (this.storage instanceof CloudStorageAdapter) {
3254
- void this.storage.preflightAuth().catch((err) => {
3255
- if (err?.code === "auth_canceled" || err?.code === "popup_blocked") return;
3256
- if (typeof console !== "undefined") {
3257
- console.warn("[vizu] preflight auth failed:", err);
3258
- }
3259
- });
3260
- }
3261
3317
  }
3262
3318
  disable() {
3263
3319
  if (!this.enabled) return;