Purs-nix - manage PureScript projects with Nix

purs-nix is a PureScript build tool written in Nix with the goal of being able to manage your PureScript projects with just Nix, as well as easily being able to incorporate PureScript into bigger Nix builds. It’s currently unstable but far enough along that it can be used.

It has it’s own package set with some niceties that the standard package set currently lacks:

  • package namespaces
  • single source of truth for package info: you can store your package info in it’s own repository and just tell purs-nix where to look.
  • Module names are not required to be unique: an easy-to-use fix for the issues this could create is planned.

Despite having it’s own package set, non-namespaced packages will still comply with the registry.

If you’ve never used Nix before and are interested in giving it a try, I have some instructions to help you set it up in the repo!

There’s currently no FAQ or How To section, I would love to get feedback on what people find confusing/would like to see examples of.

repo: https://github.com/ursi/purs-nix

14 Likes

First of all, great project. I might try this out later next week (wanted to switch my build process to Nix anyway).

One thing I’m not sure about is the custom package set. Is there a good reason for at least not, say, extending or adapting the official package sets?

I’d also suggest adding a (possibly really short) reasoning why one would use this instead of nodejs/spago/bower/… I’m not sure everybody knows Nix and why it’s great. Not that you have to explain Nix or anything, just in the context of this package…

3 Likes

Great stuff! I’m happy to see more nix tooling around Purescript!

Just yesterday I setup nix tooling for a Purescript project using Justin Woo’s easy-purescript-nix. It was painless, and might also be a good option for those who want to use nix with spago and the official package set ecosystem.

So I had my reasons for this but when writing them out I realized you’re right. I think the best approach would be to set up some code gen for the official package set as a base, and then override it where appropriate with the setup I have now. Not sure when I’ll get around to setting that up though, cuz manually adding a new package is pretty painless.

I think purs-nix is mostly for people that already use nix, or for people that want more freedom with publishing packages, and I think I already make a case to both of those crowds pretty well. Short of just trying to sell nix itself, I’m not sure what else I could say. If you don’t have any interest in nix and don’t have any problems with the official package set, I’m not sure you have any reason to switch - at least not with the current feature set (that could change in the future). That being said, I’m open to suggestions.

2 Likes

One advantage purs-nix currently has over spago2nix it that has incremental builds! Afaik with spago2nix you need to recompile the whole project every time you make a change.

6 Likes

Okay that’s nice! I second the request to support the official package set though.

2 Likes

I didn’t even know there was spago2nix. Maybe you can add a section to the readme mentioning it (and possibly easy-purescript-nix).

Other than that, I totally agree that your target audience is Nix people.

2 Likes

Codegen for the official package set has been added!

3 Likes

Nix stable is now supported! flakes are no longer a requirement

6 Likes

purs-nix now supports packaging foreign JS code with your modules! No more needing to add a dependency and then separately manage the node.js dependencies required for it to work! (as long as the package author has added support for it)

6 Likes

Great to see that project is moving forward! Thanks for the great work to all the Devs!

2 Likes

Hello,

Great project so far! It made it pretty easy to get started with nix and purescript build a todomvc, although I’m still pretty new to both.

I’m moving on to building something with both a client and a server, but I couldn’t figure out how to set that up with purs-nix. Any suggestions would be great!

Currently, I’m have a Client.Main and Server.Main. I can bundle the client just fine, and I can create a script that sources output/ServerMain for the server. Does that sound right? Is there a better way?

3 Likes

this is a very fresh topic for me as I have just started doing this myself! my current setup, has my purescript code split across three directories. font for the frontend code, back for the backend code, and middle for the code I’m sharing between them. I have these two declarations for the server and client

front =
  purs
    { dependencies = [ ... ];
      dir = ./.;
      srcs = [ "front" "middle" ];
    };

back =
  purs
    { dependencies = [ ... ];
      dir = ./.;
      srcs = [ "back" "middle" ];
    };

and in my devshell I have these

front.command { name = "front"; ... }

back.command { name = "back"; ... }

so to run my server I just go back run, to bundle the frontend I do front bundle. I have aliases set up using entr for automatically running things when files change.

3 Likes

Here is what I ended up doing conduit-purescript/flake.nix at master · BerkeleyTrue/conduit-purescript · GitHub

I create a script bin file

          conduit-server = pkgs.writeShellScriptBin "conduit-server" ''
            set -x
            ${lib.getExe pkgs.bun} --hot src/server/main.js
          '';

I added it as an overlay then I add that to the devShell packages. I can just run conduit-server in the dev shell. I’m using bun here as a trail. It has built in hot module reloading and it seems to be pretty compatible with built in nodejs modules.

The client side is just as per docs.

esbuild has a built in watch mode, but I couldn’t figure out hot to get the bundled esbuild to watch. What’s the reason there?

well watching with just esbuild isn’t enough because the purescript code needs to be compiled before it’s handed off to esbuild. what exactly do you mean by “the bundled esbuild”?

1 Like

fyi you’re doing dependencies the old way. it is idiomatic to use strings now. derivation dependencies are still a thing, but they have a specific use case now. see here

1 Like

I just meant the bundle command in purs-nix bundle

Hmm, I guess I’m not familiar with the how the build pipeline is structured. From past experience I would have the compile and bundle steps act independently. But I can how if they are more integrated, you could get a better outcome.

Do you mean this section?

          ps = purs-nix.purs {
            dependencies = with purs-nix.ps-pkgs; [
              console
              effect
              prelude

              # client
              halogen
              halogen-hooks
              halogen-helix

              # server
              httpurple
            ];

They should be strings? Is it just idiomatic or some design reason?

I’m not sure what this means. I find the whole overlays/derivations still confusing.

They should be strings? Is it just idiomatic or some design reason?

It’s idiomatic because using an actual package derivation as a dependency has a special meaning in a particular circumstance. But if you’re not making a package, then there is not difference.

Also, I see that I forgot to update this in the templates, so no wonder people are still not using strings.

1 Like

Ah ok. Thanks for the info. That is good to keep in mind.