Bun2Nix
Bun2nix is a fast rust based tool for converting lockfiles generated with the JavaScript Bun (v1.2+) package manager files to Nix expressions, which allows them to be consumed to build Bun packages reproducibly.
Advantages
Here are some of the advantages of using bun/bun2nix over the alternatives:
- Much faster than other similar lang2nix tools for the javascript ecosystem - a full cached install will only take around 50ms for a medium project with 2k packages
- Build aot complied binaries easily with bun that fit the nix model much better than npm scripts
- Quality error messages because of the static types in rust
Alternatives
Here are some alternatives to bun2nix in the JavaScript ecosystem which fulfill a similar purpose:
Installation
Bun2nix is primarily distributed as a nix flake library that contains everything you need to package your bun application with the tool.
This can be setup in two ways:
From A Template
By default 2 templates are offered for starting off a new project with bun2nix enabled by default:
- A minimal hello world binary program - the default.
- A basic react website and server setup.
Notable files
The main files of note are:
flake.nix
⇒ Contains basic project setup for a nix flake forbun2nix
default.nix
⇒ Contains build instructions for this bun packagebun.nix
⇒ Generated bun expression frombun.lock
package.json
⇒ Standard JavaScriptpackage.json
with apostinstall
script pointing tobun2nix
Default - Minimal Setup
To produce the default minimal sample, run:
nix flake init -t github:baileyluTCD/bun2nix
This is a bare-bones project created via bun init
which produces a simple hello world binary packaged via bun2nix.
React Website
To start with the React website template run
nix flake init -t github:baileyluTCD/bun2nix#react
This is a simple example of a basic React app built through bun2nix.
In a pre-existing flake
To install bun2nix in an already existing bun project with a flake.nix
, the following steps are recommended:
1. Source the bun2nix repo
Add the bun2nix
flake to your inputs as follows:
bun2nix.url = "github:baileyluTCD/bun2nix";
bun2nix.inputs.nixpkgs.follows = "nixpkgs";
1.5. (Optional) Use the binary cache
The bun2nix executable typically takes a while to compile, which is typical for many rust programs, hence, because of the garnix based CI/CD, a convenient binary cache is provided.
To add it include the following in your flake.nix
.
nixConfig = {
extra-substituters = [
"https://cache.nixos.org"
"https://cache.garnix.io"
];
extra-trusted-public-keys = [
"cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY="
"cache.garnix.io:CTFPyKSLcx5RMJKfLo5EEPUObbA78b0YQ2DTCJXqr9g="
];
};
2. Add the binary to your environment
Next, add the bun2nix program into your developer environment by adding it to your devshell.
devShells.default = pkgs.mkShell {
packages = with pkgs; [
bun
bun2nix.packages.${system}.default
];
};
NOTE: the
system
variable can be gotten in a variety of convenient ways - including flake-utils or nix-systems.
3. Use the binary in a bun postinstall
script
To keep the generated bun.nix
file produced by bun2nix up to date, add bun2nix
as a postinstall script to run it after every bun operation that modifies the packages in some way.
Add the following to package.json
:
"scripts": {
"postinstall": "bun2nix -o bun.nix"
}
4. Build your package with nix
Finally, a convenient package builder is exposed inside bun2nix
- mkBunDerivation
.
Add the following to flake.nix
:
my-package = pkgs.callPackage ./default.nix {
inherit (bun2nix.lib.${system}) mkBunDerivation;
};
And place this in a file called default.nix
{ mkBunDerivation, ... }:
mkBunDerivation {
pname = "bun2nix-example";
version = "1.0.0";
src = ./.;
bunNix = ./bun.nix;
index = "index.ts";
}
A list of available options for mkBunDerivation
can be seen at the building packages page.
The Command Line Tool
Recommended Usage
The recommended way to use bun2nix
is by adding it to your package.json
to automatically run after any package management option:
"scripts": {
"postinstall": "bun2nix -o bun.nix"
}
However, if you run without the -o
flag it will produce a text output over stdout similar to other lang2nix
tools, hence if you enforce formatting rules in your repository it is likely a good idea to pass it through a formatter before writing the file.
Options
Currently, the options available from the command line tool are as follows:
Convert Bun (v1.2+) packages to Nix expressions
Usage: bun2nix [OPTIONS]
Options:
-l, --lock-file <LOCK_FILE> The Bun (v1.2+) lockfile to use to produce the Nix expression [default: ./bun.lock]
-o, --output-file <OUTPUT_FILE> The output file to write to - if no file location is provided, print to stdout instead
-h, --help Print help
-V, --version Print version
Building Packages
bun2nix
provides a number of functions to aid building bun related packages:
Building with mkBunDerivation
mkBunDerivation
is provided as a library function to build bun packages from the file generated by the bun2nix command line tool.
Example
Currently, basic usage would look something like:
{mkBunDerivation, ...}:
mkBunDerivation {
pname = "simple-bun-app";
version = "1.0.0";
src = ./.;
bunNix = ./bun.nix;
index = "index.ts";
}
or, in the more implicit style:
{mkBunDerivation, ...}:
mkBunDerivation {
packageJson = ./package.json;
src = ./.;
bunNix = ./bun.nix;
}
NOTE: building with the implicit
package.json
values makes a number of basic assumptions about your project that it expects to hold true in the name of convenience. Approximately, these are:
name
is a field that is acceptable for use as the name of the binary produced by your package.version
is a field denoting your package version in proper semantic versioning.module
is a field pointing towards yourindex.ts file or equivalent. If you notice any strange errors while using the implict build scheme try specifying the values manually and contribute a new descriptive assert message to
mkBunDerivation`.
Arguments
The full list of accepted arguments is:
Argument | Purpose |
---|---|
packageJson | (Optional) Your project's package.json . If supplied can be used to complete pname , version and index instead of requiring them manually. |
pname | (Optional) The name of the package to build. Required if packageJson is not given. |
version | (Optional) Your package version. Required if packageJson is not given. |
src | The source code for your package |
bunNix | The file generated by the bun2nix cli |
index | (Optional) The index.{js,ts} file entry point to your bun application. If you do not have one, leave this empty and use a custom buildPhase . This should be a string containing the relative path from src . Required if packageJson is not given. |
buildFlags | Optional flags to pass into bun build in the default buildPhase . By default these flags are [ "--compile" "--minify" "--sourcemap" "--bytecode" ] . If you have issues with your build try removing some of them or read the bun documentation on single file executables. |
dontPatchShebangs | (Optional) Prevent patching shebangs in node_modules scripts. |
writeBunScriptBin
- Create Bun $ Shell Scripts
writeBunScriptBin
is useful for creating once off $ Shell scripts, in a similar manner to writeShellScriptBin
in nixpkgs.
Example
An example bun script for printing "Hello World" might look like:
writeBunScriptBin {
name = "hello-world";
text = ''
import { $ } from "bun";
await $`echo "Hello World!"`;
'';
};
Arguments
The full list of accepted arguments is:
Argument | Purpose |
---|---|
name | The name to give the binary of the script |
text | Textual contents of the script |
Create a valid node_modules
directory with mkBunNodeModules
mkBunNodeModules
is used by mkBunDerivation
for producing the node_modules directory it links to before building the app. When passed the packages
list produced by the bun2nix command line tool, it produces a fully valid node_modules
directory as would be created by a fresh bun install
.
Example
Example usage of mkBunNodeModules
might look like:
bunNix = import ./bun.nix;
node_modules = mkBunNodeModules { packages = bunNix };
Arguments
The full list of accepted arguments is:
Argument | Purpose |
---|---|
packages | The contents of the bun.nix file. |
dontPatchShebangs | (Optional) Prevent patching shebangs in node_modules scripts. |
By default, shebangs in scripts inside node_modules
are patched to use bun
instead of node
. Use dontPatchShebangs = true;
if you want to preserve the original shebangs (for example, to maintain compatibility with tools that expect Node.js).