From a064709342b6adfcafe5bdcff3b5ace453359761 Mon Sep 17 00:00:00 2001 From: "Shahar \"Dawn\" Or" Date: Wed, 12 Jul 2023 18:50:47 +0700 Subject: nixpkgs/NixOS manuals: devmode feature Co-authored-by: Alejandro Sanchez Medina --- pkgs/tools/nix/web-devmode.nix | 117 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 pkgs/tools/nix/web-devmode.nix (limited to 'pkgs/tools/nix/web-devmode.nix') diff --git a/pkgs/tools/nix/web-devmode.nix b/pkgs/tools/nix/web-devmode.nix new file mode 100644 index 0000000000000..6ebdc31118f0e --- /dev/null +++ b/pkgs/tools/nix/web-devmode.nix @@ -0,0 +1,117 @@ +{ + pkgs, + # arguments to `nix-build`, e.g. `"foo.nix -A bar"` + buildArgs, + # what path to open a browser at + open, +}: let + inherit (pkgs) lib; + + error_page = pkgs.writeShellScriptBin "error_page" '' + echo " + + + + +
$1
+ " + ''; + + # The following would have been simpler: + # 1. serve from `$serve` + # 2. pass each build a `--out-link $serve/result` + # But that way live-server does not seem to detect changes and therefore no + # auto-reloads occur. + # Instead, we copy the contents of each build to the `$serve` directory. + # Using rsync here, instead of `cp`, to get as close to an atomic + # directory copy operation as possible. `--delay-updates` should + # also go towards that. + build_and_copy = pkgs.writeShellScriptBin "build_and_copy" '' + set -euxo pipefail + + set +e + stderr=$(2>&1 nix-build --out-link $out_link ${buildArgs}) + exit_status=$? + set -e + + if [ $exit_status -eq 0 ]; + then + # setting permissions to be able to clean up + ${lib.getBin pkgs.rsync}/bin/rsync \ + --recursive \ + --chmod=u=rwX \ + --delete-before \ + --delay-updates \ + $out_link/ \ + $serve/ + else + set +x + ${lib.getBin error_page}/bin/error_page "$stderr" > $error_page_absolute + set -x + + ${lib.getBin pkgs.findutils}/bin/find $serve \ + -type f \ + ! -name $error_page_relative \ + -delete + fi + ''; + + # https://watchexec.github.io/ + watcher = pkgs.writeShellScriptBin "watcher" '' + set -euxo pipefail + + ${lib.getBin pkgs.watchexec}/bin/watchexec \ + --shell=none \ + --restart \ + --print-events \ + ${lib.getBin build_and_copy}/bin/build_and_copy + ''; + + # A Rust alternative to live-server exists, but it was not in nixpkgs. + # `--no-css-inject`: without this it seems that only CSS is auto-reloaded. + # https://www.npmjs.com/package/live-server + server = pkgs.writeShellScriptBin "server" '' + set -euxo pipefail + + ${lib.getBin pkgs.nodePackages_latest.live-server}/bin/live-server \ + --host=127.0.0.1 \ + --verbose \ + --no-css-inject \ + --entry-file=$error_page_relative \ + --open=${open} \ + $serve + ''; + + devmode = + pkgs.writeShellScriptBin "devmode" + '' + set -euxo pipefail + + function handle_exit { + rm -rf "$tmpdir" + } + + tmpdir=$(mktemp -d) + trap handle_exit EXIT + + export out_link="$tmpdir/result" + export serve="$tmpdir/serve" + mkdir $serve + export error_page_relative=error.html + export error_page_absolute=$serve/$error_page_relative + ${lib.getBin error_page}/bin/error_page "building …" > $error_page_absolute + + ${lib.getBin pkgs.parallel}/bin/parallel \ + --will-cite \ + --line-buffer \ + --tagstr '{/}' \ + ::: \ + "${lib.getBin watcher}/bin/watcher" \ + "${lib.getBin server}/bin/server" + ''; +in + devmode -- cgit 1.4.1