Skip to content

Commit

Permalink
feat!: 3.0.0 (#799)
Browse files Browse the repository at this point in the history
* feat!: remove deprecated sequential arguments API
* feat!: remove support for electron-prebuilt

BREAKING CHANGE: deprecated APIs are removed
BREAKING CHANGE: remove support for `electron-prebuilt`, as it's super old and unsupported
BREAKING CHANGE: Requires Node 12 LTS

Also adds `RebuildOptions` to the top-level API.
  • Loading branch information
malept committed Aug 9, 2021
1 parent ceb6ad5 commit 72f21bf
Show file tree
Hide file tree
Showing 8 changed files with 64 additions and 152 deletions.
4 changes: 2 additions & 2 deletions README.md
Expand Up @@ -62,10 +62,10 @@ Options:
other than your system's
-m, --module-dir The path to the app directory to rebuild
-w, --which-module A specific module to build, or comma separated
list of modules. Modules will only be rebuilt if they
list of modules. Modules will only be rebuilt if they
also match the types of dependencies being rebuilt
(see --types).
-e, --electron-prebuilt-dir The path to electron-prebuilt
-e, --electron-prebuilt-dir The path to the prebuilt electron module
-d, --dist-url Custom header tarball URL
-t, --types The types of dependencies to rebuild. Comma
separated list of "prod", "dev" and "optional".
Expand Down
2 changes: 1 addition & 1 deletion src/cli.ts
Expand Up @@ -19,7 +19,7 @@ const argv = yargs(process.argv.slice(2)).version(false).options({
'which-module': { alias: 'w', type: 'string', description: 'A specific module to build, or comma separated list of modules. Modules will only be rebuilt if they also match the types of dependencies being rebuilt (see --types).' },
// TODO: should be type: array
only: { alias: 'o', type: 'string', description: 'Only build specified module, or comma separated list of modules. All others are ignored.' },
'electron-prebuilt-dir': { alias: 'e', type: 'string', description: 'The path to prebuilt electron module' },
'electron-prebuilt-dir': { alias: 'e', type: 'string', description: 'The path to the prebuilt electron module' },
'dist-url': { alias: 'd', type: 'string', description: 'Custom header tarball URL' },
// TODO: should be type: array
types: { alias: 't', type: 'string', description: 'The types of dependencies to rebuild. Comma separated list of "prod", "dev" and "optional". Default is "prod,optional"' },
Expand Down
2 changes: 1 addition & 1 deletion src/electron-locator.ts
Expand Up @@ -2,7 +2,7 @@ import * as fs from 'fs-extra';
import * as path from 'path';
import { searchForModule } from './search-module';

const electronModuleNames = ['electron', 'electron-prebuilt', 'electron-prebuilt-compile'];
const electronModuleNames = ['electron', 'electron-prebuilt-compile'];

async function locateModuleByRequire(): Promise<string | null> {
for (const moduleName of electronModuleNames) {
Expand Down
7 changes: 2 additions & 5 deletions src/main.ts
@@ -1,9 +1,6 @@
import { rebuild, rebuildNativeModules } from './rebuild';
import { rebuild, RebuildOptions } from './rebuild';

export const installNodeHeaders = (): Promise<void> => Promise.resolve();
export const shouldRebuildNativeModules = (): Promise<boolean> => Promise.resolve(true);
export const preGypFixRun = (): Promise<void> => Promise.resolve();
export { rebuild, rebuildNativeModules };
export { rebuild, RebuildOptions };
export default rebuild;
Object.defineProperty(exports, '__esModule', {
value: true
Expand Down
80 changes: 4 additions & 76 deletions src/rebuild.ts
Expand Up @@ -363,89 +363,17 @@ export class Rebuilder {
}
}

function rebuildWithOptions(options: RebuildOptions): Promise<void> {
export type RebuildResult = Promise<void> & { lifecycle: EventEmitter };

export function rebuild(options: RebuildOptions): RebuildResult {
// eslint-disable-next-line prefer-rest-params
d('rebuilding with args:', arguments);
const lifecycle = new EventEmitter();
const rebuilderOptions: RebuilderOptions = { ...options, lifecycle };
const rebuilder = new Rebuilder(rebuilderOptions);

const ret = rebuilder.rebuild() as Promise<void> & { lifecycle: EventEmitter };
const ret = rebuilder.rebuild() as RebuildResult;
ret.lifecycle = lifecycle;

return ret;
}

export type RebuilderResult = Promise<void> & { lifecycle: EventEmitter };
export type RebuildFunctionWithOptions = (options: RebuildOptions) => RebuilderResult;
export type RebuildFunctionWithArgs = (
buildPath: string,
electronVersion: string,
arch?: string,
extraModules?: string[],
force?: boolean,
headerURL?: string,
types?: ModuleType[],
mode?: RebuildMode,
onlyModules?: string[] | null,
debug?: boolean
) => RebuilderResult;
export type RebuildFunction = RebuildFunctionWithArgs & RebuildFunctionWithOptions;

export function createOptions(
buildPath: string,
electronVersion: string,
arch: string,
extraModules: string[],
force: boolean,
headerURL: string,
types: ModuleType[],
mode: RebuildMode,
onlyModules: string[] | null,
debug: boolean ): RebuildOptions {

return {
buildPath,
electronVersion,
arch,
extraModules,
onlyModules,
force,
headerURL,
types,
mode,
debug
};
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
function doRebuild(options: any, ...args: any[]): Promise<void> {
if (typeof options === 'object') {
return rebuildWithOptions(options as RebuildOptions);
}
console.warn('You are using the deprecated electron-rebuild API, please switch to using the options object instead');
// eslint-disable-next-line @typescript-eslint/ban-types
return rebuildWithOptions((createOptions as Function)(options, ...args));
}

export const rebuild = (doRebuild as RebuildFunction);

export function rebuildNativeModules(
electronVersion: string,
modulePath: string,
whichModule= '',
_headersDir: string | null = null,
arch= process.arch,
_command: string,
_ignoreDevDeps= false,
_ignoreOptDeps= false,
_verbose= false): Promise<void> {
if (path.basename(modulePath) === 'node_modules') {
modulePath = path.dirname(modulePath);
}

d('rebuilding in:', modulePath);
console.warn('You are using the old API, please read the new docs and update to the new API');

return rebuild(modulePath, electronVersion, arch, whichModule.split(','));
}
4 changes: 2 additions & 2 deletions test/electron-locator.ts
Expand Up @@ -38,8 +38,8 @@ describe('locateElectronModule', () => {
expectElectronCanBeFound(fixtureDir, fixtureDir);
});

describe('with electron-prebuilt installed', () => {
const fixtureDir = path.join(baseFixtureDir, 'prebuilt');
describe('with electron-prebuilt-compile installed', () => {
const fixtureDir = path.join(baseFixtureDir, 'prebuilt-compile');
expectElectronCanBeFound(fixtureDir, fixtureDir);
});

Expand Down
117 changes: 52 additions & 65 deletions test/rebuild.ts
Expand Up @@ -7,7 +7,7 @@ import { spawn } from '@malept/cross-spawn-promise';
import { determineChecksum } from './helpers/checksum';
import { expectNativeModuleToBeRebuilt, expectNativeModuleToNotBeRebuilt } from './helpers/rebuild';
import { getExactElectronVersionSync } from './helpers/electron-version';
import { rebuild, RebuildOptions } from '../src/rebuild';
import { rebuild } from '../src/rebuild';

const MINUTES_IN_MILLISECONDS = 60 * 1000;
const testElectronVersion = getExactElectronVersionSync();
Expand Down Expand Up @@ -38,74 +38,56 @@ describe('rebuilder', () => {
resetMSVSVersion();
}

const optionSets: {
name: string;
args: RebuildOptions | string[];
}[] = [
{ args: [testModulePath, testElectronVersion, process.arch], name: 'sequential args' },
{ args: {
buildPath: testModulePath,
electronVersion: testElectronVersion,
arch: process.arch
}, name: 'options object' }
];
for (const options of optionSets) {
describe(`core behavior -- ${options.name}`, function() {
this.timeout(timeoutMinutes * MINUTES_IN_MILLISECONDS);

before(async () => {
await resetTestModule();

let args: RebuildOptions | string | string[] = options.args;
if (!Array.isArray(args) && typeof args === 'string') {
args = [args];
}
process.env.ELECTRON_REBUILD_TESTS = 'true';
if (Array.isArray(args)) {
// eslint-disable-next-line @typescript-eslint/ban-types
await (rebuild as Function)(...(args as string[]));
} else {
await rebuild(args);
}
});
describe('core behavior', function() {
this.timeout(timeoutMinutes * MINUTES_IN_MILLISECONDS);

it('should have rebuilt top level prod dependencies', async () => {
await expectNativeModuleToBeRebuilt(testModulePath, 'ref-napi');
});
before(async () => {
await resetTestModule();

it('should have rebuilt top level prod dependencies that are using prebuild', async () => {
await expectNativeModuleToBeRebuilt(testModulePath, 'farmhash');
process.env.ELECTRON_REBUILD_TESTS = 'true';
await rebuild({
buildPath: testModulePath,
electronVersion: testElectronVersion,
arch: process.arch
});
});

it('should have rebuilt children of top level prod dependencies', async () => {
await expectNativeModuleToBeRebuilt(testModulePath, 'leveldown');
});
it('should have rebuilt top level prod dependencies', async () => {
await expectNativeModuleToBeRebuilt(testModulePath, 'ref-napi');
});

it('should have rebuilt children of scoped top level prod dependencies', async () => {
await expectNativeModuleToBeRebuilt(testModulePath, '@newrelic/native-metrics');
});
it('should have rebuilt top level prod dependencies that are using prebuild', async () => {
await expectNativeModuleToBeRebuilt(testModulePath, 'farmhash');
});

it('should have rebuilt top level optional dependencies', async () => {
await expectNativeModuleToBeRebuilt(testModulePath, 'bcrypt');
});
it('should have rebuilt children of top level prod dependencies', async () => {
await expectNativeModuleToBeRebuilt(testModulePath, 'leveldown');
});

it('should not have rebuilt top level devDependencies', async () => {
await expectNativeModuleToNotBeRebuilt(testModulePath, 'ffi-napi');
});
it('should have rebuilt children of scoped top level prod dependencies', async () => {
await expectNativeModuleToBeRebuilt(testModulePath, '@newrelic/native-metrics');
});

it('should not download files in the module directory', async () => {
const modulePath = path.resolve(testModulePath, 'node_modules/ref-napi');
const fileNames = await fs.readdir(modulePath);
it('should have rebuilt top level optional dependencies', async () => {
await expectNativeModuleToBeRebuilt(testModulePath, 'bcrypt');
});

expect(fileNames).to.not.contain(testElectronVersion);
});
it('should not have rebuilt top level devDependencies', async () => {
await expectNativeModuleToNotBeRebuilt(testModulePath, 'ffi-napi');
});

after(async () => {
delete process.env.ELECTRON_REBUILD_TESTS;
await cleanupTestModule();
});
it('should not download files in the module directory', async () => {
const modulePath = path.resolve(testModulePath, 'node_modules/ref-napi');
const fileNames = await fs.readdir(modulePath);

expect(fileNames).to.not.contain(testElectronVersion);
});
}

after(async () => {
delete process.env.ELECTRON_REBUILD_TESTS;
await cleanupTestModule();
});
});

describe('force rebuild', function() {
this.timeout(timeoutMinutes * MINUTES_IN_MILLISECONDS);
Expand All @@ -114,10 +96,15 @@ describe('rebuilder', () => {
after(cleanupTestModule);
afterEach(resetMSVSVersion);

const buildPath = testModulePath;
const electronVersion = testElectronVersion;
const arch = process.arch;
const extraModules: string[] = [];

it('should skip the rebuild step when disabled', async () => {
await rebuild(testModulePath, testElectronVersion, process.arch);
await rebuild({ buildPath, electronVersion, arch });
resetMSVSVersion();
const rebuilder = rebuild(testModulePath, testElectronVersion, process.arch, [], false);
const rebuilder = rebuild({ buildPath, electronVersion, arch, extraModules, force: false });
let skipped = 0;
rebuilder.lifecycle.on('module-skip', () => {
skipped++;
Expand All @@ -126,10 +113,10 @@ describe('rebuilder', () => {
expect(skipped).to.equal(5);
});

it('should rebuild all modules again when disabled but the electron ABI bumped', async () => {
await rebuild(testModulePath, testElectronVersion, process.arch);
it('should rebuild all modules again when disabled but the electron ABI changed', async () => {
await rebuild({ buildPath, electronVersion, arch });
resetMSVSVersion();
const rebuilder = rebuild(testModulePath, '3.0.0', process.arch, [], false);
const rebuilder = rebuild({ buildPath, electronVersion: '3.0.0', arch, extraModules, force: false });
let skipped = 0;
rebuilder.lifecycle.on('module-skip', () => {
skipped++;
Expand All @@ -142,9 +129,9 @@ describe('rebuilder', () => {
if (process.platform === 'darwin') {
this.timeout(5 * MINUTES_IN_MILLISECONDS);
}
await rebuild(testModulePath, testElectronVersion, process.arch);
await rebuild({ buildPath, electronVersion, arch });
resetMSVSVersion();
const rebuilder = rebuild(testModulePath, testElectronVersion, process.arch, [], true);
const rebuilder = rebuild({ buildPath, electronVersion, arch, extraModules, force: true });
let skipped = 0;
rebuilder.lifecycle.on('module-skip', () => {
skipped++;
Expand Down

0 comments on commit 72f21bf

Please sign in to comment.