Rescript 12 monorepo with Bun

Hi!

I was just testing bun with rescript 12 RC in a monorepo setup, did the workspaces in package.json, listed the package dependencies in the root rescript.json and got this error when building:

We could not build package tree reading dependency 'starter', at path '<redacted>'. Error: try_package_path: upward traversal did not find 'starter' starting at '<redacted>'

Just wanted to share, by default bun uses isolated installs like pnpm I believe, and it wasn’t creating symlinks to the workspace packages in node_modules, which rescript 12 (rewatch) needs.

To solve this in an automated way (no manual symlinks) and without changing the bun linker to hoisted, I decided to add the packages to the dependencies in the root package.json like so:

  "dependencies": {
    "starter": "workspace:*"
  },

Which then when bun install it will make a symlink from the root node_modules/starter to the packages/starter folder. Then rescript works just fine.

Just sharing in case anyone else hits this issue or someone has other solutions. Here is a summary of how it looks like:

ReScript Monorepo Setup with Bun Workspaces

Directory Structure

.
├── bun.lock
├── package.json
├── rescript.json
└── packages
    └── starter
        ├── package.json
        ├── rescript.json
        └── src
            ├── Demo.res
            └── Demo.res.mjs

Root package.json

{
  "name": "monorepo",
  "private": true,
  "workspaces": {
    "packages": [
      "packages/*"
    ],
    "catalog": {
      "rescript": "^12.0.0-rc.3"
    }
  },
  "scripts": {
    "build": "rescript build",
    "clean": "rescript clean",
    "dev": "rescript watch",
    "format": "rescript format -all",
  },
  "dependencies": {
    "@monorepo/starter": "workspace:*"
  },
  "devDependencies": {
    "rescript": "catalog:"
  },
}

Root rescript.json

{
  "name": "monorepo",
  "sources": [],
  "package-specs": {
    "module": "esmodule",
    "in-source": true
  },
  "suffix": ".res.mjs",
  "dependencies": ["@monorepo/starter"],
  "compiler-flags": []
}

Package package.json (packages/starter/package.json)

{
  "name": "@monorepo/starter",
  "version": "0.0.0",
  "description": "ReScript starter package",
  "main": "src/Demo.res.mjs"
}

Package rescript.json (packages/starter/rescript.json)

{
  "name": "@scope/starter",
  "sources": {
    "dir": "src",
    "subdirs": true
  },
  "package-specs": {
    "module": "esmodule",
    "in-source": true
  },
  "suffix": ".res.mjs",
  "dependencies": [],
  "compiler-flags": []
}

Adding New Packages

  1. Create directory in packages/new-package/
  2. Add to root package.json dependencies: "@monorepo/new-package": "workspace:*"
  3. Add to root rescript.json dependencies: ["@monorepo/new-package"]
  4. Run bun install to create symlinks

And a couple of links that helped me out:

Let me know how y’all do it!

2 Likes

FYI: “isolated installs” have been added in bun 1.3, but they thinking about to change the default behavior back to “hoisted” and it’s also configurable (as stated in you link).

Yes, I recently had to add

[install]
linker = "hoisted"

as well to my bunfig.toml because rescript stopped working.
Could you please send a PR with your sample to GitHub - rescript-lang/end-to-end: Sanity checks for end users setups
Will take a look at it then.

Thx!

1 Like

What would the repo with the repro be useful for? to reproduce the error message and improve it? The solution is an unfortunate interaction between rescript/rewatch and bun 1.3.x, so I don’t think there is anything rescript itself can improve besides the error message.

Cool repo though, I’m learning a few things already.


For example today I had some issues because Bun only recognices certain extensions and when you use the recommended suffix of .res.js then any *.test.res.js or *_test.res.js don’t get recognized when you run bun test. source

There are two workarounds I considered, one, is to change the suffix of the compiled files from .res.js to .js, but that makes me scared of running rescript clean and all my .js files I have in the project getting nuked. Maybe it is not an issue?

The other workaround I went with for now is to make a package.json script that does:

    "test": "bun test ./packages/*/src/**/*_test.res.js",
    "test:watch": "bun test --watch ./packages/*/src/**/*_test.res.js"

Which uses shell expansion with relative paths (the ./ at the start was necessary) and then bun does run the test files even if they don’t match the paths it wants. But I guess this won’t detect new test files when added, sadly.

I see in your repo you are running with "suffix": ".js", source, are there any gotchas to that?

We’d like to support Bun 1.3 out of the box with ReScript. A small reproducer where it fails makes it much easier to start investigating. I’m part of the ReScript core team and worked on the new build system, and I’m a Bun user, so I have a stake in this. My time is limited, so the more ready-to-investigate samples there are, the easier it is for me to dive in. Once the problem is fixed, we can keep it working over time by using this end-to-end repo.

Not really. When running rescript clean, files without matching .res will not be removed, so you don’t need to worry about regular JS files being deleted. I used .js so Bun would pick up the tests. It might also be configurable via bunfig.toml, I didn’t check.

1 Like