README.org
March 19, 2026 · View on GitHub
#+title: mkSpagoDerivation #+author: James Leslie [[https://img.shields.io/badge/built%20for-PureScript-1d222d.svg]][[https://img.shields.io/github/license/jeslie0/mkelmderivation.svg]][[https://img.shields.io/github/actions/workflow/status/jeslie0/mkSpagoDerivation/run_tests.yaml.svg]][[https://img.shields.io/github/v/release/jeslie0/mkSpagoDerivation.svg]]
This Nix flake provides an unopinionated approach to packaging [[https://github.com/purescript/purescript][PureScript]] projects with the [[https://github.com/NixOS/nixpkgs][Nix]] package manager. This project works by treating a PureScript project's =spago.lock= as a single source of truth for dependencies and extracting the required information from [[https://github.com/purescript/registry][PureScript's registry]].
- Table of contents :toc:
- [[#examples][Examples]]
- [[#caching-dependency-build-artefacts][Caching dependency build artefacts]]
- [[#out-of-date-registry][Out of date registry]]
- [[#limitations][Limitations]]
- [[#notes][Notes]]
- [[#hooks][Hooks]]
- [[#related][Related]]
- [[#license][License]]
- Examples
The most important function that this flake provides is the
mkSpagoDerivationfunction, exposed as both an output and via an overlay. This provides a wrapper aroundstdenv.mkDerivationwhich puts all of your project's dependencies in the right place, making it easy for you to build your projects in a reproducible way.
Importantly, the =spago.lock= file is required for mkSpagoDerivation to determine your project's dependencies. Optionally, if you provide your project's =spago.yaml= file, then your project's name will be extracted and used. You can provide a =name= or =pname= argument instead.
Here is a simple =flake.nix= that builds a PureScript project. #+begin_src nix { inputs = { nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable"; flake-utils.url = "github:numtide/flake-utils"; mkSpagoDerivation.url = "github:jeslie0/mkSpagoDerivation"; ps-overlay.url = "github:thomashoneyman/purescript-overlay"; };
outputs = { self, nixpkgs, flake-utils, mkSpagoDerivation, ps-overlay }: flake-utils.lib.eachDefaultSystem ( system: let pkgs = import nixpkgs { inherit system; overlays = [ mkSpagoDerivation.overlays.default ps-overlay.overlays.default ]; }; in { packages.default = pkgs.mkSpagoDerivation { spagoYaml = ./spago.yaml; spagoLock = ./spago.lock; src = ./.; nativeBuildInputs = [ pkgs.purs-unstable pkgs.spago-unstable pkgs.esbuild ]; version = "0.1.0"; buildPhase = "spago bundle"; installPhase = "mkdir out"; buildNodeModulesArgs = { npmRoot = ./.; nodejs = pkgs.nodejs; }; }; } ); } #+end_src
The only attribute mkSpagoDerivation requires is src. The spagoYaml attribute will default to ={src}/spago.lock=. Everything else is passed into mkDerivation.
Some Spago projects have dependencies from NPM. To automatically take care of fetching NPM packages, the buildNodeModulesArgs
attribute allows specifing an argument set that is passed to the [[https://nixos.org/manual/nixpkgs/unstable/#javascript-buildNpmPackage-importNpmLock.buildNodeModules][importNpmLock.buildNodeModules]] function. This will build a =node_modules= directory for use in the derivation. See the [[./tests/nodeModulesTest][nodeModulesTest]] for an example. This attribute is completely optional and can be left out of the =mkSpagoDerivation= arguments if no node_modules directory is required.
There are no assumptions about the which version of the compiler is used - you must specify which copy of Spago and PureScript you want to use. Dependencies can be added through buildInputs or nativeBuildInputs. The following example demonstrates this, by using [[https://github.com/aristanetworks/purescript-backend-optimizer][purescript-backend-optimizer]] and using the unstable PureScript compiler from the PureScript Overlay.
#+begin_src nix
{
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
flake-utils.url = "github:numtide/flake-utils";
ps-overlay.url = "github:thomashoneyman/purescript-overlay";
mkSpagoDerivation.url = "github:jeslie0/mkSpagoDerivation";
};
outputs = { self, nixpkgs, flake-utils, ps-overlay, mkSpagoDerivation }: flake-utils.lib.eachDefaultSystem ( system: let pkgs = import nixpkgs { inherit system; overlays = [ mkSpagoDerivation.overlays.default ps-overlay.overlays.default ]; }; in { packages.default = pkgs.mkSpagoDerivation { spagoYaml = ./spago.yaml; spagoLock = ./spago.lock; src = ./.; version = "0.1.0"; nativeBuildInputs = [ pkgs.esbuild pkgs.purs-backend-es pkgs.purs-unstable pkgs.spago-unstable ]; buildPhase = "spago build && purs-backend-es bundle-app --no-build --minify --to=main.min.js"; installPhase = "mkdir out"; }; } ); } #+end_src
Some other useful functions are exposed. One is buildDotSpago, which builds a project's =.spago= directory. It takes an attribute set { spagoLock, src }, which respectively are the paths to the project's spago.lock and the root of the project. Another useful function is buildSpagoNodeJs, which builds the =spago-nodejs= directory, typically located in the user's =.cache= directory.
-
Caching dependency build artefacts mkSpagoDerivation is unopinionated and allows for a user to customise the way they build their projects. As projects get larger and require more dependencies, rebuilding all of them can add a lot of wasted time to nix builds. Spago does allow for caching the build artefacts for a project's dependencies and this can be integrated into a nix build. The general approach is to create a separate derivation that whose source is only the =spago.yaml= and =spago.lock= files, using
spago installas the build phase. An example of this can be found in the [[file:tests/cache/default.nix][cache test]]. -
Out of date registry It is possible for this repository to not have the most up-to-date registry set. If you cant wait for the GitHub action to update this repository, you can override the =registry= and =registry-index= inputs to this flake. #+begin_src nix { inputs = { nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable"; flake-utils.url = "github:numtide/flake-utils"; ps-overlay.url = "github:thomashoneyman/purescript-overlay"; mkSpagoDerivation = { url = "github:jeslie0/mkSpagoDerivation"; inputs = { registry.url = "github:purescript/registry/066f77d3b668fd7916e0af493d8d8ec7a850d774"; registry-index.url = "github:purescript/registry-index/53cfacb3b1677120eb5e6c11a1f2449d1049c2ce"; }; }; };
outputs = { self, nixpkgs, flake-utils, ps-overlay, mkSpagoDerivation }: ... #+end_src
-
Limitations At the time of writing, this project only supports PureScript projects that make use of the newer spago@next releases. In particular, the project needs a
spago.yamlfile and aspago.lockfile is required too. -
Notes ** Hooks The
buildPhaseandinstallPhasealways run =pre= and =post= hooks, even if the commands provided by the user don't specify them. -
Related
- [[https://github.com/purifix/purifix/][purifix]] A different tool to package PureScript programs with Nix.
- [[https://github.com/justinwoo/spago2nix][spago2nix]] Another tool for packaging PureScript programs with Nix.
- [[https://github.com/justinwoo/easy-purescript-nix][easy-purescript-nix]] A repository and Nix flake that provides lots of PureScript tools.
- [[https://github.com/purs-nix/purs-nix][purs-nix]] A tool for Nix based PureScript development.
- [[https://github.com/jeslie0/mkElmDerivation][mkElmDerivation]] A similar tool (that I created) to package [[https://elm-lang.org/][Elm]] applications with Nix.
- License All of this repository is under the MIT license.