From d8b226dac2e9f4b68b7ebc0e493638c9d56f0487 Mon Sep 17 00:00:00 2001 From: Nikkuss Date: Mon, 28 Jul 2025 17:40:07 +0400 Subject: [PATCH] init --- flake.nix | 11 +++++ yarn.nix | 140 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 151 insertions(+) create mode 100644 flake.nix create mode 100644 yarn.nix diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..35890cc --- /dev/null +++ b/flake.nix @@ -0,0 +1,11 @@ +{ + outputs = + { self }: + { + overlays.default = ( + final: prev: { + fetchYarnDepsV2 = final.callPackage ./yarn.nix { }; + } + ); + }; +} diff --git a/yarn.nix b/yarn.nix new file mode 100644 index 0000000..9f50226 --- /dev/null +++ b/yarn.nix @@ -0,0 +1,140 @@ +{ pkgs, ... }: + +let + inherit (pkgs) lib; + parseFile = + filePath: + let + fileContent = builtins.readFile filePath; + fileLines = lib.strings.splitString "\n" fileContent; + in + parseLines fileLines { } null false [ ]; + + parseKeyValue = + line: + let + matchResult = builtins.match ''^[ ]*"?([^" ]+)"?[ ]+"?([^"]+)"?$'' line; + in + if matchResult == null then + null + else if builtins.length matchResult < 2 then + null + else + { + key = builtins.elemAt matchResult 0; + value = builtins.elemAt matchResult 1; + }; + isDependencySection = + line: builtins.match ''^[ ]*(dependencies|optionalDependencies):$'' line != null; + parsePackageHeader = line: builtins.match ''^(.*):$'' line; + deepMergeAttr = + attrName: update: attrSet: + let + previous = attrSet.${attrName} or { }; + in + attrSet // { "${attrName}" = previous // update; }; + + cleanKey = + rawKey: + let + # Remove surrounding quotes if present + unquoted = + if builtins.match ''^"(.*)"$'' rawKey != null then + builtins.elemAt (builtins.match ''^"(.*)"$'' rawKey) 0 + else + rawKey; + # Remove leading @ if present + noAtPrefix = + if builtins.match ''^@(.*)$'' unquoted != null then + builtins.elemAt (builtins.match ''^@(.*)$'' unquoted) 0 + else + unquoted; + # Remove everything after (and including) the last @ if present + splitAt = builtins.match ''^([^@]+)@.*$'' noAtPrefix; + cleaned = if splitAt != null then builtins.elemAt splitAt 0 else noAtPrefix; + in + cleaned; + + parseLines = + lines: acc: currentPkg: inDeps: depList: + if lines == [ ] then + acc + else + let + line = builtins.head lines; + rest = builtins.tail lines; + pkgHeader = parsePackageHeader line; + in + if inDeps then + let + kv = parseKeyValue line; + in + if kv != null then + parseLines rest acc currentPkg true (depList ++ [ kv ]) + else + parseLines rest (deepMergeAttr currentPkg { deps = depList; } acc) currentPkg false [ ] + else if isDependencySection line then + parseLines rest acc currentPkg true [ ] + else if pkgHeader != null then + let + pkgName = builtins.elemAt pkgHeader 0; + in + parseLines rest (acc // { "${pkgName}" = { }; }) pkgName false depList + else if currentPkg != null then + let + kv = parseKeyValue line; + in + if kv == null then + parseLines rest acc currentPkg false depList + else + parseLines rest (deepMergeAttr currentPkg { "${kv.key}" = kv.value; } acc) currentPkg false depList + else + parseLines rest acc currentPkg false depList; + + convertKey = + key: + let + hasSlash = builtins.match ".*/.*" key != null; + split = lib.strings.splitString "/" key; + first = builtins.elemAt split 0; + last = builtins.elemAt split (builtins.length split - 1); + result = if hasSlash then "_${first}_${last}___${last}" else "${key}___${key}"; + in + result; + + parseMap = + pkgMap: + builtins.listToAttrs ( + lib.mapAttrsToList ( + originalKey: pkgAttrs: + let + cleanedKey = cleanKey originalKey; + convertedKey = convertKey cleanedKey; + filenameRaw = "${convertedKey}_${pkgAttrs.version}.tgz"; + filename = builtins.replaceStrings [ "-" ] [ "_" ] filenameRaw; + in + { + name = filename; + value = pkgs.fetchurl { + url = pkgAttrs.resolved; + hash = pkgAttrs.integrity; + }; + } + ) pkgMap + ); + combineAll = + fileMap: yarnLockPath: + let + copyCmds = lib.mapAttrsToList (filename: filePath: "cp ${filePath} $out/${filename}") fileMap; + script = builtins.concatStringsSep "\n" copyCmds; + in + pkgs.runCommand "combine-all" { } '' + mkdir -p $out; + ${script} + cp ${yarnLockPath} $out/yarn.lock + ''; +in +{ + yarnLock ? null, +}: +combineAll (parseMap (parseFile yarnLock)) yarnLock