feat: add Windows .exe support

- Add @electron-forge/maker-squirrel for Windows installer
- Create .ico icon from existing PNG
- Fix compositor platform detection for win32
- Forge config now builds both .dmg (macOS) and .exe (Windows)
This commit is contained in:
2026-06-02 04:10:11 -05:00
parent e42a484ab0
commit e7520b28f9
5 changed files with 152 additions and 7 deletions
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 361 KiB

+10 -2
View File
@@ -2,16 +2,17 @@
* Electron Forge Configuration — Bradly Desktop App * Electron Forge Configuration — Bradly Desktop App
* *
* Handles packaging and creating distributable installers. * Handles packaging and creating distributable installers.
* Currently targets macOS (.dmg) only. * Targets: macOS (.dmg) and Windows (.exe)
*/ */
import type { ForgeConfig } from '@electron-forge/shared-types'; import type { ForgeConfig } from '@electron-forge/shared-types';
import { MakerDMG } from '@electron-forge/maker-dmg'; import { MakerDMG } from '@electron-forge/maker-dmg';
import { MakerSquirrel } from '@electron-forge/maker-squirrel';
const config: ForgeConfig = { const config: ForgeConfig = {
packagerConfig: { packagerConfig: {
name: 'Bradly', name: 'Bradly',
executableName: 'bradly', executableName: 'bradly',
icon: './assets/icon', icon: './assets/icon', // .icns for macOS, .ico for Windows (auto-resolved)
asar: { asar: {
// Remotion compositor binaries MUST be outside app.asar // Remotion compositor binaries MUST be outside app.asar
// because they are native executables that need direct filesystem access // because they are native executables that need direct filesystem access
@@ -43,9 +44,16 @@ const config: ForgeConfig = {
], ],
}, },
makers: [ makers: [
// macOS installer
new MakerDMG({ new MakerDMG({
format: 'ULFO', format: 'ULFO',
}), }),
// Windows installer (.exe)
new MakerSquirrel({
name: 'Bradly',
setupIcon: './assets/icon.ico',
iconUrl: 'https://raw.githubusercontent.com/kevdevg/Bradly/main/assets/icon.ico',
}),
], ],
}; };
+135 -4
View File
@@ -1,12 +1,12 @@
{ {
"name": "react-example", "name": "bradly",
"version": "0.0.0", "version": "0.1.0",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "react-example", "name": "bradly",
"version": "0.0.0", "version": "0.1.0",
"dependencies": { "dependencies": {
"@dnd-kit/core": "^6.3.1", "@dnd-kit/core": "^6.3.1",
"@dnd-kit/utilities": "^3.2.2", "@dnd-kit/utilities": "^3.2.2",
@@ -33,6 +33,7 @@
"devDependencies": { "devDependencies": {
"@electron-forge/cli": "^7.11.2", "@electron-forge/cli": "^7.11.2",
"@electron-forge/maker-dmg": "^7.11.2", "@electron-forge/maker-dmg": "^7.11.2",
"@electron-forge/maker-squirrel": "^7.11.2",
"@types/express": "^4.17.21", "@types/express": "^4.17.21",
"@types/file-saver": "^2.0.7", "@types/file-saver": "^2.0.7",
"@types/multer": "^2.1.0", "@types/multer": "^2.1.0",
@@ -604,6 +605,24 @@
"electron-installer-dmg": "^5.0.1" "electron-installer-dmg": "^5.0.1"
} }
}, },
"node_modules/@electron-forge/maker-squirrel": {
"version": "7.11.2",
"resolved": "https://registry.npmjs.org/@electron-forge/maker-squirrel/-/maker-squirrel-7.11.2.tgz",
"integrity": "sha512-4CILo57ZDEQH1mJxjhYCSXuv+WaU7oPq67KqiTLEUOEzmiPg9u9/z7FXE34H/Tn5aKWN3dy+ngAETzv6iERCGg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@electron-forge/maker-base": "7.11.2",
"@electron-forge/shared-types": "7.11.2",
"fs-extra": "^10.0.0"
},
"engines": {
"node": ">= 16.4.0"
},
"optionalDependencies": {
"electron-winstaller": "^5.3.0"
}
},
"node_modules/@electron-forge/plugin-base": { "node_modules/@electron-forge/plugin-base": {
"version": "7.11.2", "version": "7.11.2",
"resolved": "https://registry.npmjs.org/@electron-forge/plugin-base/-/plugin-base-7.11.2.tgz", "resolved": "https://registry.npmjs.org/@electron-forge/plugin-base/-/plugin-base-7.11.2.tgz",
@@ -5964,6 +5983,66 @@
} }
} }
}, },
"node_modules/electron-winstaller": {
"version": "5.4.0",
"resolved": "https://registry.npmjs.org/electron-winstaller/-/electron-winstaller-5.4.0.tgz",
"integrity": "sha512-bO3y10YikuUwUuDUQRM4KfwNkKhnpVO7IPdbsrejwN9/AABJzzTQ4GeHwyzNSrVO+tEH3/Np255a3sVZpZDjvg==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"optional": true,
"dependencies": {
"@electron/asar": "^3.2.1",
"debug": "^4.1.1",
"fs-extra": "^7.0.1",
"lodash": "^4.17.21",
"temp": "^0.9.0"
},
"engines": {
"node": ">=8.0.0"
},
"optionalDependencies": {
"@electron/windows-sign": "^1.1.2"
}
},
"node_modules/electron-winstaller/node_modules/fs-extra": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz",
"integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==",
"dev": true,
"license": "MIT",
"optional": true,
"dependencies": {
"graceful-fs": "^4.1.2",
"jsonfile": "^4.0.0",
"universalify": "^0.1.0"
},
"engines": {
"node": ">=6 <7 || >=8"
}
},
"node_modules/electron-winstaller/node_modules/jsonfile": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
"integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==",
"dev": true,
"license": "MIT",
"optional": true,
"optionalDependencies": {
"graceful-fs": "^4.1.6"
}
},
"node_modules/electron-winstaller/node_modules/universalify": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
"integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
"dev": true,
"license": "MIT",
"optional": true,
"engines": {
"node": ">= 4.0.0"
}
},
"node_modules/electron/node_modules/@electron/get": { "node_modules/electron/node_modules/@electron/get": {
"version": "2.0.3", "version": "2.0.3",
"resolved": "https://registry.npmjs.org/@electron/get/-/get-2.0.3.tgz", "resolved": "https://registry.npmjs.org/@electron/get/-/get-2.0.3.tgz",
@@ -8364,6 +8443,14 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/lodash": {
"version": "4.18.1",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz",
"integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==",
"dev": true,
"license": "MIT",
"optional": true
},
"node_modules/lodash.get": { "node_modules/lodash.get": {
"version": "4.4.2", "version": "4.4.2",
"resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
@@ -11178,6 +11265,50 @@
"dev": true, "dev": true,
"license": "ISC" "license": "ISC"
}, },
"node_modules/temp": {
"version": "0.9.4",
"resolved": "https://registry.npmjs.org/temp/-/temp-0.9.4.tgz",
"integrity": "sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA==",
"dev": true,
"license": "MIT",
"optional": true,
"dependencies": {
"mkdirp": "^0.5.1",
"rimraf": "~2.6.2"
},
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/temp/node_modules/mkdirp": {
"version": "0.5.6",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
"integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
"dev": true,
"license": "MIT",
"optional": true,
"dependencies": {
"minimist": "^1.2.6"
},
"bin": {
"mkdirp": "bin/cmd.js"
}
},
"node_modules/temp/node_modules/rimraf": {
"version": "2.6.3",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
"integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
"deprecated": "Rimraf versions prior to v4 are no longer supported",
"dev": true,
"license": "ISC",
"optional": true,
"dependencies": {
"glob": "^7.1.3"
},
"bin": {
"rimraf": "bin.js"
}
},
"node_modules/terser": { "node_modules/terser": {
"version": "5.48.0", "version": "5.48.0",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.48.0.tgz", "resolved": "https://registry.npmjs.org/terser/-/terser-5.48.0.tgz",
+1
View File
@@ -45,6 +45,7 @@
"devDependencies": { "devDependencies": {
"@electron-forge/cli": "^7.11.2", "@electron-forge/cli": "^7.11.2",
"@electron-forge/maker-dmg": "^7.11.2", "@electron-forge/maker-dmg": "^7.11.2",
"@electron-forge/maker-squirrel": "^7.11.2",
"@types/express": "^4.17.21", "@types/express": "^4.17.21",
"@types/file-saver": "^2.0.7", "@types/file-saver": "^2.0.7",
"@types/multer": "^2.1.0", "@types/multer": "^2.1.0",
+6 -1
View File
@@ -47,7 +47,12 @@ function setupPaths() {
} }
// Compositor binaries (unpacked from asar) // Compositor binaries (unpacked from asar)
const platform = process.platform === 'darwin' ? 'darwin' : 'linux'; const platformMap: Record<string, string> = {
darwin: 'darwin',
win32: 'win32',
linux: 'linux',
};
const platform = platformMap[process.platform] || process.platform;
const arch = process.arch; const arch = process.arch;
const compositorPath = path.join( const compositorPath = path.join(
resourcesPath, resourcesPath,