|
7 | 7 | }; |
8 | 8 |
|
9 | 9 | outputs = { self, nixpkgs, flake-utils }: |
| 10 | + let |
| 11 | + # Overlay that adds probitas to pkgs |
| 12 | + overlay = final: prev: { |
| 13 | + probitas = prev.writeShellApplication { |
| 14 | + name = "probitas"; |
| 15 | + runtimeInputs = [ prev.deno ]; |
| 16 | + text = '' |
| 17 | + export DENO_NO_UPDATE_CHECK=1 |
| 18 | + exec deno run -A \ |
| 19 | + --unstable-kv \ |
| 20 | + --config=${self}/deno.json \ |
| 21 | + --frozen --lock=${self}/deno.lock \ |
| 22 | + ${self}/mod.ts "$@" |
| 23 | + ''; |
| 24 | + }; |
| 25 | + }; |
| 26 | + in |
10 | 27 | { |
11 | 28 | # Overlay for easy integration |
12 | | - overlays.default = final: prev: { |
13 | | - inherit (self.packages.${final.stdenv.hostPlatform.system}) probitas; |
14 | | - }; |
| 29 | + overlays.default = overlay; |
15 | 30 | } |
16 | 31 | // |
17 | 32 | flake-utils.lib.eachDefaultSystem (system: |
18 | 33 | let |
19 | | - pkgs = import nixpkgs { inherit system; }; |
20 | | - |
21 | | - # Map Nix platform to npm's os/cpu values (Node.js process.platform/process.arch) |
22 | | - npmPlatform = { |
23 | | - os = |
24 | | - if pkgs.stdenv.hostPlatform.isDarwin then "darwin" |
25 | | - else if pkgs.stdenv.hostPlatform.isLinux then "linux" |
26 | | - else null; |
27 | | - cpu = |
28 | | - if pkgs.stdenv.hostPlatform.isAarch64 then "arm64" |
29 | | - else if pkgs.stdenv.hostPlatform.isx86_64 then "x64" |
30 | | - else null; |
31 | | - }; |
32 | | - |
33 | | - # Use `deno cache --vendor` for deterministic output instead of $DENO_DIR cache. |
34 | | - # The cache approach (`deno install` alone) is non-deterministic due to: |
35 | | - # - JSR cache metadata with timestamps (normalizing breaks cache lookup) |
36 | | - # - SQLite databases with non-deterministic page ordering (deleting causes re-downloads) |
37 | | - deps = pkgs.stdenvNoCC.mkDerivation { |
38 | | - name = "probitas-deps"; |
39 | | - src = pkgs.lib.cleanSource ./.; |
40 | | - nativeBuildInputs = with pkgs; [ |
41 | | - deno |
42 | | - jq |
43 | | - writableTmpDirAsHomeHook |
44 | | - ]; |
45 | | - # Remove os/cpu fields from deno.lock for cross-platform deterministic hash |
46 | | - postPatch = '' |
47 | | - jq ' |
48 | | - if .npm then |
49 | | - .npm |= map_values(del(.os, .cpu)) |
50 | | - else . |
51 | | - end |
52 | | - ' deno.lock > deno.lock.tmp |
53 | | - mv deno.lock.tmp deno.lock |
54 | | - ''; |
55 | | - installPhase = '' |
56 | | - runHook preInstall |
57 | | -
|
58 | | - mkdir -p $out |
59 | | - # vendor dependencies for deterministic output |
60 | | - deno cache --vendor --frozen mod.ts jsr:@probitas/probitas@^0 |
61 | | -
|
62 | | - cp -r vendor node_modules $out/ |
63 | | -
|
64 | | - runHook postInstall |
65 | | - ''; |
66 | | - outputHashAlgo = "sha256"; |
67 | | - outputHashMode = "recursive"; |
68 | | - outputHash = "sha256-7/6p+Gcglet123zKj8ixFaeQHbMdI53b3kXNBnuafuQ="; |
| 34 | + pkgs = import nixpkgs { |
| 35 | + inherit system; |
| 36 | + overlays = [ overlay ]; |
69 | 37 | }; |
70 | 38 | in |
71 | 39 | { |
72 | 40 | packages = { |
73 | | - default = self.packages.${system}.probitas; |
74 | | - probitas = pkgs.stdenvNoCC.mkDerivation (finalAttrs: { |
75 | | - pname = "probitas"; |
76 | | - version = self.shortRev or self.dirtyShortRev or "dev"; |
77 | | - src = pkgs.lib.cleanSource ./.; |
78 | | - |
79 | | - postPatch = '' |
80 | | - substituteInPlace deno.json \ |
81 | | - --replace-fail '"version": "0.0.0"' '"version": "${finalAttrs.version}"' |
82 | | - ''; |
83 | | - |
84 | | - nativeBuildInputs = with pkgs; [ |
85 | | - deno |
86 | | - jq |
87 | | - makeBinaryWrapper |
88 | | - ] ++ pkgs.lib.optionals pkgs.stdenv.hostPlatform.isLinux [ |
89 | | - autoPatchelfHook |
90 | | - ]; |
91 | | - |
92 | | - installPhase = '' |
93 | | - runHook preInstall |
94 | | -
|
95 | | - mkdir -p $out/share/probitas |
96 | | - cp -r src assets $out/share/probitas/ |
97 | | - cp mod.ts deno.json deno.lock $out/share/probitas/ |
98 | | -
|
99 | | - cp -r ${deps}/{vendor,node_modules} $out/share/probitas/ |
100 | | - # Make node_modules writable to allow removal of platform-specific packages |
101 | | - chmod -R +w $out/share/probitas/node_modules |
102 | | -
|
103 | | - # Remove npm packages with os/cpu constraints that don't match current platform |
104 | | - # Uses deno.lock as the source of truth for platform-specific packages |
105 | | - incompatiblePackages=$(jq -r --arg os "${npmPlatform.os}" --arg cpu "${npmPlatform.cpu}" ' |
106 | | - .npm // {} | to_entries[] | |
107 | | - select( |
108 | | - (.value.os != null and (.value.os | index($os) | not)) or |
109 | | - (.value.cpu != null and (.value.cpu | index($cpu) | not)) |
110 | | - ) | |
111 | | - .key | gsub("/"; "+") |
112 | | - ' "deno.lock") |
113 | | -
|
114 | | - for pkg in $incompatiblePackages; do |
115 | | - rm -rf "$out/share/probitas/node_modules/.deno/$pkg" |
116 | | - done |
117 | | -
|
118 | | - # Clean up broken symlinks left after removing platform-specific packages |
119 | | - find "$out/share/probitas/node_modules" -xtype l -delete |
120 | | -
|
121 | | - makeWrapper ${pkgs.lib.getExe pkgs.deno} $out/bin/probitas \ |
122 | | - --set DENO_NO_UPDATE_CHECK 1 \ |
123 | | - --add-flags "run -A" \ |
124 | | - --add-flags "--unstable-kv" \ |
125 | | - --add-flags "--vendor" \ |
126 | | - --add-flags "--frozen" \ |
127 | | - --add-flags "--config=$out/share/probitas/deno.json" \ |
128 | | - --add-flags "--lock=$out/share/probitas/deno.lock" \ |
129 | | - --add-flags "$out/share/probitas/mod.ts" |
130 | | -
|
131 | | - runHook postInstall |
132 | | - ''; |
133 | | - |
134 | | - doInstallCheck = true; |
135 | | - nativeInstallCheckInputs = [ pkgs.versionCheckHook ]; |
136 | | - |
137 | | - passthru = { |
138 | | - inherit deps; |
139 | | - updateDepsHash = pkgs.writeShellScriptBin "update-probitas-deps" '' |
140 | | - set -euo pipefail |
141 | | - cd "$(${pkgs.lib.getExe pkgs.git} rev-parse --show-toplevel)" |
142 | | -
|
143 | | - fakehash="${pkgs.lib.fakeHash}" |
144 | | - curhash=$(nix eval .#probitas.deps.outputHash --raw) |
145 | | -
|
146 | | - # Replace current hash with fakeHash |
147 | | - ${pkgs.gnused}/bin/sed -i "s|\"$curhash\"|\"$fakehash\"|" flake.nix |
148 | | -
|
149 | | - # Build with fakeHash to get the correct hash from error output |
150 | | - set +e |
151 | | - newhash=$( |
152 | | - nix build .#probitas.deps --no-link --log-format internal-json 2>&1 >/dev/null \ |
153 | | - | ${pkgs.gnugrep}/bin/grep "$fakehash" \ |
154 | | - | ${pkgs.gnugrep}/bin/grep -oP 'sha256-[A-Za-z0-9+/=]+' \ |
155 | | - | tail -1 |
156 | | - ) |
157 | | - set -e |
158 | | -
|
159 | | - if [[ -n "$newhash" ]]; then |
160 | | - ${pkgs.gnused}/bin/sed -i "s|\"$fakehash\"|\"$newhash\"|" flake.nix |
161 | | - echo "Updated deps hash to: $newhash" |
162 | | - else |
163 | | - ${pkgs.gnused}/bin/sed -i "s|\"$fakehash\"|\"$curhash\"|" flake.nix |
164 | | - echo "Failed to get hash, restored original" |
165 | | - fi |
166 | | - ''; |
167 | | - }; |
168 | | - |
169 | | - meta.mainProgram = "probitas"; |
170 | | - }); |
| 41 | + inherit (pkgs) probitas; |
| 42 | + default = pkgs.probitas; |
171 | 43 | }; |
172 | 44 |
|
173 | 45 | apps.default = flake-utils.lib.mkApp { |
174 | | - drv = self.packages.${system}.default; |
| 46 | + drv = pkgs.probitas; |
175 | 47 | }; |
176 | 48 |
|
177 | 49 | devShells.default = pkgs.mkShell { |
|
0 commit comments