const PLUGIN_ID = "app";
const CHANNEL_ID = `${PLUGIN_ID}-auth-cookie-expires-at`;
const MIN_BASE_DELAY_MS = 5 * 6e4;
const ERROR_BACKOFF_START = 5e3;
const ERROR_BACKOFF_FACTOR = 2;
const ERROR_BACKOFF_MAX = 5 * 6e4;
function startCookieAuthRefresh({
  discoveryApi,
  fetchApi,
  errorApi
}) {
  let stopped = false;
  let timeout;
  let firstError = true;
  let errorBackoff = ERROR_BACKOFF_START;
  const channel = "BroadcastChannel" in window ? new BroadcastChannel(CHANNEL_ID) : void 0;
  const getDelay = (expiresAt) => {
    const margin = (1 + 3 * Math.random()) * 6e4;
    const delay = Math.max(expiresAt - Date.now(), MIN_BASE_DELAY_MS) - margin;
    return delay;
  };
  const refresh = async () => {
    try {
      const baseUrl = await discoveryApi.getBaseUrl(PLUGIN_ID);
      const requestUrl = `${baseUrl}/.backstage/auth/v1/cookie`;
      const res = await fetchApi.fetch(requestUrl, {
        credentials: "include"
      });
      if (!res.ok) {
        throw new Error(
          `Request failed with status ${res.status} ${res.statusText}, see request towards ${requestUrl} for more details`
        );
      }
      const data = await res.json();
      if (!data.expiresAt) {
        throw new Error("No expiration date in response");
      }
      const expiresAt = Date.parse(data.expiresAt);
      if (Number.isNaN(expiresAt)) {
        throw new Error("Invalid expiration date in response");
      }
      firstError = true;
      channel?.postMessage({
        action: "COOKIE_REFRESH_SUCCESS",
        payload: { expiresAt: new Date(expiresAt).toISOString() }
      });
      scheduleRefresh(getDelay(expiresAt));
    } catch (error) {
      if (firstError) {
        firstError = false;
        errorBackoff = ERROR_BACKOFF_START;
      } else {
        errorBackoff = Math.min(
          ERROR_BACKOFF_MAX,
          errorBackoff * ERROR_BACKOFF_FACTOR
        );
        console.error("Session cookie refresh failed", error);
        errorApi.post(
          new Error(
            `Session refresh failed, see developer console for details`
          )
        );
      }
      scheduleRefresh(errorBackoff);
    }
  };
  const onMessage = (event) => {
    const { data } = event;
    if (data === null || typeof data !== "object") {
      return;
    }
    if ("action" in data && data.action === "COOKIE_REFRESH_SUCCESS") {
      const expiresAt = Date.parse(data.payload.expiresAt);
      if (Number.isNaN(expiresAt)) {
        console.warn(
          "Received invalid expiration from session refresh channel"
        );
        return;
      }
      scheduleRefresh(getDelay(expiresAt));
    }
  };
  function scheduleRefresh(delayMs) {
    if (stopped) {
      return;
    }
    if (timeout) {
      clearTimeout(timeout);
    }
    timeout = setTimeout(refresh, delayMs);
  }
  channel?.addEventListener("message", onMessage);
  refresh();
  return () => {
    stopped = true;
    if (timeout) {
      clearTimeout(timeout);
    }
    channel?.removeEventListener("message", onMessage);
    channel?.close();
  };
}

export { startCookieAuthRefresh };
//# sourceMappingURL=startCookieAuthRefresh.esm.js.map
