diff --git a/packages/frontend/electron/forge.config.mjs b/packages/frontend/electron/forge.config.mjs index 1013a619c4..3f03a274b0 100644 --- a/packages/frontend/electron/forge.config.mjs +++ b/packages/frontend/electron/forge.config.mjs @@ -6,6 +6,7 @@ import { fileURLToPath } from 'node:url'; import { utils } from '@electron-forge/core'; import { + appIdMap, arch, buildType, icnsPath, @@ -96,12 +97,7 @@ export default { buildIdentifier: buildType, packagerConfig: { name: productName, - appBundleId: fromBuildIdentifier({ - internal: 'pro.affine.internal', - canary: 'pro.affine.canary', - beta: 'pro.affine.beta', - stable: 'pro.affine.app', - }), + appBundleId: fromBuildIdentifier(appIdMap), icon: icnsPath, osxSign: { identity: 'Developer ID Application: TOEVERYTHING PTE. LTD.', diff --git a/packages/frontend/electron/package.json b/packages/frontend/electron/package.json index 1e676257b3..1d1f1cd856 100644 --- a/packages/frontend/electron/package.json +++ b/packages/frontend/electron/package.json @@ -18,7 +18,8 @@ "generate-assets": "node --loader ts-node/esm/transpile-only scripts/generate-assets.ts", "package": "cross-env NODE_OPTIONS=\"--loader ts-node/esm/transpile-only\" electron-forge package", "make": "cross-env NODE_OPTIONS=\"--loader ts-node/esm/transpile-only\" electron-forge make", - "make-squirrel": "node --loader ts-node/esm/transpile-only scripts/make-squirrel.ts" + "make-squirrel": "node --loader ts-node/esm/transpile-only scripts/make-squirrel.ts", + "make-nsis": "node --loader ts-node/esm/transpile-only scripts/make-nsis.ts" }, "main": "./dist/main.js", "devDependencies": { diff --git a/packages/frontend/electron/resources/icons/nsis-sidebar.bmp b/packages/frontend/electron/resources/icons/nsis-sidebar.bmp new file mode 100644 index 0000000000..c4d7697a00 Binary files /dev/null and b/packages/frontend/electron/resources/icons/nsis-sidebar.bmp differ diff --git a/packages/frontend/electron/scripts/make-env.ts b/packages/frontend/electron/scripts/make-env.ts index 15c474507c..7c05689eab 100644 --- a/packages/frontend/electron/scripts/make-env.ts +++ b/packages/frontend/electron/scripts/make-env.ts @@ -7,6 +7,7 @@ const ReleaseTypeSchema = z.enum(['stable', 'beta', 'canary', 'internal']); const __dirname = fileURLToPath(new URL('.', import.meta.url)); +const REPO_ROOT = path.resolve(__dirname, '..', '..', '..', '..'); const ROOT = path.resolve(__dirname, '..'); const envBuildType = (process.env.BUILD_TYPE || 'canary').trim().toLowerCase(); @@ -45,7 +46,15 @@ const platform = ? process.argv[process.argv.indexOf('--platform') + 1] : process.platform; +const appIdMap = { + internal: 'pro.affine.internal', + canary: 'pro.affine.canary', + beta: 'pro.affine.beta', + stable: 'pro.affine.app', +}; + export { + appIdMap, arch, buildType, icnsPath, @@ -55,6 +64,7 @@ export { icoPath, platform, productName, + REPO_ROOT, ROOT, stableBuild, }; diff --git a/packages/frontend/electron/scripts/make-nsis.ts b/packages/frontend/electron/scripts/make-nsis.ts new file mode 100644 index 0000000000..30dd1bb81e --- /dev/null +++ b/packages/frontend/electron/scripts/make-nsis.ts @@ -0,0 +1,90 @@ +import path from 'node:path'; + +import { buildForge } from 'app-builder-lib'; +import debug from 'debug'; +import fs from 'fs-extra'; + +import { + appIdMap, + arch, + buildType, + iconPngPath, + icoPath, + platform, + productName, + REPO_ROOT, + ROOT, +} from './make-env.js'; + +const log = debug('electron-forge:make-nsis'); + +async function make() { + const appName = productName; + const makeDir = path.resolve(ROOT, 'out', buildType, 'make'); + const outPath = path.resolve(makeDir, `nsis.windows/${arch}`); + const appDirectory = path.resolve( + ROOT, + 'out', + buildType, + `${appName}-${platform}-${arch}` + ); + + await fs.ensureDir(outPath); + await fs.emptyDir(outPath); + + // create tmp dir + const tmpPath = await fs.mkdtemp(appName); + + // copy app to tmp dir + log(`Copying app to ${tmpPath}`); + await fs.copy(appDirectory, tmpPath); + + log(`Calling app-builder-lib's buildForge() with ${tmpPath}`); + const output = await buildForge( + { dir: tmpPath }, + { + win: [`nsis:${arch}`], + config: { + appId: appIdMap[buildType], + productName, + executableName: productName, + icon: iconPngPath, + extraMetadata: { + // do not use package.json's name + name: productName, + }, + nsis: { + differentialPackage: false, + perMachine: false, + oneClick: false, + license: path.resolve(REPO_ROOT, 'LICENSE'), + include: path.resolve(ROOT, 'scripts', 'nsis-installer.nsh'), + installerIcon: icoPath, + allowToChangeInstallationDirectory: true, + installerSidebar: path.resolve( + ROOT, + 'resources', + 'icons', + 'nsis-sidebar.bmp' + ), + }, + }, + } + ); + + // Move the output to the actual output folder, app-builder-lib might get it wrong + log('Received output files', output); + + const result: Array = []; + for (const file of output) { + const filePath = path.resolve(outPath, path.basename(file)); + result.push(filePath); + + await fs.move(file, filePath); + } + + // cleanup + await fs.remove(tmpPath); +} + +make(); diff --git a/packages/frontend/electron/scripts/nsis-installer.nsh b/packages/frontend/electron/scripts/nsis-installer.nsh new file mode 100644 index 0000000000..f669e22eae --- /dev/null +++ b/packages/frontend/electron/scripts/nsis-installer.nsh @@ -0,0 +1 @@ +ManifestDPIAware true