55 lines · 2.2 KB
import { env } from "cloudflare:workers";
import { editorOriginProblem } from "./origin-check";

const DEV_FORGE_HOST = "localhost";
const DEV_EDITOR_HOST = "editor.localhost";

let validated: { raw: string; url: URL | null } | null = null;

/** The configured editor origin, validated once per isolate; an unsafe value disables the editor. */
function configured(): URL | null {
  if (!env.EDITOR_ORIGIN) return null;
  if (validated?.raw === env.EDITOR_ORIGIN) return validated.url;
  const problem = editorOriginProblem(env.EDITOR_ORIGIN, new URL(env.PUBLIC_URL).hostname, {
    sites: env.SITES_DOMAIN,
  });
  if (problem) console.error(`Editor disabled: ${problem}`);
  const url = problem ? null : new URL(env.EDITOR_ORIGIN);
  validated = { raw: env.EDITOR_ORIGIN, url };
  return url;
}

/** True when EDITOR_ORIGIN is set but rejected, so callers can refuse instead of falling back to dev hosts. */
function misconfigured(): boolean {
  return Boolean(env.EDITOR_ORIGIN) && configured() === null;
}

/**
 * The editor runs on its own origin so its scripts (VS Code, Open VSX extensions) can never reach forge
 * cookies or pages. Production sets EDITOR_ORIGIN, ideally on a separate registrable domain; local dev maps
 * `localhost:<port>` to `editor.localhost:<port>` (browsers resolve `*.localhost` to loopback, and the
 * forge's host-only cookies are never sent to another host).
 */
export function editorOriginFor(forgeUrl: URL): string | null {
  const explicit = configured();
  if (explicit) return explicit.origin;
  if (misconfigured() || forgeUrl.hostname !== DEV_FORGE_HOST) return null;
  const url = new URL(forgeUrl.origin);
  url.hostname = DEV_EDITOR_HOST;
  return url.origin;
}