const path = require('node:path'); const { moshExtraResources } = require('./scripts/mosh-extra-resources.cjs'); const { etExtraResources } = require('./scripts/et-extra-resources.cjs'); // 说明:electron-builder 依赖收集器在 monorepo/workspace 项目里会漏掉 // workspace 子包引用但根 package.json 没声明的运行时依赖(hoist 上来的), // 且追踪传递依赖时容易漏包。这里直接把整个 node_modules 目录纳入 files, // 确保运行时 require 什么都能找到。用排除列表去掉前端/构建工具/文档/测试代码。 /** * @type {import('electron-builder').Configuration} */ module.exports = { // 内网环境下 electron-builder 默认会去 github.com 下载 Electron zip。 // 强制指向本地已解压的 node_modules/electron/dist,跳过联网。 electronDist: path.join(__dirname, 'node_modules', 'electron', 'dist'), appId: 'com.netcatty.app', productName: 'NetMesh', artifactName: '${productName}-${version}-${os}-${arch}.${ext}', protocols: [ { name: 'SSH URL', schemes: ['ssh'] }, { name: 'Telnet URL', schemes: ['telnet'] }, { name: 'JumpServer URL', schemes: ['jms'] } ], electronLanguages: ['en', 'en-US', 'zh_CN', 'zh-CN', 'zh_TW', 'zh-TW', 'ru'], // Give the macOS build a unique Mach-O LC_UUID before signing, so macOS // Local Network privacy treats Netcatty distinctly from every other // Electron app (which all share Electron's prebuilt LC_UUID) — see #1040 // and scripts/afterPackMacUuid.cjs. No-op on Windows/Linux. beforePack: './scripts/beforePackCursorSdk.cjs', afterPack: './scripts/afterPackMacUuid.cjs', // Platform-split icons (#813): // - public/icon.png keeps Apple's HIG grid margin so the rendered // squircle sits at ~88% of the PNG canvas. macOS needs this — // the dock renders icons with its own rounding/shadow and most // third-party apps (#803) leave that grid margin alone so the // squircle lines up with neighbors. // - public/icon-win.png uses a tight-crop viewBox so the squircle // fills 100% of the PNG. Windows / Linux taskbars render icons // full-bleed, so the Apple margin showed up as visible padding, // making the app icon look smaller than other apps in taskbar / // Start menu / desktop shortcuts. icon: 'public/icon.png', // npmRebuild 默认开启,会尝试下载 Electron headers 重新编译所有 native modules。 // 内网环境访问 www.electronjs.org 超时,关闭它直接用 dev 模式下已编译好的 native deps。 // 如果 release 后 native modules 在目标机器上报 ABI mismatch,再回来开它 + 配 npmmirror 的 ELECTRON_MIRROR。 npmRebuild: false, directories: { buildResources: 'build', output: 'release' }, files: [ // electron-builder 收集器只读根 package.json,但 workspace 子包的运行时依赖 // 会 hoist 到根 node_modules 却没在根 package.json 里声明。 // 收集器会漏掉这些包,所以把漏的补进根 package.json 后它就能追踪完整传递依赖树。 "dist/**/*", "electron/**/*", "!electron/bridges/windowsHelloHelper/build/**/*", "!electron/plugins/fixtures/**/*", "infrastructure/config/terminalFlowConstants.cjs", "infrastructure/config/terminalFlowConstants.json", "domain/terminalPromptSecurity.shared.cjs", "lib/**/*.cjs", "lib/**/*.json", "skills/**/*" ], asarUnpack: [ 'node_modules/node-pty/**/*', 'node_modules/ssh2/**/*', 'node_modules/cpu-features/**/*', 'node_modules/@vscode/windows-process-tree/**/*', 'node_modules/@anthropic-ai/claude-agent-sdk/**/*', 'node_modules/@cursor/sdk-*/**/*', 'node_modules/sqlite3/**/*', 'node_modules/@modelcontextprotocol/sdk/**/*', 'lib/**/*.cjs', 'lib/**/*.json', 'node_modules/zod/**/*', 'node_modules/zod-to-json-schema/**/*', 'node_modules/@netcatty/plugin-cli/**/*', 'node_modules/@netcatty/plugin-contract/**/*', 'node_modules/@netcatty/plugin-sdk/**/*', 'electron/plugins/runtime/**/*', 'node_modules/ajv/**/*', 'node_modules/ajv-formats/**/*', 'node_modules/fast-deep-equal/**/*', 'node_modules/fast-uri/**/*', 'node_modules/json-schema-traverse/**/*', 'electron/cli/**/*', 'electron/capabilities/**/*', 'electron/shared/**/*', 'electron/mcp/**/*', 'skills/**/*' ], mac: { // app-builder's PNG-to-ICNS conversion can corrupt the 16px/32px 1x // representations even though the source PNG is valid RGBA. Use the // iconutil-generated bundle instead so Finder and app switchers do not // render those representations as colored noise. icon: 'build/icon.icns', target: [ { target: 'dmg', arch: ['arm64', 'x64'] }, { target: 'zip', arch: ['arm64', 'x64'] } ], category: 'public.app-category.developer-tools', hardenedRuntime: true, notarize: true, entitlements: 'electron/entitlements.mac.plist', entitlementsInherit: 'electron/entitlements.mac.plist', extendInfo: { NSCameraUsageDescription: 'Netcatty may use the camera for video calls', NSMicrophoneUsageDescription: 'Netcatty may use the microphone for audio', NSLocalNetworkUsageDescription: 'Netcatty needs local network access for SSH connections', CFBundleDocumentTypes: [ { CFBundleTypeName: 'Folder', CFBundleTypeRole: 'Viewer', LSHandlerRank: 'Alternate', LSItemContentTypes: ['public.folder'] } ] }, extraResources: [...moshExtraResources('darwin'), ...etExtraResources('darwin')] }, dmg: { title: '${productName}', iconSize: 100, iconTextSize: 12, window: { width: 540, height: 380 }, contents: [ { x: 140, y: 158 }, { x: 400, y: 158, type: 'link', path: '/Applications' } ] }, win: { icon: 'build/icon.ico', // 先只打 zip(无需 NSIS / portable 联网构建),后续再按需恢复 NSIS installer target: ['zip'], extraResources: [ ...moshExtraResources('win32'), ...etExtraResources('win32'), ] }, portable: { artifactName: '${productName}-${version}-portable-${os}-${arch}.${ext}', }, nsis: { include: 'build/installer.nsh', oneClick: false, perMachine: false, allowElevation: true, allowToChangeInstallationDirectory: true, createDesktopShortcut: true, createStartMenuShortcut: true, shortcutName: 'NetMesh' }, linux: { // Linux .deb/.rpm/AppImage icons come from build/icons/* (see // scripts/generate-linux-icons.sh). Point at the icons directory // under buildResources — electron-builder still falls back to the // top-level icon (public/icon.png) when linux.icon is unset, which // installs only hicolor/1024x1024 and launchers miss the icon (#274, // #1340). Do NOT set linux.icon to a single 1024px PNG either. icon: 'icons', target: ['AppImage', 'deb', 'rpm', 'pacman'], category: 'Development', extraResources: [...moshExtraResources('linux'), ...etExtraResources('linux')] }, deb: { // Use gzip instead of default xz(lzma) for better compatibility with // Deepin OS and other distros that have issues with lzma decompression compression: 'gz', afterInstall: 'scripts/linux/after-install.tpl' }, rpm: { // Default fpm/electron-builder RPM compression is "xzmt" (multi-threaded // xz). AlmaLinux/RHEL 8 images provide `xz` but not the `xzmt` shim, so // rpmbuild fails with exit 127 during packaging. gzip is portable and // matches our deb preference for older distros. compression: 'gzip', afterInstall: 'scripts/linux/after-install.tpl', fpm: [ // Avoid rpm's generated /usr/lib/.build-id symlinks. Those hashes // are global on the host, so owning them can conflict with other RPMs. '--rpm-rpmbuild-define', '_build_id_links none', // Electron ships prebuilt binaries. RHEL/Alma brp post-install // scripts (strip/compress/etc.) can exit 127 when a helper is // missing or a gcc-toolset `strip` is on PATH; skip them. '--rpm-rpmbuild-define', '__os_install_post %{nil}', ] }, pacman: { // FPM-generated .pacman packages bypass Arch's alpm hooks that // normally refresh the hicolor icon cache. Without this, KDE cannot // resolve Icon=netcatty and shows a generic placeholder (#1358). afterInstall: 'scripts/linux/after-install.tpl', afterRemove: 'scripts/linux/after-remove.tpl', }, // publish: [ // { // provider: 'github', // owner: 'binaricat', // repo: 'Netcatty', // releaseType: 'release' // } // ], // 内网环境 —— 关闭 GitHub publish,electron-builder 不会再尝试连 github.com publish: null };