Merge pull request #3432 from balena-io/electron-11

Electron 11
This commit is contained in:
bulldozer-balena[bot] 2021-04-06 11:42:19 +00:00 committed by GitHub
commit 55d2400ac7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 2106 additions and 1958 deletions

View File

@ -15,7 +15,7 @@
}, },
"builder": { "builder": {
"appId": "io.balena.etcher", "appId": "io.balena.etcher",
"copyright": "Copyright 2016-2020 Balena Ltd", "copyright": "Copyright 2016-2021 Balena Ltd",
"productName": "balenaEtcher", "productName": "balenaEtcher",
"nodeGypRebuild": false, "nodeGypRebuild": false,
"afterPack": "./afterPack.js", "afterPack": "./afterPack.js",
@ -30,7 +30,8 @@
"category": "public.app-category.developer-tools", "category": "public.app-category.developer-tools",
"hardenedRuntime": true, "hardenedRuntime": true,
"entitlements": "entitlements.mac.plist", "entitlements": "entitlements.mac.plist",
"entitlementsInherit": "entitlements.mac.plist" "entitlementsInherit": "entitlements.mac.plist",
"artifactName": "${productName}-${version}.${ext}"
}, },
"dmg": { "dmg": {
"iconSize": 110, "iconSize": 110,

103
README.md
View File

@ -5,16 +5,16 @@
Etcher is a powerful OS image flasher built with web technologies to ensure Etcher is a powerful OS image flasher built with web technologies to ensure
flashing an SDCard or USB drive is a pleasant and safe experience. It protects flashing an SDCard or USB drive is a pleasant and safe experience. It protects
you from accidentally writing to your hard-drives, ensures every byte of data you from accidentally writing to your hard-drives, ensures every byte of data
was written correctly and much more. It can also flash directly Raspberry Pi devices that support the usbboot protocol was written correctly, and much more. It can also directly flash Raspberry Pi devices that support [USB device boot mode](https://www.raspberrypi.org/documentation/hardware/raspberrypi/bootmodes/device.md).
[![Current Release](https://img.shields.io/github/release/balena-io/etcher.svg?style=flat-square)](https://balena.io/etcher) [![Current Release](https://img.shields.io/github/release/balena-io/etcher.svg?style=flat-square)](https://balena.io/etcher)
[![License](https://img.shields.io/github/license/balena-io/etcher.svg?style=flat-square)](https://github.com/balena-io/etcher/blob/master/LICENSE) [![License](https://img.shields.io/github/license/balena-io/etcher.svg?style=flat-square)](https://github.com/balena-io/etcher/blob/master/LICENSE)
[![Dependency status](https://img.shields.io/david/balena-io/etcher.svg?style=flat-square)](https://david-dm.org/balena-io/etcher) [![Dependency status](https://img.shields.io/david/balena-io/etcher.svg?style=flat-square)](https://david-dm.org/balena-io/etcher)
[![Balena.io Forums](https://img.shields.io/discourse/https/forums.balena.io/topics.svg?style=flat-square&label=balena.io%20forums)](https://forums.balena.io/c/etcher) [![Balena.io Forums](https://img.shields.io/discourse/https/forums.balena.io/topics.svg?style=flat-square&label=balena.io%20forums)](https://forums.balena.io/c/etcher)
*** ---
[**Download**][etcher] | [**Support**][SUPPORT] | [**Documentation**][USER-DOCUMENTATION] | [**Contributing**][CONTRIBUTING] | [**Roadmap**][milestones] [**Download**][etcher] | [**Support**][support] | [**Documentation**][user-documentation] | [**Contributing**][contributing] | [**Roadmap**][milestones]
## Supported Operating Systems ## Supported Operating Systems
@ -22,7 +22,7 @@ was written correctly and much more. It can also flash directly Raspberry Pi dev
- macOS 10.10 (Yosemite) and later - macOS 10.10 (Yosemite) and later
- Microsoft Windows 7 and later - Microsoft Windows 7 and later
Note that Etcher will run on any platform officially supported by **Note**: Etcher will run on any platform officially supported by
[Electron][electron]. Read more in their [Electron][electron]. Read more in their
[documentation][electron-supported-platforms]. [documentation][electron-supported-platforms].
@ -33,24 +33,24 @@ installers for all supported operating systems.
#### Debian and Ubuntu based Package Repository (GNU/Linux x86/x64) #### Debian and Ubuntu based Package Repository (GNU/Linux x86/x64)
1. Add Etcher debian repository: 1. Add Etcher Debian repository:
```sh ```sh
echo "deb https://deb.etcher.io stable etcher" | sudo tee /etc/apt/sources.list.d/balena-etcher.list echo "deb https://deb.etcher.io stable etcher" | sudo tee /etc/apt/sources.list.d/balena-etcher.list
``` ```
2. Trust Bintray.com's GPG key: 2. Trust Bintray.com's GPG key:
```sh ```sh
sudo apt-key adv --keyserver hkps://keyserver.ubuntu.com:443 --recv-keys 379CE192D401AB61 sudo apt-key adv --keyserver hkps://keyserver.ubuntu.com:443 --recv-keys 379CE192D401AB61
``` ```
3. Update and install: 3. Update and install:
```sh ```sh
sudo apt-get update sudo apt-get update
sudo apt-get install balena-etcher-electron sudo apt-get install balena-etcher-electron
``` ```
##### Uninstall ##### Uninstall
@ -74,25 +74,46 @@ sudo zypper in balena-etcher-electron
sudo zypper rm balena-etcher-electron sudo zypper rm balena-etcher-electron
``` ```
#### Redhat (RHEL) and Fedora based Package Repository (GNU/Linux x86/x64) #### Redhat (RHEL) and Fedora-based Package Repository (GNU/Linux x86/x64)
##### DNF
1. Add Etcher rpm repository: 1. Add Etcher rpm repository:
```sh ```sh
sudo wget https://balena.io/etcher/static/etcher-rpm.repo -O /etc/yum.repos.d/etcher-rpm.repo sudo sudo dnf config-manager --add-repo https://balena.io/etcher/static/etcher-rpm.repo
``` ```
2. Update and install: 2. Update and install:
```sh ```sh
sudo yum install -y balena-etcher-electron sudo dnf install -y balena-etcher-electron
``` ```
or
```sh
sudo dnf install -y balena-etcher-electron
```
##### Uninstall ###### Uninstall
```sh
sudo dnf remove -y balena-etcher-electron
sudo rm /etc/yum.repos.d/etcher-rpm.repo
sudo dnf clean all
sudo dnf makecache
```
##### Yum
1. Add Etcher rpm repository:
```sh
sudo wget https://balena.io/etcher/static/etcher-rpm.repo -O /etc/yum.repos.d/etcher-rpm.repo
```
2. Update and install:
```sh
sudo yum install -y balena-etcher-electron
```
###### Uninstall
```sh ```sh
sudo yum remove -y balena-etcher-electron sudo yum remove -y balena-etcher-electron
@ -100,13 +121,6 @@ sudo rm /etc/yum.repos.d/etcher-rpm.repo
sudo yum clean all sudo yum clean all
sudo yum makecache fast sudo yum makecache fast
``` ```
or
```sh
sudo dnf remove -y balena-etcher-electron
sudo rm /etc/yum.repos.d/etcher-rpm.repo
sudo dnf clean all
sudo dnf makecache
```
#### Solus (GNU/Linux x64) #### Solus (GNU/Linux x64)
@ -120,11 +134,10 @@ sudo eopkg it etcher
sudo eopkg rm etcher sudo eopkg rm etcher
``` ```
#### Arch Linux / Manjaro (GNU/Linux x64) #### Arch/Manjaro Linux (GNU/Linux x64)
Etcher is offered through the Arch User Repository and can be installed on both Manjaro and Arch systems. You can compile it from the source code in this repository using [`balena-etcher`](https://aur.archlinux.org/packages/balena-etcher/). The following example uses a common AUR helper to install the latest release: Etcher is offered through the Arch User Repository and can be installed on both Manjaro and Arch systems. You can compile it from the source code in this repository using [`balena-etcher`](https://aur.archlinux.org/packages/balena-etcher/). The following example uses a common AUR helper to install the latest release:
```sh ```sh
yay -S balena-etcher yay -S balena-etcher
``` ```
@ -135,20 +148,20 @@ yay -S balena-etcher
yay -R balena-etcher yay -R balena-etcher
``` ```
#### Brew Cask (macOS) #### Brew (macOS)
Note that the Etcher Cask has to be updated manually to point to new versions, **Note**: Etcher has to be updated manually to point to new versions,
so it might not refer to the latest version immediately after an Etcher so it might not refer to the latest version immediately after an Etcher
release. release.
```sh ```sh
brew cask install balenaetcher brew install balenaetcher
``` ```
##### Uninstall ##### Uninstall
```sh ```sh
brew cask uninstall balenaetcher brew uninstall balenaetcher
``` ```
#### Chocolatey (Windows) #### Chocolatey (Windows)
@ -168,20 +181,20 @@ choco uninstall etcher
## Support ## Support
If you're having any problem, please [raise an issue][newissue] on GitHub and If you're having any problem, please [raise an issue][newissue] on GitHub, and
the balena.io team will be happy to help. the balena.io team will be happy to help.
## License ## License
Etcher is free software, and may be redistributed under the terms specified in Etcher is free software and may be redistributed under the terms specified in
the [license]. the [license].
[etcher]: https://balena.io/etcher [etcher]: https://balena.io/etcher
[electron]: https://electronjs.org/ [electron]: https://electronjs.org/
[electron-supported-platforms]: https://electronjs.org/docs/tutorial/support#supported-platforms [electron-supported-platforms]: https://electronjs.org/docs/tutorial/support#supported-platforms
[SUPPORT]: https://github.com/balena-io/etcher/blob/master/SUPPORT.md [support]: https://github.com/balena-io/etcher/blob/master/SUPPORT.md
[CONTRIBUTING]: https://github.com/balena-io/etcher/blob/master/docs/CONTRIBUTING.md [contributing]: https://github.com/balena-io/etcher/blob/master/docs/CONTRIBUTING.md
[USER-DOCUMENTATION]: https://github.com/balena-io/etcher/blob/master/docs/USER-DOCUMENTATION.md [user-documentation]: https://github.com/balena-io/etcher/blob/master/docs/USER-DOCUMENTATION.md
[milestones]: https://github.com/balena-io/etcher/milestones [milestones]: https://github.com/balena-io/etcher/milestones
[newissue]: https://github.com/balena-io/etcher/issues/new [newissue]: https://github.com/balena-io/etcher/issues/new
[license]: https://github.com/balena-io/etcher/blob/master/LICENSE [license]: https://github.com/balena-io/etcher/blob/master/LICENSE

View File

@ -6,21 +6,28 @@ const process = require('process');
// Rebuild native modules for ia32 and run webpack again for the ia32 part of windows packages // Rebuild native modules for ia32 and run webpack again for the ia32 part of windows packages
exports.default = function(context) { exports.default = function(context) {
if (context.platform.name === 'windows') { if (['windows', 'mac'].includes(context.platform.name)) {
cp.execFileSync( const run = context.platform.name === 'windows' ? 'sh' : 'node';
'bash', cp.execFileSync(
['./node_modules/.bin/electron-rebuild', '--types', 'dev', '--arch', context.arch], run,
); ['node_modules/.bin/electron-rebuild', '--types', 'dev', '--arch', context.arch],
{
env: {
...process.env,
npm_config_msvs_version: '2019',
},
},
);
rimraf.sync('generated'); rimraf.sync('generated');
cp.execFileSync( cp.execFileSync(
'bash', run,
['./node_modules/.bin/webpack'], ['node_modules/.bin/webpack'],
{ {
env: { env: {
...process.env, ...process.env,
npm_config_target_arch: context.arch, npm_config_target_arch: context.arch,
}, },
}, },
); );
} }
} }

View File

@ -1,5 +1,5 @@
appId: io.balena.etcher appId: io.balena.etcher
copyright: Copyright 2016-2020 Balena Ltd copyright: Copyright 2016-2021 Balena Ltd
productName: balenaEtcher productName: balenaEtcher
npmRebuild: true npmRebuild: true
nodeGypRebuild: false nodeGypRebuild: false
@ -16,6 +16,7 @@ mac:
hardenedRuntime: true hardenedRuntime: true
entitlements: "entitlements.mac.plist" entitlements: "entitlements.mac.plist"
entitlementsInherit: "entitlements.mac.plist" entitlementsInherit: "entitlements.mac.plist"
artifactName: "${productName}-${version}.${ext}"
dmg: dmg:
background: assets/dmg/background.tiff background: assets/dmg/background.tiff
icon: assets/icon.icns icon: assets/icon.icns

View File

@ -15,7 +15,6 @@
*/ */
import { Drive as DrivelistDrive } from 'drivelist'; import { Drive as DrivelistDrive } from 'drivelist';
import * as electron from 'electron';
import * as sdk from 'etcher-sdk'; import * as sdk from 'etcher-sdk';
import { Dictionary } from 'lodash'; import { Dictionary } from 'lodash';
import * as ipc from 'node-ipc'; import * as ipc from 'node-ipc';
@ -25,6 +24,7 @@ import * as path from 'path';
import * as packageJSON from '../../../../package.json'; import * as packageJSON from '../../../../package.json';
import * as errors from '../../../shared/errors'; import * as errors from '../../../shared/errors';
import * as permissions from '../../../shared/permissions'; import * as permissions from '../../../shared/permissions';
import { getAppPath } from '../../../shared/utils';
import { SourceMetadata } from '../components/source-selector/source-selector'; import { SourceMetadata } from '../components/source-selector/source-selector';
import * as flashState from '../models/flash-state'; import * as flashState from '../models/flash-state';
import * as selectionState from '../models/selection-state'; import * as selectionState from '../models/selection-state';
@ -93,11 +93,7 @@ function terminateServer() {
} }
function writerArgv(): string[] { function writerArgv(): string[] {
let entryPoint = path.join( let entryPoint = path.join(getAppPath(), 'generated', 'child-writer.js');
electron.remote.app.getAppPath(),
'generated',
'child-writer.js',
);
// AppImages run over FUSE, so the files inside the mount point // AppImages run over FUSE, so the files inside the mount point
// can only be accessed by the user that mounted the AppImage. // can only be accessed by the user that mounted the AppImage.
// This means we can't re-spawn Etcher as root from the same // This means we can't re-spawn Etcher as root from the same

View File

@ -278,7 +278,7 @@ export class MainPage extends React.Component<
// @ts-ignore // @ts-ignore
'-webkit-app-region': 'drag', '-webkit-app-region': 'drag',
position: 'relative', position: 'relative',
zIndex: 1, zIndex: 2,
}} }}
> >
<Flex width="100%" /> <Flex width="100%" />

View File

@ -147,6 +147,7 @@ async function createMainWindow() {
webPreferences: { webPreferences: {
backgroundThrottling: false, backgroundThrottling: false,
nodeIntegration: true, nodeIntegration: true,
contextIsolation: false,
webviewTag: true, webviewTag: true,
zoomFactor: width / defaultWidth, zoomFactor: width / defaultWidth,
enableRemoteModule: true, enableRemoteModule: true,

View File

@ -15,11 +15,12 @@
*/ */
import { execFile } from 'child_process'; import { execFile } from 'child_process';
import { app, remote } from 'electron';
import { join } from 'path'; import { join } from 'path';
import { env } from 'process'; import { env } from 'process';
import { promisify } from 'util'; import { promisify } from 'util';
import { getAppPath } from '../utils';
const execFileAsync = promisify(execFile); const execFileAsync = promisify(execFile);
const SUCCESSFUL_AUTH_MARKER = 'AUTHENTICATION SUCCEEDED'; const SUCCESSFUL_AUTH_MARKER = 'AUTHENTICATION SUCCEEDED';
@ -37,7 +38,7 @@ export async function sudo(
env: { env: {
PATH: env.PATH, PATH: env.PATH,
SUDO_ASKPASS: join( SUDO_ASKPASS: join(
(app || remote.app).getAppPath(), getAppPath(),
__dirname, __dirname,
'sudo-askpass.osascript.js', 'sudo-askpass.osascript.js',
), ),

View File

@ -15,6 +15,7 @@
*/ */
import axios from 'axios'; import axios from 'axios';
import { app, remote } from 'electron';
import { Dictionary } from 'lodash'; import { Dictionary } from 'lodash';
import * as errors from './errors'; import * as errors from './errors';
@ -47,3 +48,16 @@ export async function delay(duration: number): Promise<void> {
setTimeout(resolve, duration); setTimeout(resolve, duration);
}); });
} }
export function getAppPath(): string {
return (
(app || remote.app)
.getAppPath()
// With macOS universal builds, getAppPath() returns the path to an app.asar file containing an index.js file which will
// include the app-x64 or app-arm64 folder depending on the arch.
// We don't care about the app.asar file, we want the actual folder.
.replace(/\.asar$/, () =>
process.platform === 'darwin' ? '-' + process.arch : '',
)
);
}

3758
npm-shrinkwrap.json generated

File diff suppressed because it is too large Load Diff

View File

@ -46,6 +46,14 @@
"author": "Balena Inc. <hello@etcher.io>", "author": "Balena Inc. <hello@etcher.io>",
"license": "Apache-2.0", "license": "Apache-2.0",
"platformSpecificDependencies": [ "platformSpecificDependencies": [
"xmlbuilder",
"xmldom",
"@types/plist",
"@types/verror",
"crc",
"iconv-corefoundation",
"plist",
"dmg-license",
"fsevents", "fsevents",
"winusb-driver-generator" "winusb-driver-generator"
], ],
@ -66,18 +74,19 @@
"@types/terser-webpack-plugin": "^5.0.2", "@types/terser-webpack-plugin": "^5.0.2",
"@types/tmp": "^0.2.0", "@types/tmp": "^0.2.0",
"@types/webpack-node-externals": "^2.5.0", "@types/webpack-node-externals": "^2.5.0",
"aws4-axios": "2.2.1",
"chai": "^4.2.0", "chai": "^4.2.0",
"copy-webpack-plugin": "^7.0.0", "copy-webpack-plugin": "^7.0.0",
"css-loader": "^5.0.1", "css-loader": "^5.0.1",
"d3": "^4.13.0", "d3": "^4.13.0",
"debug": "^4.2.0", "debug": "^4.2.0",
"electron": "9.4.1", "electron": "12.0.2",
"electron-builder": "^22.9.1", "electron-builder": "^22.10.5",
"electron-mocha": "^9.3.2", "electron-mocha": "^9.3.2",
"electron-notarize": "^1.0.0", "electron-notarize": "^1.0.0",
"electron-rebuild": "^2.3.2", "electron-rebuild": "^2.3.2",
"electron-updater": "^4.3.5", "electron-updater": "^4.3.5",
"etcher-sdk": "^6.1.0", "etcher-sdk": "^6.2.1",
"file-loader": "^6.2.0", "file-loader": "^6.2.0",
"husky": "^4.2.5", "husky": "^4.2.5",
"immutable": "^3.8.1", "immutable": "^3.8.1",
@ -99,7 +108,7 @@
"semver": "^7.3.2", "semver": "^7.3.2",
"simple-progress-webpack-plugin": "^1.1.2", "simple-progress-webpack-plugin": "^1.1.2",
"sinon": "^9.0.2", "sinon": "^9.0.2",
"spectron": "^11.0.0", "spectron": "^14.0.0",
"string-replace-loader": "^3.0.1", "string-replace-loader": "^3.0.1",
"styled-components": "^5.1.0", "styled-components": "^5.1.0",
"sudo-prompt": "github:zvin/sudo-prompt#7cdede2f0da28fbcc2db48402d7d935f3a825c91", "sudo-prompt": "github:zvin/sudo-prompt#7cdede2f0da28fbcc2db48402d7d935f3a825c91",

View File

@ -29,6 +29,10 @@ const SHRINKWRAP_FILENAME = path.join(__dirname, '..', 'npm-shrinkwrap.json');
async function main() { async function main() {
try { try {
const cleaned = omit(shrinkwrap, packageInfo.platformSpecificDependencies); const cleaned = omit(shrinkwrap, packageInfo.platformSpecificDependencies);
for (const item of Object.values(cleaned.dependencies)) {
// @ts-ignore
item.dev = true;
}
await writeFileAsync( await writeFileAsync(
SHRINKWRAP_FILENAME, SHRINKWRAP_FILENAME,
JSON.stringify(cleaned, null, JSON_INDENT), JSON.stringify(cleaned, null, JSON_INDENT),

@ -1 +1 @@
Subproject commit 214ddc7e3d35f7c37424c5a7696e33b10e424f43 Subproject commit d1b05ad312e65ea82b1c16b31f5af3c0b5fa2777

View File

@ -15,46 +15,52 @@
*/ */
import { expect } from 'chai'; import { expect } from 'chai';
import { platform } from 'os';
import { Application } from 'spectron'; import { Application } from 'spectron';
import * as electronPath from 'electron'; import * as electronPath from 'electron';
describe('Spectron', function () { // TODO: spectron fails to start on the CI with:
// Mainly for CI jobs // Error: Failed to create session.
this.timeout(40000); // unknown error: Chrome failed to start: exited abnormally
if (platform() !== 'darwin') {
describe('Spectron', function () {
// Mainly for CI jobs
this.timeout(40000);
const app = new Application({ const app = new Application({
path: (electronPath as unknown) as string, path: (electronPath as unknown) as string,
args: ['--no-sandbox', '.'], args: ['--no-sandbox', '.'],
});
before('app:start', async () => {
await app.start();
});
after('app:stop', async () => {
if (app && app.isRunning()) {
await app.stop();
}
});
describe('Browser Window', () => {
it('should open a browser window', async () => {
// We can't use `isVisible()` here as it won't work inside
// a Windows Docker container, but we can approximate it
// with these set of checks:
const bounds = await app.browserWindow.getBounds();
expect(bounds.height).to.be.above(0);
expect(bounds.width).to.be.above(0);
expect(await app.browserWindow.isMinimized()).to.be.false;
expect(
(await app.browserWindow.isVisible()) ||
(await app.browserWindow.isFocused()),
).to.be.true;
}); });
it('should set a proper title', async () => { before('app:start', async () => {
// @ts-ignore (SpectronClient.getTitle exists) await app.start();
return expect(await app.client.getTitle()).to.equal('Etcher'); });
after('app:stop', async () => {
if (app && app.isRunning()) {
await app.stop();
}
});
describe('Browser Window', () => {
it('should open a browser window', async () => {
// We can't use `isVisible()` here as it won't work inside
// a Windows Docker container, but we can approximate it
// with these set of checks:
const bounds = await app.browserWindow.getBounds();
expect(bounds.height).to.be.above(0);
expect(bounds.width).to.be.above(0);
expect(await app.browserWindow.isMinimized()).to.be.false;
expect(
(await app.browserWindow.isVisible()) ||
(await app.browserWindow.isFocused()),
).to.be.true;
});
it('should set a proper title', async () => {
// @ts-ignore (SpectronClient.getTitle exists)
return expect(await app.client.getTitle()).to.equal('Etcher');
});
}); });
}); });
}); }

View File

@ -68,6 +68,8 @@ function renameNodeModules(resourcePath: string) {
path path
.relative(__dirname, resourcePath) .relative(__dirname, resourcePath)
.replace('node_modules', 'modules') .replace('node_modules', 'modules')
// use the same name on all architectures so electron-builder can build a universal dmg on mac
.replace(LZMA_BINDINGS_FOLDER, LZMA_BINDINGS_FOLDER_RENAMED)
// file-loader expects posix paths, even on Windows // file-loader expects posix paths, even on Windows
.replace(/\\/g, '/') .replace(/\\/g, '/')
); );
@ -87,6 +89,7 @@ function findLzmaNativeBindingsFolder(): string {
} }
const LZMA_BINDINGS_FOLDER = findLzmaNativeBindingsFolder(); const LZMA_BINDINGS_FOLDER = findLzmaNativeBindingsFolder();
const LZMA_BINDINGS_FOLDER_RENAMED = 'binding';
interface ReplacementRule { interface ReplacementRule {
search: string; search: string;
@ -117,7 +120,15 @@ function fetchWasm(...where: string[]) {
} catch { } catch {
} }
function appPath() { function appPath() {
return Path.isAbsolute(__dirname) ? __dirname : Path.join(electron.remote.app.getAppPath(), 'generated'); return Path.isAbsolute(__dirname) ?
__dirname :
Path.join(
// With macOS universal builds, getAppPath() returns the path to an app.asar file containing an index.js file which will
// include the app-x64 or app-arm64 folder depending on the arch.
// We don't care about the app.asar file, we want the actual folder.
electron.remote.app.getAppPath().replace(/\\.asar$/, () => process.platform === 'darwin' ? '-' + process.arch : ''),
'generated'
);
} }
scriptDirectory = Path.join(appPath(), 'modules', ${whereStr}, '/'); scriptDirectory = Path.join(appPath(), 'modules', ${whereStr}, '/');
`; `;
@ -126,6 +137,7 @@ function fetchWasm(...where: string[]) {
const commonConfig = { const commonConfig = {
mode: 'production', mode: 'production',
optimization: { optimization: {
moduleIds: 'natural',
minimize: true, minimize: true,
minimizer: [ minimizer: [
new TerserPlugin({ new TerserPlugin({
@ -190,12 +202,7 @@ const commonConfig = {
// remove node-pre-gyp magic from lzma-native // remove node-pre-gyp magic from lzma-native
{ {
search: 'require(binding_path)', search: 'require(binding_path)',
replace: () => { replace: `require('./${LZMA_BINDINGS_FOLDER}/lzma_native.node')`,
return `require('./${path.posix.join(
LZMA_BINDINGS_FOLDER,
'lzma_native.node',
)}')`;
},
}, },
// use regular stream module instead of readable-stream // use regular stream module instead of readable-stream
{ {
@ -239,7 +246,19 @@ const commonConfig = {
"return await readFile(Path.join(__dirname, '..', 'blobs', filename));", "return await readFile(Path.join(__dirname, '..', 'blobs', filename));",
replace: outdent` replace: outdent`
const { app, remote } = require('electron'); const { app, remote } = require('electron');
return await readFile(Path.join((app || remote.app).getAppPath(), 'generated', __dirname.replace('node_modules', 'modules'), '..', 'blobs', filename)); return await readFile(
Path.join(
// With macOS universal builds, getAppPath() returns the path to an app.asar file containing an index.js file which will
// include the app-x64 or app-arm64 folder depending on the arch.
// We don't care about the app.asar file, we want the actual folder.
(app || remote.app).getAppPath().replace(/\\.asar$/, () => process.platform === 'darwin' ? '-' + process.arch : ''),
'generated',
__dirname.replace('node_modules', 'modules'),
'..',
'blobs',
filename
)
);
`, `,
}), }),
// Use the libext2fs.wasm file in the generated folder // Use the libext2fs.wasm file in the generated folder
@ -317,7 +336,7 @@ if (os.platform() === 'win32') {
// liblzma.dll is required on Windows for lzma-native // liblzma.dll is required on Windows for lzma-native
guiConfigCopyPatterns.push({ guiConfigCopyPatterns.push({
from: `node_modules/lzma-native/${LZMA_BINDINGS_FOLDER}/liblzma.dll`, from: `node_modules/lzma-native/${LZMA_BINDINGS_FOLDER}/liblzma.dll`,
to: `modules/lzma-native/${LZMA_BINDINGS_FOLDER}/liblzma.dll`, to: `modules/lzma-native/${LZMA_BINDINGS_FOLDER_RENAMED}/liblzma.dll`,
}); });
} }