{ lib, stdenv, fetchFromGitHub, nodejs_22, pnpm, python3, gcc, gnumake, pkg-config, makeWrapper, electron_40, vpkmerge, sqlite, callPackage, makeDesktopItem, copyDesktopItems, }: let sources = callPackage ../../../../_sources/generated.nix {}; src = sources.grimoire.src; version = src.rev; # This would go into nvfetcher but it isnt versioned.. grimoire-social-src = fetchFromGitHub { owner = "Slush97"; repo = "grimoire-social"; rev = "main"; hash = "sha256-f+wUZOR7dqigxd/IZtay1BrLS5rcSnaDage3NXxqsPE="; }; pnpmDeps = pnpm.fetchDeps { pname = "grimoire"; inherit version src; fetcherVersion = 3; hash = "sha256-X7KLUag9HPHVit0l/tA3BxQZ2/Cj0A5KiG4Oevx2268="; }; desktopItem = makeDesktopItem { name = "grimoire"; exec = "grimoire %u"; desktopName = "Grimoire"; categories = ["Utility"]; mimeTypes = ["x-scheme-handler/grimoire"]; }; in stdenv.mkDerivation { pname = "grimoire"; inherit version src; nativeBuildInputs = [ nodejs_22 pnpm pnpm.configHook python3 gcc gnumake pkg-config makeWrapper electron_40 copyDesktopItems ]; desktopItems = [desktopItem]; buildInputs = [ sqlite ]; inherit pnpmDeps; env = { GRIMOIRE_SOCIAL_BASE_URL = "https://grimoire-social.slusheliott.workers.dev"; # electron-builder must not try to fetch an Electron binary over the # network; we hand it the Nix one via --config.electronDist below. ELECTRON_SKIP_BINARY_DOWNLOAD = "1"; }; postPatch = '' cp -r ${grimoire-social-src} ../grimoire-social chmod -R u+w ../grimoire-social mkdir -p resources/vpkmerge cp ${vpkmerge}/bin/vpkmerge resources/vpkmerge/vpkmerge-linux-x86_64 chmod +x resources/vpkmerge/vpkmerge-linux-x86_64 ''; buildPhase = '' runHook preBuild mkdir -p ../grimoire-social/node_modules ln -sfn "$(realpath node_modules/zod)" ../grimoire-social/node_modules/zod # Rebuild the better-sqlite3 native addon against the Electron ABI. We do # this ourselves (and disable electron-builder's own rebuild below) so no # network fetch of Electron headers is needed inside the sandbox. ( cd node_modules/better-sqlite3 HOME="$TMPDIR" node \ "${nodejs_22}/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js" \ rebuild \ --nodedir="${electron_40.headers}" ) # Package the app the same way upstream CI does (release.yml): # `electron-vite build && electron-builder`. We stop at the unpacked # `--dir` output instead of building AppImage/deb installers, then wrap # the Nix Electron around the produced app.asar. Building through # electron-builder (rather than launching Electron on the raw dist/) # makes `app.isPackaged` true, which is what disables the dev-only # DevTools auto-open and the dev vpkmerge lookup path. export HOME="$TMPDIR" pnpm exec electron-vite build pnpm exec electron-builder --linux dir \ --config.npmRebuild=false \ --config.electronDist=${electron_40.dist} \ --config.electronVersion=${electron_40.version} runHook postBuild ''; installPhase = '' runHook preInstall mkdir -p $out/lib/grimoire # electron-builder emits the packaged app (app.asar, app.asar.unpacked, # and extraResources such as vpkmerge) under release/linux-unpacked/resources. cp -r release/linux-unpacked/resources $out/lib/grimoire/resources # Launch the Nix Electron against the packaged asar. process.resourcesPath # resolves to the directory holding app.asar, so the bundled vpkmerge at # resources/vpkmerge/ is found at runtime. mkdir -p $out/bin makeWrapper ${electron_40}/bin/electron $out/bin/grimoire \ --add-flags "$out/lib/grimoire/resources/app.asar" \ --set NODE_ENV production runHook postInstall ''; meta = { description = "Grimoire — Electron-based mod manager"; platforms = ["x86_64-linux"]; }; }