{ lib, nodejs_20, buildNpmPackage, fetchFromGitHub, writeShellScriptBin, nss, cmake, pkg-config, openssl, libdatachannel, }: let nodejs = nodejs_20; buildNpmPackage' = buildNpmPackage.override { inherit nodejs; }; version = "1.19.0"; src = fetchFromGitHub { owner = "httptoolkit"; repo = "httptoolkit-server"; rev = "refs/tags/v${version}"; hash = "sha256-S4Io4X5Hlvm/5HoKIQ/OTor9jZvMz6me5RyfZ8FwOdM="; }; overridesNodeModules = buildNpmPackage' { pname = "httptoolkit-server-overrides-node-modules"; inherit version src; sourceRoot = "${src.name}/overrides/js"; npmDepsHash = "sha256-GRN6ua3FY1AE61bB7PM2wgbKPZI/zJeXa5HOOh/2N2Y="; dontBuild = true; installPhase = '' mkdir -p $out cp -r node_modules $out/node_modules ''; }; nodeDatachannel = buildNpmPackage' { pname = "node-datachannel"; version = "0.4.3"; src = fetchFromGitHub { owner = "murat-dogan"; repo = "node-datachannel"; rev = "refs/tags/v${nodeDatachannel.version}"; hash = "sha256-BlfeocqSG+pqbK0onnCf0VKbQw8Qq4qMxhAcfGlFYR8="; }; npmFlags = [ "--ignore-scripts" ]; makeCacheWritable = true; npmDepsHash = "sha256-pgcOOjiuWKlpD+WJyPj/c9ZhDjYuEnybpLS/BPmzeFM="; nativeBuildInputs = [ cmake pkg-config ]; buildInputs = [ openssl libdatachannel ]; dontUseCmakeConfigure = true; env.NIX_CFLAGS_COMPILE = "-I${nodejs}/include/node"; env.CXXFLAGS = "-include stdexcept"; # for GCC13 preBuild = '' # don't use static libs and don't use FetchContent substituteInPlace CMakeLists.txt \ --replace-fail 'OPENSSL_USE_STATIC_LIBS TRUE' 'OPENSSL_USE_STATIC_LIBS FALSE' \ --replace-fail 'if(NOT libdatachannel)' 'if(false)' \ --replace-fail 'datachannel-static' 'datachannel' # don't fetch node headers substituteInPlace node_modules/cmake-js/lib/dist.js \ --replace-fail '!this.downloaded' 'false' npm rebuild --verbose ''; installPhase = '' runHook preInstall install -Dm755 build/Release/*.node -t $out/build/Release runHook postInstall ''; }; in buildNpmPackage' { pname = "httptoolkit-server"; inherit version src; patches = [ ./only-build-for-one-platform.patch ]; npmDepsHash = "sha256-njSNdpo+CIfS9LTnshawJ7297tFc8ssjUqJcHk8kBZE="; npmFlags = [ "--ignore-scripts" ]; makeCacheWritable = true; nativeBuildInputs = [ # the build system uses the `git` executable to get the current revision # we use a fake git to provide it with a fake revision (writeShellScriptBin "git" "echo '???'") ]; postConfigure = '' # make sure `oclif-dev' doesn't fetch `node` binary to bundle with the app substituteInPlace node_modules/@oclif/dev-cli/lib/tarballs/node.js --replace-fail \ 'async function fetchNodeBinary({ nodeVersion, output, platform, arch, tmp }) {' \ 'async function fetchNodeBinary({ nodeVersion, output, platform, arch, tmp }) { return;' # manually place our prebuilt `node-datachannel` binary into its place, since we used '--ignore-scripts' ln -s ${nodeDatachannel}/build node_modules/node-datachannel/build cp -r ${overridesNodeModules}/node_modules overrides/js/node_modules # don't run `npm ci` in `overrides/js` since we already copied node_modules into the directory substituteInPlace prepare.ts --replace-fail "'ci', '--production'" "'--version'" patchShebangs *.sh ''; preBuild = '' npm run build:src ''; npmBuildScript = "build:release"; installPhase = '' runHook preInstall # we don't actually use any of the generated tarballs, we just copy from the tmp directory, since that's easier mkdir -p $out/share/httptoolkit-server cp -r build/tmp/httptoolkit-server/* -r $out/share/httptoolkit-server # remove unneeded executables rm -r $out/share/httptoolkit-server/bin/httptoolkit-server* # since `oclif-dev pack` ran `npm install` again, we need to place the prebuilt binary here again ln -s ${nodeDatachannel}/build $out/share/httptoolkit-server/node_modules/node-datachannel/build # disable updating functionality substituteInPlace $out/share/httptoolkit-server/node_modules/@oclif/plugin-update/lib/commands/update.js \ --replace-fail "await this.skipUpdate()" "'cannot update nix based package'" # the app determines if it's in production by checking if HTTPTOOLKIT_SERVER_BINPATH is set to anything makeWrapper $out/share/httptoolkit-server/bin/run $out/bin/httptoolkit-server \ --set HTTPTOOLKIT_SERVER_BINPATH dummy \ --prefix PATH : ${lib.makeBinPath [ nss.tools ]} runHook postInstall ''; passthru = { inherit nodeDatachannel; }; meta = { description = "Backend for HTTP Toolkit"; homepage = "https://httptoolkit.com/"; license = lib.licenses.agpl3Plus; mainProgram = "httptoolkit-server"; maintainers = with lib.maintainers; [ tomasajt ]; platforms = lib.platforms.unix; }; }