"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 __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
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);
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);

// src/index.ts
var src_exports = {};
__export(src_exports, {
  BuiltinPlatform: () => BuiltinPlatform,
  CompileError: () => CompileError,
  PreflightError: () => PreflightError,
  compile: () => compile,
  determineTargetFromPlatforms: () => determineTargetFromPlatforms,
  generateWingDocs: () => generateWingDocs,
  invoke: () => invoke,
  load: () => load
});
module.exports = __toCommonJS(src_exports);

// src/compile.ts
var import_fs = require("fs");
var import_path2 = require("path");
var os = __toESM(require("os"));

// src/util.ts
function normalPath(path) {
  if (process.platform === "win32") {
    return path.replace(/\\+/g, "/");
  } else {
    return path;
  }
}
__name(normalPath, "normalPath");

// src/wingc.ts
var import_wasi_js = __toESM(require("wasi-js"));
var import_path = require("path");
var import_node = __toESM(require("wasi-js/dist/bindings/node"));
var import_child_process = require("child_process");
var import_util2 = require("util");
async function load(options) {
  const { log } = options;
  const fs2 = options.fs ?? require("fs");
  const WINGSDK_MANIFEST_ROOT = options.wingsdkManifestRoot ?? // using resolve.call so webpack will ignore the sdk package
  (0, import_path.resolve)(require.resolve.call(null, "@winglang/sdk"), "../..");
  let preopens = {};
  preopens["/"] = "/";
  preopens["."] = (0, import_path.resolve)(".");
  if (process.platform === "win32") {
    const wmicCommand = await (0, import_util2.promisify)(import_child_process.exec)("wmic logicaldisk get name");
    if (wmicCommand.stderr) {
      throw new Error(`Unable to get available system drives to run WASM compiler: ${wmicCommand.stderr}`);
    }
    const drives = wmicCommand.stdout.split("\r\r\n").filter((value) => /[C-Zc-z]:/.test(value)).map((value) => value.trim());
    for (const drive of drives) {
      try {
        let actualPath = `${drive}\\`;
        await fs2.promises.access(actualPath, fs2.constants.R_OK | fs2.constants.F_OK);
        preopens[`${drive}/`] = actualPath;
      } catch {
      }
    }
  } else {
    const rootDeviceId = await fs2.promises.stat("/").then((stat) => stat.dev.toString());
    const rootFiles = await fs2.promises.readdir("/");
    for (const file of rootFiles) {
      if (file.startsWith(".")) {
        continue;
      }
      const fullPath = `/${file}`;
      const fileStat = await fs2.promises.stat(fullPath)?.catch((err) => {
        log?.(`Failed to stat "${fullPath}": ${err}`);
        return void 0;
      });
      if (
        // ignore anything we can't stat (e.g. broken symlinks)
        fileStat && // include directories and symlinks to directories
        fileStat.isDirectory() && // on mac only preopen directories within the root device
        (process.platform !== "darwin" || fileStat.dev.toString() === rootDeviceId)
      ) {
        try {
          await fs2.promises.access(fullPath, fs2.constants.R_OK | fs2.constants.F_OK);
          preopens[fullPath] = fullPath;
        } catch {
        }
      }
    }
  }
  let dirI = 1;
  while (true) {
    const dir = "../".repeat(dirI++);
    const resolvedDir = (0, import_path.resolve)(dir);
    preopens[dir.slice(0, -1)] = resolvedDir;
    if (resolvedDir === "/" || resolvedDir.match(/^[A-Z]:\\$/i)) {
      break;
    } else if (dirI > 100) {
      throw new Error(`Unable to find root directory to preopen for WASM compiler`);
    }
  }
  preopens = {
    ...preopens,
    ...options.preopens ?? {}
  };
  const bindings = {
    ...import_node.default,
    fs: fs2
  };
  const wasi = new import_wasi_js.default({
    bindings,
    env: {
      ...process.env,
      RUST_BACKTRACE: "full",
      WINGSDK_MANIFEST_ROOT: normalPath(WINGSDK_MANIFEST_ROOT),
      ...options.env ?? {}
    },
    preopens
  });
  const importObject = {
    wasi_snapshot_preview1: wasi.wasiImport,
    env: {
      // This function is used only by the lsp
      send_diagnostic: /* @__PURE__ */ __name(() => {
      }, "send_diagnostic")
    },
    ...options.imports ?? {}
  };
  log?.("compiling wingc WASM module");
  const binary = options.wingcWASMData ?? new Uint8Array(await fs2.promises.readFile((0, import_path.resolve)(__dirname, "../wingc.wasm")));
  const mod = new WebAssembly.Module(binary);
  log?.("instantiating wingc WASM module with importObject: %o", importObject);
  const instance = new WebAssembly.Instance(mod, importObject);
  log?.("starting wingc WASM module");
  wasi.start(instance);
  const exports2 = instance.exports;
  exports2.wingc_init();
  return instance;
}
__name(load, "load");
var LOW_MASK = 2n ** 32n - 1n;
var HIGH_MASK = BigInt(32);
function invoke(instance, func, arg) {
  const exports2 = instance.exports;
  const bytes = new TextEncoder().encode(arg);
  const argPointer = exports2.wingc_malloc(bytes.byteLength);
  const toFree = [
    [
      argPointer,
      bytes.byteLength
    ]
  ];
  try {
    const argMemoryBuffer = new Uint8Array(exports2.memory.buffer, argPointer, bytes.byteLength);
    argMemoryBuffer.set(bytes);
    const result = exports2[func](argPointer, bytes.byteLength);
    if (result === 0 || result === void 0 || result === 0n) {
      return 0;
    } else {
      const returnPtr = Number(result >> HIGH_MASK);
      const returnLen = Number(result & LOW_MASK);
      const entireMemoryBuffer = new Uint8Array(exports2.memory.buffer);
      const extractedBuffer = entireMemoryBuffer.slice(returnPtr, returnPtr + returnLen);
      toFree.push([
        returnPtr,
        returnLen
      ]);
      return new TextDecoder().decode(extractedBuffer) + "";
    }
  } finally {
    toFree.forEach(([pointer, length]) => {
      exports2.wingc_free(pointer, length);
    });
  }
}
__name(invoke, "invoke");

// src/compile.ts
var import_fs2 = require("fs");

// src/constants.ts
var BuiltinPlatform = {
  TF_AWS: "tf-aws",
  TF_AZURE: "tf-azure",
  TF_GCP: "tf-gcp",
  SIM: "sim",
  AWSCDK: "awscdk"
};

// src/errors/compile-error.ts
var _CompileError = class _CompileError extends Error {
  constructor(diagnostics) {
    super("compilation error");
    __publicField(this, "diagnostics");
    this.diagnostics = diagnostics;
  }
};
__name(_CompileError, "CompileError");
var CompileError = _CompileError;

// src/errors/preflight-error.ts
var _PreflightError = class _PreflightError extends Error {
  constructor(causedBy, artifactPath, artifact) {
    super(causedBy.message);
    __publicField(this, "causedBy");
    __publicField(this, "artifactPath");
    __publicField(this, "artifact");
    this.causedBy = causedBy;
    this.artifactPath = artifactPath;
    this.artifact = artifact;
  }
};
__name(_PreflightError, "PreflightError");
var PreflightError = _PreflightError;

// src/compile.ts
var import_promises = require("fs/promises");
var import_child_process2 = require("child_process");
Error.stackTraceLimit = 50;
var WINGC_COMPILE = "wingc_compile";
var WINGC_PREFLIGHT = "preflight.cjs";
var DOT_WING = ".wing";
var BUILTIN_PLATFORMS = [
  BuiltinPlatform.SIM,
  BuiltinPlatform.TF_AWS,
  BuiltinPlatform.TF_AZURE,
  BuiltinPlatform.TF_GCP,
  BuiltinPlatform.AWSCDK
];
var defaultSynthDir = /* @__PURE__ */ __name((model) => {
  switch (model) {
    case BuiltinPlatform.TF_AWS:
      return "tfaws";
    case BuiltinPlatform.TF_AZURE:
      return "tfazure";
    case BuiltinPlatform.TF_GCP:
      return "tfgcp";
    case BuiltinPlatform.SIM:
      return "wsim";
    default:
      return model;
  }
}, "defaultSynthDir");
function resolveSynthDir(outDir, entrypoint, target, testing) {
  const targetDirSuffix = defaultSynthDir(target);
  let entrypointName;
  try {
    const isDirectory = (0, import_fs.lstatSync)(entrypoint).isDirectory();
    if (isDirectory) {
      entrypointName = (0, import_path2.basename)((0, import_path2.resolve)(entrypoint));
    } else {
      entrypointName = (0, import_path2.basename)(entrypoint, ".w");
    }
  } catch (err) {
    if (err.code !== "ENOENT") {
      console.error(err);
    }
    throw new Error("Source file cannot be found");
  }
  const randomPart = testing && target !== BuiltinPlatform.SIM ? `.${Date.now().toString().slice(-6)}` : "";
  const lastPart = `${entrypointName}.${targetDirSuffix}${randomPart}`;
  if (testing) {
    return (0, import_path2.join)(outDir, "test", lastPart);
  } else {
    return (0, import_path2.join)(outDir, lastPart);
  }
}
__name(resolveSynthDir, "resolveSynthDir");
function determineTargetFromPlatforms(platforms) {
  if (platforms.length === 0) {
    return "";
  }
  const platform2 = platforms[0];
  if (BUILTIN_PLATFORMS.includes(platform2)) {
    return platform2;
  }
  const { _loadCustomPlatform } = require("@winglang/sdk/lib/platform");
  return _loadCustomPlatform(platform2).target;
}
__name(determineTargetFromPlatforms, "determineTargetFromPlatforms");
async function compile(entrypoint, options) {
  const { log } = options;
  const preflightLog = options.preflightLog ?? process.stdout.write.bind(process.stdout);
  const targetdir = options.targetDir ?? (0, import_path2.join)((0, import_path2.dirname)(entrypoint), "target");
  const entrypointFile = (0, import_path2.resolve)(entrypoint);
  log?.("wing file: %s", entrypointFile);
  const projectDir = (0, import_path2.resolve)((0, import_path2.dirname)(entrypointFile));
  log?.("wing dir: %s", projectDir);
  const testing = options.testing ?? false;
  log?.("testing: %s", testing);
  const target = determineTargetFromPlatforms(options.platform);
  const synthDir = options.output ?? resolveSynthDir(targetdir, entrypointFile, target, testing);
  log?.("synth dir: %s", synthDir);
  const workDir = (0, import_path2.resolve)(synthDir, DOT_WING);
  log?.("work dir: %s", workDir);
  let wingcErrors = [];
  let failed = false;
  const nearestNodeModules = /* @__PURE__ */ __name((dir) => {
    let nodeModules = (0, import_path2.join)(dir, "node_modules");
    while (!(0, import_fs2.existsSync)(nodeModules)) {
      nodeModules = (0, import_path2.dirname)((0, import_path2.dirname)(nodeModules));
      if (nodeModules === "/" || nodeModules.match(/^[A-Z]:\\/)) {
        break;
      }
      nodeModules = (0, import_path2.resolve)(nodeModules, "node_modules");
    }
    return nodeModules;
  }, "nearestNodeModules");
  let wingNodeModules = nearestNodeModules(projectDir);
  if (!(0, import_fs2.existsSync)(synthDir)) {
    await import_fs.promises.mkdir(workDir, {
      recursive: true
    });
  }
  const compileForPreflightResult = await compileForPreflight({
    entrypointFile,
    workDir,
    projectDir,
    synthDir,
    color: options.color,
    log
  });
  wingcErrors = compileForPreflightResult.diagnostics;
  if (compileForPreflightResult.diagnostics.map((d) => d.severity).includes("error")) {
    failed = true;
  }
  let preflightError;
  if (!failed && isEntrypointFile(entrypoint)) {
    let preflightEnv = {
      ...process.env,
      WING_TARGET: target,
      WING_PLATFORMS: resolvePlatformPaths(options.platform),
      WING_SYNTH_DIR: synthDir,
      WING_SOURCE_DIR: projectDir,
      WING_IS_TEST: process.env["WING_IS_TEST"] ?? testing.toString(),
      WING_VALUES: options.value?.length == 0 ? void 0 : options.value,
      WING_VALUES_FILE: options.values ?? defaultValuesFile(),
      WING_NODE_MODULES: wingNodeModules,
      WING_IMPORTED_NAMESPACES: compileForPreflightResult.compilerOutput?.imported_namespaces.join(";")
    };
    if (options.rootId) {
      preflightEnv.WING_ROOT_ID = options.rootId;
    }
    if (os.platform() === "win32") {
      if ("Path" in preflightEnv) {
        preflightEnv.PATH = preflightEnv.Path;
        delete preflightEnv.Path;
      }
    }
    let [err, finished] = await runPreflightCodeInWorkerThread(compileForPreflightResult.preflightEntrypoint, preflightEnv, (data) => preflightLog?.(data.toString()));
    preflightError = err;
    if (!finished) {
      failed = true;
    }
  }
  return {
    outputDir: !failed ? synthDir : void 0,
    wingcErrors,
    preflightError
  };
}
__name(compile, "compile");
function isEntrypointFile(path) {
  return path.endsWith(".ts") || path.endsWith(".main.w") || path.endsWith(".test.w") || path.endsWith("/main.w") || path.endsWith("\\main.w") || path === "main.w";
}
__name(isEntrypointFile, "isEntrypointFile");
async function compileForPreflight(props) {
  if (props.entrypointFile.endsWith(".ts")) {
    return await compileTypeScriptForPreflight(props);
  } else {
    return await compileWingForPreflight(props);
  }
}
__name(compileForPreflight, "compileForPreflight");
async function compileTypeScriptForPreflight(props) {
  const diagnostics = [];
  let typescriptFramework;
  try {
    typescriptFramework = (await import("@wingcloud/framework")).internal;
  } catch (err) {
    return {
      preflightEntrypoint: "",
      diagnostics: [
        {
          message: `  Failed to load "@wingcloud/framework": ${err.message}
  
  To use Wing with TypeScript files, you must install "@wingcloud/framework" as a dependency of your project.
  npm i @wingcloud/framework
  `,
          severity: "error",
          annotations: [],
          hints: []
        }
      ]
    };
  }
  return {
    preflightEntrypoint: await typescriptFramework.compile({
      workDir: props.workDir,
      entrypoint: props.entrypointFile
    }),
    diagnostics
  };
}
__name(compileTypeScriptForPreflight, "compileTypeScriptForPreflight");
async function compileWingForPreflight(props) {
  let env = {
    RUST_BACKTRACE: "full",
    WING_SYNTH_DIR: normalPath(props.synthDir)
  };
  if (props.color !== void 0) {
    env.CLICOLOR = props.color ? "1" : "0";
  }
  const wingc = await load({
    env,
    imports: {
      env: {
        send_diagnostic
      }
    }
  });
  const diagnostics = [];
  function send_diagnostic(data_ptr, data_len) {
    const data_buf = Buffer.from(wingc.exports.memory.buffer, data_ptr, data_len);
    const data_str = new TextDecoder().decode(data_buf);
    diagnostics.push(JSON.parse(data_str));
  }
  __name(send_diagnostic, "send_diagnostic");
  const arg = `${normalPath(props.entrypointFile)};${normalPath(props.workDir)}`;
  props.log?.(`invoking %s with: "%s"`, WINGC_COMPILE, arg);
  let compilerOutput = "";
  try {
    compilerOutput = invoke(wingc, WINGC_COMPILE, arg);
  } catch (error) {
  }
  return {
    preflightEntrypoint: (0, import_path2.join)(props.workDir, WINGC_PREFLIGHT),
    compilerOutput: JSON.parse(compilerOutput),
    diagnostics
  };
}
__name(compileWingForPreflight, "compileWingForPreflight");
function defaultValuesFile() {
  const defaultConfigs = [
    "wing.toml",
    "wing.yaml",
    "wing.yml",
    "wing.json"
  ];
  for (const configFile of defaultConfigs) {
    if ((0, import_fs2.existsSync)((0, import_path2.join)(process.cwd(), configFile))) {
      return configFile;
    }
  }
  return "";
}
__name(defaultValuesFile, "defaultValuesFile");
async function runPreflightCodeInWorkerThread(entrypoint, env, onStdout) {
  try {
    env.WING_PREFLIGHT_ENTRYPOINT = JSON.stringify(entrypoint);
    return await new Promise((resolve3, reject) => {
      const worker = (0, import_child_process2.fork)((0, import_path2.join)(__dirname, "..", "preflight.shim.cjs"), {
        env,
        stdio: "pipe"
      });
      worker.stdout?.on("data", onStdout);
      worker.stderr?.on("data", onStdout);
      worker.on("message", reject);
      worker.on("error", reject);
      worker.on("exit", (code) => {
        if (code === 0) {
          resolve3([
            void 0,
            true
          ]);
        } else {
          reject(new Error(`Worker stopped with exit code ${code}`));
        }
      });
    });
  } catch (error) {
    const artifact = await (0, import_promises.readFile)(entrypoint, "utf-8");
    return [
      new PreflightError(error, entrypoint, artifact),
      false
    ];
  }
}
__name(runPreflightCodeInWorkerThread, "runPreflightCodeInWorkerThread");
function resolvePlatformPaths(platform2) {
  const resolvedPluginPaths = [];
  for (const plugin of platform2) {
    if (plugin.startsWith("@")) {
      resolvedPluginPaths.push(plugin);
      continue;
    }
    resolvedPluginPaths.push((0, import_path2.resolve)(process.cwd(), plugin));
  }
  return resolvedPluginPaths.join(";");
}
__name(resolvePlatformPaths, "resolvePlatformPaths");

// src/generateDocs.ts
var WINGC_GENERATE_DOCS = "wingc_generate_docs";
async function generateWingDocs(props) {
  let env = {
    RUST_BACKTRACE: "full"
  };
  if (props.color !== void 0) {
    env.CLICOLOR = props.color ? "1" : "0";
  }
  const wingc = await load({
    env,
    imports: {
      env: {
        send_diagnostic
      }
    }
  });
  const diagnostics = [];
  function send_diagnostic(data_ptr, data_len) {
    const data_buf = Buffer.from(wingc.exports.memory.buffer, data_ptr, data_len);
    const data_str = new TextDecoder().decode(data_buf);
    diagnostics.push(JSON.parse(data_str));
  }
  __name(send_diagnostic, "send_diagnostic");
  const arg = normalPath(props.projectDir);
  props.log?.(`invoking %s with: "%s"`, WINGC_GENERATE_DOCS, arg);
  let docsContents = "";
  const result = invoke(wingc, WINGC_GENERATE_DOCS, arg);
  if (typeof result === "number") {
  } else {
    docsContents = result;
  }
  return {
    docsContents,
    diagnostics
  };
}
__name(generateWingDocs, "generateWingDocs");
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  BuiltinPlatform,
  CompileError,
  PreflightError,
  compile,
  determineTargetFromPlatforms,
  generateWingDocs,
  invoke,
  load
});
