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; + }; +} diff --git a/pkgs/by-name/ht/httptoolkit/package.nix b/pkgs/by-name/ht/httptoolkit/package.nix new file mode 100644 index 000000000000..173e093cb71c --- /dev/null +++ b/pkgs/by-name/ht/httptoolkit/package.nix @@ -0,0 +1,101 @@ +{ + lib, + stdenv, + buildNpmPackage, + fetchFromGitHub, + makeWrapper, + makeDesktopItem, + copyDesktopItems, + electron, + httptoolkit-server, +}: + +buildNpmPackage rec { + pname = "httptoolkit"; + version = "1.19.0"; + + src = fetchFromGitHub { + owner = "httptoolkit"; + repo = "httptoolkit-desktop"; + rev = "refs/tags/v${version}"; + hash = "sha256-e+ngBZMwMTvwzY1K7IaxlNoRkZUPDdJvKxvxuCsc9pw="; + }; + + npmDepsHash = "sha256-XgJIs4P1ezCEPPitIIfYpNkX0/3dPdajeIiDwHm7DSU="; + + env = { + ELECTRON_SKIP_BINARY_DOWNLOAD = "1"; + # disable code signing on Darwin + CSC_IDENTITY_AUTO_DISCOVERY = "false"; + }; + + nativeBuildInputs = [ makeWrapper ] ++ lib.optionals stdenv.isLinux [ copyDesktopItems ]; + + npmBuildScript = "build:src"; + + postBuild = '' + substituteInPlace package.json --replace-fail \ + '"forceCodeSigning": true' \ + '"forceCodeSigning": false' + + cp -r ${electron.dist} electron-dist + chmod -R u+w electron-dist + + npm exec electron-builder -- \ + --dir \ + -c.electronDist=electron-dist \ + -c.electronVersion=${electron.version} + ''; + + installPhase = '' + runHook preInstall + + ${lib.optionalString stdenv.isLinux '' + mkdir -p $out/share/httptoolkit + cp -r dist/*-unpacked/{locales,resources{,.pak}} $out/share/httptoolkit + + ln -s ${httptoolkit-server} $out/share/httptoolkit/resources/httptoolkit-server + + install -Dm644 src/icons/icon.svg $out/share/icons/hicolor/scalable/apps/httptoolkit.svg + + makeWrapper ${lib.getExe electron} $out/bin/httptoolkit \ + --add-flags $out/share/httptoolkit/resources/app.asar \ + --add-flags "\''${NIXOS_OZONE_WL:+\''${WAYLAND_DISPLAY:+--ozone-platform-hint=auto --enable-features=WaylandWindowDecorations}}" \ + --inherit-argv0 + ''} + + ${lib.optionalString stdenv.isDarwin '' + mkdir -p $out/Applications + cp -r dist/mac*/"HTTP Toolkit.app" $out/Applications + + ln -s ${httptoolkit-server} "$out/Applications/HTTP Toolkit.app/Contents/Resources/httptoolkit-server" + + makeWrapper "$out/Applications/HTTP Toolkit.app/Contents/MacOS/HTTP Toolkit" $out/bin/httptoolkit + ''} + + runHook postInstall + ''; + + desktopItems = [ + (makeDesktopItem { + name = "httptoolkit"; + desktopName = "HTTP Toolkit"; + exec = "httptoolkit %U"; + terminal = false; + icon = "httptoolkit"; + startupWMClass = "HTTP Toolkit"; + comment = meta.description; + categories = [ "Development" ]; + startupNotify = true; + }) + ]; + + meta = { + description = "HTTP(S) debugging, development & testing tool"; + homepage = "https://httptoolkit.com/"; + license = lib.licenses.agpl3Plus; + mainProgram = "httptoolkit"; + maintainers = with lib.maintainers; [ tomasajt ]; + platforms = electron.meta.platforms; + }; +} diff --git a/pkgs/development/libraries/libdatachannel/default.nix b/pkgs/development/libraries/libdatachannel/default.nix index d5e5f1db552a..bc831d354e77 100644 --- a/pkgs/development/libraries/libdatachannel/default.nix +++ b/pkgs/development/libraries/libdatachannel/default.nix @@ -1,14 +1,15 @@ -{ stdenv -, lib -, fetchFromGitHub -, cmake -, ninja -, pkg-config -, libnice -, openssl -, plog -, srtp -, usrsctp +{ + stdenv, + lib, + fetchFromGitHub, + cmake, + ninja, + pkg-config, + libnice, + openssl, + plog, + srtp, + usrsctp, }: stdenv.mkDerivation rec { @@ -22,14 +23,19 @@ stdenv.mkDerivation rec { hash = "sha256-3fax57oaJvOgbTDPCiiUdtsfAGhICfPkuMihawq06SA="; }; - outputs = [ "out" "dev" ]; + outputs = [ + "out" + "dev" + ]; strictDeps = true; + nativeBuildInputs = [ cmake ninja pkg-config ]; + buildInputs = [ libnice openssl @@ -47,7 +53,7 @@ stdenv.mkDerivation rec { postFixup = '' # Fix include path that will be incorrect due to the "dev" output substituteInPlace "$dev/lib/cmake/LibDataChannel/LibDataChannelTargets.cmake" \ - --replace "\''${_IMPORT_PREFIX}/include" "$dev/include" + --replace-fail "\''${_IMPORT_PREFIX}/include" "$dev/include" ''; meta = with lib; { @@ -55,6 +61,6 @@ stdenv.mkDerivation rec { homepage = "https://libdatachannel.org/"; license = with licenses; [ mpl20 ]; maintainers = with maintainers; [ erdnaxe ]; - platforms = platforms.linux; + platforms = platforms.linux ++ platforms.darwin; }; }