mirror of
https://gitee.com/mateos/mateclaw.git
synced 2026-09-13 19:23:42 +08:00
* feat(desktop): support remote lite build mode without bundled JRE/JAR Add a dual packaging mode system controlled by the BUILD_MODE env var: - **local** (default): Full build bundling JRE + Spring Boot JAR, identical to the previous behavior. Supports both embedded local backend and remote server connection. - **remote** (lite): Omits the ~530 MB JRE/JAR resources, producing an installer that is ~81% smaller (97 MB vs 523 MB on macOS arm64). The app only supports connecting to a remote server; the "local" option is hidden from the splash connection chooser. Changes: - Replace static electron-builder.json with dynamic electron-builder.cjs that conditionally includes extraResources based on BUILD_MODE - Add build mode detection at runtime (checks JAR existence) with graceful fallback to remote-only mode - Add IPC handler app:get-build-mode and expose via preload - Hide "本地运行" option in splash when running a remote build - Ignore stale 'local' saved config in remote builds - Add package scripts: package:mac:local, package:mac:remote, etc. - Add missing build scripts: build.sh, download-jre.sh, build-all-platforms.sh - Add no-op afterPack hook (trim-playwright-driver.cjs) placeholder - Add cross-env devDependency for cross-platform BUILD_MODE support * feat(desktop): add white-label branding system for build-time rebranding Add a Vite plugin (scripts/branding.cjs) that replaces hardcoded "MateClaw" strings at build time, enabling white-label/OEM rebranding without modifying any source code. Configuration: - Edit branding.config.json (name, tagline, team, copyright, appId, githubUrl) - Or set BRAND_* env vars (BRAND_NAME, BRAND_TAGLINE, BRAND_TEAM, etc.) Usage: # Default build (MateClaw brand) npm run package:mac # Custom brand via env vars BRAND_NAME=MyAI BRAND_TAGLINE="Smart AI Helper" npm run package:mac:remote # Or edit branding.config.json and build normally npm run package:mac:remote Replacements applied at build time: - Brand name (window title, About dialog, error messages, console logs) - Tagline, team name, copyright line - GitHub repo/issues URLs - Logo file path - electron-builder config (productName, appId, artifactName, dmg title, publish repo) The branding plugin runs in Vite's transform hook, covering the renderer (App.vue, index.html), electron main process, and preload script. Server-coupled strings (H2 database name, Spring Boot property names) are intentionally NOT replaced to avoid breaking backend compatibility. --------- Co-authored-by: qiaozhipeng <qiaozhipeng@daojia-inc.com>
140 lines
4.1 KiB
JavaScript
140 lines
4.1 KiB
JavaScript
/**
|
|
* electron-builder.cjs — Dynamic build configuration.
|
|
*
|
|
* Two packaging modes are controlled by the BUILD_MODE environment variable:
|
|
*
|
|
* BUILD_MODE=local (default) Full build: bundles the embedded JRE and
|
|
* Spring Boot JAR so the desktop app can run a
|
|
* local backend. Original behavior.
|
|
*
|
|
* BUILD_MODE=remote Lightweight build: omits the JRE/JAR
|
|
* resources (~530 MB smaller on macOS). The app
|
|
* can only connect to a remote server — the
|
|
* "local" connection option is hidden in the
|
|
* splash UI.
|
|
*
|
|
* Branding is controlled by branding.config.json or BRAND_* env vars.
|
|
* See scripts/branding.cjs for details.
|
|
*
|
|
* Usage:
|
|
* BUILD_MODE=remote npx electron-builder --mac
|
|
* npm run package:mac:remote
|
|
* BRAND_NAME=MyAI npm run package:mac:remote
|
|
*/
|
|
'use strict'
|
|
|
|
const { loadBrandConfig } = require('./scripts/branding.cjs')
|
|
|
|
const mode = process.env.BUILD_MODE === 'remote' ? 'remote' : 'local'
|
|
const brand = loadBrandConfig(__dirname)
|
|
|
|
// Derive a short slug from the brand name for artifact file names.
|
|
// "MyAI" → "MyAI", "Cool App" → "Cool_App"
|
|
const brandSlug = brand.name.replace(/\s+/g, '_')
|
|
|
|
// Parse GitHub URL for publish config (owner/repo)
|
|
let githubOwner = 'matevip'
|
|
let githubRepo = 'mateclaw'
|
|
const ghMatch = brand.githubUrl.match(/github\.com\/([^/]+)\/([^/]+)/)
|
|
if (ghMatch) {
|
|
githubOwner = ghMatch[1]
|
|
githubRepo = ghMatch[2]
|
|
}
|
|
|
|
/** @type {import('electron-builder').Configuration} */
|
|
const config = {
|
|
appId: brand.appId,
|
|
productName: brand.name,
|
|
copyright: brand.copyright,
|
|
directories: { output: 'release' },
|
|
publish: [
|
|
{
|
|
provider: 'github',
|
|
owner: githubOwner,
|
|
repo: githubRepo,
|
|
},
|
|
],
|
|
files: ['dist-electron', 'dist'],
|
|
afterPack: 'scripts/trim-playwright-driver.cjs',
|
|
|
|
// extraResources: only bundle JRE + JAR in local mode.
|
|
// In remote mode this array is empty — the packaged app contains only the
|
|
// Electron + Vue shell, cutting ~530 MB from the installer.
|
|
extraResources:
|
|
mode === 'local'
|
|
? [
|
|
{
|
|
from: 'resources/jre/${os}-${arch}/',
|
|
to: 'jre/',
|
|
filter: ['**/*'],
|
|
},
|
|
{
|
|
from: 'resources/app.jar',
|
|
to: 'app.jar',
|
|
},
|
|
]
|
|
: [],
|
|
|
|
mac: {
|
|
category: 'public.app-category.productivity',
|
|
target: [
|
|
{ target: 'dmg', arch: ['arm64', 'x64'] },
|
|
{ target: 'zip', arch: ['arm64', 'x64'] },
|
|
],
|
|
icon: 'build/icon.icns',
|
|
hardenedRuntime: true,
|
|
gatekeeperAssess: false,
|
|
entitlements: 'build/entitlements.mac.plist',
|
|
entitlementsInherit: 'build/entitlements.mac.inherit.plist',
|
|
// Differentiate installers so users can tell local vs remote builds apart.
|
|
artifactName:
|
|
mode === 'remote'
|
|
? `${brandSlug}_Remote_${'$'}{version}_${'$'}{arch}.${'$'}{ext}`
|
|
: `${brandSlug}_${'$'}{version}_${'$'}{arch}.${'$'}{ext}`,
|
|
},
|
|
|
|
dmg: {
|
|
contents: [
|
|
{ x: 130, y: 220 },
|
|
{ x: 410, y: 220, type: 'link', path: '/Applications' },
|
|
],
|
|
title: `${brand.name} ${'$'}{version}`,
|
|
},
|
|
|
|
win: {
|
|
target: [
|
|
{ target: 'nsis', arch: 'x64' },
|
|
{ target: 'nsis', arch: 'arm64' },
|
|
],
|
|
icon: 'build/icon.ico',
|
|
artifactName:
|
|
mode === 'remote'
|
|
? `${brandSlug}_Remote_${'$'}{version}_${'$'}{arch}_Setup.${'$'}{ext}`
|
|
: `${brandSlug}_${'$'}{version}_${'$'}{arch}_Setup.${'$'}{ext}`,
|
|
},
|
|
|
|
nsis: {
|
|
oneClick: false,
|
|
perMachine: false,
|
|
allowToChangeInstallationDirectory: true,
|
|
deleteAppDataOnUninstall: false,
|
|
installerIcon: 'build/icon.ico',
|
|
uninstallerIcon: 'build/icon.ico',
|
|
installerHeaderIcon: 'build/icon.ico',
|
|
createDesktopShortcut: true,
|
|
createStartMenuShortcut: true,
|
|
},
|
|
|
|
linux: {
|
|
target: ['AppImage'],
|
|
icon: 'build/icon.png',
|
|
category: 'Utility',
|
|
artifactName:
|
|
mode === 'remote'
|
|
? `${brandSlug}_Remote_${'$'}{version}.${'$'}{ext}`
|
|
: `${brandSlug}_${'$'}{version}.${'$'}{ext}`,
|
|
},
|
|
}
|
|
|
|
module.exports = config
|