anchor.diff: -{stdenv, python, nodejs, utillinux, runCommand}:
  +{stdenv, python, nodejs, utillinux, runCommand, writeTextFile}:
   
   let
     # Function that generates a TGZ file from a NPM project
  
positive.code:       
        buildPhase = args.buildPhase or "true";
        
        installPhase = args.installPhase or ''
          # Create and enter a root node_modules/ folder
          mkdir -p $out/lib/node_modules
          cd $out/lib/node_modules
            
          # Compose the package and all its dependencies
          ${composePackage args}
          
          # Patch the shebangs of the bundled modules to prevent them from
          # calling executables outside the Nix store as much as possible
  
negative.code: 
    # Recursively composes the dependencies of a package
    composePackage = { name, src, dependencies ? [], ... }@args:
      let
        fixImpureDependencies = writeTextFile {
          name = "fixDependencies.js";
          text = ''
            var fs = require('fs');
            var url = require('url');
            
            /*
             * Replaces an impure version specification by *
             */
            function replaceImpureVersionSpec(versionSpec) {
                var parsedUrl = url.parse(versionSpec);
                
                if(versionSpec == "latest" || versionSpec == "unstable" ||
                    versionSpec.substr(0, 2) == ".." || dependency.substr(0, 2) == "./" || dependency.substr(0, 2) == "~/" || dependency.substr(0, 1) == '/')
                    return '*';
                else if(parsedUrl.protocol == "git:" || parsedUrl.protocol == "git+ssh:" || parsedUrl.protocol == "git+http:" || parsedUrl.protocol == "git+https:" ||
                    parsedUrl.protocol == "http:" || parsedUrl.protocol == "https:")
                    return '*';
                else
                    return versionSpec;
            }
        
            var packageObj = JSON.parse(fs.readFileSync('./package.json'));
        
            /* Replace dependencies */
            if(packageObj.dependencies !== undefined) {
                for(var dependency in packageObj.dependencies) {
                    var versionSpec = packageObj.dependencies[dependency];
                    packageObj.dependencies[dependency] = replaceImpureVersionSpec(versionSpec);
                }
            }
            
            /* Replace development dependencies */
            if(packageObj.devDependencies !== undefined) {
                for(var dependency in packageObj.devDependencies) {
                    var versionSpec = packageObj.devDependencies[dependency];
                    packageObj.devDependencies[dependency] = replaceImpureVersionSpec(versionSpec);
                }
            }
            
            /* Replace optional dependencies */
            if(packageObj.optionalDependencies !== undefined) {
                for(var dependency in packageObj.optionalDependencies) {
                    var versionSpec = packageObj.optionalDependencies[dependency];
                    packageObj.optionalDependencies[dependency] = replaceImpureVersionSpec(versionSpec);
                }
            }
            
            /* Write the fixed JSON file */
            fs.writeFileSync("package.json", JSON.stringify(packageObj));
          '';
        };
      in
      ''
        DIR=$(pwd)
        cd $TMPDIR
        
        unpackFile ${src}
  
        if [ -f "${src}" ]
        then
            # Restore write permissions to make building work
            chmod -R u+w package
            
            # Move the extracted tarball into the output folder
            mv package "$DIR/${name}"
        elif [ "$strippedName" != "${name}" ]
        then
            # Restore write permissions to make building work
            chmod -R u+w $strippedName
            
            # Move the extracted directory into the output folder
            mv $strippedName "$DIR/${name}"
        fi
        
        # Unset the stripped name to not confuse the next unpack step
        unset strippedName
        
        # Some version specifiers (latest, unstable, URLs, file paths) force NPM to make remote connections or consult paths outside the Nix store.
        # The following JavaScript replaces these by * to prevent that
        cd $DIR/${name}
        node ${fixImpureDependencies}
        
        # Include the dependencies of the package
        ${includeDependencies { inherit dependencies; }}
        cd ..
      '';
  