import crypto from "node:crypto";
import fs from "node:fs/promises";
import path from "pathe";
import { Resource } from "../resource.js";
import { logger } from "../util/logger.js";
/**
 * esbuild Bundle Resource
 *
 * Creates and manages bundled JavaScript/TypeScript files using esbuild.
 * Supports various output formats, sourcemaps, and platform targets.
 *
 * @example
 * // Bundle a TypeScript file for Node.js
 * const bundle = await Bundle("handler", {
 *   entryPoint: "src/handler.ts",
 *   outdir: ".alchemy/.out",
 *   format: "esm",
 *   platform: "node",
 *   target: "node18"
 * });
 */
export const Bundle = Resource("esbuild::Bundle", {
    alwaysUpdate: true,
}, async function (_id, props) {
    if (this.phase === "delete") {
        if (this.output.path) {
            try {
                await fs.rm(this.output.path, { force: true });
            }
            catch (error) {
                if (error instanceof Error && error.message.includes("ENOENT")) {
                    // File doesn't exist, so we can ignore the error
                }
                else {
                    throw error;
                }
            }
        }
        return this.destroy();
    }
    const result = await bundle(props);
    const bundlePath = Object.entries(result.metafile.outputs).find(([_, output]) => {
        if (output.entryPoint === undefined) {
            return false;
        }
        // resolve to absolute and then relative to ensure consistent result (e.g. ./src/handler.ts instead of src/handler.ts)
        const relativeOutput = path.relative(process.cwd(), path.resolve(output.entryPoint));
        return (relativeOutput ===
            path.relative(process.cwd(), path.resolve(process.cwd(), props.entryPoint)));
    })?.[0];
    const outputFile = result.outputFiles?.[0];
    if (outputFile === undefined && bundlePath === undefined) {
        throw new Error("Failed to create bundle");
    }
    if (outputFile) {
        return {
            ...props,
            path: bundlePath,
            hash: outputFile.hash,
            content: outputFile.text,
        };
    }
    const content = await fs.readFile(bundlePath, "utf-8");
    return {
        ...props,
        path: bundlePath,
        hash: crypto.createHash("sha256").update(content).digest("hex"),
        content,
    };
});
export async function bundle(props) {
    const { entryPoint, ...rest } = props;
    const options = {
        ...rest,
        write: !(props.outdir === undefined && props.outfile === undefined),
        // write:
        //   props.outdir === undefined && props.outfile === undefined ? false : true,
        // write: false,
        entryPoints: [entryPoint],
        outdir: props.outdir ? props.outdir : props.outfile ? undefined : ".out",
        outfile: props.outfile,
        bundle: true,
        format: props.format,
        target: props.target,
        minify: props.minify,
        sourcemap: props.sourcemap,
        external: props.external,
        platform: props.platform,
        metafile: true,
    };
    if (process.env.DEBUG) {
        logger.log(options);
    }
    const esbuild = await import("esbuild");
    return await esbuild.build(options);
}
//# sourceMappingURL=bundle.js.map