rescript-bun icon indicating copy to clipboard operation
rescript-bun copied to clipboard

Bun plugin to run ReScript file

Open nojaf opened this issue 5 months ago • 0 comments

Hi there,

I made a quick proof of concept plugin for Bun:

import { plugin, $ } from "bun";
import path from "bun:path";


await plugin({
    name: "ReScript",
    async setup(build) {
        build.onLoad({filter: /\.res$/}, async (args) => {
            const bscArgs = await $`bunx rescript compiler-args ${args.path}`.json();
            let astFile = bscArgs["compiler_args"].find(a => a.endsWith(".ast"));
            if (!astFile) {
                throw new Error(`No ast file found in bsc args: ${bscArgs}`);
            }

            astFile = path.resolve("lib/bs", astFile);

       
            const parserArgs = bscArgs["parser_args"];
            await $`bunx bsc ${parserArgs}`.cwd("lib/bs");
            

            let extension = bscArgs["compiler_args"].find(a => a.includes("esmodule:"));
            if (extension) {
                extension = extension.split(":").at(-1);
            } else {
                throw new Error(`No extension found in ${bscArgs}`);
            }

            const compilerArgs = bscArgs["compiler_args"];
            const output = await $`bunx bsc ${compilerArgs}`.cwd("lib/bs").nothrow();
            if (output.exitCode === 0) {
                const contents = await Bun.file(args.path.replace(".res", extension)).text();
                return {
                    contents,
                    loader: "js"
                }
            } else {
                throw new Error(`Bsc failed with exit code ${output.exitCode}`);
            }
        })
    }
})

wiring this up in a bunfig.toml

preload = ["./res-loader.js"]

Allows for bun run script/Foo.res to just run in one go! You still need to set everything up as a regular rescript project, but I think it's pretty cool to have this. Would you be interested in a PR for this?

nojaf avatar Jul 19 '25 08:07 nojaf