Merge branch 'main' into fix_ers_publishing

This commit is contained in:
PashaFG 2024-10-07 18:01:58 +03:00 коммит произвёл GitHub
Родитель e89c6f2a47 1193d150b8
Коммит e78bb0c148
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
99 изменённых файлов: 2336 добавлений и 2870 удалений

Просмотреть файл

@ -129,6 +129,17 @@
"node/no-unpublished-require": "off",
"node/shebang": "off"
}
},
{
"files": ["packages/plugin/vite/src/**/*.ts"],
"rules": {
"node/no-unpublished-import": [
"error",
{
"allowModules": ["vite"]
}
]
}
}
]
}

1
.nvmrc Normal file
Просмотреть файл

@ -0,0 +1 @@
20.17.0

Просмотреть файл

@ -1,6 +1,5 @@
{
"$schema": "node_modules/lerna/schemas/lerna-schema.json",
"useWorkspaces": true,
"version": "7.4.0",
"version": "7.5.0",
"npmClient": "yarn"
}

Просмотреть файл

@ -23,5 +23,11 @@
"test:slow": {
"dependsOn": ["^test:slow"]
}
},
"$schema": "./node_modules/nx/schemas/nx-schema.json",
"namedInputs": {
"default": ["{projectRoot}/**/*", "sharedGlobals"],
"sharedGlobals": [],
"production": ["default"]
}
}

Просмотреть файл

@ -30,10 +30,9 @@
"preversion": "yarn build"
},
"dependencies": {
"@aws-sdk/abort-controller": "^3.29.0",
"@aws-sdk/client-s3": "^3.461.0",
"@aws-sdk/lib-storage": "^3.28.0",
"@aws-sdk/types": "^3.25.0",
"@aws-sdk/client-s3": "^3.654.0",
"@aws-sdk/lib-storage": "^3.654.0",
"@aws-sdk/types": "^3.654.0",
"@doyensec/electronegativity": "^1.9.1",
"@electron/get": "^3.0.0",
"@electron/osx-sign": "^1.0.5",
@ -130,7 +129,7 @@
"generate-changelog": "^1.8.0",
"husky": "^7.0.1",
"inquirer": "^8.0.0",
"lerna": "^6.6.2",
"lerna": "^7.4.2",
"lint-staged": "^12.1.7",
"minimist": "^1.2.6",
"mocha": "^9.0.1",
@ -140,7 +139,7 @@
"rimraf": "^3.0.1",
"sinon": "^13.0.1",
"sinon-chai": "^3.6.0",
"syncpack": "^8.4.11",
"syncpack": "^11.2.1",
"ts-node": "^10.0.0",
"typedoc": "0.25.13",
"typescript": "^4.6.3",

Просмотреть файл

@ -1,6 +1,6 @@
{
"name": "@electron-forge/cli",
"version": "7.4.0",
"version": "7.5.0",
"description": "A complete tool for building modern Electron applications",
"repository": "https://github.com/electron/forge",
"author": "Samuel Attard",
@ -17,8 +17,8 @@
"mocha": "^9.0.1"
},
"dependencies": {
"@electron-forge/core": "7.4.0",
"@electron-forge/shared-types": "7.4.0",
"@electron-forge/core": "7.5.0",
"@electron-forge/shared-types": "7.5.0",
"@electron/get": "^3.0.0",
"chalk": "^4.0.0",
"commander": "^4.1.1",

Просмотреть файл

@ -1 +1,3 @@
export declare function dynamicImport(path: string): Promise<any>;
/** Like {@link dynamicImport()}, except it tries out {@link require()} first. */
export declare function dynamicImportMaybe(path: string): Promise<any>;

Просмотреть файл

@ -1,5 +1,23 @@
const url = require('url');
const fs = require('fs');
exports.dynamicImport = function dynamicImport(path) {
return import(url.pathToFileURL(path));
exports.dynamicImport = async function dynamicImport(path) {
try {
return await import(fs.existsSync(path) ? url.pathToFileURL(path) : path);
} catch (error) {
return Promise.reject(error);
}
};
exports.dynamicImportMaybe = async function dynamicImportMaybe(path) {
try {
return require(path);
} catch (e1) {
try {
return await exports.dynamicImport(path);
} catch (e2) {
e1.message = '\n1. ' + e1.message + '\n2. ' + e2.message;
throw e1;
}
}
};

Просмотреть файл

@ -1,6 +1,6 @@
{
"name": "@electron-forge/core",
"version": "7.4.0",
"version": "7.5.0",
"description": "A complete tool for building modern Electron applications",
"repository": "https://github.com/electron/forge",
"main": "dist/api/index.js",
@ -15,16 +15,16 @@
"test:slow": "yarn test:base test/slow/**/*_spec_slow.ts"
},
"devDependencies": {
"@electron-forge/maker-appx": "7.4.0",
"@electron-forge/maker-deb": "7.4.0",
"@electron-forge/maker-dmg": "7.4.0",
"@electron-forge/maker-flatpak": "7.4.0",
"@electron-forge/maker-rpm": "7.4.0",
"@electron-forge/maker-snap": "7.4.0",
"@electron-forge/maker-squirrel": "7.4.0",
"@electron-forge/maker-wix": "7.4.0",
"@electron-forge/maker-zip": "7.4.0",
"@electron-forge/test-utils": "7.4.0",
"@electron-forge/maker-appx": "7.5.0",
"@electron-forge/maker-deb": "7.5.0",
"@electron-forge/maker-dmg": "7.5.0",
"@electron-forge/maker-flatpak": "7.5.0",
"@electron-forge/maker-rpm": "7.5.0",
"@electron-forge/maker-snap": "7.5.0",
"@electron-forge/maker-squirrel": "7.5.0",
"@electron-forge/maker-wix": "7.5.0",
"@electron-forge/maker-zip": "7.5.0",
"@electron-forge/test-utils": "7.5.0",
"@types/interpret": "^1.1.1",
"@types/progress": "^2.0.5",
"@types/rechoir": "^0.6.1",
@ -40,17 +40,17 @@
"yaml-hook": "^1.0.0"
},
"dependencies": {
"@electron-forge/core-utils": "7.4.0",
"@electron-forge/maker-base": "7.4.0",
"@electron-forge/plugin-base": "7.4.0",
"@electron-forge/publisher-base": "7.4.0",
"@electron-forge/shared-types": "7.4.0",
"@electron-forge/template-base": "7.4.0",
"@electron-forge/template-vite": "7.4.0",
"@electron-forge/template-vite-typescript": "7.4.0",
"@electron-forge/template-webpack": "7.4.0",
"@electron-forge/template-webpack-typescript": "7.4.0",
"@electron-forge/tracer": "7.4.0",
"@electron-forge/core-utils": "7.5.0",
"@electron-forge/maker-base": "7.5.0",
"@electron-forge/plugin-base": "7.5.0",
"@electron-forge/publisher-base": "7.5.0",
"@electron-forge/shared-types": "7.5.0",
"@electron-forge/template-base": "7.5.0",
"@electron-forge/template-vite": "7.5.0",
"@electron-forge/template-vite-typescript": "7.5.0",
"@electron-forge/template-webpack": "7.5.0",
"@electron-forge/template-webpack-typescript": "7.5.0",
"@electron-forge/tracer": "7.5.0",
"@electron/get": "^3.0.0",
"@electron/packager": "^18.3.5",
"@electron/rebuild": "^3.2.10",

Просмотреть файл

@ -2,7 +2,7 @@ import { ForgeTemplate } from '@electron-forge/shared-types';
import debug from 'debug';
import resolvePackage from 'resolve-package';
import { PossibleModule } from '../../util/require-search';
import { PossibleModule } from '../../util/import-search';
const d = debug('electron-forge:init:find-template');

Просмотреть файл

@ -22,10 +22,10 @@ import logSymbols from 'log-symbols';
import getForgeConfig from '../util/forge-config';
import { getHookListrTasks, runMutatingHook } from '../util/hook';
import importSearch from '../util/import-search';
import getCurrentOutDir from '../util/out-dir';
import parseArchs from '../util/parse-archs';
import { readMutatedPackageJson } from '../util/read-package-json';
import requireSearch from '../util/require-search';
import resolveDir from '../util/resolve-dir';
import { listrPackage } from './package';
@ -168,7 +168,7 @@ export const listrMake = (
throw new Error(`The following maker config has a maker name that is not a string: ${JSON.stringify(resolvableTarget)}`);
}
const MakerClass = requireSearch<typeof MakerImpl>(dir, [resolvableTarget.name]);
const MakerClass = await importSearch<typeof MakerImpl>(dir, [resolvableTarget.name]);
if (!MakerClass) {
throw new Error(
`Could not find module with name '${resolvableTarget.name}'. If this is a package from NPM, make sure it's listed in the devDependencies of your package.json. If this is a local module, make sure you have the correct path to its entry point. Try using the DEBUG="electron-forge:require-search" environment variable for more information.`

Просмотреть файл

@ -14,10 +14,10 @@ import { Listr, PRESET_TIMER } from 'listr2';
import getForgeConfig from '../util/forge-config';
import { getHookListrTasks, runHook } from '../util/hook';
import importSearch from '../util/import-search';
import { warn } from '../util/messages';
import getCurrentOutDir from '../util/out-dir';
import { readMutatedPackageJson } from '../util/read-package-json';
import requireSearch from '../util/require-search';
import resolveDir from '../util/resolve-dir';
const d = debug('electron-forge:packager');
@ -25,9 +25,9 @@ const d = debug('electron-forge:packager');
/**
* Resolves hooks if they are a path to a file (instead of a `Function`).
*/
function resolveHooks<F = HookFunction>(hooks: (string | F)[] | undefined, dir: string) {
async function resolveHooks<F = HookFunction>(hooks: (string | F)[] | undefined, dir: string) {
if (hooks) {
return hooks.map((hook) => (typeof hook === 'string' ? (requireSearch<F>(dir, [hook]) as F) : hook));
return await Promise.all(hooks.map(async (hook) => (typeof hook === 'string' ? ((await importSearch<F>(dir, [hook])) as F) : hook)));
}
return [];
@ -216,13 +216,12 @@ export const listrPackage = (
const rebuildTasks = new Map<string, Promise<ForgeListrTask<never>>[]>();
const signalRebuildStart = new Map<string, ((task: ForgeListrTask<never>) => void)[]>();
const afterFinalizePackageTargetsHooks: FinalizePackageTargetsHookFunction[] = [
(targets, done) => {
provideTargets(targets);
done();
},
...resolveHooks(forgeConfig.packagerConfig.afterFinalizePackageTargets, ctx.dir),
...(await resolveHooks(forgeConfig.packagerConfig.afterFinalizePackageTargets, ctx.dir)),
];
const pruneEnabled = !('prune' in forgeConfig.packagerConfig) || forgeConfig.packagerConfig.prune;
@ -265,7 +264,7 @@ export const listrPackage = (
await fs.writeJson(path.resolve(buildPath, 'package.json'), copiedPackageJSON, { spaces: 2 });
done();
},
...resolveHooks(forgeConfig.packagerConfig.afterCopy, ctx.dir),
...(await resolveHooks(forgeConfig.packagerConfig.afterCopy, ctx.dir)),
];
const afterCompleteHooks: HookFunction[] = [
@ -273,13 +272,13 @@ export const listrPackage = (
signalPackageDone.get(getTargetKey({ platform: pPlatform, arch: pArch }))?.pop()?.();
done();
},
...resolveHooks(forgeConfig.packagerConfig.afterComplete, ctx.dir),
...(await resolveHooks(forgeConfig.packagerConfig.afterComplete, ctx.dir)),
];
const afterPruneHooks = [];
if (pruneEnabled) {
afterPruneHooks.push(...resolveHooks(forgeConfig.packagerConfig.afterPrune, ctx.dir));
afterPruneHooks.push(...(await resolveHooks(forgeConfig.packagerConfig.afterPrune, ctx.dir)));
}
afterPruneHooks.push((async (buildPath, electronVersion, pPlatform, pArch, done) => {
@ -293,7 +292,7 @@ export const listrPackage = (
done();
}) as HookFunction,
];
afterExtractHooks.push(...resolveHooks(forgeConfig.packagerConfig.afterExtract, ctx.dir));
afterExtractHooks.push(...(await resolveHooks(forgeConfig.packagerConfig.afterExtract, ctx.dir)));
type PackagerArch = Exclude<ForgeArch, 'arm'>;

Просмотреть файл

@ -19,9 +19,9 @@ import fs from 'fs-extra';
import { Listr } from 'listr2';
import getForgeConfig from '../util/forge-config';
import importSearch from '../util/import-search';
import getCurrentOutDir from '../util/out-dir';
import PublishState from '../util/publish-state';
import requireSearch from '../util/require-search';
import resolveDir from '../util/resolve-dir';
import { listrMake, MakeOptions } from './make';
@ -198,7 +198,7 @@ export default autoTrace(
} else {
const resolvablePublishTarget = publishTarget as IForgeResolvablePublisher;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const PublisherClass: any = requireSearch(dir, [resolvablePublishTarget.name]);
const PublisherClass: any = await importSearch(dir, [resolvablePublishTarget.name]);
if (!PublisherClass) {
throw new Error(
`Could not find a publish target with the name: ${resolvablePublishTarget.name}. Make sure it's listed in the devDependencies of your package.json`

Просмотреть файл

@ -6,7 +6,7 @@ import * as interpret from 'interpret';
import { template } from 'lodash';
import * as rechoir from 'rechoir';
import { dynamicImport } from '../../helper/dynamic-import.js';
import { dynamicImportMaybe } from '../../helper/dynamic-import.js';
import { runMutatingHook } from './hook';
import PluginInterface from './plugin-interface';
@ -74,6 +74,14 @@ const proxify = <T extends ProxiedObject>(buildIdentifier: string | (() => strin
};
/* eslint-enable @typescript-eslint/no-explicit-any */
export const registeredForgeConfigs: Map<string, ForgeConfig> = new Map();
export function registerForgeConfigForDirectory(dir: string, config: ForgeConfig): void {
registeredForgeConfigs.set(path.resolve(dir), config);
}
export function unregisterForgeConfigForDirectory(dir: string): void {
registeredForgeConfigs.delete(path.resolve(dir));
}
export type BuildIdentifierMap<T> = Record<string, T | undefined>;
export type BuildIdentifierConfig<T> = {
map: BuildIdentifierMap<T>;
@ -109,8 +117,12 @@ type MaybeESM<T> = T | { default: T };
type AsyncForgeConfigGenerator = () => Promise<ForgeConfig>;
export default async (dir: string): Promise<ResolvedForgeConfig> => {
let forgeConfig: ForgeConfig | string | null | undefined = registeredForgeConfigs.get(dir);
const packageJSON = await readRawPackageJson(dir);
let forgeConfig: ForgeConfig | string | null = packageJSON.config && packageJSON.config.forge ? packageJSON.config.forge : null;
if (forgeConfig === undefined) {
forgeConfig = packageJSON.config && packageJSON.config.forge ? packageJSON.config.forge : null;
}
if (!forgeConfig || typeof forgeConfig === 'string') {
for (const extension of ['.js', ...Object.keys(interpret.extensions)]) {
@ -128,13 +140,7 @@ export default async (dir: string): Promise<ResolvedForgeConfig> => {
const forgeConfigPath = path.resolve(dir, forgeConfig as string);
try {
// The loaded "config" could potentially be a static forge config, ESM module or async function
let loaded;
try {
loaded = (await dynamicImport(forgeConfigPath)) as MaybeESM<ForgeConfig | AsyncForgeConfigGenerator>;
} catch (err) {
// eslint-disable-next-line @typescript-eslint/no-var-requires
loaded = require(forgeConfigPath) as MaybeESM<ForgeConfig | AsyncForgeConfigGenerator>;
}
const loaded = (await dynamicImportMaybe(forgeConfigPath)) as MaybeESM<ForgeConfig | AsyncForgeConfigGenerator>;
const maybeForgeConfig = 'default' in loaded ? loaded.default : loaded;
forgeConfig = typeof maybeForgeConfig === 'function' ? await maybeForgeConfig() : maybeForgeConfig;
} catch (err) {
@ -161,7 +167,7 @@ export default async (dir: string): Promise<ResolvedForgeConfig> => {
const templateObj = { ...packageJSON, year: new Date().getFullYear() };
renderConfigTemplate(dir, templateObj, resolvedForgeConfig);
resolvedForgeConfig.pluginInterface = new PluginInterface(dir, resolvedForgeConfig);
resolvedForgeConfig.pluginInterface = await PluginInterface.create(dir, resolvedForgeConfig);
resolvedForgeConfig = await runMutatingHook(resolvedForgeConfig, 'resolveForgeConfig', resolvedForgeConfig);

Просмотреть файл

@ -2,7 +2,9 @@ import path from 'path';
import debug from 'debug';
const d = debug('electron-forge:require-search');
import { dynamicImportMaybe } from '../../helper/dynamic-import.js';
const d = debug('electron-forge:import-search');
// https://github.com/nodejs/node/blob/da0ede1ad55a502a25b4139f58aab3fb1ee3bf3f/lib/internal/modules/cjs/loader.js#L353-L359
type RequireError = Error & {
@ -11,14 +13,14 @@ type RequireError = Error & {
requestPath: string | undefined;
};
export function requireSearchRaw<T>(relativeTo: string, paths: string[]): T | null {
export async function importSearchRaw<T>(relativeTo: string, paths: string[]): Promise<T | null> {
// Attempt to locally short-circuit if we're running from a checkout of forge
if (__dirname.includes('forge/packages/api/core/') && paths.length === 1 && paths[0].startsWith('@electron-forge/')) {
const [moduleType, moduleName] = paths[0].split('/')[1].split('-');
try {
const localPath = path.resolve(__dirname, '..', '..', '..', '..', moduleType, moduleName);
d('testing local forge build', { moduleType, moduleName, localPath });
return require(localPath);
return await dynamicImportMaybe(localPath);
} catch {
// Ignore
}
@ -32,7 +34,7 @@ export function requireSearchRaw<T>(relativeTo: string, paths: string[]): T | nu
for (const testPath of testPaths) {
try {
d('testing', testPath);
return require(testPath);
return await dynamicImportMaybe(testPath);
} catch (err) {
if (err instanceof Error) {
const requireErr = err as RequireError;
@ -51,7 +53,7 @@ export type PossibleModule<T> = {
default?: T;
} & T;
export default <T>(relativeTo: string, paths: string[]): T | null => {
const result = requireSearchRaw<PossibleModule<T>>(relativeTo, paths);
export default async <T>(relativeTo: string, paths: string[]): Promise<T | null> => {
const result = await importSearchRaw<PossibleModule<T>>(relativeTo, paths);
return typeof result === 'object' && result && result.default ? result.default : (result as T | null);
};

Просмотреть файл

@ -1,6 +1,14 @@
import { getElectronVersion, hasYarn, yarnOrNpmSpawn } from '@electron-forge/core-utils';
import { BuildIdentifierConfig, BuildIdentifierMap, fromBuildIdentifier } from './forge-config';
import {
BuildIdentifierConfig,
BuildIdentifierMap,
fromBuildIdentifier,
registerForgeConfigForDirectory,
unregisterForgeConfigForDirectory,
} from './forge-config';
import type { ForgeConfig } from '@electron-forge/shared-types';
export default class ForgeUtils {
/**
@ -19,4 +27,20 @@ export default class ForgeUtils {
hasYarn = hasYarn;
yarnOrNpmSpawn = yarnOrNpmSpawn;
/**
* Register a virtual config file for forge to find.
* Takes precedence over other configuration options like a forge.config.js file.
* Dir should point to the folder containing the app.
*/
registerForgeConfigForDirectory(dir: string, config: ForgeConfig): void {
return registerForgeConfigForDirectory(dir, config);
}
/**
* Unregister a forge config previously registered with registerForgeConfigForDirectory.
*/
unregisterForgeConfigForDirectory(dir: string): void {
return unregisterForgeConfigForDirectory(dir);
}
}

Просмотреть файл

@ -16,7 +16,7 @@ import debug from 'debug';
import { StartOptions } from '../api';
import requireSearch from './require-search';
import importSearch from './import-search';
const d = debug('electron-forge:plugins');
@ -25,30 +25,45 @@ function isForgePlugin(plugin: IForgePlugin | unknown): plugin is IForgePlugin {
}
export default class PluginInterface implements IForgePluginInterface {
private plugins: IForgePlugin[];
private plugins: IForgePlugin[] = [];
private _pluginPromise: Promise<void> = Promise.resolve();
private config: ResolvedForgeConfig;
constructor(dir: string, forgeConfig: ResolvedForgeConfig) {
this.plugins = forgeConfig.plugins.map((plugin) => {
if (isForgePlugin(plugin)) {
return plugin;
}
static async create(dir: string, forgeConfig: ResolvedForgeConfig): Promise<PluginInterface> {
const int = new PluginInterface(dir, forgeConfig);
await int._pluginPromise;
return int;
}
if (typeof plugin === 'object' && 'name' in plugin && 'config' in plugin) {
const { name: pluginName, config: opts } = plugin;
if (typeof pluginName !== 'string') {
throw new Error(`Expected plugin[0] to be a string but found ${pluginName}`);
private constructor(dir: string, forgeConfig: ResolvedForgeConfig) {
this._pluginPromise = Promise.all(
forgeConfig.plugins.map(async (plugin): Promise<IForgePlugin> => {
if (isForgePlugin(plugin)) {
return plugin;
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const Plugin = requireSearch<any>(dir, [pluginName]);
if (!Plugin) {
throw new Error(`Could not find module with name: ${pluginName}. Make sure it's listed in the devDependencies of your package.json`);
}
return new Plugin(opts);
}
throw new Error(`Expected plugin to either be a plugin instance or a { name, config } object but found ${JSON.stringify(plugin)}`);
if (typeof plugin === 'object' && 'name' in plugin && 'config' in plugin) {
const { name: pluginName, config: opts } = plugin;
if (typeof pluginName !== 'string') {
throw new Error(`Expected plugin[0] to be a string but found ${pluginName}`);
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const Plugin = await importSearch<any>(dir, [pluginName]);
if (!Plugin) {
throw new Error(`Could not find module with name: ${pluginName}. Make sure it's listed in the devDependencies of your package.json`);
}
return new Plugin(opts);
}
throw new Error(`Expected plugin to either be a plugin instance or a { name, config } object but found ${JSON.stringify(plugin)}`);
})
).then((plugins) => {
this.plugins = plugins;
for (const plugin of this.plugins) {
plugin.init(dir, forgeConfig);
}
return;
});
// TODO: fix hack
// eslint-disable-next-line @typescript-eslint/no-explicit-any
@ -59,11 +74,6 @@ export default class PluginInterface implements IForgePluginInterface {
configurable: false,
writable: false,
});
for (const plugin of this.plugins) {
plugin.init(dir, forgeConfig);
}
this.triggerHook = this.triggerHook.bind(this);
this.overrideStartLogic = this.overrideStartLogic.bind(this);
}

Просмотреть файл

@ -4,6 +4,7 @@ import { getElectronVersion } from '@electron-forge/core-utils';
import debug from 'debug';
import fs from 'fs-extra';
import { registeredForgeConfigs } from './forge-config';
import { readRawPackageJson } from './read-package-json';
const d = debug('electron-forge:project-resolver');
@ -12,15 +13,19 @@ const d = debug('electron-forge:project-resolver');
// and / or forge config then we need to be able to resolve
// the dir without calling getElectronVersion
export default async (dir: string): Promise<string | null> => {
let mDir = dir;
let mDir = path.resolve(dir);
let bestGuessDir: string | null = null;
let lastError: string | null = null;
let prevDir;
while (prevDir !== mDir) {
prevDir = mDir;
const testPath = path.resolve(mDir, 'package.json');
d('searching for project in:', mDir);
if (registeredForgeConfigs.has(mDir)) {
d('virtual config found in:', mDir);
return mDir;
}
const testPath = path.resolve(mDir, 'package.json');
if (await fs.pathExists(testPath)) {
const packageJSON = await readRawPackageJson(mDir);

Просмотреть файл

@ -3,7 +3,12 @@ import path from 'path';
import { ResolvedForgeConfig } from '@electron-forge/shared-types';
import { expect } from 'chai';
import findConfig, { forgeConfigIsValidFilePath, renderConfigTemplate } from '../../src/util/forge-config';
import findConfig, {
forgeConfigIsValidFilePath,
registerForgeConfigForDirectory,
renderConfigTemplate,
unregisterForgeConfigForDirectory,
} from '../../src/util/forge-config';
const defaults = {
packagerConfig: {},
@ -47,6 +52,51 @@ describe('forge-config', () => {
expect(config).to.deep.equal(defaults);
});
it('should resolve to the virtual config if present', async () => {
const fixturePath = path.resolve(__dirname, '../fixture/no_forge_config');
try {
registerForgeConfigForDirectory(fixturePath, { outDir: 'magic' });
const config = await findConfig(fixturePath);
delete (config as any).pluginInterface;
expect(config).to.be.deep.equal({
...defaults,
outDir: 'magic',
});
} finally {
unregisterForgeConfigForDirectory(fixturePath);
}
});
it('should resolve virtual config instead of package.json', async () => {
const fixturePath = path.resolve(__dirname, '../fixture/dummy_app');
try {
registerForgeConfigForDirectory(fixturePath, { outDir: 'magic' });
const config = await findConfig(fixturePath);
delete (config as any).pluginInterface;
expect(config).to.be.deep.equal({
...defaults,
outDir: 'magic',
});
} finally {
unregisterForgeConfigForDirectory(fixturePath);
}
});
it('should resolve virtual config instead of forge.config.js', async () => {
const fixturePath = path.resolve(__dirname, '../fixture/async_forge_config');
try {
registerForgeConfigForDirectory(fixturePath, { outDir: 'magic' });
const config = await findConfig(fixturePath);
delete (config as any).pluginInterface;
expect(config).to.be.deep.equal({
...defaults,
outDir: 'magic',
});
} finally {
unregisterForgeConfigForDirectory(fixturePath);
}
});
it('should resolve the object in package.json with defaults if one exists', async () => {
const config = await findConfig(path.resolve(__dirname, '../fixture/dummy_app'));
// eslint-disable-next-line @typescript-eslint/no-explicit-any

Просмотреть файл

@ -0,0 +1,21 @@
import { expect } from 'chai';
import findConfig from '../../src/util/forge-config';
import importSearch from '../../src/util/import-search';
describe('import-search', () => {
it('should resolve null if no file exists', async () => {
const resolved = await importSearch(__dirname, ['../../src/util/wizard-secrets']);
expect(resolved).to.equal(null);
});
it('should resolve a file if it exists', async () => {
const resolved = await importSearch(__dirname, ['../../src/util/forge-config']);
expect(resolved).to.equal(findConfig);
});
it('should throw if file exists but fails to load', async () => {
const promise = importSearch(__dirname, ['../fixture/require-search/throw-error']);
await expect(promise).to.be.rejectedWith('test');
});
});

Просмотреть файл

@ -60,7 +60,7 @@ describe('publish', () => {
config.publishers = publishers;
return config;
},
'../util/require-search': (_: string, [name]: [string]) => {
'../util/import-search': async (_: string, [name]: [string]) => {
if (name === 'void') {
return fakePublisher(voidStub);
}

Просмотреть файл

@ -1,22 +0,0 @@
import { expect } from 'chai';
import findConfig from '../../src/util/forge-config';
import requireSearch from '../../src/util/require-search';
describe('require-search', () => {
it('should resolve null if no file exists', () => {
const resolved = requireSearch(__dirname, ['../../src/util/wizard-secrets']);
expect(resolved).to.equal(null);
});
it('should resolve a file if it exists', () => {
const resolved = requireSearch(__dirname, ['../../src/util/forge-config']);
expect(resolved).to.equal(findConfig);
});
it('should throw if file exists but fails to load', () => {
expect(() => {
requireSearch(__dirname, ['../fixture/require-search/throw-error']);
}).to.throw('test');
});
});

Просмотреть файл

@ -2,6 +2,7 @@ import path from 'path';
import { expect } from 'chai';
import { registerForgeConfigForDirectory, unregisterForgeConfigForDirectory } from '../../src/util/forge-config';
import resolveDir from '../../src/util/resolve-dir';
describe('resolve-dir', () => {
@ -20,4 +21,14 @@ describe('resolve-dir', () => {
expect(await resolveDir(path.resolve(__dirname, '../fixture/dummy_app/foo'))).to.not.be.equal(null);
expect(await resolveDir(path.resolve(__dirname, '../fixture/dummy_app/foo'))).to.be.equal(path.resolve(__dirname, '../fixture/dummy_app'));
});
it('should return a directory if it finds a virtual config', async () => {
try {
registerForgeConfigForDirectory('/foo/var/virtual', {});
expect(await resolveDir('/foo/var/virtual')).to.not.be.equal(null);
expect(await resolveDir(path.resolve(__dirname, '/foo/var/virtual'))).to.be.equal(path.resolve(__dirname, '/foo/var/virtual'));
} finally {
unregisterForgeConfigForDirectory('/foo/var/virtual');
}
});
});

Просмотреть файл

@ -1,13 +1,13 @@
{
"name": "create-electron-app",
"version": "7.4.0",
"version": "7.5.0",
"description": "Create Electron App",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
"author": "Samuel Attard",
"license": "MIT",
"dependencies": {
"@electron-forge/cli": "7.4.0"
"@electron-forge/cli": "7.5.0"
},
"bin": {
"create-electron-app": "dist/index.js"

Просмотреть файл

@ -1,6 +1,6 @@
{
"name": "@electron-forge/maker-appx",
"version": "7.4.0",
"version": "7.5.0",
"description": "AppX maker for Electron Forge",
"repository": "https://github.com/electron/forge",
"author": "Samuel Attard",
@ -15,8 +15,8 @@
"node": ">= 16.4.0"
},
"dependencies": {
"@electron-forge/maker-base": "7.4.0",
"@electron-forge/shared-types": "7.4.0",
"@electron-forge/maker-base": "7.5.0",
"@electron-forge/shared-types": "7.5.0",
"cross-spawn": "^7.0.3",
"fs-extra": "^10.0.0",
"parse-author": "^2.0.0"

Просмотреть файл

@ -1,6 +1,6 @@
{
"name": "@electron-forge/maker-base",
"version": "7.4.0",
"version": "7.5.0",
"description": "Base maker for Electron Forge",
"repository": "https://github.com/electron/forge",
"author": "Samuel Attard",
@ -16,7 +16,7 @@
"node": ">= 16.4.0"
},
"dependencies": {
"@electron-forge/shared-types": "7.4.0",
"@electron-forge/shared-types": "7.5.0",
"fs-extra": "^10.0.0",
"which": "^2.0.2"
},

Просмотреть файл

@ -1,6 +1,6 @@
{
"name": "@electron-forge/maker-deb",
"version": "7.4.0",
"version": "7.5.0",
"description": "Deb maker for Electron Forge",
"repository": "https://github.com/electron/forge",
"author": "Samuel Attard",
@ -18,8 +18,8 @@
"node": ">= 16.4.0"
},
"dependencies": {
"@electron-forge/maker-base": "7.4.0",
"@electron-forge/shared-types": "7.4.0"
"@electron-forge/maker-base": "7.5.0",
"@electron-forge/shared-types": "7.5.0"
},
"optionalDependencies": {
"electron-installer-debian": "^3.2.0"

Просмотреть файл

@ -1,6 +1,6 @@
{
"name": "@electron-forge/maker-dmg",
"version": "7.4.0",
"version": "7.5.0",
"description": "DMG maker for Electron Forge",
"repository": "https://github.com/electron/forge",
"author": "Samuel Attard",
@ -22,8 +22,8 @@
"node": ">= 16.4.0"
},
"dependencies": {
"@electron-forge/maker-base": "7.4.0",
"@electron-forge/shared-types": "7.4.0",
"@electron-forge/maker-base": "7.5.0",
"@electron-forge/shared-types": "7.5.0",
"fs-extra": "^10.0.0"
},
"optionalDependencies": {

Просмотреть файл

@ -1,6 +1,6 @@
{
"name": "@electron-forge/maker-flatpak",
"version": "7.4.0",
"version": "7.5.0",
"description": "Flatpak maker for Electron Forge",
"repository": "https://github.com/electron/forge",
"author": "Samuel Attard",
@ -22,8 +22,8 @@
"node": ">= 16.4.0"
},
"dependencies": {
"@electron-forge/maker-base": "7.4.0",
"@electron-forge/shared-types": "7.4.0",
"@electron-forge/maker-base": "7.5.0",
"@electron-forge/shared-types": "7.5.0",
"fs-extra": "^10.0.0"
},
"optionalDependencies": {

Просмотреть файл

@ -1,6 +1,6 @@
{
"name": "@electron-forge/maker-pkg",
"version": "7.4.0",
"version": "7.5.0",
"description": "PKG maker for Electron Forge",
"repository": "https://github.com/electron/forge",
"license": "MIT",
@ -17,8 +17,8 @@
"node": ">= 16.4.0"
},
"dependencies": {
"@electron-forge/maker-base": "7.4.0",
"@electron-forge/shared-types": "7.4.0",
"@electron-forge/maker-base": "7.5.0",
"@electron-forge/shared-types": "7.5.0",
"@electron/osx-sign": "^1.0.5"
},
"publishConfig": {

Просмотреть файл

@ -1,6 +1,6 @@
{
"name": "@electron-forge/maker-rpm",
"version": "7.4.0",
"version": "7.5.0",
"description": "Rpm maker for Electron Forge",
"repository": "https://github.com/electron/forge",
"author": "Samuel Attard",
@ -22,8 +22,8 @@
"node": ">= 16.4.0"
},
"dependencies": {
"@electron-forge/maker-base": "7.4.0",
"@electron-forge/shared-types": "7.4.0"
"@electron-forge/maker-base": "7.5.0",
"@electron-forge/shared-types": "7.5.0"
},
"optionalDependencies": {
"electron-installer-redhat": "^3.2.0"

Просмотреть файл

@ -1,6 +1,6 @@
{
"name": "@electron-forge/maker-snap",
"version": "7.4.0",
"version": "7.5.0",
"description": "Snap maker for Electron Forge",
"repository": "https://github.com/electron/forge",
"license": "MIT",
@ -21,8 +21,8 @@
"node": ">= 16.4.0"
},
"dependencies": {
"@electron-forge/maker-base": "7.4.0",
"@electron-forge/shared-types": "7.4.0"
"@electron-forge/maker-base": "7.5.0",
"@electron-forge/shared-types": "7.5.0"
},
"optionalDependencies": {
"electron-installer-snap": "^5.2.0"

Просмотреть файл

@ -1,6 +1,6 @@
{
"name": "@electron-forge/maker-squirrel",
"version": "7.4.0",
"version": "7.5.0",
"description": "Squirrel maker for Electron Forge",
"repository": "https://github.com/electron/forge",
"author": "Samuel Attard",
@ -15,8 +15,8 @@
"node": ">= 16.4.0"
},
"dependencies": {
"@electron-forge/maker-base": "7.4.0",
"@electron-forge/shared-types": "7.4.0",
"@electron-forge/maker-base": "7.5.0",
"@electron-forge/shared-types": "7.5.0",
"fs-extra": "^10.0.0"
},
"optionalDependencies": {

Просмотреть файл

@ -1,6 +1,6 @@
{
"name": "@electron-forge/maker-wix",
"version": "7.4.0",
"version": "7.5.0",
"description": "Wix maker for Electron Forge",
"repository": "https://github.com/electron/forge",
"author": "Samuel Attard",
@ -15,8 +15,8 @@
"node": ">= 16.4.0"
},
"dependencies": {
"@electron-forge/maker-base": "7.4.0",
"@electron-forge/shared-types": "7.4.0",
"@electron-forge/maker-base": "7.5.0",
"@electron-forge/shared-types": "7.5.0",
"chalk": "^4.0.0",
"electron-wix-msi": "^5.1.3",
"log-symbols": "^4.0.0",

Просмотреть файл

@ -1,6 +1,6 @@
{
"name": "@electron-forge/maker-zip",
"version": "7.4.0",
"version": "7.5.0",
"description": "ZIP maker for Electron Forge",
"repository": "https://github.com/electron/forge",
"author": "Samuel Attard",
@ -16,8 +16,8 @@
"node": ">= 16.4.0"
},
"dependencies": {
"@electron-forge/maker-base": "7.4.0",
"@electron-forge/shared-types": "7.4.0",
"@electron-forge/maker-base": "7.5.0",
"@electron-forge/shared-types": "7.5.0",
"cross-zip": "^4.0.0",
"fs-extra": "^10.0.0",
"got": "^11.8.5"

Просмотреть файл

@ -1,6 +1,6 @@
{
"name": "@electron-forge/plugin-auto-unpack-natives",
"version": "7.4.0",
"version": "7.5.0",
"description": "Auto Unpack Natives plugin for Electron Forge, automatically adds native node modules to asar.unpacked",
"repository": "https://github.com/electron/forge",
"author": "Samuel Attard",
@ -11,8 +11,8 @@
"node": ">= 16.4.0"
},
"dependencies": {
"@electron-forge/plugin-base": "7.4.0",
"@electron-forge/shared-types": "7.4.0"
"@electron-forge/plugin-base": "7.5.0",
"@electron-forge/shared-types": "7.5.0"
},
"publishConfig": {
"access": "public"

Просмотреть файл

@ -1,6 +1,6 @@
{
"name": "@electron-forge/plugin-base",
"version": "7.4.0",
"version": "7.5.0",
"description": "Base plugin for Electron Forge",
"repository": "https://github.com/electron/forge",
"author": "Samuel Attard",
@ -15,7 +15,7 @@
"node": ">= 16.4.0"
},
"dependencies": {
"@electron-forge/shared-types": "7.4.0"
"@electron-forge/shared-types": "7.5.0"
},
"publishConfig": {
"access": "public"

Просмотреть файл

@ -1,6 +1,6 @@
{
"name": "@electron-forge/plugin-electronegativity",
"version": "7.4.0",
"version": "7.5.0",
"description": "Integrate Electronegativity into the Electron Forge workflow",
"repository": {
"type": "git",
@ -16,8 +16,8 @@
},
"dependencies": {
"@doyensec/electronegativity": "^1.9.1",
"@electron-forge/plugin-base": "7.4.0",
"@electron-forge/shared-types": "7.4.0"
"@electron-forge/plugin-base": "7.5.0",
"@electron-forge/shared-types": "7.5.0"
},
"publishConfig": {
"access": "public"

Просмотреть файл

@ -1,6 +1,6 @@
{
"name": "@electron-forge/plugin-fuses",
"version": "7.4.0",
"version": "7.5.0",
"description": "A plugin for flipping Electron Fuses in Electron Forge",
"repository": "https://github.com/electron/forge",
"author": "Erik Moura <erikian@erikian.dev>",
@ -31,8 +31,8 @@
"node": ">= 16.4.0"
},
"dependencies": {
"@electron-forge/plugin-base": "7.4.0",
"@electron-forge/shared-types": "7.4.0"
"@electron-forge/plugin-base": "7.5.0",
"@electron-forge/shared-types": "7.5.0"
},
"publishConfig": {
"access": "public"

Просмотреть файл

@ -1,6 +1,6 @@
{
"name": "@electron-forge/plugin-local-electron",
"version": "7.4.0",
"version": "7.5.0",
"description": "Local Electron plugin for Electron Forge, let's you use a local build of Electron",
"repository": "https://github.com/electron/forge",
"author": "Samuel Attard",
@ -11,8 +11,8 @@
"node": ">= 16.4.0"
},
"dependencies": {
"@electron-forge/plugin-base": "7.4.0",
"@electron-forge/shared-types": "7.4.0",
"@electron-forge/plugin-base": "7.5.0",
"@electron-forge/shared-types": "7.5.0",
"fs-extra": "^10.0.0"
},
"devDependencies": {

Просмотреть файл

@ -1,5 +1,7 @@
## plugin-vite
_Note: This plugin is considered experimental and is under active development; we do not offer API stability guarantees as development continues. Minor versions may include breaking changes - see release notes for details on migration._
This plugin makes it easy to set up standard vite tooling to compile both your main process code and your renderer process code, with built-in support for Hot Module Replacement (HMR) in the renderer process and support for multiple renderers.
```javascript

Просмотреть файл

@ -1,4 +1,5 @@
export {}; // Make this a module
import type { VitePluginConfig } from './src/Config';
declare global {
// This allows TypeScript to pick up the magic constants that's auto-generated by Forge's Vite
@ -7,15 +8,6 @@ declare global {
const MAIN_WINDOW_VITE_DEV_SERVER_URL: string;
const MAIN_WINDOW_VITE_NAME: string;
namespace NodeJS {
interface Process {
// Used for hot reload after preload scripts.
viteDevServers: Record<string, import('vite').ViteDevServer>;
}
}
type VitePluginConfig = ConstructorParameters<typeof import('@electron-forge/plugin-vite').VitePlugin>[0];
interface VitePluginRuntimeKeys {
VITE_DEV_SERVER_URL: `${string}_VITE_DEV_SERVER_URL`;
VITE_NAME: `${string}_VITE_NAME`;

Просмотреть файл

@ -1,6 +1,6 @@
{
"name": "@electron-forge/plugin-vite",
"version": "7.4.0",
"version": "7.5.0",
"description": "Vite plugin for Electron Forge, lets you use Vite directly in your tooling",
"repository": {
"type": "git",
@ -15,10 +15,10 @@
"test": "xvfb-maybe mocha --config ../../../.mocharc.js test/**/*_spec.ts test/*_spec.ts"
},
"dependencies": {
"@electron-forge/core-utils": "7.4.0",
"@electron-forge/plugin-base": "7.4.0",
"@electron-forge/shared-types": "7.4.0",
"@electron-forge/web-multi-logger": "7.4.0",
"@electron-forge/core-utils": "7.5.0",
"@electron-forge/plugin-base": "7.5.0",
"@electron-forge/shared-types": "7.5.0",
"@electron-forge/web-multi-logger": "7.5.0",
"chalk": "^4.0.0",
"debug": "^4.3.1",
"fs-extra": "^10.0.0",

Просмотреть файл

@ -1,22 +1,26 @@
// eslint-disable-next-line node/no-unpublished-import
import type { LibraryOptions } from 'vite';
export interface VitePluginBuildConfig {
/**
* Alias of `build.lib.entry` in `config`.
*/
entry?: LibraryOptions['entry'];
entry: LibraryOptions['entry'];
/**
* Vite config file path.
*/
config: string;
/**
* The build target is main process or preload script.
* @defaultValue 'main'
*/
target?: 'main' | 'preload';
}
export interface VitePluginRendererConfig {
/**
* Human friendly name of your entry point.
*/
name?: string;
name: string;
/**
* Vite config file path.
*/

Просмотреть файл

@ -1,33 +1,47 @@
import debug from 'debug';
// eslint-disable-next-line node/no-unpublished-import
import { loadConfigFromFile } from 'vite';
import { loadConfigFromFile, mergeConfig } from 'vite';
import { getConfig as getMainViteConfig } from './config/vite.main.config';
import { getConfig as getPreloadViteConfig } from './config/vite.preload.config';
import { getConfig as getRendererViteConfig } from './config/vite.renderer.config';
import type { VitePluginBuildConfig, VitePluginConfig, VitePluginRendererConfig } from './Config';
// eslint-disable-next-line node/no-unpublished-import
import type { ConfigEnv, UserConfig } from 'vite';
const d = debug('@electron-forge/plugin-vite:ViteConfig');
type Target = NonNullable<VitePluginBuildConfig['target']> | 'renderer';
export default class ViteConfigGenerator {
constructor(private readonly pluginConfig: VitePluginConfig, private readonly projectDir: string, private readonly isProd: boolean) {
d('Config mode:', this.mode);
}
resolveConfig(buildConfig: VitePluginBuildConfig | VitePluginRendererConfig, configEnv: Partial<ConfigEnv> = {}) {
// @see - https://vitejs.dev/config/#conditional-config
configEnv.command ??= this.isProd ? 'build' : 'serve';
// `mode` affects `.env.[mode]` file load.
configEnv.mode ??= this.mode;
async resolveConfig(buildConfig: VitePluginBuildConfig | VitePluginRendererConfig, target: Target): Promise<UserConfig> {
const configEnv: ConfigEnv = {
// @see - https://vitejs.dev/config/#conditional-config
command: this.isProd ? 'build' : 'serve',
// `mode` affects `.env.[mode]` file load.
mode: this.mode,
// Hack! Pass the forge runtime config to the vite config file in the template.
Object.assign(configEnv, {
// Forge extension variables.
root: this.projectDir,
forgeConfig: this.pluginConfig,
forgeConfigSelf: buildConfig,
});
};
// `configEnv` is to be passed as an arguments when the user export a function in `vite.config.js`.
return loadConfigFromFile(configEnv as ConfigEnv, buildConfig.config);
const userConfig = (await loadConfigFromFile(configEnv, buildConfig.config))?.config ?? {};
switch (target) {
case 'main':
return mergeConfig(getMainViteConfig(configEnv as ConfigEnv<'build'>), userConfig);
case 'preload':
return mergeConfig(getPreloadViteConfig(configEnv as ConfigEnv<'build'>), userConfig);
case 'renderer':
return mergeConfig(getRendererViteConfig(configEnv as ConfigEnv<'renderer'>), userConfig);
default:
throw new Error(`Unknown target: ${target}, expected 'main', 'preload' or 'renderer'`);
}
}
get mode(): string {
@ -45,7 +59,7 @@ export default class ViteConfigGenerator {
const configs = this.pluginConfig.build
// Prevent load the default `vite.config.js` file.
.filter(({ config }) => config)
.map<Promise<UserConfig>>(async (buildConfig) => (await this.resolveConfig(buildConfig))?.config ?? {});
.map((buildConfig) => this.resolveConfig(buildConfig, buildConfig.target ?? 'main'));
return await Promise.all(configs);
}
@ -56,8 +70,9 @@ export default class ViteConfigGenerator {
}
const configs = this.pluginConfig.renderer
// Prevent load the default `vite.config.js` file.
.filter(({ config }) => config)
.map<Promise<UserConfig>>(async (buildConfig) => (await this.resolveConfig(buildConfig))?.config ?? {});
.map((buildConfig) => this.resolveConfig(buildConfig, 'renderer'));
return await Promise.all(configs);
}

Просмотреть файл

@ -5,10 +5,8 @@ import chalk from 'chalk';
import debug from 'debug';
import fs from 'fs-extra';
import { PRESET_TIMER } from 'listr2';
// eslint-disable-next-line node/no-unpublished-import
import { default as vite } from 'vite';
import { getFlatDependencies } from './util/package';
import { onBuildDone } from './util/plugins';
import ViteConfigGenerator from './ViteConfig';
@ -95,8 +93,10 @@ Your packaged app may be larger than expected if you dont ignore everything othe
forgeConfig.packagerConfig.ignore = (file: string) => {
if (!file) return false;
// Always starts with `/`
// `file` always starts with `/`
// @see - https://github.com/electron/packager/blob/v18.1.3/src/copy-filter.ts#L89-L93
// Collect the files built by Vite
return !file.startsWith('/.vite');
};
return forgeConfig;
@ -104,7 +104,6 @@ Your packaged app may be larger than expected if you dont ignore everything othe
packageAfterCopy = async (_forgeConfig: ResolvedForgeConfig, buildPath: string): Promise<void> => {
const pj = await fs.readJson(path.resolve(this.projectDir, 'package.json'));
const flatDependencies = await getFlatDependencies(this.projectDir);
if (!pj.main?.includes('.vite/')) {
throw new Error(`Electron Forge is configured to use the Vite plugin. The plugin expects the
@ -116,14 +115,7 @@ the generated files). Instead, it is ${JSON.stringify(pj.main)}`);
delete pj.config.forge;
}
await fs.writeJson(path.resolve(buildPath, 'package.json'), pj, {
spaces: 2,
});
// Copy the dependencies in package.json
for (const dep of flatDependencies) {
await fs.copy(dep.src, path.resolve(buildPath, dep.dest));
}
await fs.writeJson(path.resolve(buildPath, 'package.json'), pj, { spaces: 2 });
};
startLogic = async (): Promise<StartResult> => {

Просмотреть файл

@ -1,11 +1,15 @@
import { builtinModules } from 'node:module';
import type { AddressInfo } from 'node:net';
import type { ConfigEnv, Plugin, UserConfig } from 'vite';
import pkg from './package.json';
import type { ConfigEnv, Plugin, UserConfig, ViteDevServer } from 'vite';
export const builtins = ['electron', ...builtinModules.map((m) => [m, `node:${m}`]).flat()];
export const external = [...builtins, ...Object.keys('dependencies' in pkg ? (pkg.dependencies as Record<string, unknown>) : {})];
export const external = [...builtins];
// Used for hot reload after preload scripts.
const viteDevServers: Record<string, ViteDevServer> = {};
const viteDevServerUrls: Record<string, string> = {};
export function getBuildConfig(env: ConfigEnv<'build'>): UserConfig {
const { root, mode, command } = env;
@ -46,7 +50,7 @@ export function getBuildDefine(env: ConfigEnv<'build'>) {
const define = Object.entries(defineKeys).reduce((acc, [name, keys]) => {
const { VITE_DEV_SERVER_URL, VITE_NAME } = keys;
const def = {
[VITE_DEV_SERVER_URL]: command === 'serve' ? JSON.stringify(process.env[VITE_DEV_SERVER_URL]) : undefined,
[VITE_DEV_SERVER_URL]: command === 'serve' ? JSON.stringify(viteDevServerUrls[VITE_DEV_SERVER_URL]) : undefined,
[VITE_NAME]: JSON.stringify(name),
};
return { ...acc, ...def };
@ -61,14 +65,13 @@ export function pluginExposeRenderer(name: string): Plugin {
return {
name: '@electron-forge/plugin-vite:expose-renderer',
configureServer(server) {
process.viteDevServers ??= {};
// Expose server for preload scripts hot reload.
process.viteDevServers[name] = server;
viteDevServers[name] = server;
server.httpServer?.once('listening', () => {
const addressInfo = server.httpServer!.address() as AddressInfo;
const addressInfo = server.httpServer?.address() as AddressInfo;
// Expose env constant for main process use.
process.env[VITE_DEV_SERVER_URL] = `http://localhost:${addressInfo?.port}`;
viteDevServerUrls[VITE_DEV_SERVER_URL] = `http://localhost:${addressInfo?.port}`;
});
},
};
@ -79,14 +82,15 @@ export function pluginHotRestart(command: 'reload' | 'restart'): Plugin {
name: '@electron-forge/plugin-vite:hot-restart',
closeBundle() {
if (command === 'reload') {
for (const server of Object.values(process.viteDevServers)) {
for (const server of Object.values(viteDevServers)) {
// Preload scripts hot reload.
server.ws.send({ type: 'full-reload' });
}
} else {
} else if (command === 'restart') {
// Main process hot restart.
// https://github.com/electron/forge/blob/v7.2.0/packages/api/core/src/api/start.ts#L216-L223
process.stdin.emit('data', 'rs');
// TODO: blocked in #3380
// process.stdin.emit('data', 'rs');
}
},
};

Просмотреть файл

@ -0,0 +1,29 @@
import { type ConfigEnv, mergeConfig, type UserConfig } from 'vite';
import { external, getBuildConfig, getBuildDefine, pluginHotRestart } from './vite.base.config';
export function getConfig(forgeEnv: ConfigEnv<'build'>): UserConfig {
const { forgeConfigSelf } = forgeEnv;
const define = getBuildDefine(forgeEnv);
const config: UserConfig = {
build: {
lib: {
entry: forgeConfigSelf.entry,
fileName: () => '[name].js',
formats: ['cjs'],
},
rollupOptions: {
external,
},
},
plugins: [pluginHotRestart('restart')],
define,
resolve: {
// Load the Node.js entry.
conditions: ['node'],
mainFields: ['module', 'jsnext:main', 'jsnext'],
},
};
return mergeConfig(getBuildConfig(forgeEnv), config);
}

Просмотреть файл

@ -0,0 +1,27 @@
import { type ConfigEnv, mergeConfig, type UserConfig } from 'vite';
import { external, getBuildConfig, pluginHotRestart } from './vite.base.config';
export function getConfig(forgeEnv: ConfigEnv<'build'>): UserConfig {
const { forgeConfigSelf } = forgeEnv;
const config: UserConfig = {
build: {
rollupOptions: {
external,
// Preload scripts may contain Web assets, so use the `build.rollupOptions.input` instead `build.lib.entry`.
input: forgeConfigSelf.entry,
output: {
format: 'cjs',
// It should not be split chunks.
inlineDynamicImports: true,
entryFileNames: '[name].js',
chunkFileNames: '[name].js',
assetFileNames: '[name].[ext]',
},
},
},
plugins: [pluginHotRestart('reload')],
};
return mergeConfig(getBuildConfig(forgeEnv), config);
}

Просмотреть файл

@ -0,0 +1,23 @@
import { type ConfigEnv, type UserConfig } from 'vite';
import { pluginExposeRenderer } from './vite.base.config';
// https://vitejs.dev/config
export function getConfig(forgeEnv: ConfigEnv<'renderer'>) {
const { root, mode, forgeConfigSelf } = forgeEnv;
const name = forgeConfigSelf.name ?? '';
return {
root,
mode,
base: './',
build: {
outDir: `.vite/renderer/${name}`,
},
plugins: [pluginExposeRenderer(name)],
resolve: {
preserveSymlinks: true,
},
clearScreen: false,
} as UserConfig;
}

Просмотреть файл

@ -1,108 +0,0 @@
import path from 'node:path';
import fs from 'fs-extra';
export interface Dependency {
name: string;
path: SourceAndDestination;
dependencies: Dependency[];
}
export interface SourceAndDestination {
src: string;
dest: string;
}
function isRootPath(dir: string) {
// *unix or Windows root path
return dir === '/' || /^[a-zA-Z]:\\$/i.test(dir);
}
export async function isDirectory(p: string): Promise<boolean> {
try {
const stat = await fs.promises.stat(p);
return stat.isDirectory();
} catch {
return false;
}
}
export async function lookupNodeModulesPaths(root: string, paths: string[] = []): Promise<string[]> {
if (!root) return paths;
if (!path.isAbsolute(root)) return paths;
const p = path.join(root, 'node_modules');
if (await isDirectory(p)) {
paths = paths.concat(p);
}
root = path.join(root, '..');
return isRootPath(root) ? paths : await lookupNodeModulesPaths(root, paths);
}
export async function resolveDependencies(root: string) {
const rootDependencies = Object.keys((await fs.readJson(path.join(root, 'package.json'))).dependencies || {});
const resolve = async (prePath: string, dependencies: string[], collected: Map<string, Dependency> = new Map()) =>
await Promise.all(
dependencies.map(async (name) => {
let curPath = prePath,
depPath = null,
packageJson = null;
while (!packageJson && !isRootPath(curPath)) {
const allNodeModules = await lookupNodeModulesPaths(curPath);
for (const nodeModules of allNodeModules) {
depPath = path.join(nodeModules, name);
if (await fs.pathExists(depPath)) break;
}
if (depPath) {
try {
packageJson = await fs.readJson(path.join(depPath, 'package.json'));
} catch (err) {
// lookup node_modules
curPath = path.join(curPath, '..');
if (curPath.length < root.length) {
console.error(`not found 'node_modules' in root path: ${root}`);
throw err;
}
}
}
}
if (!depPath || !packageJson) {
throw new Error(`find dependencies error in: ${curPath}`);
}
const result: Dependency = {
name,
path: {
src: depPath,
dest: path.relative(root, depPath),
},
dependencies: [],
};
const shouldResolveDeps = !collected.has(depPath);
collected.set(depPath, result);
if (shouldResolveDeps) {
result.dependencies = await resolve(depPath, Object.keys(packageJson.dependencies || {}), collected);
}
return result;
})
);
return resolve(root, rootDependencies);
}
export async function getFlatDependencies(root = process.cwd()) {
const depsTree = await resolveDependencies(root);
const depsFlat = new Map<string, SourceAndDestination>();
const flatten = (dep: Dependency) => {
depsFlat.set(dep.path.src, dep.path); // dedup
dep.dependencies.forEach(flatten);
};
depsTree.forEach(flatten);
return [...depsFlat.values()];
}

Просмотреть файл

@ -1,4 +1,3 @@
// eslint-disable-next-line node/no-unpublished-import
import type { Plugin } from 'vite';
export function onBuildDone(callback: () => void) {

Просмотреть файл

@ -1,64 +1,101 @@
import { builtinModules } from 'node:module';
import path from 'node:path';
import { expect } from 'chai';
import { external } from '../src/config/vite.base.config';
import ViteConfigGenerator from '../src/ViteConfig';
import type { VitePluginConfig } from '../src/Config';
import type { UserConfig } from 'vite';
import type { Plugin } from 'vite';
const builtins = ['electron', ...builtinModules.map((m) => [m, `node:${m}`]).flat()];
const configRoot = path.join(__dirname, 'fixture/config');
const configRoot = path.join(__dirname, 'fixtures/vite-configs');
describe('ViteConfigGenerator', () => {
it('getBuildConfig', async () => {
const config = {
build: [{ config: path.join(configRoot, 'vite.main.config.mjs') }],
renderer: [],
} as VitePluginConfig;
const generator = new ViteConfigGenerator(config, configRoot, true);
const buildConfig1 = (await generator.getBuildConfig())[0];
const buildConfig2: UserConfig = {
root: configRoot,
mode: 'production',
build: {
lib: {
it('getBuildConfig:main', async () => {
const forgeConfig: VitePluginConfig = {
build: [
{
entry: 'src/main.js',
formats: ['cjs'],
// shims
fileName: (buildConfig1.build?.lib as any)?.fileName,
config: path.join(configRoot, 'vite.main.config.mjs'),
target: 'main',
},
emptyOutDir: false,
outDir: '.vite/build',
minify: true, // this.isProd === true
watch: null,
rollupOptions: {
external: builtins,
},
},
clearScreen: false,
],
renderer: [],
};
const generator = new ViteConfigGenerator(forgeConfig, configRoot, true);
const buildConfig = (await generator.getBuildConfig())[0];
expect(buildConfig1).deep.equal(buildConfig2);
expect(buildConfig.root).equal(configRoot);
expect(buildConfig.mode).equal('production');
expect(buildConfig.build?.emptyOutDir).false;
expect(buildConfig.build?.outDir).equal('.vite/build');
expect(buildConfig.build?.watch).null;
expect(buildConfig.build?.minify).true;
expect(buildConfig.build?.lib && buildConfig.build.lib.entry).equal('src/main.js');
expect(buildConfig.build?.lib && (buildConfig.build.lib.fileName as () => string)()).equal('[name].js');
expect(buildConfig.build?.lib && buildConfig.build.lib.formats).deep.equal(['cjs']);
expect(buildConfig.build?.rollupOptions?.external).deep.equal(external);
expect(buildConfig.clearScreen).false;
expect(buildConfig.plugins?.map((plugin) => (plugin as Plugin).name)).deep.equal(['@electron-forge/plugin-vite:hot-restart']);
expect(buildConfig.define).deep.equal({});
expect(buildConfig.resolve).deep.equal({
conditions: ['node'],
mainFields: ['module', 'jsnext:main', 'jsnext'],
});
});
it('getRendererConfig', async () => {
const config = {
build: [{ config: path.join(configRoot, 'vite.renderer.config.mjs') }],
it('getBuildConfig:preload', async () => {
const forgeConfig: VitePluginConfig = {
build: [
{
entry: 'src/preload.js',
config: path.join(configRoot, 'vite.preload.config.mjs'),
target: 'preload',
},
],
renderer: [],
} as VitePluginConfig;
const generator = new ViteConfigGenerator(config, configRoot, true);
const buildConfig1 = (await generator.getBuildConfig())[0];
const buildConfig2: UserConfig = {
root: configRoot,
mode: 'production',
base: './',
build: {
outDir: 'renderer/main_window',
},
};
const generator = new ViteConfigGenerator(forgeConfig, configRoot, true);
const buildConfig = (await generator.getBuildConfig())[0];
expect(buildConfig1).deep.equal(buildConfig2);
expect(buildConfig.root).equal(configRoot);
expect(buildConfig.mode).equal('production');
expect(buildConfig.build?.emptyOutDir).false;
expect(buildConfig.build?.outDir).equal('.vite/build');
expect(buildConfig.build?.watch).null;
expect(buildConfig.build?.minify).true;
expect(buildConfig.build?.rollupOptions?.external).deep.equal(external);
expect(buildConfig.build?.rollupOptions?.input).equal('src/preload.js');
expect(buildConfig.build?.rollupOptions?.output).deep.equal({
format: 'cjs',
inlineDynamicImports: true,
entryFileNames: '[name].js',
chunkFileNames: '[name].js',
assetFileNames: '[name].[ext]',
});
expect(buildConfig.clearScreen).false;
expect(buildConfig.plugins?.map((plugin) => (plugin as Plugin).name)).deep.equal(['@electron-forge/plugin-vite:hot-restart']);
});
it('getRendererConfig:renderer', async () => {
const forgeConfig = {
build: [],
renderer: [
{
name: 'main_window',
config: path.join(configRoot, 'vite.renderer.config.mjs'),
},
],
};
const generator = new ViteConfigGenerator(forgeConfig, configRoot, true);
const rendererConfig = (await generator.getRendererConfig())[0];
expect(rendererConfig.root).equal(configRoot);
expect(rendererConfig.mode).equal('production');
expect(rendererConfig.base).equal('./');
expect(rendererConfig.build?.outDir).equal('.vite/renderer/main_window');
expect(rendererConfig.plugins?.map((plugin) => (plugin as Plugin).name)).deep.equal(['@electron-forge/plugin-vite:expose-renderer']);
expect(rendererConfig.resolve).deep.equal({ preserveSymlinks: true });
expect(rendererConfig.clearScreen).false;
});
});

Просмотреть файл

@ -0,0 +1,107 @@
import path from 'node:path';
import { expect } from 'chai';
import { default as vite } from 'vite';
import { getBuildDefine, getDefineKeys, pluginExposeRenderer } from '../../src/config/vite.base.config';
import type { VitePluginConfig } from '../../src/Config';
const configRoot = path.join(__dirname, 'fixtures/vite-configs');
const forgeConfig: VitePluginConfig = {
build: [
{
entry: 'src/main.js',
config: path.join(configRoot, 'vite.main.config.mjs'),
target: 'main',
},
{
entry: 'src/preload.js',
config: path.join(configRoot, 'vite.preload.config.mjs'),
target: 'preload',
},
],
renderer: [
{
name: 'main_window',
config: path.join(configRoot, 'vite.renderer.config.mjs'),
},
{
name: 'second_window',
config: path.join(configRoot, 'vite.renderer.config.mjs'),
},
],
};
describe('vite.base.config', () => {
it('getDefineKeys', () => {
const defineKeys1 = getDefineKeys(forgeConfig.renderer.map(({ name }) => name));
const defineKeys2 = {
main_window: {
VITE_DEV_SERVER_URL: 'MAIN_WINDOW_VITE_DEV_SERVER_URL',
VITE_NAME: 'MAIN_WINDOW_VITE_NAME',
},
second_window: {
VITE_DEV_SERVER_URL: 'SECOND_WINDOW_VITE_DEV_SERVER_URL',
VITE_NAME: 'SECOND_WINDOW_VITE_NAME',
},
};
expect(defineKeys1).deep.equal(defineKeys2);
});
it('getBuildDefine:build', () => {
const define1 = getBuildDefine({
command: 'build',
mode: 'production',
root: configRoot,
forgeConfig,
forgeConfigSelf: forgeConfig.build[0],
});
const define2 = {
MAIN_WINDOW_VITE_DEV_SERVER_URL: undefined,
MAIN_WINDOW_VITE_NAME: '"main_window"',
SECOND_WINDOW_VITE_DEV_SERVER_URL: undefined,
SECOND_WINDOW_VITE_NAME: '"second_window"',
};
expect(define1).deep.equal(define2);
});
it('getBuildDefine:serve', async () => {
const servers = await Promise.all(
forgeConfig.renderer.map(({ name }) =>
vite.createServer({
publicDir: false,
plugins: [pluginExposeRenderer(name)],
})
)
);
let port = 5173;
for (const server of servers) {
await server.listen(port);
port++;
}
const define1 = getBuildDefine({
command: 'serve',
mode: 'development',
root: configRoot,
forgeConfig,
forgeConfigSelf: forgeConfig.build[0],
});
const define2 = {
MAIN_WINDOW_VITE_DEV_SERVER_URL: '"http://localhost:5173"',
MAIN_WINDOW_VITE_NAME: '"main_window"',
SECOND_WINDOW_VITE_DEV_SERVER_URL: '"http://localhost:5174"',
SECOND_WINDOW_VITE_NAME: '"second_window"',
};
for (const server of servers) {
await server.close();
}
expect(define1).deep.equal(define2);
});
});

Просмотреть файл

@ -1,31 +0,0 @@
import { builtinModules } from 'node:module';
// eslint-disable-next-line import/namespace
import { defineConfig } from 'vite';
const builtins = [
'electron',
...builtinModules.map((m) => [m, `node:${m}`]).flat(),
];
export default defineConfig((env) => ({
root: env.root,
mode: env.mode,
build: {
lib: {
entry: 'src/main.js',
fileName: () => '[name].js',
formats: ['cjs'],
},
// Prevent multiple builds from interfering with each other.
emptyOutDir: false,
// 🚧 Multiple builds may conflict.
outDir: '.vite/build',
minify: env.command === 'build',
watch: env.command === 'serve' ? {} : null,
rollupOptions: {
external: builtins,
},
},
clearScreen: false,
}));

Просмотреть файл

@ -1,11 +0,0 @@
// eslint-disable-next-line import/namespace
import { defineConfig } from 'vite';
export default defineConfig((env) => ({
root: env.root,
mode: env.mode,
base: './',
build: {
outDir: 'renderer/main_window',
},
}));

Просмотреть файл

@ -1,7 +0,0 @@
{
"name": "@electron-forge/plugin-vite-test-util-package",
"version": "0.1.0",
"dependencies": {
"electron-squirrel-startup": "^1.0.0"
}
}

Просмотреть файл

Просмотреть файл

@ -0,0 +1,2 @@
/* eslint-disable */
export default {};

Просмотреть файл

@ -0,0 +1,2 @@
/* eslint-disable */
export default {};

Просмотреть файл

@ -0,0 +1,2 @@
/* eslint-disable */
export default {};

Просмотреть файл

@ -1,75 +0,0 @@
import { exec } from 'node:child_process';
import path from 'node:path';
import { promisify } from 'node:util';
import { expect } from 'chai';
import { getFlatDependencies, isDirectory, lookupNodeModulesPaths, resolveDependencies } from '../../src/util/package';
const execPromise = promisify(exec);
const packageRoot = path.join(__dirname, '../fixture/package');
const depsTree = [
{
name: 'electron-squirrel-startup',
path: {
src: path.join(packageRoot, 'node_modules', 'electron-squirrel-startup'),
dest: path.join('node_modules', 'electron-squirrel-startup'),
},
dependencies: [
{
name: 'debug',
path: {
src: path.join(packageRoot, 'node_modules', 'debug'),
dest: path.join('node_modules', 'debug'),
},
dependencies: [
{
name: 'ms',
path: {
src: path.join(packageRoot, 'node_modules', 'ms'),
dest: path.join('node_modules', 'ms'),
},
dependencies: [],
},
],
},
],
},
];
const depsFlat = [
{
src: path.join(packageRoot, 'node_modules', 'electron-squirrel-startup'),
dest: path.join('node_modules', 'electron-squirrel-startup'),
},
{
src: path.join(packageRoot, 'node_modules', 'debug'),
dest: path.join('node_modules', 'debug'),
},
{
src: path.join(packageRoot, 'node_modules', 'ms'),
dest: path.join('node_modules', 'ms'),
},
];
describe('util/package', () => {
before(async () => {
await execPromise('npm install', { cwd: packageRoot });
});
it('dependencies of package.json is resolved correct', async () => {
const depsT = await resolveDependencies(packageRoot);
const depsF = await getFlatDependencies(packageRoot);
expect(depsTree).deep.equal(depsT);
expect(depsFlat).deep.equal(depsF);
});
it('isDirectory check is correct', async () => {
expect(await isDirectory(packageRoot)).true;
expect(await isDirectory(path.join(packageRoot, 'package.json'))).false;
});
it('node_modules paths is lookup correct', async () => {
const paths = await lookupNodeModulesPaths(packageRoot);
expect(paths.length).gt(0);
});
});

Просмотреть файл

@ -1,6 +1,6 @@
{
"name": "@electron-forge/plugin-webpack",
"version": "7.4.0",
"version": "7.5.0",
"description": "Webpack plugin for Electron Forge, lets you use Webpack directly in your tooling",
"repository": "https://github.com/electron/forge",
"author": "Samuel Attard",
@ -24,10 +24,10 @@
"node": ">= 16.4.0"
},
"dependencies": {
"@electron-forge/core-utils": "7.4.0",
"@electron-forge/plugin-base": "7.4.0",
"@electron-forge/shared-types": "7.4.0",
"@electron-forge/web-multi-logger": "7.4.0",
"@electron-forge/core-utils": "7.5.0",
"@electron-forge/plugin-base": "7.5.0",
"@electron-forge/shared-types": "7.5.0",
"@electron-forge/web-multi-logger": "7.5.0",
"chalk": "^4.0.0",
"debug": "^4.3.1",
"fast-glob": "^3.2.7",

Просмотреть файл

@ -1,6 +1,6 @@
{
"name": "@electron-forge/publisher-static",
"version": "7.4.0",
"version": "7.5.0",
"description": "Base publisher for Electron Forge",
"repository": "https://github.com/electron/forge",
"author": "Samuel Attard",
@ -12,8 +12,8 @@
"test:base": "cross-env TS_NODE_FILES=1 mocha --config ../../../.mocharc.js"
},
"dependencies": {
"@electron-forge/publisher-base": "7.4.0",
"@electron-forge/shared-types": "7.4.0"
"@electron-forge/publisher-base": "7.5.0",
"@electron-forge/shared-types": "7.5.0"
},
"devDependencies": {
"chai": "^4.3.3",

Просмотреть файл

@ -1,6 +1,6 @@
{
"name": "@electron-forge/publisher-base",
"version": "7.4.0",
"version": "7.5.0",
"description": "Base publisher for Electron Forge",
"repository": "https://github.com/electron/forge",
"author": "Samuel Attard",
@ -12,7 +12,7 @@
"test:base": "cross-env TS_NODE_FILES=1 mocha --config ../../../.mocharc.js"
},
"dependencies": {
"@electron-forge/shared-types": "7.4.0"
"@electron-forge/shared-types": "7.5.0"
},
"devDependencies": {
"chai": "^4.3.3",

Просмотреть файл

@ -1,6 +1,6 @@
{
"name": "@electron-forge/publisher-bitbucket",
"version": "7.4.0",
"version": "7.5.0",
"description": "Bitbucket publisher for Electron Forge",
"repository": "https://github.com/electron/forge",
"author": "Luke Batchelor",
@ -15,7 +15,7 @@
"node": ">= 16.4.0"
},
"dependencies": {
"@electron-forge/publisher-base": "7.4.0",
"@electron-forge/publisher-base": "7.5.0",
"form-data": "^4.0.0",
"fs-extra": "^10.0.0",
"node-fetch": "^2.6.7"

Просмотреть файл

@ -1,6 +1,6 @@
{
"name": "@electron-forge/publisher-electron-release-server",
"version": "7.4.0",
"version": "7.5.0",
"description": "Electron release server publisher for Electron Forge",
"repository": "https://github.com/electron/forge",
"author": "Samuel Attard",
@ -18,8 +18,8 @@
"node": ">= 16.4.0"
},
"dependencies": {
"@electron-forge/publisher-base": "7.4.0",
"@electron-forge/shared-types": "7.4.0",
"@electron-forge/publisher-base": "7.5.0",
"@electron-forge/shared-types": "7.5.0",
"debug": "^4.3.1",
"form-data": "^4.0.0",
"fs-extra": "^10.0.0",

Просмотреть файл

@ -1,6 +1,6 @@
{
"name": "@electron-forge/publisher-gcs",
"version": "7.4.0",
"version": "7.5.0",
"description": "Google Cloud Storage publisher for Electron Forge",
"repository": "https://github.com/electron/forge",
"author": "Evgeny Vlasenko",
@ -15,8 +15,8 @@
"node": ">= 16.4.0"
},
"dependencies": {
"@electron-forge/publisher-static": "7.4.0",
"@electron-forge/shared-types": "7.4.0",
"@electron-forge/publisher-static": "7.5.0",
"@electron-forge/shared-types": "7.5.0",
"@google-cloud/storage": "^7.5.0",
"debug": "^4.3.1"
},

Просмотреть файл

@ -23,7 +23,9 @@ export default class PublisherGCS extends PublisherStatic<PublisherGCSConfig> {
async publish({ makeResults, setStatusLine }: PublisherOptions): Promise<void> {
const artifacts: GCSArtifact[] = [];
if (!this.config.bucket) {
const { storageOptions, bucket: configBucket, folder, ...uploadOptions } = this.config;
if (!configBucket) {
throw new Error('In order to publish to Google Cloud Storage you must set the "bucket" property in your Forge config.');
}
@ -31,16 +33,16 @@ export default class PublisherGCS extends PublisherStatic<PublisherGCSConfig> {
artifacts.push(
...makeResult.artifacts.map((artifact) => ({
path: artifact,
keyPrefix: this.config.folder || this.GCSKeySafe(makeResult.packageJSON.name),
keyPrefix: folder || this.GCSKeySafe(makeResult.packageJSON.name),
platform: makeResult.platform,
arch: makeResult.arch,
}))
);
}
const storage = new Storage(this.config.storageOptions);
const storage = new Storage(storageOptions);
const bucket = storage.bucket(this.config.bucket);
const bucket = storage.bucket(configBucket);
d('creating Google Cloud Storage client with options:', this.config);
@ -51,14 +53,11 @@ export default class PublisherGCS extends PublisherStatic<PublisherGCSConfig> {
await Promise.all(
artifacts.map(async (artifact) => {
d('uploading:', artifact.path);
await bucket.upload(artifact.path, {
metadata: this.config.metadataGenerator ? this.config.metadataGenerator(artifact) : {},
gzip: true,
destination: this.keyForArtifact(artifact),
predefinedAcl: this.config.predefinedAcl,
public: this.config.public,
private: this.config.private,
...uploadOptions,
});
uploaded += 1;

Просмотреть файл

@ -1,6 +1,6 @@
{
"name": "@electron-forge/publisher-github",
"version": "7.4.0",
"version": "7.5.0",
"description": "Github publisher for Electron Forge",
"repository": "https://github.com/electron/forge",
"author": "Samuel Attard",
@ -21,8 +21,8 @@
"node": ">= 16.4.0"
},
"dependencies": {
"@electron-forge/publisher-base": "7.4.0",
"@electron-forge/shared-types": "7.4.0",
"@electron-forge/publisher-base": "7.5.0",
"@electron-forge/shared-types": "7.5.0",
"@octokit/core": "^3.2.4",
"@octokit/plugin-retry": "^3.0.9",
"@octokit/request-error": "^2.0.5",

Просмотреть файл

@ -1,6 +1,6 @@
{
"name": "@electron-forge/publisher-nucleus",
"version": "7.4.0",
"version": "7.5.0",
"description": "Nucleus publisher for Electron Forge",
"repository": "https://github.com/electron/forge",
"author": "Samuel Attard",
@ -15,8 +15,8 @@
"node": ">= 16.4.0"
},
"dependencies": {
"@electron-forge/publisher-base": "7.4.0",
"@electron-forge/shared-types": "7.4.0",
"@electron-forge/publisher-base": "7.5.0",
"@electron-forge/shared-types": "7.5.0",
"debug": "^4.3.1",
"form-data": "^4.0.0",
"node-fetch": "^2.6.7"

Просмотреть файл

@ -1,6 +1,6 @@
{
"name": "@electron-forge/publisher-s3",
"version": "7.4.0",
"version": "7.5.0",
"description": "S3 publisher for Electron Forge",
"repository": "https://github.com/electron/forge",
"author": "Samuel Attard",
@ -15,12 +15,11 @@
"node": ">= 16.4.0"
},
"dependencies": {
"@aws-sdk/abort-controller": "^3.29.0",
"@aws-sdk/client-s3": "^3.461.0",
"@aws-sdk/lib-storage": "^3.28.0",
"@aws-sdk/types": "^3.25.0",
"@electron-forge/publisher-static": "7.4.0",
"@electron-forge/shared-types": "7.4.0",
"@aws-sdk/client-s3": "^3.654.0",
"@aws-sdk/lib-storage": "^3.654.0",
"@aws-sdk/types": "^3.654.0",
"@electron-forge/publisher-static": "7.5.0",
"@electron-forge/shared-types": "7.5.0",
"debug": "^4.3.1"
},
"publishConfig": {

Просмотреть файл

@ -1,6 +1,6 @@
{
"name": "@electron-forge/publisher-snapcraft",
"version": "7.4.0",
"version": "7.5.0",
"description": "Snapcraft publisher for Electron Forge",
"repository": "https://github.com/electron/forge",
"author": "Samuel Attard",
@ -15,7 +15,7 @@
"node": ">= 16.4.0"
},
"dependencies": {
"@electron-forge/publisher-base": "7.4.0",
"@electron-forge/publisher-base": "7.5.0",
"fs-extra": "^10.0.0"
},
"optionalDependencies": {

Просмотреть файл

@ -1,6 +1,6 @@
{
"name": "@electron-forge/template-base",
"version": "7.4.0",
"version": "7.5.0",
"description": "Base template for Electron Forge",
"repository": "https://github.com/electron/forge",
"author": "Samuel Attard",
@ -14,14 +14,14 @@
"node": ">= 16.4.0"
},
"dependencies": {
"@electron-forge/shared-types": "7.4.0",
"@electron-forge/shared-types": "7.5.0",
"@malept/cross-spawn-promise": "^2.0.0",
"debug": "^4.3.1",
"fs-extra": "^10.0.0",
"username": "^5.1.0"
},
"devDependencies": {
"@electron-forge/test-utils": "7.4.0",
"@electron-forge/test-utils": "7.5.0",
"chai": "^4.3.3",
"mocha": "^9.0.1",
"proxyquire": "^2.1.3",

Просмотреть файл

@ -1,6 +1,6 @@
{
"name": "@electron-forge/template-vite-typescript",
"version": "7.4.0",
"version": "7.5.0",
"description": "Vite-TypeScript template for Electron Forge, gets you started with Vite really quickly",
"repository": {
"type": "git",
@ -18,13 +18,13 @@
"node": ">= 16.4.0"
},
"dependencies": {
"@electron-forge/shared-types": "7.4.0",
"@electron-forge/template-base": "7.4.0",
"@electron-forge/shared-types": "7.5.0",
"@electron-forge/template-base": "7.5.0",
"fs-extra": "^10.0.0"
},
"devDependencies": {
"@electron-forge/core-utils": "7.4.0",
"@electron-forge/test-utils": "7.4.0",
"@electron-forge/core-utils": "7.5.0",
"@electron-forge/test-utils": "7.5.0",
"chai": "^4.3.3",
"fast-glob": "^3.2.7"
},

Просмотреть файл

@ -25,7 +25,6 @@ class ViteTypeScriptTemplate extends BaseTemplate {
const filePath = (fileName: string) => path.join(directory, 'src', fileName);
// Copy Vite files
await this.copyTemplateFile(directory, 'vite.base.config.ts');
await this.copyTemplateFile(directory, 'vite.main.config.ts');
await this.copyTemplateFile(directory, 'vite.preload.config.ts');
await this.copyTemplateFile(directory, 'vite.renderer.config.ts');

Просмотреть файл

@ -41,7 +41,6 @@ describe('ViteTypeScriptTemplate', () => {
'.eslintrc.json',
'forge.env.d.ts',
'forge.config.ts',
'vite.base.config.ts',
'vite.main.config.ts',
'vite.preload.config.ts',
'vite.renderer.config.ts',

Просмотреть файл

@ -22,10 +22,12 @@ const config: ForgeConfig = {
// `entry` is just an alias for `build.lib.entry` in the corresponding file of `config`.
entry: 'src/main.ts',
config: 'vite.main.config.ts',
target: 'main',
},
{
entry: 'src/preload.ts',
config: 'vite.preload.config.ts',
target: 'preload',
},
],
renderer: [

Просмотреть файл

@ -1,31 +1 @@
export {}; // Make this a module
declare global {
// This allows TypeScript to pick up the magic constants that's auto-generated by Forge's Vite
// plugin that tells the Electron app where to look for the Vite-bundled app code (depending on
// whether you're running in development or production).
const MAIN_WINDOW_VITE_DEV_SERVER_URL: string;
const MAIN_WINDOW_VITE_NAME: string;
namespace NodeJS {
interface Process {
// Used for hot reload after preload scripts.
viteDevServers: Record<string, import('vite').ViteDevServer>;
}
}
type VitePluginConfig = ConstructorParameters<typeof import('@electron-forge/plugin-vite').VitePlugin>[0];
interface VitePluginRuntimeKeys {
VITE_DEV_SERVER_URL: `${string}_VITE_DEV_SERVER_URL`;
VITE_NAME: `${string}_VITE_NAME`;
}
}
declare module 'vite' {
interface ConfigEnv<K extends keyof VitePluginConfig = keyof VitePluginConfig> {
root: string;
forgeConfig: VitePluginConfig;
forgeConfigSelf: VitePluginConfig[K][number];
}
}
/// <reference types="@electron-forge/plugin-vite/forge-vite-env" />

Просмотреть файл

@ -1,30 +1,4 @@
import type { ConfigEnv, UserConfig } from 'vite';
import { defineConfig, mergeConfig } from 'vite';
import { getBuildConfig, getBuildDefine, external, pluginHotRestart } from './vite.base.config';
import { defineConfig } from 'vite';
// https://vitejs.dev/config
export default defineConfig((env) => {
const forgeEnv = env as ConfigEnv<'build'>;
const { forgeConfigSelf } = forgeEnv;
const define = getBuildDefine(forgeEnv);
const config: UserConfig = {
build: {
lib: {
entry: forgeConfigSelf.entry!,
fileName: () => '[name].js',
formats: ['cjs'],
},
rollupOptions: {
external,
},
},
plugins: [pluginHotRestart('restart')],
define,
resolve: {
// Load the Node.js entry.
mainFields: ['module', 'jsnext:main', 'jsnext'],
},
};
return mergeConfig(getBuildConfig(forgeEnv), config);
});
export default defineConfig({});

Просмотреть файл

@ -1,29 +1,4 @@
import type { ConfigEnv, UserConfig } from 'vite';
import { defineConfig, mergeConfig } from 'vite';
import { getBuildConfig, external, pluginHotRestart } from './vite.base.config';
import { defineConfig } from 'vite';
// https://vitejs.dev/config
export default defineConfig((env) => {
const forgeEnv = env as ConfigEnv<'build'>;
const { forgeConfigSelf } = forgeEnv;
const config: UserConfig = {
build: {
rollupOptions: {
external,
// Preload scripts may contain Web assets, so use the `build.rollupOptions.input` instead `build.lib.entry`.
input: forgeConfigSelf.entry!,
output: {
format: 'cjs',
// It should not be split chunks.
inlineDynamicImports: true,
entryFileNames: '[name].js',
chunkFileNames: '[name].js',
assetFileNames: '[name].[ext]',
},
},
},
plugins: [pluginHotRestart('reload')],
};
return mergeConfig(getBuildConfig(forgeEnv), config);
});
export default defineConfig({});

Просмотреть файл

@ -1,24 +1,4 @@
import type { ConfigEnv, UserConfig } from 'vite';
import { defineConfig } from 'vite';
import { pluginExposeRenderer } from './vite.base.config';
// https://vitejs.dev/config
export default defineConfig((env) => {
const forgeEnv = env as ConfigEnv<'renderer'>;
const { root, mode, forgeConfigSelf } = forgeEnv;
const name = forgeConfigSelf.name ?? '';
return {
root,
mode,
base: './',
build: {
outDir: `.vite/renderer/${name}`,
},
plugins: [pluginExposeRenderer(name)],
resolve: {
preserveSymlinks: true,
},
clearScreen: false,
} as UserConfig;
});
export default defineConfig({});

Просмотреть файл

@ -1,6 +1,6 @@
{
"name": "@electron-forge/template-vite",
"version": "7.4.0",
"version": "7.5.0",
"description": "Vite template for Electron Forge, gets you started with Vite really quickly",
"repository": {
"type": "git",
@ -18,12 +18,12 @@
"node": ">= 16.4.0"
},
"dependencies": {
"@electron-forge/shared-types": "7.4.0",
"@electron-forge/template-base": "7.4.0",
"@electron-forge/shared-types": "7.5.0",
"@electron-forge/template-base": "7.5.0",
"fs-extra": "^10.0.0"
},
"devDependencies": {
"@electron-forge/test-utils": "7.4.0",
"@electron-forge/test-utils": "7.5.0",
"chai": "^4.3.3",
"listr2": "^7.0.2"
},

Просмотреть файл

@ -15,14 +15,12 @@ class ViteTemplate extends BaseTemplate {
title: 'Setting up Forge configuration',
task: async () => {
await this.copyTemplateFile(directory, 'forge.config.js');
await this.copyTemplateFile(directory, 'forge.env.d.txt');
await fs.rename(path.join(directory, 'forge.env.d.txt'), path.join(directory, 'forge.env.d.ts'));
await this.copyTemplateFile(directory, 'forge.env.d.ts');
},
},
{
title: 'Setting up Vite configuration',
task: async () => {
await this.copyTemplateFile(directory, 'vite.base.config.mjs');
await this.copyTemplateFile(directory, 'vite.main.config.mjs');
await this.copyTemplateFile(directory, 'vite.preload.config.mjs');
await this.copyTemplateFile(directory, 'vite.renderer.config.mjs');

Просмотреть файл

@ -30,7 +30,6 @@ describe('ViteTemplate', () => {
'package.json',
'forge.env.d.ts',
'forge.config.js',
'vite.base.config.mjs',
'vite.main.config.mjs',
'vite.preload.config.mjs',
'vite.renderer.config.mjs',

Просмотреть файл

@ -35,10 +35,12 @@ module.exports = {
// `entry` is just an alias for `build.lib.entry` in the corresponding file of `config`.
entry: 'src/main.js',
config: 'vite.main.config.mjs',
target: 'main',
},
{
entry: 'src/preload.js',
config: 'vite.preload.config.mjs',
target: 'preload',
},
],
renderer: [

1
packages/template/vite/tmpl/forge.env.d.ts поставляемый Normal file
Просмотреть файл

@ -0,0 +1 @@
/// <reference types="@electron-forge/plugin-vite/forge-vite-env" />

Просмотреть файл

@ -1,109 +0,0 @@
import { builtinModules } from 'node:module';
import pkg from './package.json';
export const builtins = [
'electron',
...builtinModules.map((m) => [m, `node:${m}`]).flat(),
];
export const external = [...builtins, ...Object.keys(pkg.dependencies || {})];
/** @type {(env: import('vite').ConfigEnv<'build'>) => import('vite').UserConfig} */
export const getBuildConfig = (env) => {
const { root, mode, command } = env;
return {
root,
mode,
build: {
// Prevent multiple builds from interfering with each other.
emptyOutDir: false,
// 🚧 Multiple builds may conflict.
outDir: '.vite/build',
watch: command === 'serve' ? {} : null,
minify: command === 'build',
},
clearScreen: false,
};
};
/** @type {(names: string[]) => { [name: string]: VitePluginRuntimeKeys } }} */
export const getDefineKeys = (names) => {
/** @type {{ [name: string]: VitePluginRuntimeKeys }} */
const define = {};
return names.reduce((acc, name) => {
const NAME = name.toUpperCase();
/** @type {VitePluginRuntimeKeys} */
const keys = {
VITE_DEV_SERVER_URL: `${NAME}_VITE_DEV_SERVER_URL`,
VITE_NAME: `${NAME}_VITE_NAME`,
};
return { ...acc, [name]: keys };
}, define);
};
/** @type {(env: import('vite').ConfigEnv<'build'>) => Record<string, any>} */
export const getBuildDefine = (env) => {
const { command, forgeConfig } = env;
const names = forgeConfig.renderer
.filter(({ name }) => name != null)
.map(({ name }) => name);
const defineKeys = getDefineKeys(names);
const define = Object.entries(defineKeys).reduce((acc, [name, keys]) => {
const { VITE_DEV_SERVER_URL, VITE_NAME } = keys;
const def = {
[VITE_DEV_SERVER_URL]:
command === 'serve'
? JSON.stringify(process.env[VITE_DEV_SERVER_URL])
: undefined,
[VITE_NAME]: JSON.stringify(name),
};
return { ...acc, ...def };
}, {});
return define;
};
/** @type {(name: string) => import('vite').Plugin} */
export const pluginExposeRenderer = (name) => {
const { VITE_DEV_SERVER_URL } = getDefineKeys([name])[name];
return {
name: '@electron-forge/plugin-vite:expose-renderer',
configureServer(server) {
process.viteDevServers ??= {};
// Expose server for preload scripts hot reload.
process.viteDevServers[name] = server;
server.httpServer?.once('listening', () => {
/** @type {import('node:net').AddressInfo} */
const addressInfo = server.httpServer?.address();
// Expose env constant for main process use.
process.env[
VITE_DEV_SERVER_URL
] = `http://localhost:${addressInfo?.port}`;
});
},
};
};
/** @type {(command: 'reload' | 'restart') => import('vite').Plugin} */
export const pluginHotRestart = (command) => {
return {
name: '@electron-forge/plugin-vite:hot-restart',
closeBundle() {
if (command === 'reload') {
for (const server of Object.values(process.viteDevServers)) {
// Preload scripts hot reload.
server.ws.send({ type: 'full-reload' });
}
} else {
// Main process hot restart.
// https://github.com/electron/forge/blob/v7.2.0/packages/api/core/src/api/start.ts#L216-L223
process.stdin.emit('data', 'rs');
}
},
};
};

Просмотреть файл

@ -1,35 +1,4 @@
import { defineConfig, mergeConfig } from 'vite';
import {
getBuildConfig,
getBuildDefine,
external,
pluginHotRestart,
} from './vite.base.config.mjs';
import { defineConfig } from 'vite';
// https://vitejs.dev/config
export default defineConfig((env) => {
/** @type {import('vite').ConfigEnv<'build'>} */
const forgeEnv = env;
const { forgeConfigSelf } = forgeEnv;
const define = getBuildDefine(forgeEnv);
const config = {
build: {
lib: {
entry: forgeConfigSelf.entry,
fileName: () => '[name].js',
formats: ['cjs'],
},
rollupOptions: {
external,
},
},
plugins: [pluginHotRestart('restart')],
define,
resolve: {
// Load the Node.js entry.
mainFields: ['module', 'jsnext:main', 'jsnext'],
},
};
return mergeConfig(getBuildConfig(forgeEnv), config);
});
export default defineConfig({});

Просмотреть файл

@ -1,34 +1,4 @@
import { defineConfig, mergeConfig } from 'vite';
import {
getBuildConfig,
external,
pluginHotRestart,
} from './vite.base.config.mjs';
import { defineConfig } from 'vite';
// https://vitejs.dev/config
export default defineConfig((env) => {
/** @type {import('vite').ConfigEnv<'build'>} */
const forgeEnv = env;
const { forgeConfigSelf } = forgeEnv;
/** @type {import('vite').UserConfig} */
const config = {
build: {
rollupOptions: {
external,
// Preload scripts may contain Web assets, so use the `build.rollupOptions.input` instead `build.lib.entry`.
input: forgeConfigSelf.entry,
output: {
format: 'cjs',
// It should not be split chunks.
inlineDynamicImports: true,
entryFileNames: '[name].js',
chunkFileNames: '[name].js',
assetFileNames: '[name].[ext]',
},
},
},
plugins: [pluginHotRestart('reload')],
};
return mergeConfig(getBuildConfig(forgeEnv), config);
});
export default defineConfig({});

Просмотреть файл

@ -1,25 +1,4 @@
import { defineConfig } from 'vite';
import { pluginExposeRenderer } from './vite.base.config.mjs';
// https://vitejs.dev/config
export default defineConfig((env) => {
/** @type {import('vite').ConfigEnv<'renderer'>} */
const forgeEnv = env;
const { root, mode, forgeConfigSelf } = forgeEnv;
const name = forgeConfigSelf.name ?? '';
/** @type {import('vite').UserConfig} */
return {
root,
mode,
base: './',
build: {
outDir: `.vite/renderer/${name}`,
},
plugins: [pluginExposeRenderer(name)],
resolve: {
preserveSymlinks: true,
},
clearScreen: false,
};
});
export default defineConfig({});

Просмотреть файл

@ -1,6 +1,6 @@
{
"name": "@electron-forge/template-webpack-typescript",
"version": "7.4.0",
"version": "7.5.0",
"description": "Webpack-TypeScript template for Electron Forge",
"repository": "https://github.com/electron/forge",
"author": "Shelley Vohr <shelley.vohr@gmail.com>",
@ -14,18 +14,18 @@
"node": ">= 16.4.0"
},
"dependencies": {
"@electron-forge/shared-types": "7.4.0",
"@electron-forge/template-base": "7.4.0",
"@electron-forge/shared-types": "7.5.0",
"@electron-forge/template-base": "7.5.0",
"fs-extra": "^10.0.0"
},
"devDependencies": {
"@electron-forge/core-utils": "7.4.0",
"@electron-forge/maker-deb": "7.4.0",
"@electron-forge/maker-rpm": "7.4.0",
"@electron-forge/maker-squirrel": "7.4.0",
"@electron-forge/maker-zip": "7.4.0",
"@electron-forge/plugin-webpack": "7.4.0",
"@electron-forge/test-utils": "7.4.0",
"@electron-forge/core-utils": "7.5.0",
"@electron-forge/maker-deb": "7.5.0",
"@electron-forge/maker-rpm": "7.5.0",
"@electron-forge/maker-squirrel": "7.5.0",
"@electron-forge/maker-zip": "7.5.0",
"@electron-forge/plugin-webpack": "7.5.0",
"@electron-forge/test-utils": "7.5.0",
"chai": "^4.3.3",
"fast-glob": "^3.2.7",
"fork-ts-checker-webpack-plugin": "^7.2.13",

Просмотреть файл

@ -1,6 +1,6 @@
{
"name": "@electron-forge/template-webpack",
"version": "7.4.0",
"version": "7.5.0",
"description": "Webpack template for Electron Forge, gets you started with Webpack really quickly",
"repository": "https://github.com/electron/forge",
"author": "Samuel Attard",
@ -14,12 +14,12 @@
"node": ">= 16.4.0"
},
"dependencies": {
"@electron-forge/shared-types": "7.4.0",
"@electron-forge/template-base": "7.4.0",
"@electron-forge/shared-types": "7.5.0",
"@electron-forge/template-base": "7.5.0",
"fs-extra": "^10.0.0"
},
"devDependencies": {
"@electron-forge/test-utils": "7.4.0",
"@electron-forge/test-utils": "7.5.0",
"chai": "^4.3.3",
"listr2": "^7.0.2"
},

Просмотреть файл

@ -1,6 +1,6 @@
{
"name": "@electron-forge/core-utils",
"version": "7.4.0",
"version": "7.5.0",
"description": "Core utilities for the Electron Forge packages",
"repository": "https://github.com/electron/forge",
"author": "Samuel Attard",
@ -8,7 +8,7 @@
"main": "dist/index.js",
"typings": "dist/index.d.ts",
"dependencies": {
"@electron-forge/shared-types": "7.4.0",
"@electron-forge/shared-types": "7.5.0",
"@electron/rebuild": "^3.2.10",
"@malept/cross-spawn-promise": "^2.0.0",
"chalk": "^4.0.0",

Просмотреть файл

@ -1,6 +1,6 @@
{
"name": "@electron-forge/test-utils",
"version": "7.4.0",
"version": "7.5.0",
"description": "Helper utilities for the Electron Forge testsuite",
"repository": "https://github.com/electron/forge",
"author": "Mark Lee",

Просмотреть файл

@ -1,6 +1,6 @@
{
"name": "@electron-forge/tracer",
"version": "7.4.0",
"version": "7.5.0",
"description": "Tracing helpers for Electron Forge",
"repository": "https://github.com/electron/forge",
"author": "Samuel Attard",

Просмотреть файл

@ -1,6 +1,6 @@
{
"name": "@electron-forge/shared-types",
"version": "7.4.0",
"version": "7.5.0",
"description": "Shared types across Electron Forge",
"repository": "https://github.com/electron/forge",
"author": "Samuel Attard",
@ -8,7 +8,7 @@
"main": "dist/index.js",
"typings": "dist/index.d.ts",
"dependencies": {
"@electron-forge/tracer": "7.4.0",
"@electron-forge/tracer": "7.5.0",
"@electron/packager": "^18.3.5",
"@electron/rebuild": "^3.2.10",
"listr2": "^7.0.2"

Просмотреть файл

@ -1,6 +1,6 @@
{
"name": "@electron-forge/web-multi-logger",
"version": "7.4.0",
"version": "7.5.0",
"description": "Display multiple streams of logs in one window",
"repository": "https://github.com/electron/forge",
"author": "Samuel Attard",

3599
yarn.lock

Разница между файлами не показана из-за своего большого размера Загрузить разницу