Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(core): adding register/unregisterForgeConfigForDirectory to utils #3626

Merged
merged 1 commit into from
Sep 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion packages/api/core/src/util/forge-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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>;
Expand Down Expand Up @@ -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)]) {
Expand Down
26 changes: 25 additions & 1 deletion packages/api/core/src/util/index.ts
Original file line number Diff line number Diff line change
@@ -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 {
/**
Expand All @@ -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);
}
}
9 changes: 7 additions & 2 deletions packages/api/core/src/util/resolve-dir.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand All @@ -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);

Expand Down
52 changes: 51 additions & 1 deletion packages/api/core/test/fast/forge-config_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: {},
Expand Down Expand Up @@ -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
Expand Down
11 changes: 11 additions & 0 deletions packages/api/core/test/fast/resolve-dir_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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', () => {
Expand All @@ -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');
}
});
});