diff --git a/package.json b/package.json index 22f76a5f81..f2eb3bfd4f 100644 --- a/package.json +++ b/package.json @@ -91,6 +91,7 @@ }, "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.1", + "@knodes/typedoc-plugin-monorepo-readmes": "0.22.5", "@malept/eslint-config": "^2.0.0", "@swc/cli": "^0.1.49", "@swc/core": "^1.2.87", @@ -133,6 +134,7 @@ "eslint-plugin-promise": "^6.0.0", "eslint-plugin-tsdoc": "^0.2.14", "fetch-mock": "^9.10.7", + "fork-ts-checker-webpack-plugin": "^7.2.13", "generate-changelog": "^1.8.0", "husky": "^8.0.1", "lint-staged": "^13.0.3", @@ -149,7 +151,6 @@ "typedoc": "^0.22.15", "typedoc-plugin-missing-exports": "^1.0.0", "typedoc-plugin-rename-defaults": "^0.6.4", - "@knodes/typedoc-plugin-monorepo-readmes": "0.22.5", "typescript": "^4.6.3", "xvfb-maybe": "^0.2.1" }, diff --git a/packages/api/core/package.json b/packages/api/core/package.json index 0c72c2edc3..ee0ac8d424 100644 --- a/packages/api/core/package.json +++ b/packages/api/core/package.json @@ -40,6 +40,7 @@ }, "dependencies": { "@electron-forge/async-ora": "6.0.0-beta.70", + "@electron-forge/core-utils": "^6.0.0-beta.70", "@electron-forge/maker-base": "6.0.0-beta.70", "@electron-forge/plugin-base": "6.0.0-beta.70", "@electron-forge/publisher-base": "6.0.0-beta.70", diff --git a/packages/api/core/src/api/import.ts b/packages/api/core/src/api/import.ts index 981788f249..728272976e 100644 --- a/packages/api/core/src/api/import.ts +++ b/packages/api/core/src/api/import.ts @@ -1,13 +1,13 @@ import path from 'path'; import { asyncOra } from '@electron-forge/async-ora'; +import { updateElectronDependency } from '@electron-forge/core-utils'; import baseTemplate from '@electron-forge/template-base'; import chalk from 'chalk'; import debug from 'debug'; import fs from 'fs-extra'; import { merge } from 'lodash'; -import { updateElectronDependency } from '../util/electron-version'; import installDepList, { DepType, DepVersionRestriction } from '../util/install-dependencies'; import { info, warn } from '../util/messages'; import { readRawPackageJson } from '../util/read-package-json'; diff --git a/packages/api/core/src/api/make.ts b/packages/api/core/src/api/make.ts index aa9a169f0f..edefe796b9 100644 --- a/packages/api/core/src/api/make.ts +++ b/packages/api/core/src/api/make.ts @@ -1,6 +1,7 @@ import path from 'path'; import { asyncOra } from '@electron-forge/async-ora'; +import { getElectronVersion } from '@electron-forge/core-utils'; import { MakerBase } from '@electron-forge/maker-base'; import { ForgeArch, ForgeConfigMaker, ForgeMakeResult, ForgePlatform, IForgeResolvableMaker, ResolvedForgeConfig } from '@electron-forge/shared-types'; import { getHostArch } from '@electron/get'; @@ -8,7 +9,6 @@ import chalk from 'chalk'; import filenamify from 'filenamify'; import fs from 'fs-extra'; -import { getElectronVersion } from '../util/electron-version'; import getForgeConfig from '../util/forge-config'; import { runHook, runMutatingHook } from '../util/hook'; import { info, warn } from '../util/messages'; diff --git a/packages/api/core/src/api/package.ts b/packages/api/core/src/api/package.ts index 5b0dd50ed3..4a180eeeee 100644 --- a/packages/api/core/src/api/package.ts +++ b/packages/api/core/src/api/package.ts @@ -2,6 +2,7 @@ import path from 'path'; import { promisify } from 'util'; import { fakeOra, OraImpl, ora as realOra } from '@electron-forge/async-ora'; +import { getElectronVersion } from '@electron-forge/core-utils'; import { ForgeArch, ForgePlatform } from '@electron-forge/shared-types'; import { getHostArch } from '@electron/get'; import chalk from 'chalk'; @@ -10,7 +11,6 @@ import packager, { HookFunction } from 'electron-packager'; import glob from 'fast-glob'; import fs from 'fs-extra'; -import { getElectronVersion } from '../util/electron-version'; import getForgeConfig from '../util/forge-config'; import { runHook } from '../util/hook'; import { warn } from '../util/messages'; diff --git a/packages/api/core/src/api/start.ts b/packages/api/core/src/api/start.ts index 3884f8494c..bfea25b5f1 100644 --- a/packages/api/core/src/api/start.ts +++ b/packages/api/core/src/api/start.ts @@ -1,12 +1,12 @@ import { spawn, SpawnOptions } from 'child_process'; import { asyncOra } from '@electron-forge/async-ora'; +import { getElectronVersion } from '@electron-forge/core-utils'; import { ElectronProcess, ForgeArch, ForgePlatform, StartOptions } from '@electron-forge/shared-types'; import chalk from 'chalk'; import debug from 'debug'; import locateElectronExecutable from '../util/electron-executable'; -import { getElectronVersion } from '../util/electron-version'; import getForgeConfig from '../util/forge-config'; import { runHook } from '../util/hook'; import { readMutatedPackageJson } from '../util/read-package-json'; diff --git a/packages/api/core/src/util/electron-executable.ts b/packages/api/core/src/util/electron-executable.ts index 2c7e159374..d0e7f435bc 100644 --- a/packages/api/core/src/util/electron-executable.ts +++ b/packages/api/core/src/util/electron-executable.ts @@ -1,10 +1,9 @@ import path from 'path'; +import { getElectronModulePath } from '@electron-forge/core-utils'; import chalk from 'chalk'; import logSymbols from 'log-symbols'; -import { getElectronModulePath } from './electron-version'; - type PackageJSON = Record; type Dependencies = Record; diff --git a/packages/api/core/src/util/index.ts b/packages/api/core/src/util/index.ts index a7a9f788c8..4d3d3c030b 100644 --- a/packages/api/core/src/util/index.ts +++ b/packages/api/core/src/util/index.ts @@ -1,7 +1,6 @@ -import { getElectronVersion } from './electron-version'; +import { getElectronVersion, hasYarn, packagerRebuildHook, yarnOrNpmSpawn } from '@electron-forge/core-utils'; + import { BuildIdentifierConfig, BuildIdentifierMap, fromBuildIdentifier } from './forge-config'; -import rebuildHook from './rebuild'; -import { hasYarn, yarnOrNpmSpawn } from './yarn-or-npm'; export default class ForgeUtils { /** @@ -19,7 +18,7 @@ export default class ForgeUtils { hasYarn = hasYarn; - rebuildHook = rebuildHook; + rebuildHook = packagerRebuildHook; yarnOrNpmSpawn = yarnOrNpmSpawn; } diff --git a/packages/api/core/src/util/install-dependencies.ts b/packages/api/core/src/util/install-dependencies.ts index cdc599f415..cbc61b0a72 100644 --- a/packages/api/core/src/util/install-dependencies.ts +++ b/packages/api/core/src/util/install-dependencies.ts @@ -1,8 +1,7 @@ +import { hasYarn, yarnOrNpmSpawn } from '@electron-forge/core-utils'; import { ExitError } from '@malept/cross-spawn-promise'; import debug from 'debug'; -import { hasYarn, yarnOrNpmSpawn } from './yarn-or-npm'; - const d = debug('electron-forge:dependency-installer'); export enum DepType { diff --git a/packages/api/core/src/util/resolve-dir.ts b/packages/api/core/src/util/resolve-dir.ts index 0b1edd406d..07551c104d 100644 --- a/packages/api/core/src/util/resolve-dir.ts +++ b/packages/api/core/src/util/resolve-dir.ts @@ -1,9 +1,9 @@ import path from 'path'; +import { getElectronVersion } from '@electron-forge/core-utils'; import debug from 'debug'; import fs from 'fs-extra'; -import { getElectronVersion } from './electron-version'; import { readRawPackageJson } from './read-package-json'; const d = debug('electron-forge:project-resolver'); diff --git a/packages/api/core/test/fast/install-dependencies_spec.ts b/packages/api/core/test/fast/install-dependencies_spec.ts index 6487ab00ca..425ed649c8 100644 --- a/packages/api/core/test/fast/install-dependencies_spec.ts +++ b/packages/api/core/test/fast/install-dependencies_spec.ts @@ -21,7 +21,7 @@ describe('Install dependencies', () => { spawnSpy.returns(spawnPromise); hasYarnSpy = stub(); install = proxyquire.noCallThru().load('../../src/util/install-dependencies', { - './yarn-or-npm': { + '@electron-forge/core-utils': { yarnOrNpmSpawn: spawnSpy, hasYarn: hasYarnSpy, }, diff --git a/packages/api/core/test/fast/make_spec.ts b/packages/api/core/test/fast/make_spec.ts index fd628eab1b..47cca20bf7 100644 --- a/packages/api/core/test/fast/make_spec.ts +++ b/packages/api/core/test/fast/make_spec.ts @@ -32,7 +32,7 @@ describe('make', () => { before(() => { const electronPath = path.resolve(__dirname, 'node_modules/electron'); stubbedMake = proxyquire.noCallThru().load('../../src/api/make', { - '../util/electron-version': { + '@electron-forge/core-utils': { getElectronModulePath: () => Promise.resolve(electronPath), getElectronVersion: () => Promise.resolve('1.0.0'), }, diff --git a/packages/api/core/test/fast/start_spec.ts b/packages/api/core/test/fast/start_spec.ts index f98b9145ed..49e3427228 100644 --- a/packages/api/core/test/fast/start_spec.ts +++ b/packages/api/core/test/fast/start_spec.ts @@ -21,7 +21,7 @@ describe('start', () => { start = proxyquire.noCallThru().load('../../src/api/start', { '../util/electron-executable': () => Promise.resolve('fake_electron_path'), - '../util/electron-version': { + '@electron-forge/core-utils': { getElectronVersion: () => Promise.resolve('1.0.0'), }, '../util/forge-config': async () => ({ diff --git a/packages/plugin/webpack/package.json b/packages/plugin/webpack/package.json index 7d6c2e7ed2..b941bd4420 100644 --- a/packages/plugin/webpack/package.json +++ b/packages/plugin/webpack/package.json @@ -25,7 +25,7 @@ }, "dependencies": { "@electron-forge/async-ora": "6.0.0-beta.70", - "@electron-forge/core": "6.0.0-beta.70", + "@electron-forge/core-utils": "^6.0.0-beta.70", "@electron-forge/plugin-base": "6.0.0-beta.70", "@electron-forge/shared-types": "6.0.0-beta.70", "@electron-forge/web-multi-logger": "6.0.0-beta.70", diff --git a/packages/plugin/webpack/src/WebpackPlugin.ts b/packages/plugin/webpack/src/WebpackPlugin.ts index 2dceaa327d..d4e335423c 100644 --- a/packages/plugin/webpack/src/WebpackPlugin.ts +++ b/packages/plugin/webpack/src/WebpackPlugin.ts @@ -2,7 +2,7 @@ import http from 'http'; import path from 'path'; import { asyncOra } from '@electron-forge/async-ora'; -import { utils } from '@electron-forge/core'; +import { getElectronVersion, packagerRebuildHook } from '@electron-forge/core-utils'; import { PluginBase } from '@electron-forge/plugin-base'; import { ForgeHookMap, ResolvedForgeConfig } from '@electron-forge/shared-types'; import Logger, { Tab } from '@electron-forge/web-multi-logger'; @@ -155,9 +155,9 @@ export default class WebpackPlugin extends PluginBase { return { prePackage: async (config, platform, arch) => { await fs.remove(this.baseDir); - await utils.rebuildHook( + await packagerRebuildHook( this.projectDir, - await utils.getElectronVersion(this.projectDir, await fs.readJson(path.join(this.projectDir, 'package.json'))), + await getElectronVersion(this.projectDir, await fs.readJson(path.join(this.projectDir, 'package.json'))), platform, arch, config.rebuildConfig diff --git a/packages/template/typescript-webpack/package.json b/packages/template/typescript-webpack/package.json index 228e35085d..b876768d30 100644 --- a/packages/template/typescript-webpack/package.json +++ b/packages/template/typescript-webpack/package.json @@ -20,8 +20,14 @@ "fs-extra": "^10.0.0" }, "devDependencies": { + "@electron-forge/maker-deb": "^6.0.0-beta.70", + "@electron-forge/maker-rpm": "^6.0.0-beta.70", + "@electron-forge/maker-squirrel": "^6.0.0-beta.70", + "@electron-forge/maker-zip": "^6.0.0-beta.70", + "@electron-forge/plugin-webpack": "^6.0.0-beta.70", "@electron-forge/test-utils": "6.0.0-beta.70", "chai": "^4.3.3", - "fast-glob": "^3.2.7" + "fast-glob": "^3.2.7", + "fork-ts-checker-webpack-plugin": "^7.2.13" } } diff --git a/packages/template/typescript-webpack/src/TypeScriptWebpackTemplate.ts b/packages/template/typescript-webpack/src/TypeScriptWebpackTemplate.ts index 250f93d5f1..1f6c9f41d4 100644 --- a/packages/template/typescript-webpack/src/TypeScriptWebpackTemplate.ts +++ b/packages/template/typescript-webpack/src/TypeScriptWebpackTemplate.ts @@ -18,10 +18,10 @@ class TypeScriptWebpackTemplate extends BaseTemplate { const filePath = (fileName: string) => path.join(directory, 'src', fileName); // Copy Webpack files - await this.copyTemplateFile(directory, 'webpack.main.config.js'); - await this.copyTemplateFile(directory, 'webpack.renderer.config.js'); - await this.copyTemplateFile(directory, 'webpack.rules.js'); - await this.copyTemplateFile(directory, 'webpack.plugins.js'); + await this.copyTemplateFile(directory, 'webpack.main.config.ts'); + await this.copyTemplateFile(directory, 'webpack.renderer.config.ts'); + await this.copyTemplateFile(directory, 'webpack.rules.ts'); + await this.copyTemplateFile(directory, 'webpack.plugins.ts'); await this.updateFileByLine(path.resolve(directory, 'src', 'index.html'), (line) => { if (line.includes('link rel="stylesheet"')) return ''; diff --git a/packages/template/typescript-webpack/test/TypeScriptWebpackTemplate_spec.ts b/packages/template/typescript-webpack/test/TypeScriptWebpackTemplate_spec_slow.ts similarity index 73% rename from packages/template/typescript-webpack/test/TypeScriptWebpackTemplate_spec.ts rename to packages/template/typescript-webpack/test/TypeScriptWebpackTemplate_spec_slow.ts index 3692bfb927..d23ce24705 100644 --- a/packages/template/typescript-webpack/test/TypeScriptWebpackTemplate_spec.ts +++ b/packages/template/typescript-webpack/test/TypeScriptWebpackTemplate_spec_slow.ts @@ -5,6 +5,7 @@ import { expect } from 'chai'; import glob from 'fast-glob'; import fs from 'fs-extra'; +import { api } from '../../../api/core'; import template from '../src/TypeScriptWebpackTemplate'; describe('TypeScriptWebpackTemplate', () => { @@ -15,17 +16,22 @@ describe('TypeScriptWebpackTemplate', () => { }); it('should succeed in initializing the typescript template', async () => { - await template.initializeTemplate(dir, {}); + await api.init({ + dir, + template: path.resolve(__dirname, '..', 'src', 'TypeScriptWebpackTemplate'), + interactive: false, + }); }); context('template files are copied to project', () => { const expectedFiles = [ 'tsconfig.json', '.eslintrc.json', - 'webpack.main.config.js', - 'webpack.renderer.config.js', - 'webpack.rules.js', - 'webpack.plugins.js', + 'forge.config.ts', + 'webpack.main.config.ts', + 'webpack.renderer.config.ts', + 'webpack.rules.ts', + 'webpack.plugins.ts', path.join('src', 'index.ts'), path.join('src', 'renderer.ts'), path.join('src', 'preload.ts'), @@ -44,10 +50,13 @@ describe('TypeScriptWebpackTemplate', () => { describe('lint', () => { before(async () => { + delete process.env.TS_NODE_PROJECT; await testUtils.ensureModulesInstalled( dir, ['electron', 'electron-squirrel-startup'], - template.devDependencies.filter((moduleName) => moduleName.includes('eslint') || moduleName.includes('typescript')) + template.devDependencies + .filter((moduleName) => moduleName.includes('eslint') || moduleName.includes('typescript')) + .concat(['@electron-forge/plugin-webpack']) ); }); diff --git a/packages/template/typescript-webpack/tmpl/forge.config.ts b/packages/template/typescript-webpack/tmpl/forge.config.ts index 808b0bf043..e356488d91 100644 --- a/packages/template/typescript-webpack/tmpl/forge.config.ts +++ b/packages/template/typescript-webpack/tmpl/forge.config.ts @@ -1,43 +1,35 @@ -module.exports = { +import type { ForgeConfig } from '@electron-forge/shared-types'; +import { MakerSquirrel } from '@electron-forge/maker-squirrel'; +import { MakerZIP } from '@electron-forge/maker-zip'; +import { MakerDeb } from '@electron-forge/maker-deb'; +import { MakerRpm } from '@electron-forge/maker-rpm'; +import { WebpackPlugin } from '@electron-forge/plugin-webpack'; + +import { mainConfig } from './webpack.main.config'; +import { rendererConfig } from './webpack.renderer.config'; + +const config: ForgeConfig = { packagerConfig: {}, rebuildConfig: {}, - makers: [ - { - name: '@electron-forge/maker-squirrel', - config: {}, - }, - { - name: '@electron-forge/maker-zip', - platforms: ['darwin'], - }, - { - name: '@electron-forge/maker-deb', - config: {}, - }, - { - name: '@electron-forge/maker-rpm', - config: {}, - }, - ], + makers: [new MakerSquirrel({}), new MakerZIP({}, ['darwin']), new MakerRpm({}), new MakerDeb({})], plugins: [ - { - name: '@electron-forge/plugin-webpack', - config: { - mainConfig: './webpack.main.config.js', - renderer: { - config: './webpack.renderer.config.js', - entryPoints: [ - { - html: './src/index.html', - js: './src/renderer.ts', - name: 'main_window', - preload: { - js: './src/preload.ts', - }, + new WebpackPlugin({ + mainConfig, + renderer: { + config: rendererConfig, + entryPoints: [ + { + html: './src/index.html', + js: './src/renderer.ts', + name: 'main_window', + preload: { + js: './src/preload.ts', }, - ], - }, + }, + ], }, - }, + }), ], }; + +export default config; diff --git a/packages/template/typescript-webpack/tmpl/package.json b/packages/template/typescript-webpack/tmpl/package.json index 918ab619fb..72d70fb4d9 100644 --- a/packages/template/typescript-webpack/tmpl/package.json +++ b/packages/template/typescript-webpack/tmpl/package.json @@ -7,7 +7,7 @@ "css-loader": "^6.0.0", "eslint": "^8.0.1", "eslint-plugin-import": "^2.25.0", - "fork-ts-checker-webpack-plugin": "^7.2.1", + "fork-ts-checker-webpack-plugin": "^7.2.13", "node-loader": "^2.0.0", "style-loader": "^3.0.0", "ts-loader": "^9.2.2", diff --git a/packages/template/typescript-webpack/tmpl/webpack.main.config.js b/packages/template/typescript-webpack/tmpl/webpack.main.config.ts similarity index 79% rename from packages/template/typescript-webpack/tmpl/webpack.main.config.js rename to packages/template/typescript-webpack/tmpl/webpack.main.config.ts index 391374667f..5d93dd4558 100644 --- a/packages/template/typescript-webpack/tmpl/webpack.main.config.js +++ b/packages/template/typescript-webpack/tmpl/webpack.main.config.ts @@ -1,4 +1,6 @@ -module.exports = { +import type { Configuration } from 'webpack'; + +export const mainConfig: Configuration = { /** * This is the main entry point for your application, it's the first file * that runs in the main process. diff --git a/packages/template/typescript-webpack/tmpl/webpack.plugins.js b/packages/template/typescript-webpack/tmpl/webpack.plugins.js deleted file mode 100644 index 0aebcd9dce..0000000000 --- a/packages/template/typescript-webpack/tmpl/webpack.plugins.js +++ /dev/null @@ -1,3 +0,0 @@ -const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin'); - -module.exports = [new ForkTsCheckerWebpackPlugin()]; diff --git a/packages/template/typescript-webpack/tmpl/webpack.plugins.ts b/packages/template/typescript-webpack/tmpl/webpack.plugins.ts new file mode 100644 index 0000000000..3e2af0453a --- /dev/null +++ b/packages/template/typescript-webpack/tmpl/webpack.plugins.ts @@ -0,0 +1,6 @@ +import type IForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin'; + +// eslint-disable-next-line @typescript-eslint/no-var-requires +const ForkTsCheckerWebpackPlugin: typeof IForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin'); + +export const plugins = [new ForkTsCheckerWebpackPlugin()]; diff --git a/packages/template/typescript-webpack/tmpl/webpack.renderer.config.js b/packages/template/typescript-webpack/tmpl/webpack.renderer.config.ts similarity index 51% rename from packages/template/typescript-webpack/tmpl/webpack.renderer.config.js rename to packages/template/typescript-webpack/tmpl/webpack.renderer.config.ts index 36f4fb05bc..69c8b10dcb 100644 --- a/packages/template/typescript-webpack/tmpl/webpack.renderer.config.js +++ b/packages/template/typescript-webpack/tmpl/webpack.renderer.config.ts @@ -1,16 +1,18 @@ -const rules = require('./webpack.rules'); -const plugins = require('./webpack.plugins'); +import type { Configuration } from 'webpack'; + +import { rules } from './webpack.rules'; +import { plugins } from './webpack.plugins'; rules.push({ test: /\.css$/, use: [{ loader: 'style-loader' }, { loader: 'css-loader' }], }); -module.exports = { +export const rendererConfig: Configuration = { module: { rules, }, - plugins: plugins, + plugins, resolve: { extensions: ['.js', '.ts', '.jsx', '.tsx', '.css'], }, diff --git a/packages/template/typescript-webpack/tmpl/webpack.rules.js b/packages/template/typescript-webpack/tmpl/webpack.rules.ts similarity index 86% rename from packages/template/typescript-webpack/tmpl/webpack.rules.js rename to packages/template/typescript-webpack/tmpl/webpack.rules.ts index 174b3205d2..73dc119ab2 100644 --- a/packages/template/typescript-webpack/tmpl/webpack.rules.js +++ b/packages/template/typescript-webpack/tmpl/webpack.rules.ts @@ -1,4 +1,6 @@ -module.exports = [ +import type { ModuleOptions } from 'webpack'; + +export const rules: Required['rules'] = [ // Add support for native node modules { // We're specifying native_modules in the test because the asset relocator loader generates a diff --git a/packages/utils/core-utils/package.json b/packages/utils/core-utils/package.json new file mode 100644 index 0000000000..c9a9aaa89b --- /dev/null +++ b/packages/utils/core-utils/package.json @@ -0,0 +1,29 @@ +{ + "name": "@electron-forge/core-utils", + "version": "6.0.0-beta.70", + "description": "Core utilities for the Electron Forge packages", + "repository": "https://github.com/electron-userland/electron-forge", + "author": "Samuel Attard", + "license": "MIT", + "main": "dist/index.js", + "typings": "dist/index.d.ts", + "dependencies": { + "@electron-forge/async-ora": "^6.0.0-beta.70", + "@electron-forge/shared-types": "^6.0.0-beta.70", + "@malept/cross-spawn-promise": "^2.0.0", + "chalk": "^4.0.0", + "debug": "^4.3.1", + "electron-rebuild": "^3.2.6", + "find-up": "^5.0.0", + "fs-extra": "^10.0.0", + "log-symbols": "^4.0.0", + "semver": "^7.2.1", + "yarn-or-npm": "^3.0.1" + }, + "engines": { + "node": ">= 14.17.5" + }, + "devDependencies": { + "chai": "^4.3.3" + } +} diff --git a/packages/api/core/src/util/electron-version.ts b/packages/utils/core-utils/src/electron-version.ts similarity index 97% rename from packages/api/core/src/util/electron-version.ts rename to packages/utils/core-utils/src/electron-version.ts index 1c32dfc366..2709800a98 100644 --- a/packages/api/core/src/util/electron-version.ts +++ b/packages/utils/core-utils/src/electron-version.ts @@ -5,7 +5,7 @@ import findUp from 'find-up'; import fs from 'fs-extra'; import semver from 'semver'; -import yarnOrNpm from './yarn-or-npm'; +import { safeYarnOrNpm } from './yarn-or-npm'; const d = debug('electron-forge:electron-version'); @@ -44,7 +44,7 @@ async function determineNodeModulesPath(dir: string, packageName: string): Promi export class PackageNotFoundError extends Error { constructor(packageName: string, dir: string) { - super(`Cannot find the package "${packageName}". Perhaps you need to run "${yarnOrNpm()} install" in "${dir}"?`); + super(`Cannot find the package "${packageName}". Perhaps you need to run "${safeYarnOrNpm()} install" in "${dir}"?`); } } diff --git a/packages/utils/core-utils/src/index.ts b/packages/utils/core-utils/src/index.ts new file mode 100644 index 0000000000..2b4f1876ef --- /dev/null +++ b/packages/utils/core-utils/src/index.ts @@ -0,0 +1,3 @@ +export * from './rebuild'; +export * from './electron-version'; +export * from './yarn-or-npm'; diff --git a/packages/utils/core-utils/src/rebuild.ts b/packages/utils/core-utils/src/rebuild.ts new file mode 100644 index 0000000000..abfe6ae853 --- /dev/null +++ b/packages/utils/core-utils/src/rebuild.ts @@ -0,0 +1,39 @@ +import { asyncOra } from '@electron-forge/async-ora'; +import { ForgeArch, ForgePlatform } from '@electron-forge/shared-types'; +import { rebuild, RebuildOptions } from 'electron-rebuild'; + +export const packagerRebuildHook = async ( + buildPath: string, + electronVersion: string, + _platform: ForgePlatform, + arch: ForgeArch, + config: Partial = {} +): Promise => { + await asyncOra('Preparing native dependencies', async (rebuildSpinner) => { + const rebuilder = rebuild({ + ...config, + buildPath, + electronVersion, + arch, + }); + const { lifecycle } = rebuilder; + + let found = 0; + let done = 0; + + const redraw = () => { + rebuildSpinner.text = `Preparing native dependencies: ${done} / ${found}`; + }; + + lifecycle.on('module-found', () => { + found += 1; + redraw(); + }); + lifecycle.on('module-done', () => { + done += 1; + redraw(); + }); + + await rebuilder; + }); +}; diff --git a/packages/api/core/src/util/yarn-or-npm.ts b/packages/utils/core-utils/src/yarn-or-npm.ts similarity index 91% rename from packages/api/core/src/util/yarn-or-npm.ts rename to packages/utils/core-utils/src/yarn-or-npm.ts index 4360fe3d93..a2ddb4d259 100644 --- a/packages/api/core/src/util/yarn-or-npm.ts +++ b/packages/utils/core-utils/src/yarn-or-npm.ts @@ -3,7 +3,7 @@ import chalk from 'chalk'; import logSymbols from 'log-symbols'; import yarnOrNpm from 'yarn-or-npm'; -const safeYarnOrNpm = (): string => { +export const safeYarnOrNpm = () => { const system = yarnOrNpm(); switch (process.env.NODE_INSTALLER) { case 'yarn': @@ -17,8 +17,6 @@ const safeYarnOrNpm = (): string => { } }; -export default safeYarnOrNpm; - export const yarnOrNpmSpawn = (args?: CrossSpawnArgs, opts?: CrossSpawnOptions): Promise => spawn(safeYarnOrNpm(), args, opts); export const hasYarn = (): boolean => safeYarnOrNpm() === 'yarn'; diff --git a/packages/api/core/test/fast/electron-version_spec.ts b/packages/utils/core-utils/test/electron-version_spec.ts similarity index 88% rename from packages/api/core/test/fast/electron-version_spec.ts rename to packages/utils/core-utils/test/electron-version_spec.ts index 0623a87801..26838e426d 100644 --- a/packages/api/core/test/fast/electron-version_spec.ts +++ b/packages/utils/core-utils/test/electron-version_spec.ts @@ -4,8 +4,10 @@ import path from 'path'; import { expect } from 'chai'; import fs from 'fs-extra'; -import { devDeps, exactDevDeps } from '../../src/api/init-scripts/init-npm'; -import { getElectronModulePath, getElectronVersion, updateElectronDependency } from '../../src/util/electron-version'; +import { devDeps, exactDevDeps } from '../../../api/core/src/api/init-scripts/init-npm'; +import { getElectronModulePath, getElectronVersion, updateElectronDependency } from '../src/electron-version'; + +const fixturePath = path.resolve(__dirname, '..', '..', '..', 'api', 'core', 'test', 'fixture'); describe('updateElectronDependency', () => { it('adds an Electron dep if one does not already exist', () => { @@ -14,6 +16,7 @@ describe('updateElectronDependency', () => { expect(dev).to.deep.equal(devDeps); expect(exact).to.deep.equal(exactDevDeps); }); + it('does not add an Electron dep if one already exists', () => { const packageJSON = { dependencies: {}, @@ -23,6 +26,7 @@ describe('updateElectronDependency', () => { expect(dev).to.deep.equal(devDeps); expect(exact).to.deep.equal([]); }); + it('moves an Electron dependency from dependencies to devDependencies', () => { const packageJSON = { dependencies: { electron: '0.37.0' }, @@ -41,12 +45,12 @@ describe('getElectronVersion', () => { expect(getElectronVersion('', { devDependencies: {} })).to.eventually.be.rejectedWith('Electron packages in devDependencies')); it('fails with a non-exact version and no electron installed', () => { - const fixtureDir = path.resolve(__dirname, '..', 'fixture', 'dummy_app'); + const fixtureDir = path.resolve(fixturePath, 'dummy_app'); return expect(getElectronVersion(fixtureDir, { devDependencies: { electron: '^4.0.2' } })).to.eventually.be.rejectedWith('Cannot find the package'); }); it('works with a non-exact version with electron installed', () => { - const fixtureDir = path.resolve(__dirname, '..', 'fixture', 'non-exact'); + const fixtureDir = path.resolve(fixturePath, 'non-exact'); return expect(getElectronVersion(fixtureDir, { devDependencies: { electron: '^4.0.2' } })).to.eventually.equal('4.0.9'); }); @@ -84,7 +88,7 @@ describe('getElectronVersion', () => { }); it('works with a non-exact version', async () => { - const fixtureDir = path.resolve(__dirname, '..', 'fixture', 'yarn-workspace', 'packages', 'subpackage'); + const fixtureDir = path.resolve(fixturePath, 'yarn-workspace', 'packages', 'subpackage'); const packageJSON = { devDependencies: { electron: '^4.0.4' }, }; @@ -111,7 +115,7 @@ describe('getElectronModulePath', () => { }); it('throws an error saying it cannot find electron', async () => { - const fixtureDir = path.resolve(__dirname, '..', 'fixture', 'dummy_app'); + const fixtureDir = path.resolve(fixturePath, 'dummy_app'); await fs.copy(fixtureDir, tempDir); return expect(getElectronModulePath(tempDir, { devDependencies: { electron: '^4.0.2' } })).to.eventually.be.rejectedWith('Cannot find the package'); }); @@ -122,7 +126,7 @@ describe('getElectronModulePath', () => { }); it('works with electron', () => { - const fixtureDir = path.resolve(__dirname, '..', 'fixture', 'non-exact'); + const fixtureDir = path.resolve(fixturePath, 'non-exact'); return expect(getElectronModulePath(fixtureDir, { devDependencies: { electron: '^4.0.2' } })).to.eventually.equal( path.join(fixtureDir, 'node_modules', 'electron') ); @@ -134,7 +138,7 @@ describe('getElectronModulePath', () => { }); it('finds the top-level electron module', async () => { - const workspaceDir = path.resolve(__dirname, '..', 'fixture', 'npm-workspace'); + const workspaceDir = path.resolve(fixturePath, 'npm-workspace'); const fixtureDir = path.join(workspaceDir, 'packages', 'subpackage'); const packageJSON = { devDependencies: { electron: '^4.0.4' }, @@ -154,7 +158,7 @@ describe('getElectronModulePath', () => { }); it('finds the top-level electron module', async () => { - const workspaceDir = path.resolve(__dirname, '..', 'fixture', 'yarn-workspace'); + const workspaceDir = path.resolve(fixturePath, 'yarn-workspace'); const fixtureDir = path.join(workspaceDir, 'packages', 'subpackage'); const packageJSON = { devDependencies: { electron: '^4.0.4' }, @@ -164,7 +168,7 @@ describe('getElectronModulePath', () => { }); it('finds the top-level electron module despite the additional node_modules folder inside the package', async () => { - const workspaceDir = path.resolve(__dirname, '..', 'fixture', 'yarn-workspace'); + const workspaceDir = path.resolve(fixturePath, 'yarn-workspace'); const fixtureDir = path.join(workspaceDir, 'packages', 'with-node-modules'); const packageJSON = { devDependencies: { electron: '^4.0.4' }, @@ -174,7 +178,7 @@ describe('getElectronModulePath', () => { }); it('finds the correct electron module in nohoist mode', async () => { - const workspaceDir = path.resolve(__dirname, '..', 'fixture', 'yarn-workspace'); + const workspaceDir = path.resolve(fixturePath, 'yarn-workspace'); const fixtureDir = path.join(workspaceDir, 'packages', 'electron-folder-in-node-modules'); const packageJSON = { devDependencies: { electron: '^13.0.0' }, diff --git a/packages/api/core/test/fast/yarn-or-npm_spec.ts b/packages/utils/core-utils/test/yarn-or-npm_spec.ts similarity index 76% rename from packages/api/core/test/fast/yarn-or-npm_spec.ts rename to packages/utils/core-utils/test/yarn-or-npm_spec.ts index 44321195b0..8be7ecc9d6 100644 --- a/packages/api/core/test/fast/yarn-or-npm_spec.ts +++ b/packages/utils/core-utils/test/yarn-or-npm_spec.ts @@ -1,7 +1,7 @@ import { expect } from 'chai'; import systemYarnOrNpm from 'yarn-or-npm'; -import yarnOrNpm from '../../src/util/yarn-or-npm'; +import { safeYarnOrNpm } from '../src/yarn-or-npm'; describe('yarn-or-npm', () => { let nodeInstaller: string | undefined; @@ -20,21 +20,21 @@ describe('yarn-or-npm', () => { }); it('should by default equal the system yarn-or-npm value', () => { - expect(yarnOrNpm()).to.be.equal(systemYarnOrNpm()); + expect(safeYarnOrNpm()).to.be.equal(systemYarnOrNpm()); }); it('should return yarn if NODE_INSTALLER=yarn', () => { process.env.NODE_INSTALLER = 'yarn'; - expect(yarnOrNpm()).to.be.equal('yarn'); + expect(safeYarnOrNpm()).to.be.equal('yarn'); }); it('should return npm if NODE_INSTALLER=npm', () => { process.env.NODE_INSTALLER = 'npm'; - expect(yarnOrNpm()).to.be.equal('npm'); + expect(safeYarnOrNpm()).to.be.equal('npm'); }); it('should return system value if NODE_INSTALLER is an unrecognized installer', () => { process.env.NODE_INSTALLER = 'magical_unicorn'; - expect(yarnOrNpm()).to.be.equal(systemYarnOrNpm()); + expect(safeYarnOrNpm()).to.be.equal(systemYarnOrNpm()); }); }); diff --git a/packages/utils/types/src/index.ts b/packages/utils/types/src/index.ts index fda98ebb26..f1d8b2edde 100644 --- a/packages/utils/types/src/index.ts +++ b/packages/utils/types/src/index.ts @@ -125,10 +125,10 @@ export interface IForgePlugin { } export interface IForgeResolvableMaker { - enabled: boolean; name: string; - platforms: ForgePlatform[] | null; config: any; // eslint-disable-line @typescript-eslint/no-explicit-any + enabled?: boolean; + platforms?: ForgePlatform[] | null; } export interface IForgeMaker { diff --git a/yarn.lock b/yarn.lock index d193a3c293..baec4c52d5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -851,7 +851,7 @@ dependencies: "@babel/highlight" "^7.10.4" -"@babel/code-frame@^7.16.7", "@babel/code-frame@^7.18.6": +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.16.7", "@babel/code-frame@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.18.6.tgz#3b25d38c89600baa2dcc219edfa88a74eb2c427a" integrity sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q== @@ -1965,6 +1965,11 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-18.0.3.tgz#463fc47f13ec0688a33aec75d078a0541a447199" integrity sha512-HzNRZtp4eepNitP+BD6k2L6DROIDG4Q0fm4x+dwfsr6LGmROENnok75VGw40628xf+iR24WeMFcHuuBDUAzzsQ== +"@types/parse-json@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" + integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== + "@types/progress@^2.0.5": version "2.0.5" resolved "https://registry.yarnpkg.com/@types/progress/-/progress-2.0.5.tgz#6e0febf3a82cc0ffdc1cebb4e56d6949fd108775" @@ -3019,7 +3024,7 @@ chalk@^2.0.0, chalk@^2.4.1, chalk@^2.4.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1: +chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1, chalk@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -3409,6 +3414,17 @@ core-util-is@~1.0.0: resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== +cosmiconfig@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.0.1.tgz#714d756522cace867867ccb4474c5d01bbae5d6d" + integrity sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ== + dependencies: + "@types/parse-json" "^4.0.0" + import-fresh "^3.2.1" + parse-json "^5.0.0" + path-type "^4.0.0" + yaml "^1.10.0" + create-require@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" @@ -3569,6 +3585,11 @@ deep-is@^0.1.3: resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== +deepmerge@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" + integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== + default-gateway@^6.0.3: version "6.0.3" resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-6.0.3.tgz#819494c888053bdb743edbf343d6cdf7f2943a71" @@ -4052,7 +4073,7 @@ err-code@^2.0.2: resolved "https://registry.yarnpkg.com/err-code/-/err-code-2.0.3.tgz#23c2f3b756ffdfc608d30e27c9a941024807e7f9" integrity sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA== -error-ex@^1.2.0: +error-ex@^1.2.0, error-ex@^1.3.1: version "1.3.2" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== @@ -4916,6 +4937,24 @@ foreground-child@^2.0.0: cross-spawn "^7.0.0" signal-exit "^3.0.2" +fork-ts-checker-webpack-plugin@^7.2.13: + version "7.2.13" + resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-7.2.13.tgz#51ffd6a2f96f03ab64b92f8aedf305dbf3dee0f1" + integrity sha512-fR3WRkOb4bQdWB/y7ssDUlVdrclvwtyCUIHCfivAoYxq9dF7XfrDKbMdZIfwJ7hxIAqkYSGeU7lLJE6xrxIBdg== + dependencies: + "@babel/code-frame" "^7.16.7" + chalk "^4.1.2" + chokidar "^3.5.3" + cosmiconfig "^7.0.1" + deepmerge "^4.2.2" + fs-extra "^10.0.0" + memfs "^3.4.1" + minimatch "^3.0.4" + node-abort-controller "^3.0.1" + schema-utils "^3.1.1" + semver "^7.3.5" + tapable "^2.2.1" + form-data@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" @@ -6291,6 +6330,11 @@ linenumber@^1.0.1: resolved "https://registry.yarnpkg.com/linenumber/-/linenumber-1.0.1.tgz#e45aba6ee50ec01626773c89224a8b46d0b2d77d" integrity sha512-g7x+bxzGaJ7yUk1chFXmY4NT1oIiSQREUs33M29cjDPFUP1W/dlM3YGD1cR7qeSehp5TEpxAFP0L+Rpk3nUKzw== +lines-and-columns@^1.1.6: + version "1.2.4" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" + integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== + lint-staged@^13.0.3: version "13.0.3" resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-13.0.3.tgz#d7cdf03a3830b327a2b63c6aec953d71d9dc48c6" @@ -6587,7 +6631,7 @@ mem@^4.3.0: mimic-fn "^2.0.0" p-is-promise "^2.0.0" -memfs@^3.4.3: +memfs@^3.4.1, memfs@^3.4.3: version "3.4.7" resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.4.7.tgz#e5252ad2242a724f938cb937e3c4f7ceb1f70e5a" integrity sha512-ygaiUSNalBX85388uskeCyhSAoOSgzBbtVCr9jA2RROssFL9Q19/ZXFqS+2Th2sr1ewNIWgFdLzLC3Yl1Zv+lw== @@ -6985,6 +7029,11 @@ node-abi@^3.0.0: dependencies: semver "^7.3.5" +node-abort-controller@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/node-abort-controller/-/node-abort-controller-3.0.1.tgz#f91fa50b1dee3f909afabb7e261b1e1d6b0cb74e" + integrity sha512-/ujIVxthRs+7q6hsdjHMaj8hRG9NuWmwrz+JdRwZ14jdFoKSkm+vDsCbF9PLpnSqjaWQJuTmVtcWHNLr+vrOFw== + node-addon-api@^3.1.0: version "3.2.1" resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-3.2.1.tgz#81325e0a2117789c0128dab65e7e38f07ceba161" @@ -7454,6 +7503,16 @@ parse-json@^2.2.0: dependencies: error-ex "^1.2.0" +parse-json@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" + integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-even-better-errors "^2.3.0" + lines-and-columns "^1.1.6" + parse-ms@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/parse-ms/-/parse-ms-2.1.0.tgz#348565a753d4391fa524029956b172cb7753097d" @@ -8763,7 +8822,7 @@ table@^6.0.9: string-width "^4.2.3" strip-ansi "^6.0.1" -tapable@^2.0.0, tapable@^2.1.1, tapable@^2.2.0: +tapable@^2.0.0, tapable@^2.1.1, tapable@^2.2.0, tapable@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== @@ -9526,6 +9585,11 @@ yallist@^4.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== +yaml@^1.10.0: + version "1.10.2" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" + integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== + yaml@^2.1.1: version "2.1.3" resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.1.3.tgz#9b3a4c8aff9821b696275c79a8bee8399d945207"