import { logger as p, LogSeverity as F, errorLogPath as E } from "@php-wasm/logger";
import { consumeAPI as L, SupportedPHPVersions as O, printDebugDetails as Z, PHPResponse as $, exposeAPI as _, exposeSyncAPI as N } from "@php-wasm/universal";
import { resolveRemoteBlueprint as J, isBlueprintBundle as Q, compileBlueprint as Y, runBlueprintSteps as X } from "@wp-playground/blueprints";
import { zipDirectory as C, RecommendedPHPVersion as H, unzipFile as G } from "@wp-playground/common";
import m from "fs";
import { Worker as K, MessageChannel as ee } from "worker_threads";
import { p as T, a as te, e as re } from "./mounts-D1_eXSTw.js";
import oe from "express";
import { FileLockManagerForNode as ie } from "@php-wasm/node";
import se, { cpus as ne } from "os";
import { jspi as ae } from "wasm-feature-detect";
import le from "yargs";
import w, { basename as pe } from "path";
import { NodeJsFilesystem as ue, OverlayFilesystem as de, InMemoryFilesystem as ce, ZipFilesystem as he } from "@wp-playground/storage";
import { EmscriptenDownloadMonitor as fe, ProgressTracker as me } from "@php-wasm/progress";
import { resolveWordPressRelease as we } from "@wp-playground/wordpress";
import v from "fs-extra";
import { startBridge as ye } from "@php-wasm/xdebug-bridge";
async function be(e) {
  const r = oe(), t = await new Promise((s, n) => {
    const l = r.listen(e.port, () => {
      const a = l.address();
      a === null || typeof a == "string" ? n(new Error("Server address is not available")) : s(l);
    });
  });
  r.use("/", async (s, n) => {
    const l = await e.handleRequest({
      url: s.url,
      headers: Pe(s),
      method: s.method,
      body: await ge(s)
    });
    n.statusCode = l.httpStatusCode;
    for (const a in l.headers)
      n.setHeader(a, l.headers[a]);
    n.end(l.bytes);
  });
  const o = t.address().port;
  return await e.onBind(t, o);
}
const ge = async (e) => await new Promise((r) => {
  const t = [];
  e.on("data", (i) => {
    t.push(i);
  }), e.on("end", () => {
    r(new Uint8Array(Buffer.concat(t)));
  });
}), Pe = (e) => {
  const r = {};
  if (e.rawHeaders && e.rawHeaders.length)
    for (let t = 0; t < e.rawHeaders.length; t += 2)
      r[e.rawHeaders[t].toLowerCase()] = e.rawHeaders[t + 1];
  return r;
};
class ke {
  constructor(r) {
    this.workerLoads = [], this.addWorker(r);
  }
  addWorker(r) {
    this.workerLoads.push({
      worker: r,
      activeRequests: /* @__PURE__ */ new Set()
    });
  }
  async handleRequest(r) {
    let t = this.workerLoads[0];
    for (let o = 1; o < this.workerLoads.length; o++) {
      const s = this.workerLoads[o];
      s.activeRequests.size < t.activeRequests.size && (t = s);
    }
    const i = t.worker.request(r);
    return t.activeRequests.add(i), i.url = r.url, i.finally(() => {
      t.activeRequests.delete(i);
    });
  }
}
function ve(e) {
  return /^latest$|^trunk$|^nightly$|^(?:(\d+)\.(\d+)(?:\.(\d+))?)((?:-beta(?:\d+)?)|(?:-RC(?:\d+)?))?$/.test(e);
}
async function Se({
  sourceString: e,
  blueprintMayReadAdjacentFiles: r
}) {
  if (!e)
    return;
  if (e.startsWith("http://") || e.startsWith("https://"))
    return await J(e);
  let t = w.resolve(process.cwd(), e);
  if (!m.existsSync(t))
    throw new Error(`Blueprint file does not exist: ${t}`);
  const i = m.statSync(t);
  if (i.isDirectory() && (t = w.join(t, "blueprint.json")), !i.isFile() && i.isSymbolicLink())
    throw new Error(
      `Blueprint path is neither a file nor a directory: ${t}`
    );
  const o = w.extname(t);
  switch (o) {
    case ".zip":
      return he.fromArrayBuffer(
        m.readFileSync(t).buffer
      );
    case ".json": {
      const s = m.readFileSync(t, "utf-8");
      try {
        JSON.parse(s);
      } catch {
        throw new Error(
          `Blueprint file at ${t} is not a valid JSON file`
        );
      }
      const n = w.dirname(t), l = new ue(n);
      return new de([
        new ce({
          "blueprint.json": s
        }),
        /**
         * Wrap the NodeJS filesystem to prevent access to local files
         * unless the user explicitly allowed it.
         */
        {
          read(a) {
            if (!r)
              throw new Error(
                `Error: Blueprint contained tried to read a local file at path "${a}" (via a resource of type "bundled"). Playground restricts access to local resources by default as a security measure. 

You can allow this Blueprint to read files from the same parent directory by explicitly adding the --blueprint-may-read-adjacent-files option to your command.`
              );
            return l.read(a);
          }
        }
      ]);
    }
    default:
      throw new Error(
        `Unsupported blueprint file extension: ${o}. Only .zip and .json files are supported.`
      );
  }
}
const R = "" + new URL("worker-thread-v2-Pfv6UYF4.js", import.meta.url).href;
class xe {
  constructor(r, t) {
    this.lastProgressMessage = "", this.args = r, this.siteUrl = t.siteUrl, this.processIdSpaceLength = t.processIdSpaceLength, this.phpVersion = r.php;
  }
  getWorkerUrl() {
    return process.env.VITEST && R.startsWith("/src/") ? w.join(
      import.meta.dirname,
      "..",
      "..",
      R
    ) : R;
  }
  async bootPrimaryWorker(r, t) {
    const i = L(r);
    await i.useFileLockManager(t);
    const o = {
      ...this.args,
      php: this.phpVersion,
      siteUrl: this.siteUrl,
      firstProcessId: 1,
      processIdSpaceLength: this.processIdSpaceLength,
      trace: this.args.debug || !1,
      blueprint: this.args.blueprint
    };
    return await i.bootAsPrimaryWorker(o), i;
  }
  async bootSecondaryWorker({
    worker: r,
    fileLockManagerPort: t,
    firstProcessId: i
  }) {
    const o = L(r.phpPort);
    await o.useFileLockManager(t);
    const s = {
      ...this.args,
      php: this.phpVersion,
      siteUrl: this.siteUrl,
      firstProcessId: i,
      processIdSpaceLength: this.processIdSpaceLength,
      trace: this.args.debug || !1,
      blueprint: this.args.blueprint
    };
    return await o.bootAsSecondaryWorker(s), o;
  }
  writeProgressUpdate(r, t, i) {
    t !== this.lastProgressMessage && (this.lastProgressMessage = t, r.isTTY ? (r.cursorTo(0), r.write(t), r.clearLine(1), i && r.write(`
`)) : r.write(`${t}
`));
  }
}
const U = w.join(se.homedir(), ".wordpress-playground");
async function We(e) {
  return await V(
    "https://github.com/WordPress/sqlite-database-integration/archive/refs/heads/develop.zip",
    "sqlite.zip",
    e
  );
}
async function V(e, r, t) {
  const i = w.join(U, r);
  return v.existsSync(i) || (v.ensureDirSync(U), await Le(e, i, t)), q(i);
}
async function Le(e, r, t) {
  const o = (await t.monitorFetch(fetch(e))).body.getReader(), s = `${r}.partial`, n = v.createWriteStream(s);
  for (; ; ) {
    const { done: l, value: a } = await o.read();
    if (a && n.write(a), l)
      break;
  }
  n.close(), n.closed || await new Promise((l, a) => {
    n.on("finish", () => {
      v.renameSync(s, r), l(null);
    }), n.on("error", (u) => {
      v.removeSync(s), a(u);
    });
  });
}
function q(e, r) {
  return new File([v.readFileSync(e)], pe(e));
}
const B = "" + new URL("worker-thread-v1-BTJIbQLy.js", import.meta.url).href;
class Ie {
  constructor(r, t) {
    this.lastProgressMessage = "", this.args = r, this.siteUrl = t.siteUrl, this.processIdSpaceLength = t.processIdSpaceLength;
  }
  getWorkerUrl() {
    return process.env.VITEST && B.startsWith("/src/") ? w.join(
      import.meta.dirname,
      "..",
      "..",
      B
    ) : B;
  }
  async bootPrimaryWorker(r, t) {
    const i = await this.compileInputBlueprint(
      this.args["additional-blueprint-steps"] || []
    );
    this.phpVersion = i.versions.php;
    let o;
    const s = new fe();
    if (!this.args.skipWordPressSetup) {
      let h = !1;
      s.addEventListener("progress", (I) => {
        if (h)
          return;
        const { loaded: f, total: y } = I.detail, P = Math.floor(
          Math.min(100, 100 * f / y)
        );
        h = P === 100, this.writeProgressUpdate(
          process.stdout,
          `Downloading WordPress ${P}%...`,
          h
        );
      }), o = await we(this.args.wp), p.log(
        `Resolved WordPress release URL: ${o?.releaseUrl}`
      );
    }
    const n = o && w.join(
      U,
      `prebuilt-wp-content-for-wp-${o.version}.zip`
    ), l = o ? m.existsSync(n) ? q(n) : await V(
      o.releaseUrl,
      `${o.version}.zip`,
      s
    ) : void 0;
    p.log("Fetching SQLite integration plugin...");
    const a = this.args.skipSqliteSetup ? void 0 : await We(s), u = this.args.followSymlinks === !0, d = this.args.experimentalTrace === !0, b = this.args["mount-before-install"] || [], S = this.args.mount || [], c = L(r);
    return await c.isConnected(), p.log("Booting WordPress..."), await c.useFileLockManager(t), await c.bootAsPrimaryWorker({
      phpVersion: this.phpVersion,
      wpVersion: i.versions.wp,
      absoluteUrl: this.siteUrl,
      mountsBeforeWpInstall: b,
      mountsAfterWpInstall: S,
      wordPressZip: l && await l.arrayBuffer(),
      sqliteIntegrationPluginZip: await a?.arrayBuffer(),
      firstProcessId: 0,
      processIdSpaceLength: this.processIdSpaceLength,
      followSymlinks: u,
      trace: d,
      internalCookieStore: this.args.internalCookieStore,
      withXdebug: this.args.xdebug
    }), o && !this.args["mount-before-install"] && !m.existsSync(n) && (p.log("Caching preinstalled WordPress for the next boot..."), m.writeFileSync(
      n,
      await C(c, "/wordpress")
    ), p.log("Cached!")), c;
  }
  async bootSecondaryWorker({
    worker: r,
    fileLockManagerPort: t,
    firstProcessId: i
  }) {
    const o = L(
      r.phpPort
    );
    return await o.isConnected(), await o.useFileLockManager(t), await o.bootAsSecondaryWorker({
      phpVersion: this.phpVersion,
      absoluteUrl: this.siteUrl,
      mountsBeforeWpInstall: this.args["mount-before-install"] || [],
      mountsAfterWpInstall: this.args.mount || [],
      // Skip WordPress zip because we share the /wordpress directory
      // populated by the initial worker.
      wordPressZip: void 0,
      // Skip SQLite integration plugin for now because we
      // will copy it from primary's `/internal` directory.
      sqliteIntegrationPluginZip: void 0,
      dataSqlPath: "/wordpress/wp-content/database/.ht.sqlite",
      firstProcessId: i,
      processIdSpaceLength: this.processIdSpaceLength,
      followSymlinks: this.args.followSymlinks === !0,
      trace: this.args.experimentalTrace === !0,
      // @TODO: Move this to the request handler or else every worker
      //        will have a separate cookie store.
      internalCookieStore: this.args.internalCookieStore,
      withXdebug: this.args.xdebug
    }), await o.isReady(), o;
  }
  async compileInputBlueprint(r) {
    const t = this.args, i = t.blueprint, o = Q(i) ? i : {
      login: t.login,
      ...i || {},
      preferredVersions: {
        php: t.php ?? i?.preferredVersions?.php ?? H,
        wp: t.wp ?? i?.preferredVersions?.wp ?? "latest",
        ...i?.preferredVersions || {}
      }
    }, s = new me();
    let n = "", l = !1;
    return s.addEventListener("progress", (a) => {
      if (l)
        return;
      l = a.detail.progress === 100;
      const u = Math.floor(a.detail.progress);
      n = a.detail.caption || n || "Running the Blueprint";
      const d = `${n.trim()} – ${u}%`;
      this.writeProgressUpdate(
        process.stdout,
        d,
        l
      );
    }), await Y(o, {
      progress: s,
      additionalSteps: r
    });
  }
  writeProgressUpdate(r, t, i) {
    this.args.verbosity !== M.Quiet.name && t !== this.lastProgressMessage && (this.lastProgressMessage = t, r.isTTY ? (r.cursorTo(0), r.write(t), r.clearLine(1), i && r.write(`
`)) : r.write(`${t}
`));
  }
}
const M = {
  Quiet: { name: "quiet", severity: F.Fatal },
  Normal: { name: "normal", severity: F.Info },
  Debug: { name: "debug", severity: F.Debug }
};
async function Qe() {
  try {
    const e = le(process.argv.slice(2)).usage("Usage: wp-playground <command> [options]").positional("command", {
      describe: "Command to run",
      choices: ["server", "run-blueprint", "build-snapshot"],
      demandOption: !0
    }).option("outfile", {
      describe: "When building, write to this output file.",
      type: "string",
      default: "wordpress.zip"
    }).option("port", {
      describe: "Port to listen on when serving.",
      type: "number",
      default: 9400
    }).option("site-url", {
      describe: "Site URL to use for WordPress. Defaults to http://127.0.0.1:{port}",
      type: "string"
    }).option("php", {
      describe: "PHP version to use.",
      type: "string",
      default: H,
      choices: O
    }).option("wp", {
      describe: "WordPress version to use.",
      type: "string",
      default: "latest"
    }).option("mount", {
      describe: "Mount a directory to the PHP runtime (can be used multiple times). Format: /host/path:/vfs/path",
      type: "array",
      string: !0,
      coerce: T
    }).option("mount-before-install", {
      describe: "Mount a directory to the PHP runtime before WordPress installation (can be used multiple times). Format: /host/path:/vfs/path",
      type: "array",
      string: !0,
      coerce: T
    }).option("mount-dir", {
      describe: 'Mount a directory to the PHP runtime (can be used multiple times). Format: "/host/path" "/vfs/path"',
      type: "array",
      nargs: 2,
      array: !0
      // coerce: parseMountDirArguments,
    }).option("mount-dir-before-install", {
      describe: 'Mount a directory before WordPress installation (can be used multiple times). Format: "/host/path" "/vfs/path"',
      type: "string",
      nargs: 2,
      array: !0,
      coerce: te
    }).option("login", {
      describe: "Should log the user in",
      type: "boolean",
      default: !1
    }).option("blueprint", {
      describe: "Blueprint to execute.",
      type: "string"
    }).option("blueprint-may-read-adjacent-files", {
      describe: 'Consent flag: Allow "bundled" resources in a local blueprint to read files in the same directory as the blueprint file.',
      type: "boolean",
      default: !1
    }).option("skip-wordpress-setup", {
      describe: "Do not download, unzip, and install WordPress. Useful for mounting a pre-configured WordPress directory at /wordpress.",
      type: "boolean",
      default: !1
    }).option("skip-sqlite-setup", {
      describe: "Skip the SQLite integration plugin setup to allow the WordPress site to use MySQL.",
      type: "boolean",
      default: !1
    }).option("quiet", {
      describe: "Do not output logs and progress messages.",
      type: "boolean",
      default: !1,
      hidden: !0
    }).option("verbosity", {
      describe: "Output logs and progress messages.",
      type: "string",
      choices: Object.values(M).map(
        (o) => o.name
      ),
      default: "normal"
    }).option("debug", {
      describe: "Print PHP error log content if an error occurs during Playground boot.",
      type: "boolean",
      default: !1
    }).option("auto-mount", {
      describe: "Automatically mount the specified directory. If no path is provided, mount the current working directory. You can mount a WordPress directory, a plugin directory, a theme directory, a wp-content directory, or any directory containing PHP and HTML files.",
      type: "string"
    }).option("follow-symlinks", {
      describe: `Allow Playground to follow symlinks by automatically mounting symlinked directories and files encountered in mounted directories. 
Warning: Following symlinks will expose files outside mounted directories to Playground and could be a security risk.`,
      type: "boolean",
      default: !1
    }).option("experimental-trace", {
      describe: "Print detailed messages about system behavior to the console. Useful for troubleshooting.",
      type: "boolean",
      default: !1,
      // Hide this option because we want to replace with a more general log-level flag.
      hidden: !0
    }).option("internal-cookie-store", {
      describe: "Enable internal cookie handling. When enabled, Playground will manage cookies internally using an HttpCookieStore that persists cookies across requests. When disabled, cookies are handled externally (e.g., by a browser in Node.js environments).",
      type: "boolean",
      default: !1
    }).option("xdebug", {
      describe: "Enable Xdebug.",
      type: "boolean",
      default: !1
    }).option("experimental-devtools", {
      describe: "Enable experimental browser development tools.",
      type: "boolean",
      default: !1
    }).option("experimental-multi-worker", {
      describe: "Enable experimental multi-worker support which requires a /wordpress directory backed by a real filesystem. Pass a positive number to specify the number of workers to use. Otherwise, default to the number of CPUs minus 1.",
      type: "number",
      coerce: (o) => o ?? ne().length - 1
    }).option("experimental-blueprints-v2-runner", {
      describe: "Use the experimental Blueprint V2 runner.",
      type: "boolean",
      default: !1,
      // Remove the "hidden" flag once Blueprint V2 is fully supported
      hidden: !0
    }).option("mode", {
      describe: "Blueprints v2 runner mode to use. This option is required when using the --experimental-blueprints-v2-runner flag with a blueprint.",
      type: "string",
      choices: ["create-new-site", "apply-to-existing-site"],
      // Remove the "hidden" flag once Blueprint V2 is fully supported
      hidden: !0
    }).showHelpOnFail(!1).strictOptions().check(async (o) => {
      if (o.wp !== void 0 && !ve(o.wp))
        try {
          new URL(o.wp);
        } catch {
          throw new Error(
            'Unrecognized WordPress version. Please use "latest", a URL, or a numeric version such as "6.2", "6.0.1", "6.2-beta1", or "6.2-RC1"'
          );
        }
      if (o["site-url"] !== void 0 && o["site-url"] !== "")
        try {
          new URL(o["site-url"]);
        } catch {
          throw new Error(
            `Invalid site-url "${o["site-url"]}". Please provide a valid URL (e.g., http://localhost:8080 or https://example.com)`
          );
        }
      if (o["auto-mount"]) {
        let s = !1;
        try {
          s = m.statSync(o["auto-mount"]).isDirectory();
        } catch {
          s = !1;
        }
        if (!s)
          throw new Error(
            `The specified --auto-mount path is not a directory: '${o["auto-mount"]}'.`
          );
      }
      if (o["experimental-multi-worker"] !== void 0) {
        if (o["experimental-multi-worker"] <= 1)
          throw new Error(
            "The --experimental-multi-worker flag must be a positive integer greater than 1."
          );
        const s = (n) => n.vfsPath === "/wordpress";
        if (!o.mount?.some(s) && !o["mount-before-install"]?.some(
          s
        ))
          throw new Error(
            "Please mount a real filesystem directory as the /wordpress directory before using the --experimental-multi-worker flag. For example: --mount-dir-before-install ./empty-dir /wordpress"
          );
      }
      if (o["experimental-blueprints-v2-runner"] === !0) {
        if (o.mode !== void 0) {
          if ("skip-wordpress-setup" in o)
            throw new Error(
              "The --skipWordPressSetup option cannot be used with the --mode option. Use one or the other."
            );
          if ("skip-sqlite-setup" in o)
            throw new Error(
              "The --skipSqliteSetup option is not supported in Blueprint V2 mode."
            );
          if (o["auto-mount"] !== void 0)
            throw new Error(
              "The --mode option cannot be used with --auto-mount because --auto-mount automatically sets the mode."
            );
        } else
          o["skip-wordpress-setup"] === !0 ? o.mode = "apply-to-existing-site" : o.mode = "create-new-site";
        const s = o.allow || [];
        o.followSymlinks === !0 && s.push("follow-symlinks"), o["blueprint-may-read-adjacent-files"] === !0 && s.push("read-local-fs"), o.allow = s;
      } else if (o.mode !== void 0)
        throw new Error(
          "The --mode option requires the --experimentalBlueprintsV2Runner flag."
        );
      return !0;
    });
    e.wrap(e.terminalWidth());
    const r = await e.argv, t = r._[0];
    ["run-blueprint", "server", "build-snapshot"].includes(t) || (e.showHelp(), process.exit(1));
    const i = {
      ...r,
      command: t,
      mount: [...r.mount || [], ...r["mount-dir"] || []],
      "mount-before-install": [
        ...r["mount-before-install"] || [],
        ...r["mount-dir-before-install"] || []
      ]
    };
    await Fe(i);
  } catch (e) {
    if (!(e instanceof Error))
      throw e;
    if (process.argv.includes("--debug"))
      Z(e);
    else {
      const t = [];
      let i = e;
      do
        t.push(i.message), i = i.cause;
      while (i instanceof Error);
      console.error(
        "\x1B[1m" + t.join(" caused by ") + "\x1B[0m"
      );
    }
    process.exit(1);
  }
}
async function Fe(e) {
  let r, t;
  const i = [];
  if (e.autoMount !== void 0 && (e.autoMount === "" && (e = { ...e, autoMount: process.cwd() }), e = re(e)), e.quiet && (e.verbosity = "quiet", delete e.quiet), e.debug ? e.verbosity = "debug" : e.verbosity === "debug" && (e.debug = !0), e.verbosity) {
    const a = Object.values(M).find(
      (u) => u.name === e.verbosity
    ).severity;
    p.setSeverityFilterLevel(a);
  }
  const o = await import("fs-ext").then((a) => a.flockSync).catch(() => {
    p.warn(
      "The fs-ext package is not installed. Internal file locking will not be integrated with host OS file locking."
    );
  }), s = new ie(o);
  let n = !1, l = !0;
  return p.log("Starting a PHP server..."), be({
    port: e.port,
    onBind: async (a, u) => {
      const d = `http://127.0.0.1:${u}`, b = e["site-url"] || d, S = e.experimentalMultiWorker ?? 1, c = Math.floor(
        Number.MAX_SAFE_INTEGER / S
      );
      let h;
      e["experimental-blueprints-v2-runner"] ? h = new xe(e, {
        siteUrl: b,
        processIdSpaceLength: c
      }) : (h = new Ie(e, {
        siteUrl: b,
        processIdSpaceLength: c
      }), typeof e.blueprint == "string" && (e.blueprint = await Se({
        sourceString: e.blueprint,
        blueprintMayReadAdjacentFiles: e["blueprint-may-read-adjacent-files"] === !0
      })));
      const I = Re(
        h.getWorkerUrl(),
        S,
        ({ exitCode: f, isMain: y, workerIndex: P }) => {
          f !== 0 && (p.error(
            `Worker ${P} exited with code ${f}
`
          ), y && e.exitOnPrimaryWorkerCrash && process.exit(1));
        }
      );
      p.log(`Setting up WordPress ${e.wp}`);
      try {
        const [f, ...y] = await I, P = await A(
          s
        );
        if (t = await h.bootPrimaryWorker(
          f.phpPort,
          P
        ), i.push({
          playground: t,
          worker: f.worker
        }), await t.isReady(), n = !0, p.log("Booted!"), r = new ke(t), !e["experimental-blueprints-v2-runner"]) {
          const k = await h.compileInputBlueprint(
            e["additional-blueprint-steps"] || []
          );
          k && (p.log("Running the Blueprint..."), await X(k, t), p.log("Finished running the blueprint"));
        }
        if (e.command === "build-snapshot" ? (await Be(t, e.outfile), p.log(`WordPress exported to ${e.outfile}`), process.exit(0)) : e.command === "run-blueprint" && (p.log("Blueprint executed"), process.exit(0)), e.experimentalMultiWorker && e.experimentalMultiWorker > 1) {
          p.log("Preparing additional workers...");
          const k = await C(
            t,
            "/internal"
          ), g = c;
          await Promise.all(
            y.map(async (W, z) => {
              const j = g + z * c, D = await A(s), x = await h.bootSecondaryWorker({
                worker: W,
                fileLockManagerPort: D,
                firstProcessId: j
              });
              i.push({
                playground: x,
                worker: W.worker
              }), await x.writeFile(
                "/tmp/internal.zip",
                k
              ), await G(
                x,
                "/tmp/internal.zip",
                "/internal"
              ), await x.unlink(
                "/tmp/internal.zip"
              ), r.addWorker(x);
            })
          ), p.log("Ready!");
        }
        return p.log(`WordPress is running on ${d}`), e.experimentalDevtools && e.xdebug && (await ye({
          getPHPFile: async (g) => await t.readFileAsText(g)
        })).start(), {
          playground: t,
          server: a,
          [Symbol.asyncDispose]: async function() {
            await Promise.all(
              i.map(
                async ({ playground: g, worker: W }) => {
                  await g.dispose(), await W.terminate();
                }
              )
            ), await new Promise((g) => a.close(g));
          },
          workerThreadCount: S
        };
      } catch (f) {
        if (!e.debug)
          throw f;
        let y = "";
        throw await t?.fileExists(E) && (y = await t.readFileAsText(E)), new Error(y, { cause: f });
      }
    },
    async handleRequest(a) {
      if (!n)
        return $.forHttpCode(
          502,
          "WordPress is not ready yet"
        );
      if (l) {
        l = !1;
        const u = {
          "Content-Type": ["text/plain"],
          "Content-Length": ["0"],
          Location: ["/"]
        };
        return a.headers?.cookie?.includes(
          "playground_auto_login_already_happened"
        ) && (u["Set-Cookie"] = [
          "playground_auto_login_already_happened=1; Max-Age=0; Expires=Thu, 01 Jan 1970 00:00:00 GMT; Path=/"
        ]), new $(302, u, new Uint8Array());
      }
      return await r.handleRequest(a);
    }
  });
}
function Re(e, r, t) {
  const i = new URL(e, import.meta.url), o = [];
  for (let s = 0; s < r; s++) {
    const n = new K(i), l = (a) => {
      t({
        exitCode: a,
        isMain: s === 0,
        workerIndex: s
      });
    };
    o.push(
      new Promise(
        (a, u) => {
          n.once("message", function(d) {
            d.command === "worker-script-initialized" && a({ worker: n, phpPort: d.phpPort });
          }), n.once("error", function(d) {
            console.error(d);
            const b = new Error(
              `Worker failed to load at ${i}. ${d.message ? `Original error: ${d.message}` : ""}`
            );
            b.filename = i, u(b);
          }), n.once("exit", l);
        }
      )
    );
  }
  return Promise.all(o);
}
async function A(e) {
  const { port1: r, port2: t } = new ee();
  return await ae() ? _(e, null, r) : await N(e, r), t;
}
async function Be(e, r) {
  await e.run({
    code: `<?php
		$zip = new ZipArchive();
		if(false === $zip->open('/tmp/build.zip', ZipArchive::CREATE | ZipArchive::OVERWRITE)) {
			throw new Exception('Failed to create ZIP');
		}
		$files = new RecursiveIteratorIterator(
			new RecursiveDirectoryIterator('/wordpress')
		);
		foreach ($files as $file) {
			echo $file . PHP_EOL;
			if (!$file->isFile()) {
				continue;
			}
			$zip->addFile($file->getPathname(), $file->getPathname());
		}
		$zip->close();

	`
  });
  const t = await e.readFileAsBuffer("/tmp/build.zip");
  m.writeFileSync(r, t);
}
export {
  M as L,
  Qe as p,
  Fe as r
};
//# sourceMappingURL=run-cli-ob90MazJ.js.map
