# This file is generated by running "yarn install" inside your project. # Manual changes might be lost - proceed with caution! { lib, stdenv, nodejs, git, cacert, fetchurl, writeShellScript, writeShellScriptBin }: { src, overrideAttrs ? null, ... } @ args: let cacheFolder = @@CACHE_FOLDER@@; #@@ IF NEED_ISOLATED_BUILD_SUPPRORT lockfile = ./@@LOCKFILE@@; #@@ ENDIF NEED_ISOLATED_BUILD_SUPPRORT # Call overrideAttrs on a derivation if a function is provided. optionalOverride = fn: drv: if fn == null then drv else drv.overrideAttrs fn; # Simple stub that provides the global yarn command. yarn = writeShellScriptBin "yarn" '' exec '${nodejs}/bin/node' '${./@@YARN_PATH@@}' "$@" ''; # Common attributes between Yarn derivations. drvCommon = { # Make sure the build uses the right Node.js version everywhere. buildInputs = [ nodejs yarn ]; # Tell node-gyp to use the provided Node.js headers for native code builds. npm_config_nodedir = nodejs; }; # Comman variables that we set in a Nix build, but not in a Nix shell. buildVars = '' # Make Yarn produce friendlier logging for automated builds. export CI=1 # Tell node-pre-gyp to never fetch binaries / always build from source. export npm_config_build_from_source=true # Disable Nixify plugin to save on some unnecessary processing. export yarn_enable_nixify=false ''; # Create derivations for fetching dependencies. cacheDrvs = let builder = writeShellScript "yarn-cache-builder" '' source $stdenv/setup cd "$src" ${buildVars} HOME="$TMP" yarn_cache_folder="$TMP" \ yarn nixify fetch-one $locator # Because we change the cache dir, Yarn may generate a different name. mv "$TMP/$(sed 's/-[^-]*\.[^-]*$//' <<< "$outputFilename")"-* $out ''; in lib.mapAttrs (locator: { filename, sha512 }: stdenv.mkDerivation { inherit src builder locator; name = lib.strings.sanitizeDerivationName locator; buildInputs = [ yarn git cacert ]; outputFilename = filename; outputHashMode = "flat"; outputHashAlgo = "sha512"; outputHash = sha512; }) cacheEntries; # Create a shell snippet to copy dependencies from a list of derivations. mkCacheBuilderForDrvs = drvs: writeShellScript "collect-yarn-cache" (lib.concatMapStrings (drv: '' cp ${drv} '${drv.outputFilename}' '') drvs); #@@ IF NEED_ISOLATED_BUILD_SUPPRORT # Create a shell snippet to copy dependencies from a list of locators. mkCacheBuilderForLocators = let pickCacheDrvs = map (locator: cacheDrvs.${locator}); in locators: mkCacheBuilderForDrvs (pickCacheDrvs locators); # Create a derivation that builds a node-pre-gyp module in isolation. mkIsolatedBuild = { pname, version, reference, locators }: stdenv.mkDerivation (drvCommon // { inherit pname version; dontUnpack = true; configurePhase = '' ${buildVars} unset yarn_enable_nixify # plugin is not present ''; buildPhase = '' mkdir -p .yarn/cache pushd .yarn/cache > /dev/null source ${mkCacheBuilderForLocators locators} popd > /dev/null echo '{ "dependencies": { "${pname}": "${reference}" } }' > package.json install -m 0600 ${lockfile} ./yarn.lock export yarn_global_folder="$TMP" export YARN_ENABLE_IMMUTABLE_INSTALLS=false yarn --immutable-cache ''; installPhase = '' unplugged=( .yarn/unplugged/${pname}-*/node_modules/* ) if [[ ! -e "''${unplugged[@]}" ]]; then echo >&2 "Could not find the unplugged path for ${pname}" exit 1 fi mv "$unplugged" $out ''; }); #@@ ENDIF NEED_ISOLATED_BUILD_SUPPRORT # Main project derivation. project = stdenv.mkDerivation (drvCommon // { inherit src; name = @@PROJECT_NAME@@; configurePhase = '' ${buildVars} # Copy over the Yarn cache. rm -fr '${cacheFolder}' mkdir -p '${cacheFolder}' pushd '${cacheFolder}' > /dev/null source ${mkCacheBuilderForDrvs (lib.attrValues cacheDrvs)} popd > /dev/null # Yarn may need a writable home directory. export yarn_global_folder="$TMP" # Some node-gyp calls may call out to npm, which could fail due to an # read-only home dir. export HOME="$TMP" # running preConfigure after the cache is populated allows for # preConfigure to contain substituteInPlace for dependencies as well as the # main project. This is necessary for native bindings that maybe have # hardcoded values. runHook preConfigure @@ISOLATED_INTEGRATION@@ # Run normal Yarn install to complete dependency installation. yarn install --immutable --immutable-cache runHook postConfigure ''; buildPhase = '' runHook preBuild runHook postBuild ''; installPhase = '' runHook preInstall # Move the package contents to the output directory. if grep -q '"workspaces"' package.json; then # We can't use `yarn pack` in a workspace setup, because it only # packages the outer workspace. mkdir -p "$out/libexec" mv $PWD "$out/libexec/$name" else # - If the package.json has a `files` field, only files matching those patterns are copied # - Otherwise all files are copied. yarn pack --out package.tgz mkdir -p "$out/libexec/$name" tar xzvf package.tgz --directory "$out/libexec/$name" --strip-components=1 cp .yarnrc* '@@LOCKFILE@@' "$out/libexec/$name" cp --recursive .yarn "$out/libexec/$name" # If the project uses the node-modules linker, then # include the node_modules folder in the package. if [ -d node_modules ]; then cp --recursive node_modules "$out/libexec/$name" else # Otherwise, assume PnP. Copy the loader into the package. cp .pnp.* "$out/libexec/$name" fi fi cd "$out/libexec/$name" # Invoke a plugin internal command to setup binaries. mkdir -p "$out/bin" yarn nixify install-bin $out/bin # A package with node_modules doesn't need the cache if [ -d node_modules ]; then yarn cache clean fi runHook postInstall ''; passthru = { inherit nodejs; yarn-freestanding = yarn; yarn = writeShellScriptBin "yarn" '' exec '${yarn}/bin/yarn' --cwd '${overriddenProject}/libexec/${overriddenProject.name}' "$@" ''; }; }); overriddenProject = optionalOverride overrideAttrs project; @@CACHE_ENTRIES@@ @@ISOLATED@@ in overriddenProject