import {
  setupDefaultEntrypointIfNeeded
} from "./chunk-TFHHHZM6.js";
import {
  dirname,
  resolveFilePath,
  resolveFilePathOrThrow
} from "./chunk-5UJ4EED4.js";
import {
  normalizeFsMap
} from "./chunk-7SIVWFC6.js";

// webworker/execution-context.ts
import { RootCircuit } from "@tscircuit/core";
import * as tscircuitCore from "@tscircuit/core";
import * as React from "react";
import * as jscadFiber from "jscad-fiber";
import * as tscircuitMathUtils from "@tscircuit/math-utils";
function createExecutionContext(webWorkerConfiguration, opts = {}) {
  globalThis.React = React;
  const circuit = new RootCircuit();
  if (opts.name) {
    circuit.name = opts.name;
  }
  return {
    fsMap: {},
    entrypoint: "",
    preSuppliedImports: {
      "@tscircuit/core": tscircuitCore,
      tscircuit: tscircuitCore,
      "@tscircuit/math-utils": tscircuitMathUtils,
      react: React,
      "jscad-fiber": jscadFiber,
      // This is usually used as a type import, we can remove the shim when we
      // ignore type imports in getImportsFromCode
      "@tscircuit/props": {}
    },
    circuit,
    ...webWorkerConfiguration
  };
}

// lib/runner/CircuitRunner.ts
import "react";

// webworker/eval-compiled-js.ts
function evalCompiledJs(compiledCode, preSuppliedImports, cwd) {
  ;
  globalThis.__tscircuit_require = (name) => {
    const resolvedFilePath = resolveFilePath(name, preSuppliedImports, cwd);
    const hasResolvedFilePath = resolvedFilePath && preSuppliedImports[resolvedFilePath];
    if (!preSuppliedImports[name] && !hasResolvedFilePath) {
      throw new Error(`Import "${name}" not found ${cwd ? `in "${cwd}"` : ""}`);
    }
    const mod = preSuppliedImports[name] || preSuppliedImports[resolvedFilePath];
    return new Proxy(mod, {
      get(target, prop) {
        if (!(prop in target)) {
          if (prop === "default") {
            if (target.default !== void 0) {
              return target.default;
            }
            if (target.__esModule) {
              return void 0;
            }
            if (typeof target === "function" || typeof target === "object") {
              return target;
            }
            return void 0;
          }
          if (prop === "__esModule") {
            return true;
          }
          throw new Error(
            `Component "${String(prop)}" is not exported by "${name}"`
          );
        }
        return target[prop];
      }
    });
  };
  const functionBody = `
  var exports = {};
  var require = globalThis.__tscircuit_require;
  var module = { exports };
  var circuit = globalThis.__tscircuit_circuit;
  ${compiledCode};
  return module;`.trim();
  return Function(functionBody).call(globalThis);
}

// webworker/import-eval-path.ts
import "@babel/standalone";

// webworker/import-local-file.ts
import * as Babel from "@babel/standalone";

// lib/utils/get-imports-from-code.ts
var getImportsFromCode = (code) => {
  const importRegex = /^\s*import\s+(?:(?:[\w\s]+,\s*)?(?:\*\s+as\s+[\w\s]+|\{[\s\w,]+\}|\w+)\s+from\s+)?['"](.+?)['"]/gm;
  const imports = [];
  let match;
  while ((match = importRegex.exec(code)) !== null) {
    imports.push(match[1]);
  }
  const reExportRegex = /^\s*export\s+(?:\*|(?:\{[\s\w,]+\}))\s+from\s+['"](.+?)['"]/gm;
  let reExportMatch;
  while ((reExportMatch = reExportRegex.exec(code)) !== null) {
    imports.push(reExportMatch[1]);
  }
  return imports;
};

// webworker/import-local-file.ts
var importLocalFile = async (importName, ctx, depth = 0) => {
  const { fsMap, preSuppliedImports } = ctx;
  const fsPath = resolveFilePathOrThrow(importName, fsMap);
  if (!ctx.fsMap[fsPath]) {
    throw new Error(`File "${fsPath}" not found`);
  }
  const fileContent = fsMap[fsPath];
  if (fsPath.endsWith(".json")) {
    const jsonData = JSON.parse(fileContent);
    preSuppliedImports[fsPath] = {
      __esModule: true,
      default: jsonData
    };
  } else if (fsPath.endsWith(".tsx") || fsPath.endsWith(".ts")) {
    const importNames = getImportsFromCode(fileContent);
    for (const importName2 of importNames) {
      if (!preSuppliedImports[importName2]) {
        await importEvalPath(importName2, ctx, depth + 1, {
          cwd: dirname(fsPath)
        });
      }
    }
    const result = Babel.transform(fileContent, {
      presets: ["react", "typescript"],
      plugins: ["transform-modules-commonjs"],
      filename: "virtual.tsx"
    });
    if (!result || !result.code) {
      throw new Error("Failed to transform code");
    }
    try {
      const importRunResult = evalCompiledJs(
        result.code,
        preSuppliedImports,
        dirname(fsPath)
      );
      preSuppliedImports[fsPath] = importRunResult.exports;
    } catch (error) {
      throw new Error(
        `Eval compiled js error for "${importName}": ${error.message}`
      );
    }
  } else if (fsPath.endsWith(".js")) {
    const result = Babel.transform(fileContent, {
      presets: ["env"],
      plugins: ["transform-modules-commonjs"],
      filename: fsPath
    });
    if (!result || !result.code) {
      throw new Error("Failed to transform JS code");
    }
    preSuppliedImports[fsPath] = evalCompiledJs(
      result.code,
      preSuppliedImports,
      dirname(fsPath)
    ).exports;
  } else {
    throw new Error(
      `Unsupported file extension "${fsPath.split(".").pop()}" for "${fsPath}"`
    );
  }
};

// webworker/import-snippet.ts
import "@babel/standalone";
async function importSnippet(importName, ctx, depth = 0) {
  const { preSuppliedImports } = ctx;
  const fullSnippetName = importName.replace("@tsci/", "").replace(".", "/");
  const { cjs, error } = await fetch(`${ctx.cjsRegistryUrl}/${fullSnippetName}`).then(async (res) => ({ cjs: await res.text(), error: null })).catch((e) => ({ error: e, cjs: null }));
  if (error) {
    console.error("Error fetching import", importName, error);
    return;
  }
  try {
    preSuppliedImports[importName] = evalCompiledJs(
      cjs,
      preSuppliedImports
    ).exports;
  } catch (e) {
    console.error("Error importing snippet", e);
  }
}

// lib/utils/resolve-node-module.ts
function createContext(modulePath, fsMap, basePath) {
  return {
    fsMap,
    extensions: [".js", ".jsx", ".ts", ".tsx", ".json"],
    basePath,
    modulePath
  };
}
function findPackageJson(nodeModulesPath, ctx) {
  const packageJsonPath = `${nodeModulesPath}/package.json`;
  if (!ctx.fsMap[packageJsonPath]) return null;
  try {
    return JSON.parse(ctx.fsMap[packageJsonPath]);
  } catch {
    return null;
  }
}
function tryResolveWithExtensions(path, ctx) {
  if (ctx.fsMap[path]) return path;
  for (const ext of ctx.extensions) {
    const pathWithExt = path.replace(/\.js$|\.jsx$/, "") + ext;
    if (ctx.fsMap[pathWithExt]) return pathWithExt;
  }
  return null;
}
function resolveExportPath(nodeModulesPath, exportPath, ctx) {
  const fullExportPath = `${nodeModulesPath}/${exportPath.replace(/^\.\//, "")}`;
  return tryResolveWithExtensions(fullExportPath, ctx);
}
function resolvePackageExports(nodeModulesPath, packageJson, remainingPath, ctx) {
  if (!packageJson.exports) return null;
  const defaultExport = packageJson.exports["."];
  if (remainingPath === "" && defaultExport) {
    if (typeof defaultExport === "string") {
      const resolved = resolveExportPath(nodeModulesPath, defaultExport, ctx);
      if (resolved) return resolved;
    }
  }
  const subpathExport = remainingPath ? packageJson.exports[`./${remainingPath}`] : null;
  if (subpathExport && typeof subpathExport === "string") {
    const resolved = resolveExportPath(nodeModulesPath, subpathExport, ctx);
    if (resolved) return resolved;
  }
  const importExport = packageJson.exports["import"];
  if (remainingPath === "" && importExport && typeof importExport === "string") {
    const resolved = resolveExportPath(nodeModulesPath, importExport, ctx);
    if (resolved) return resolved;
  }
  return null;
}
function resolvePackageEntryPoint(nodeModulesPath, packageJson, ctx) {
  const entryPoint = packageJson.module || packageJson.main || "index.js";
  const fullPath = `${nodeModulesPath}/${entryPoint}`;
  return tryResolveWithExtensions(fullPath, ctx);
}
function resolveRemainingPath(nodeModulesPath, remainingPath, ctx) {
  if (!remainingPath) {
    for (const ext of ctx.extensions) {
      const indexPath = `${nodeModulesPath}/index${ext}`;
      if (ctx.fsMap[indexPath]) return indexPath;
    }
    return null;
  }
  const fullPath = `${nodeModulesPath}/${remainingPath}`;
  const directMatch = tryResolveWithExtensions(fullPath, ctx);
  if (directMatch) return directMatch;
  for (const ext of ctx.extensions) {
    const indexPath = `${fullPath}/index${ext}`;
    if (ctx.fsMap[indexPath]) return indexPath;
  }
  return null;
}
function resolveNodeModuleInPath(searchPath, ctx) {
  const moduleParts = ctx.modulePath.split("/");
  const scope = moduleParts[0].startsWith("@") ? moduleParts.slice(0, 2).join("/") : moduleParts[0];
  const remainingPath = moduleParts.slice(scope.includes("/") ? 2 : 1).join("/");
  const nodeModulesPath = `${searchPath == "." ? "" : `${searchPath}/`}node_modules/${scope}`;
  const packageJson = findPackageJson(nodeModulesPath, ctx);
  if (packageJson) {
    const exportsResolution = resolvePackageExports(
      nodeModulesPath,
      packageJson,
      remainingPath,
      ctx
    );
    if (exportsResolution) return exportsResolution;
    const entryPointResolution = resolvePackageEntryPoint(
      nodeModulesPath,
      packageJson,
      ctx
    );
    if (entryPointResolution) return entryPointResolution;
  }
  const remainingPathResolution = resolveRemainingPath(
    nodeModulesPath,
    remainingPath,
    ctx
  );
  if (remainingPathResolution) return remainingPathResolution;
  const parentPath = dirname(searchPath);
  if (parentPath && parentPath !== searchPath) {
    return resolveNodeModuleInPath(parentPath, ctx);
  }
  return null;
}
function resolveNodeModule(modulePath, fsMap, basePath) {
  const ctx = createContext(modulePath, fsMap, basePath);
  return resolveNodeModuleInPath(ctx.basePath, ctx);
}

// webworker/import-node-module.ts
var importNodeModule = async (importName, ctx, depth = 0) => {
  const { preSuppliedImports } = ctx;
  if (preSuppliedImports[importName]) {
    return;
  }
  const resolvedNodeModulePath = resolveNodeModule(importName, ctx.fsMap, "");
  if (!resolvedNodeModulePath) {
    throw new Error(`Node module "${importName}" not found`);
  }
  await importLocalFile(resolvedNodeModulePath, ctx, depth);
  preSuppliedImports[importName] = preSuppliedImports[resolvedNodeModulePath];
  const unprefixedPath = resolvedNodeModulePath.replace(/^node_modules\//, "");
  preSuppliedImports[unprefixedPath] = preSuppliedImports[resolvedNodeModulePath];
  if (resolvedNodeModulePath.endsWith("/index.tsx") || resolvedNodeModulePath.endsWith("/index.ts") || resolvedNodeModulePath.endsWith("/index.js")) {
    const dirPath = resolvedNodeModulePath.replace(/\/index\.(tsx?|js)$/, "");
    const unprefixedDirPath = dirPath.replace(/^node_modules\//, "");
    preSuppliedImports[unprefixedDirPath] = preSuppliedImports[resolvedNodeModulePath];
    if (unprefixedDirPath.startsWith("@")) {
      const scopeParts = unprefixedDirPath.split("/");
      if (scopeParts.length >= 2) {
        const scopedName = `${scopeParts[0]}/${scopeParts[1]}`;
        preSuppliedImports[scopedName] = preSuppliedImports[resolvedNodeModulePath];
      }
    }
  }
};

// webworker/import-eval-path.ts
async function importEvalPath(importName, ctx, depth = 0, opts = {}) {
  if (ctx.verbose) {
    console.log(`[Worker] ${"  ".repeat(depth)}\u27A1\uFE0F`, importName);
  }
  const { preSuppliedImports } = ctx;
  if (preSuppliedImports[importName]) return;
  if (importName.startsWith("./") && preSuppliedImports[importName.slice(2)])
    return;
  if (depth > 5) {
    console.log("Max depth for imports reached");
    return;
  }
  const resolvedLocalImportPath = resolveFilePath(
    importName,
    ctx.fsMap,
    opts.cwd
  );
  if (resolvedLocalImportPath) {
    return importLocalFile(resolvedLocalImportPath, ctx, depth);
  }
  const resolvedNodeModulePath = resolveNodeModule(
    importName,
    ctx.fsMap,
    opts.cwd || ""
  );
  if (resolvedNodeModulePath) {
    return importNodeModule(importName, ctx, depth);
  }
  if (importName.startsWith("@tsci/")) {
    return importSnippet(importName, ctx, depth);
  }
  throw new Error(
    `Unresolved import "${importName}" ${opts.cwd ? `from directory "${opts.cwd}"` : ""}`
  );
}

// lib/runner/CircuitRunner.ts
var CircuitRunner = class {
  constructor() {
    this._executionContext = null;
    this._circuitRunnerConfiguration = {
      snippetsApiBaseUrl: "https://registry-api.tscircuit.com",
      cjsRegistryUrl: "https://cjs.tscircuit.com",
      verbose: false
    };
    this._eventListeners = {};
  }
  async executeWithFsMap(ogOpts) {
    const opts = { ...ogOpts };
    if (this._circuitRunnerConfiguration.verbose) {
      console.log("[CircuitRunner] executeWithFsMap called with:", {
        entrypoint: opts.entrypoint,
        fsMapKeys: Object.keys(opts.fsMap),
        name: opts.name
      });
    }
    setupDefaultEntrypointIfNeeded(opts);
    this._executionContext = createExecutionContext(
      this._circuitRunnerConfiguration,
      {
        name: opts.name
      }
    );
    this._bindEventListeners(this._executionContext.circuit);
    this._executionContext.fsMap = normalizeFsMap(opts.fsMap);
    if (!this._executionContext.fsMap[opts.entrypoint]) {
      throw new Error(`Entrypoint "${opts.entrypoint}" not found`);
    }
    ;
    globalThis.__tscircuit_circuit = this._executionContext.circuit;
    const entrypoint = opts.entrypoint.startsWith("./") ? opts.entrypoint : `./${opts.entrypoint}`;
    await importEvalPath(entrypoint, this._executionContext);
  }
  async execute(code, opts = {}) {
    if (this._circuitRunnerConfiguration.verbose) {
      console.log(
        "[CircuitRunner] execute called with code length:",
        code.length
      );
    }
    this._executionContext = createExecutionContext(
      this._circuitRunnerConfiguration,
      opts
    );
    this._bindEventListeners(this._executionContext.circuit);
    this._executionContext.fsMap["entrypoint.tsx"] = code;
    globalThis.__tscircuit_circuit = this._executionContext.circuit;
    await importEvalPath("./entrypoint.tsx", this._executionContext);
  }
  on(event, callback) {
    var _a;
    (_a = this._eventListeners)[event] ?? (_a[event] = []);
    this._eventListeners[event].push(callback);
    this._executionContext?.circuit.on(event, callback);
  }
  async renderUntilSettled() {
    if (!this._executionContext) {
      throw new Error("No circuit has been created");
    }
    await this._executionContext.circuit.renderUntilSettled();
  }
  async getCircuitJson() {
    if (!this._executionContext) {
      throw new Error("No circuit has been created");
    }
    return this._executionContext.circuit.getCircuitJson();
  }
  clearEventListeners() {
    if (this._executionContext?.circuit) {
      for (const event in this._eventListeners) {
        for (const listener of this._eventListeners[event]) {
          const circuit = this._executionContext.circuit;
          circuit.removeListener?.(event, listener);
        }
      }
    }
    for (const event in this._eventListeners) {
      delete this._eventListeners[event];
    }
  }
  async kill() {
    this._executionContext = null;
  }
  async setSnippetsApiBaseUrl(baseUrl) {
    this._circuitRunnerConfiguration.snippetsApiBaseUrl = baseUrl;
  }
  _bindEventListeners(circuit) {
    for (const event in this._eventListeners) {
      for (const listener of this._eventListeners[event]) {
        circuit.on(event, listener);
      }
    }
  }
};

export {
  CircuitRunner
};
