Build PureScript projects from a spago.yaml
file with a Nix
function instead of spago
.
Like with spago
, with purifix
your spago.yaml
file acts as a
single source of truth. When you change spago.yaml
you don’t
need to change the Nix expression, purifix
automatically picks up
the changes.
For example, this is how you would build the PureScript package
./examples/purescript-package/
with purifix
:
purifix {
src = ./examples/purescript-package;
}
-
spago.yaml
as single source of truth. -
Compiles all package sets on the PureScript registry.
-
Support for multiple PureScript backends.
-
Support for bundling with
esbuild
. -
Incremental compilation (that is, you only compile
prelude
once)This is done by manually merging the
cache-db.json
file generated bypurs
. -
Support for running tests with Node.js.
-
Support for running the main module.
-
Support for generating documentation and outputting markdown or html for your package and all of its dependencies.
-
Support for monorepos and local packages installed from the file system.
-
Support for entering a development shell where you can quickly compile your package sources.
The purifix
function lives in this repo, and the recommended installation procedure is to include this flake and add the exported overlay to overlays when importing nixpkgs.
A simple package could be installed in a flake.nix file like below:
{
inputs = {
nixpkgs = {
url = "github:NixOS/nixpkgs";
};
purifix = {
url = "github:purifix/purifix";
};
flake-utils = {
url = "github:numtide/flake-utils";
};
};
outputs = inputs:
inputs.flake-utils.lib.eachDefaultSystem (system:
let
pkgs = import inputs.nixpkgs {
inherit system;
overlays = [ inputs.purifix.overlay ];
};
my-package = pkgs.purifix {
src = ./.;
};
in
{
packages = {
default = my-package;
};
defaultPackage = my-package;
});
}
You can also use purifix
without flakes by importing the purifix
function like so:
let
purifix = import (builtins.fetchGit "https://github.com/purifix/purifix.git") {};
in purifix {
src = ./.;
}
It's recommended to pin the fetched purifix
commit using the rev
attribute so
that your builds remain reproducible.
Building the derivation produced by purifix
is as simple as calling
nix-build
on it. Here is how you would build the example PureScript package
in this repo:
$ nix-build ./nix/examples.nix -A purifix-example
...
/nix/store/iyk9zzl7bwyvij4s67529xcmqlr3nqil-example-purescript-package-0.0.1
This produces an output with a single directory output/
. output/
contains
all the transpiled PureScript code:
$ tree /nix/store/hjcxs72xkjm4qad78railg6kflbljpcz-example-purescript-package-0.0.1
/nix/store/hjcxs72xkjm4qad78railg6kflbljpcz-example-purescript-package-0.0.1
└── output
├── cache-db.json
├── Control.Alt
│ ├── docs.json
│ ├── externs.cbor
│ └── index.js
├── Control.Alternative
│ ├── docs.json
│ ├── externs.cbor
...
This repository contain some example packages to show how to get
started using purifix
to build your PureScript sources. Below is a minimal
spago.yaml
defining how to build all the PureScript in the src directory.
Required fields are name
, version
, dependencies
and package_set
.
package:
name: example-purescript-package
version: 0.0.1
dependencies: [ "console", "effect", "foldable-traversable", "prelude"]
workspace:
package_set:
registry: 11.3.0
To create a development shell where you can easily compile your package sources
without having to wait for a full nix build
you can run nix develop
or
nix-shell
on the develop
attribute of your purifix
package.
(purifix {
src = ./examples/purescript-package;
}).develop
This will place you in a shell where you have the purifix
executable. This executable
will copy the precompiled dependencies to the output
directory and then only compile your
package-specific files.
$ purifix src/Main.purs
will compile the Main.purs
file and place the result in the output
directory together with
the precompiled dependencies.
You can use purescript-language-server
with purifix
. Make sure that you
include spago.yaml
when finding the root of your PureScript package.
Below is an example of configuring coc.nvim to use the purescript-language-server.
"purescript": {
"command": "purescript-language-server",
"args": ["--stdio"],
"filetypes": ["purescript"],
"trace.server": "off",
"rootPatterns": ["spago.yaml", "psc-package.json", "spago.dhall"],
"settings": {
"purescript": {
"addSpagoSources": true,
"addNpmPath": true
}
}
}
Before you load your project with the purescript-language-server
it can be
useful to run purifix
in the development shell so that you don't have to
compile all your dependencies again.
(purifix {
src = ./examples/purescript-package;
}).bundle {
format = "iife";
minify = true;
app = true;
}
You can use purifix
with monorepos containing multiple PureScript packages.
If your src
directory contains more than one package purifix
will return an
attribute set from package name to package. Set the src
attribute of the call
purifix
to the root of your repository and let purifix
search for your nested packages.
If your individual packages do not contain a workspace
field to specify which package
set to use purifix
will try to parse workspace
from a spago.yaml
file in the root
of your src
folder.
(purifix {
src = ./examples/local-monorepo;
}).example-purescript-package
(purifix {
src = ./examples/local-monorepo;
}).example-purescript-package.test
(purifix {
src = ./examples/local-monorepo;
}).example-purescript-package.run
$ nix build .#example-registry-package-run --out-link result
$ ./result/bin/example-purescript-package
🍝
1337
This can also be packaged as an app in a flake. The executable is given the same name as the package.
You can generate documentation for your package with
(purifix {
src = ./examples/purescript-package;
}).docs {
format = "html";
}