From 457e409607d806c8de78aeda885af901d3aa1c4f Mon Sep 17 00:00:00 2001 From: TomaSajt <62384384+TomaSajt@users.noreply.github.com> Date: Thu, 12 Sep 2024 16:49:35 +0200 Subject: [PATCH] httptoolkit-server: init at 1.19.0 --- .../only-build-for-one-platform.patch | 39 ++++ .../by-name/ht/httptoolkit-server/package.nix | 173 ++++++++++++++++++ 2 files changed, 212 insertions(+) create mode 100644 pkgs/by-name/ht/httptoolkit-server/only-build-for-one-platform.patch create mode 100644 pkgs/by-name/ht/httptoolkit-server/package.nix diff --git a/pkgs/by-name/ht/httptoolkit-server/only-build-for-one-platform.patch b/pkgs/by-name/ht/httptoolkit-server/only-build-for-one-platform.patch new file mode 100644 index 000000000000..3d36c01d2ca4 --- /dev/null +++ b/pkgs/by-name/ht/httptoolkit-server/only-build-for-one-platform.patch @@ -0,0 +1,39 @@ +diff --git a/pack.ts b/pack.ts +index aba98cc..03ce86a 100644 +--- a/pack.ts ++++ b/pack.ts +@@ -75,33 +75,7 @@ const packageApp = async () => { + delete pJson.scripts.prepack; // We don't want to rebuild - all built code will be in the packed content + await fs.writeJson(path.join(OUTPUT_DIR, 'package.json'), pJson); + +- const buildScript = path.join(OUTPUT_DIR, 'build-release.sh'); +- +- // Run build-release in this folder, for each platform. For each bundle, we copy in +- // only the relevant platform-specific NSS files. +- console.log('Building for Linux'); +- await fs.mkdir(path.join(OUTPUT_DIR, 'nss')); +- await fs.copy(path.join(__dirname, 'nss', 'linux'), path.join(OUTPUT_DIR, 'nss', 'linux')); +- await spawn(buildScript, ['linux'], { cwd: OUTPUT_DIR, stdio: 'inherit' }); +- +- console.log('Building for Darwin'); +- await fs.remove(path.join(OUTPUT_DIR, 'nss', 'linux')); +- await fs.copy(path.join(__dirname, 'nss', 'darwin'), path.join(OUTPUT_DIR, 'nss', 'darwin')); +- await spawn(buildScript, ['darwin'], { cwd: OUTPUT_DIR, stdio: 'inherit' }); +- +- console.log('Building for Win32'); +- await fs.remove(path.join(OUTPUT_DIR, 'nss', 'darwin')); +- await fs.copy(path.join(__dirname, 'nss', 'win32'), path.join(OUTPUT_DIR, 'nss', 'win32')); +- await spawn(buildScript, ['win32'], { cwd: OUTPUT_DIR, stdio: 'inherit' }); +- +- // Oclif builds a nodeless platform-agnostic bundle too (although in our case, nothing is +- // really platform agnostic). Not necessary, probably won't work - drop it. +- await fs.remove(path.join( +- OUTPUT_DIR, +- 'dist', +- `v${pJson.version}`, +- `httptoolkit-server-v${pJson.version}.tar.gz` +- )); ++ await spawn('npm', ['exec', '--', 'oclif-dev', 'pack', '--targets=linux-x64'], { cwd: OUTPUT_DIR, stdio: 'inherit' }); + } + + packageApp().catch(e => { diff --git a/pkgs/by-name/ht/httptoolkit-server/package.nix b/pkgs/by-name/ht/httptoolkit-server/package.nix new file mode 100644 index 000000000000..1bc90738b120 --- /dev/null +++ b/pkgs/by-name/ht/httptoolkit-server/package.nix @@ -0,0 +1,173 @@ +{ + 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; + }; +}