diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 5c360229753f7..96dc3fbfa8826 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -344,6 +344,7 @@ ./programs/vim.nix ./programs/virt-manager.nix ./programs/vivid.nix + ./programs/vortex.nix ./programs/vscode.nix ./programs/wavemon.nix ./programs/wayland/dms-shell.nix diff --git a/nixos/modules/programs/vortex.nix b/nixos/modules/programs/vortex.nix new file mode 100644 index 0000000000000..0c2f5b3527676 --- /dev/null +++ b/nixos/modules/programs/vortex.nix @@ -0,0 +1,35 @@ +{ + config, + lib, + pkgs, + ... +}: + +let + cfg = config.programs.vortex; + inherit (lib) mkEnableOption mkPackageOption mkIf; +in +{ + options.programs.vortex = { + enable = mkEnableOption "Vortex mod manager"; + + package = mkPackageOption pkgs "vortex" { }; + + nxmSchemeHandler = lib.mkEnableOption '' + registration of the nxm:// URL scheme handler for Vortex + ''; + }; + + config = mkIf cfg.enable { + environment.systemPackages = [ cfg.package ]; + + xdg.mime.defaultApplications = mkIf cfg.nxmSchemeHandler { + "x-scheme-handler/nxm" = "com.nexusmods.vortex.desktop"; + }; + }; + + meta.maintainers = with lib.maintainers; [ + caniko + MattSturgeon + ]; +} diff --git a/pkgs/by-name/vo/vortex/package.nix b/pkgs/by-name/vo/vortex/package.nix new file mode 100644 index 0000000000000..5310364feccfa --- /dev/null +++ b/pkgs/by-name/vo/vortex/package.nix @@ -0,0 +1,236 @@ +{ + lib, + cacert, + clang, + electron_42-bin, + fetchFromGitHub, + fetchPnpmDeps, + fontconfig, + jq, + librsvg, + makeBinaryWrapper, + node-gyp, + nodejs, + pkg-config, + pnpmBuildHook, + pnpmConfigHook, + pnpm_11, + python3, + stdenvNoCC, +}: +let + electron = electron_42-bin; + pnpm = pnpm_11; +in + +stdenvNoCC.mkDerivation (finalAttrs: { + + __structuredAttrs = true; + strictDeps = true; + + pname = "vortex"; + version = "2.2.0"; + + src = fetchFromGitHub { + owner = "Nexus-Mods"; + repo = "Vortex"; + tag = "v${finalAttrs.version}"; + hash = "sha256-BRzw/ziwIYJ8kaf+EQPCTxo0f8oJXn51pNWnhdfjyLw="; + }; + + pnpmDeps = fetchPnpmDeps { + inherit pnpm; + inherit (finalAttrs) + pname + version + src + pnpmBuildScript + pnpmInstallFlags + ; + fetcherVersion = 4; + hash = "sha256-0qTAS/wF/V3vB6E0EjmCQXeemAa8mhtepCEuJKeQivo="; + }; + + duckdbExtensions = stdenvNoCC.mkDerivation { + __structuredAttrs = true; + strictDeps = true; + + pname = finalAttrs.pname + "-duckdb-extensions"; + inherit (finalAttrs) version src pnpmDeps; + outputHash = "sha256-LZkR9l1YA3vZVAktwqc6o19uC0d+MYPJxunZNgia+7U="; + outputHashMode = "recursive"; + + nativeBuildInputs = [ + cacert + nodejs + jq + pnpm + pnpmConfigHook + ]; + + buildPhase = '' + runHook preBuild + pnpm tsx src/main/download-duckdb-extensions.ts + runHook postBuild + ''; + + installPhase = '' + runHook preInstall + dest=$(jq --raw-output .outputDir src/main/duckdb-extensions.json) + mv "src/main/$dest" "$out" + runHook postInstall + ''; + }; + + env = { + NX_NATIVE_COMMAND_RUNNER = "false"; + NODE_PATH = "${node-gyp}/lib/node_modules"; + + ELECTRON_SKIP_BINARY_DOWNLOAD = "1"; + ELECTRON_OVERRIDE_DIST_PATH = "${electron.dist}"; + }; + + pnpmBuildScript = "package:nosign"; + pnpmInstallFlags = [ + "--ignore-scripts" + ]; + + nativeBuildInputs = [ + pnpmConfigHook + pnpmBuildHook + + clang + jq + makeBinaryWrapper + node-gyp + nodejs + pnpm + + pkg-config + (python3.withPackages (ps: [ ps.setuptools ])) + ]; + + buildInputs = [ + fontconfig + ]; + + runtimeInputs = [ + nodejs + ]; + + runtimeEnv = { + NODE_ENV = "production"; + GDK_PIXBUF_MODULE_FILE = "${librsvg}/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache"; + CHROME_DEVEL_SANDBOX = "${electron}/libexec/electron/chrome-sandbox"; + }; + + makeWrapperArgs = [ + "--inherit-argv0" + "--prefix" + "PATH" + ":" + (lib.makeBinPath finalAttrs.runtimeInputs) + ] + ++ lib.foldlAttrs ( + acc: name: value: + acc + ++ [ + "--set" + name + (if lib.isBool value then lib.optionalString value "1" else value) + ] + ) [ ] finalAttrs.runtimeEnv; + + postPatch = '' + # Add forceLegacyDeploy workaround (pnpm 11 shared lockfile bug) + # https://github.com/pnpm/pnpm/issues/5315 + cat pnpm-workspace.yaml > pnpm-workspace.yaml.bak + echo "forceLegacyDeploy: true" >> pnpm-workspace.yaml + + mkdir -p src/main/build + duckdbExtensionsDest=$(jq --raw-output .outputDir src/main/duckdb-extensions.json) + ln -s "$duckdbExtensions" "src/main/$duckdbExtensionsDest" + + substituteInPlace flatpak/com.nexusmods.vortex.desktop \ + --replace-fail run.sh vortex + + jqInPlace() { + local file="$1" + shift + local tmp=$(mktemp) + jq "$@" "$file" > "$tmp" && mv -f "$tmp" "$file" + } + + jqInPlace src/main/electron-builder.config.json \ + --arg dist ${electron.dist} \ + --arg version ${electron.version} \ + '.electronDist = $dist | .electronVersion = $version' + + # Ensure deploy uses legacy algorithm (pnpm 11 shared lockfile bug workaround) + # https://github.com/pnpm/pnpm/issues/5315 + substituteInPlace src/main/package.json \ + --replace-fail \ + 'deploy ./dist' \ + 'deploy --offline --frozen-lockfile ./dist' + ''; + + preBuild = '' + # Copy metadata from store to HOME cache for offline pnpm deploy. + storeDir=$(pnpm config get store-dir 2>/dev/null) + cacheDir=''${HOME:+$HOME/.cache/pnpm} + if [ -n "$storeDir" ] && [ -d "$storeDir/v11/metadata" ] && [ -n "$cacheDir" ] && [ ! -d "$cacheDir/v11/metadata" ]; then + mkdir -p "$cacheDir/v11" + cp -r "$storeDir/v11/metadata" "$cacheDir/v11/" + fi + ''; + + buildPhase = '' + runHook preBuild + + pushd node_modules/.pnpm/font-scanner*/node_modules/font-scanner + node-gyp rebuild --release + popd + + pnpmBuildHook + + runHook postBuild + ''; + + installPhase = '' + runHook preInstall + + mkdir -p "$out/bin" "$out/lib" + + install -Dm644 flatpak/com.nexusmods.vortex.desktop \ + "$out/share/applications/com.nexusmods.vortex.desktop" + install -Dm644 assets/images/vortex.png \ + "$out/share/icons/hicolor/256x256/apps/com.nexusmods.vortex.png" + + install -d "$out/main" + cp -a dist/linux*-unpacked/. "$out/main/" + + makeWrapper ${lib.getExe electron} "$out/bin/vortex" \ + --add-flag "$out/main/vortex" \ + "''${makeWrapperArgs[@]}" + + runHook postInstall + ''; + + meta = { + description = "Open-source mod manager from Nexus Mods"; + homepage = "https://github.com/Nexus-Mods/Vortex"; + changelog = "https://github.com/Nexus-Mods/Vortex/releases/tag/${finalAttrs.src.tag}"; + license = lib.licenses.gpl3Only; + mainProgram = "vortex"; + platforms = lib.platforms.linux; + maintainers = with lib.maintainers; [ + caniko + MattSturgeon + ]; + problems = [ + { + message = "The Linux build of Vortex is pre-alpha software. It lacks wine/proton integration, xdg-portals for file pickers, and several features the Windows version has. Most users should run the Windows version under wine or proton instead."; + } + ]; + }; +})