"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  // If the importer is in node compatibility mode or this is not an ESM
  // file that has been converted to a CommonJS file using a Babel-
  // compatible transform (i.e. "__esModule" has not been set), then set
  // "default" to the CommonJS "module.exports" for node compatibility.
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);

// src/index.ts
var src_exports = {};
__export(src_exports, {
  WebContainerServer: () => WebContainerServer
});
module.exports = __toCommonJS(src_exports);
var import_socket = require("socket.io");
var import_child_process = require("child_process");
var import_promises = __toESM(require("fs/promises"), 1);
var import_path = __toESM(require("path"), 1);
var WebContainerServer = class {
  constructor(config = {}) {
    this.workspaces = /* @__PURE__ */ new Map();
    this.processes = /* @__PURE__ */ new Map();
    this.config = {
      port: config.port || 3e3,
      host: config.host || "localhost",
      workspaceRoot: config.workspaceRoot || import_path.default.join(process.cwd(), "workspaces")
    };
    this.io = new import_socket.Server({
      cors: {
        origin: "*",
        methods: ["GET", "POST"]
      }
    });
    this.setupSocketHandlers();
  }
  start() {
    import_promises.default.mkdir(this.config.workspaceRoot, { recursive: true }).then(() => {
      this.io.listen(this.config.port);
      console.log(`WebContainer Server is running on http://${this.config.host}:${this.config.port}`);
      console.log(`Workspace root: ${this.config.workspaceRoot}`);
    }).catch((error) => {
      console.error("Failed to create workspace directory:", error);
      process.exit(1);
    });
    return this;
  }
  setupSocketHandlers() {
    this.io.on("connection", (socket) => {
      const workspaceId = Math.random().toString(36).substr(2, 9);
      const workspacePath = import_path.default.join(this.config.workspaceRoot, workspaceId);
      this.workspaces.set(socket.id, workspacePath);
      this.processes.set(socket.id, []);
      console.log(`Client connected. Workspace created at: ${workspacePath}`);
      socket.on("mount", async (files, callback) => {
        try {
          await this.handleMount(workspacePath, files);
          callback({ success: true });
        } catch (error) {
          const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
          callback({ error: errorMessage });
        }
      });
      socket.on("spawn", async (data, callback) => {
        try {
          const result = await this.handleSpawn(socket.id, workspacePath, data.command, data.args);
          callback({ success: true, result });
        } catch (error) {
          const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
          callback({ error: errorMessage });
        }
      });
      socket.on("fs:list", async (path2, callback) => {
        try {
          const result = await this.handleList(workspacePath, path2);
          callback({ success: true, result });
        } catch (error) {
          const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
          callback({ error: errorMessage });
        }
      });
      socket.on("fs:read", async (path2, callback) => {
        try {
          const result = await this.handleRead(workspacePath, path2);
          callback({ success: true, result });
        } catch (error) {
          const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
          callback({ error: errorMessage });
        }
      });
      socket.on("fs:write", async (data, callback) => {
        try {
          await this.handleWrite(workspacePath, data.path, data.content);
          callback({ success: true });
        } catch (error) {
          const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
          callback({ error: errorMessage });
        }
      });
      socket.on("fs:delete", async (path2, callback) => {
        try {
          await this.handleDelete(workspacePath, path2);
          callback({ success: true });
        } catch (error) {
          const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
          callback({ error: errorMessage });
        }
      });
      socket.on("fs:mkdir", async (path2, callback) => {
        try {
          await this.handleMkdir(workspacePath, path2);
          callback({ success: true });
        } catch (error) {
          const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
          callback({ error: errorMessage });
        }
      });
      socket.on("disconnect", () => {
        console.log(`Client disconnected. Cleaning up workspace: ${workspacePath}`);
        this.killAllProcesses(socket.id);
        import_promises.default.rm(workspacePath, { recursive: true, force: true }).catch((error) => console.error(`Failed to cleanup workspace: ${error}`));
        this.workspaces.delete(socket.id);
        this.processes.delete(socket.id);
      });
    });
  }
  killAllProcesses(socketId) {
    const processes = this.processes.get(socketId) || [];
    for (const process2 of processes) {
      try {
        process2.kill("SIGTERM");
        console.log(`Process ${process2.pid} terminated`);
      } catch (error) {
        console.error(`Failed to kill process ${process2.pid}:`, error);
      }
    }
  }
  async handleMount(workspacePath, files) {
    await import_promises.default.mkdir(workspacePath, { recursive: true });
    await this.createFiles(workspacePath, files);
  }
  async createFiles(basePath, files) {
    for (const [name, item] of Object.entries(files)) {
      const fullPath = import_path.default.join(basePath, name);
      if ("file" in item) {
        await import_promises.default.writeFile(fullPath, item.file.contents);
      } else if ("directory" in item) {
        await import_promises.default.mkdir(fullPath, { recursive: true });
        await this.createFiles(fullPath, item.directory.contents);
      }
    }
  }
  async handleSpawn(socketId, workspacePath, command, args = []) {
    return new Promise((resolve, reject) => {
      this.io.to(socketId).emit("process:output", {
        type: "stdout",
        data: `\r
$ ${command} ${args.join(" ")}\r
`
      });
      const process2 = (0, import_child_process.spawn)(command, args, {
        cwd: workspacePath,
        stdio: ["pipe", "pipe", "pipe"]
      });
      const processes = this.processes.get(socketId) || [];
      processes.push(process2);
      this.processes.set(socketId, processes);
      let stdout = "";
      let stderr = "";
      process2.stdout.on("data", (data) => {
        const output = data.toString();
        stdout += output;
        console.log(`[${command}] stdout:`, output);
        this.io.to(socketId).emit("process:output", {
          type: "stdout",
          data: output
        });
      });
      process2.stderr.on("data", (data) => {
        const output = data.toString();
        stderr += output;
        console.error(`[${command}] stderr:`, output);
        this.io.to(socketId).emit("process:output", {
          type: "stderr",
          data: output
        });
      });
      process2.on("close", (code) => {
        const processes2 = this.processes.get(socketId) || [];
        const index = processes2.indexOf(process2);
        if (index > -1) {
          processes2.splice(index, 1);
        }
        this.io.to(socketId).emit("process:output", {
          type: "exit",
          data: `\r
Process exited with code ${code}\r
$ `
        });
        if (code === 0) {
          resolve({ code, stdout, stderr });
        } else {
          reject(new Error(`Process exited with code ${code}
${stderr}`));
        }
      });
      process2.on("error", (error) => {
        const processes2 = this.processes.get(socketId) || [];
        const index = processes2.indexOf(process2);
        if (index > -1) {
          processes2.splice(index, 1);
        }
        this.io.to(socketId).emit("process:output", {
          type: "stderr",
          data: `\r
Error: ${error.message}\r
$ `
        });
        reject(error);
      });
    });
  }
  async handleList(workspacePath, relativePath) {
    const fullPath = import_path.default.join(workspacePath, relativePath);
    const entries = await import_promises.default.readdir(fullPath, { withFileTypes: true });
    return entries.map((entry) => ({
      name: entry.name,
      type: entry.isDirectory() ? "directory" : "file"
    }));
  }
  async handleRead(workspacePath, relativePath) {
    const fullPath = import_path.default.join(workspacePath, relativePath);
    return import_promises.default.readFile(fullPath, "utf-8");
  }
  async handleWrite(workspacePath, relativePath, content) {
    const fullPath = import_path.default.join(workspacePath, relativePath);
    await import_promises.default.mkdir(import_path.default.dirname(fullPath), { recursive: true });
    await import_promises.default.writeFile(fullPath, content);
  }
  async handleDelete(workspacePath, relativePath) {
    const fullPath = import_path.default.join(workspacePath, relativePath);
    await import_promises.default.rm(fullPath, { recursive: true, force: true });
  }
  async handleMkdir(workspacePath, relativePath) {
    const fullPath = import_path.default.join(workspacePath, relativePath);
    await import_promises.default.mkdir(fullPath, { recursive: true });
  }
};
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  WebContainerServer
});
