Skip to content

Latest commit

 

History

History
255 lines (205 loc) · 7.01 KB

README.md

File metadata and controls

255 lines (205 loc) · 7.01 KB

purifix

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;
}

Features

  • 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 by purs.

  • 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.

Installing / Getting purifix

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

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
...

Creating a package

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

Developing using purifix

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.

Using purescript-language-server

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.

Creating an application bundle

(purifix {
  src = ./examples/purescript-package;
}).bundle {
  format = "iife";
  minify = true;
  app = true;
}

Monorepos

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

Running tests

(purifix {
  src = ./examples/local-monorepo;
}).example-purescript-package.test

Running the main module with node

(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.

Generating documentation

You can generate documentation for your package with

(purifix {
  src = ./examples/purescript-package;
}).docs {
  format = "html";
}