function h(e, t) {
  switch (e) {
    case "warning":
      break;
    case "error":
      console.error(`${t.code}: ${t.message}`, t.error || "");
      break;
  }
}
class r extends Error {
  constructor(t, n) {
    super(`${t}: ${n}`), this.code = t, h("error", { code: t, message: n });
  }
}
function f(e) {
  const t = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
  let n = new Uint8Array(e);
  return window.crypto.getRandomValues(n), n = n.map((o) => t.charCodeAt(o % t.length)), String.fromCharCode.apply(null, Array.from(n));
}
function U(e) {
  return btoa(e).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
}
function R(e) {
  return Object.keys(e).filter((t) => e[t]).map((t) => `${t}=${encodeURIComponent(e[t])}`).join("&");
}
function l(e) {
  const t = e.replace(/^(http(?:s)?:\/\/)/, "");
  return t.endsWith("/") ? t.replace(/\/+$/, "") : t;
}
async function u(e, t) {
  return fetch(e, t).then(async (n) => {
    if (n.status >= 200 && n.status <= 299)
      return await n.json();
    throw new r("ERR_AUTH_HTTP_REQUEST", n.statusText);
  }).then((n) => n).catch((n) => {
    throw n instanceof r ? n : new r("ERR_AUTH_HTTP_REQUEST", n);
  });
}
function g(e, t) {
  return window.addEventListener(e, t), () => {
    window.removeEventListener(e, t);
  };
}
const O = "Authorize Frontify", y = { title: O, width: 800, height: 600, top: 50, left: 50 }, a = class {
  constructor(e) {
    this.listeners = {}, this.domain = "", this.attachEventListeners = () => (n) => {
      switch (n.data) {
        case a.EVENT_NAME_CANCELLED:
          this.call(a.EVENT_METHOD_CANCELLED);
          break;
        case a.EVENT_NAME_SUCCESS:
          this.call(a.EVENT_METHOD_SUCCESS);
          break;
        default:
          n.data.domain ? (this.setDomain(n.data.domain), this.call(a.EVENT_METHOD_DOMAIN)) : n.data.aborted && this.call(a.EVENT_METHOD_ABORTED);
          break;
      }
    };
    const t = { ...y, ...e };
    this.popUp = a.openPopUp(t), this.unregisterEventListener = g("message", this.attachEventListeners()), this.interval = setInterval(() => {
      this.popUp && this.popUp.closed && (clearInterval(this.interval), this.call(a.EVENT_METHOD_CANCELLED), this.call(a.EVENT_METHOD_ABORTED));
    }, 100);
  }
  static openPopUp(e) {
    const t = window.open("about:blank", e.title, `width=${e.width}, 
            height=${e.height}, 
            left=${e.left}, 
            top=${e.top}, 
            toolbar=no, menubar=no, 
            location=no, status=no, 
            directories=no, titlebar=no`);
    if (!t)
      throw new r("ERR_AUTH_POPUP_BLOCKED", "Popup is blocked. Make sure to enable popups.");
    return t;
  }
  call(e) {
    this.listeners[e] && this.listeners[e]();
  }
  setDomain(e) {
    this.domain = e;
  }
  getDomain() {
    return this.domain;
  }
  onDomain(e) {
    this.listeners.domain = e;
  }
  onAborted(e) {
    this.listeners.aborted = e;
  }
  onSuccess(e) {
    this.listeners.success = e;
  }
  onCancelled(e) {
    this.listeners.canceled = e;
  }
  close() {
    this.listeners = {}, clearInterval(this.interval), this.unregisterEventListener(), this.popUp && !this.popUp.closed && this.popUp.close();
  }
  navigateToUrl(e) {
    if (this.popUp && !this.popUp.closed) {
      this.popUp.location.replace(e);
      return;
    }
    throw new r("ERR_AUTH_POPUP_CLOSED", "Popup is closed.");
  }
};
let c = a;
c.EVENT_NAME_CANCELLED = "frontify-oauth-authorize-cancelled", c.EVENT_NAME_SUCCESS = "frontify-oauth-authorize-success", c.EVENT_METHOD_CANCELLED = "cancelled", c.EVENT_METHOD_SUCCESS = "success", c.EVENT_METHOD_DOMAIN = "domain", c.EVENT_METHOD_ABORTED = "aborted";
const N = 64, S = "code", D = "S256", w = "/connection/authenticator", C = "authorization_code", H = "refresh_token", P = "SHA-256", m = "Bearer";
async function k(e) {
  const t = new TextEncoder().encode(e), n = await window.crypto.subtle.digest(P, t), o = String.fromCharCode.apply(null, Array.from(new Uint8Array(n)));
  return U(o);
}
async function b(e) {
  try {
    const t = f(N), n = await k(t), o = await L(e.domain) || "";
    return { authorizationUrl: `https://${l(e.domain)}/api/oauth/authorize?${R({ response_type: S, client_id: e.clientId, scope: e.scopes.join("+"), code_challenge: n, code_challenge_method: D, redirect_uri: w, session_id: o })}`, codeVerifier: t, sessionId: o };
  } catch {
    throw new r("ERR_AUTH_COMPUTE_URL", "Error computing authorization url.");
  }
}
async function L(e) {
  var t;
  try {
    return (t = await u(`https://${l(e)}/api/oauth/create/session`, { method: "POST" })) == null ? void 0 : t.data.key;
  } catch {
    throw new r("ERR_AUTH_SESSION", "Error generating session.");
  }
}
async function I(e, t) {
  try {
    return (await u(`https://${l(e.domain)}/api/oauth/poll`, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ session_id: t }) }).catch(() => {
      throw new r("ERR_AUTH_POLL_REQUEST", "Error requesting oauth session poll.");
    })).data.payload.code;
  } catch {
    throw new r("ERR_AUTH_POLL", "Error polling oauth session.");
  }
}
async function M(e, t, n) {
  try {
    const o = l(e == null ? void 0 : e.domain), i = await u(`https://${o}/api/oauth/accesstoken`, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ grant_type: C, code: t, code_verifier: n, client_id: e.clientId, redirect_uri: w }) });
    return { bearerToken: { tokenType: m, expiresIn: i.expires_in, accessToken: i.access_token, refreshToken: i.refresh_token, domain: o }, clientId: e.clientId, scopes: e.scopes };
  } catch {
    throw new r("ERR_AUTH_ACCESS_TOKEN", "Error retrieving token.");
  }
}
async function v(e, t, n, o) {
  try {
    const i = l(e), _ = await u(`https://${i}/api/oauth/refresh`, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ grant_type: H, refresh_token: t, client_id: n, scope: o.join("+") }) });
    return { bearerToken: { tokenType: m, expiresIn: _.expires_in, accessToken: _.access_token, refreshToken: _.refresh_token, domain: i }, clientId: n, scopes: o };
  } catch {
    throw new r("ERR_AUTH_REFRESH_TOKEN", "Error refreshing token.");
  }
}
const $ = "https://app.frontify.com/finder", V = "Authorize Frontify", s = { open: !1 };
let p, d, T, E;
async function x(e, t) {
  if (s.open && p.close(), p = F(t != null ? t : { title: V, width: 800, height: 600, top: 50, left: 50 }), s.open = !0, e.domain ? await A(e, p).then((n) => {
    s.open = !1, n && (d = n);
  }).catch((n) => {
    throw n === !1 ? new r("ERR_AUTH_POPUP_CLOSED", "Auth aborted by client.") : new r("ERR_AUTH_FAILED", "Auth failed.");
  }) : await z(e, p).then((n) => {
    s.open = !1, d = n;
  }).catch((n) => {
    throw n === !1 ? new r("ERR_AUTH_DOMAIN_POPUP_CLOSED", "Domain cancelled by client.") : new r("ERR_AUTH_FAILED", "Auth failed.");
  }), !d)
    throw new r("ERR_AUTH_NO_TOKEN", "No token returned.");
  return d;
}
async function W(e) {
  return v(e.bearerToken.domain, e.bearerToken.refreshToken, e.clientId, e.scopes);
}
async function A(e, t) {
  var n;
  try {
    const o = await b(e);
    return await j(o.authorizationUrl, t).then(async () => {
      const i = await I(e, o.sessionId);
      return M(e, i, o.codeVerifier);
    });
  } catch (o) {
    const i = "Error generating session. Make sure that the inserted domain is a valid and secure Frontify instance.";
    throw (n = t.popUp) == null || n.postMessage({ domainError: i }, "*"), o instanceof r && o.code === "ERR_AUTH_COMPUTE_URL" ? new r("ERR_AUTH_SESSION", "Failed generating session.") : (s.open = !1, new r("ERR_AUTH", "Failed retrieving access token."));
  }
}
function z(e, t) {
  return t.navigateToUrl($), h("warning", { code: "WARN_DOMAIN_POPUP_OPEN", message: "Domain popup opened." }), new Promise((n, o) => {
    T = setTimeout(() => {
      s.open = !1, t.close(), h("warning", { code: "WARN_DOMAIN_TIMEOUT", message: "Domain popup timed out." });
    }, 5 * 60 * 1e3), t.onDomain(() => {
      clearTimeout(T), e.domain = p.getDomain(), A(e, p).then((i) => {
        i && n(i);
      }).catch((i) => {
        i instanceof r && i.code !== "ERR_AUTH_SESSION" ? o() : delete e.domain;
      }), h("warning", { code: "WARN_DOMAIN_SELECT", message: "Domain input submitted." });
    }), t.onAborted(() => {
      s.open = !1, clearTimeout(T), t.close(), o(!1);
    });
  });
}
function j(e, t) {
  return t.navigateToUrl(e), h("warning", { code: "WARN_AUTH_POPUP_OPEN", message: "Auth popup opened." }), new Promise((n, o) => {
    E = setTimeout(() => {
      s.open = !1, t.close(), h("warning", { code: "WARN_AUTH_TIMEOUT", message: "Auth popup timed out." });
    }, 5 * 60 * 1e3), t.onAborted(() => {
      s.open = !1, clearTimeout(E), t.close(), o(!1);
    }), t.onSuccess(() => {
      s.open = !1, clearTimeout(E), t.close(), h("warning", { code: "WARN_AUTH_SUCCESS", message: "Auth success." }), n();
    }), t.onCancelled(() => {
      s.open = !1, clearTimeout(E), t.close(), o(!1);
    });
  });
}
function F(e) {
  return new c(e != null ? e : {});
}
export {
  x as authorize,
  W as refresh
};
//# sourceMappingURL=index.es.es.js.map
