IFD-embracing Nix expression to import pnpm lock files in Nix derivations

feat: initial implementation

Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>

+141
+6
default.nix
··· 1 + { 2 + pkgs ? import <nixpkgs> { }, 3 + }: 4 + { 5 + importPnpmLock = pkgs.callPackage ./importPnpmLock.nix { }; 6 + }
+43
flake.lock
··· 1 + { 2 + "nodes": { 3 + "nixpkgs": { 4 + "locked": { 5 + "lastModified": 1772624091, 6 + "narHash": "sha256-QKyJ0QGWBn6r0invrMAK8dmJoBYWoOWy7lN+UHzW1jc=", 7 + "owner": "nixos", 8 + "repo": "nixpkgs", 9 + "rev": "80bdc1e5ce51f56b19791b52b2901187931f5353", 10 + "type": "github" 11 + }, 12 + "original": { 13 + "owner": "nixos", 14 + "ref": "nixos-unstable", 15 + "repo": "nixpkgs", 16 + "type": "github" 17 + } 18 + }, 19 + "root": { 20 + "inputs": { 21 + "nixpkgs": "nixpkgs", 22 + "systems": "systems" 23 + } 24 + }, 25 + "systems": { 26 + "locked": { 27 + "lastModified": 1681028828, 28 + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", 29 + "owner": "nix-systems", 30 + "repo": "default", 31 + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", 32 + "type": "github" 33 + }, 34 + "original": { 35 + "owner": "nix-systems", 36 + "repo": "default", 37 + "type": "github" 38 + } 39 + } 40 + }, 41 + "root": "root", 42 + "version": 7 43 + }
+27
flake.nix
··· 1 + { 2 + description = "A very basic flake"; 3 + 4 + inputs = { 5 + nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable"; 6 + systems.url = "github:nix-systems/default"; 7 + }; 8 + 9 + outputs = 10 + { nixpkgs, systems, ... }: 11 + let 12 + forSystems = 13 + attrs: 14 + nixpkgs.lib.genAttrs (import systems) ( 15 + system: 16 + attrs { 17 + inherit system; 18 + pkgs = nixpkgs.legacyPackages.${system}; 19 + } 20 + ); 21 + in 22 + { 23 + legacyPackages = forSystems ({ pkgs, ... }: import ./. { inherit pkgs; }); 24 + 25 + formatter = forSystems ({ pkgs, ... }: pkgs.nixfmt-tree); 26 + }; 27 + }
+65
importPnpmLock.nix
··· 1 + { 2 + lib, 3 + runCommand, 4 + yj, 5 + mitm-cache, 6 + }: 7 + { 8 + lockFile, 9 + manualEntries ? { }, 10 + }: 11 + let 12 + importYAML = 13 + file: 14 + let 15 + # convert to json 16 + json = runCommand "converted.json" { } '' 17 + ${yj}/bin/yj < ${file} > $out 18 + ''; 19 + in 20 + lib.importJSON json; 21 + 22 + splitName = builtins.match "^(@?[^@]+)@(.+)$"; 23 + 24 + urlFromName = 25 + name: 26 + let 27 + c = splitName name; 28 + scopedName = builtins.head c; 29 + version = lib.last c; 30 + versionIsUrl = lib.hasPrefix "http" version; 31 + packageName = lib.last (lib.splitString "/" scopedName); 32 + in 33 + if versionIsUrl then 34 + version 35 + else 36 + "https://registry.npmjs.org/${scopedName}/-/${packageName}-${version}.tgz"; 37 + 38 + data = importYAML lockFile; 39 + 40 + mapPackageToMitmCacheEntry = 41 + name: package: 42 + let 43 + url = urlFromName name; 44 + integrity = (package.resolution or { }).integrity or manualEntries.${name} or null; 45 + in 46 + assert lib.assertMsg (integrity != null) '' 47 + Package ${name} doesn't have an integrity entry. 48 + 49 + To fix this, add a manual entry using 50 + 51 + importPnpmLock { 52 + lockFile = ${lockFile}; 53 + manualEntries = { 54 + "${name}" = ""; 55 + }; 56 + } 57 + ''; 58 + lib.nameValuePair url { 59 + hash = integrity; 60 + }; 61 + in 62 + mitm-cache.fetch { 63 + name = "npm-cache"; 64 + data = lib.mapAttrs' mapPackageToMitmCacheEntry data.packages; 65 + }