Skip to content
This repository has been archived by the owner on Sep 9, 2021. It is now read-only.

Make applyConfig transform argv instead of builders #84

Merged
merged 1 commit into from
Feb 15, 2021
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
4 changes: 2 additions & 2 deletions src/builders.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Builder } from './types/package';
import { Builders } from './types/package';

const builders: Builder = {
const builders: Builders = {
src: {
alias: 's',
describe: 'Source file',
Expand Down
30 changes: 13 additions & 17 deletions src/cli.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import yargs from 'yargs/yargs';
import { SnapsCliGlobals } from './types/package';
import { assignGlobals, sanitizeInputs } from './utils';
import { applyConfig, sanitizeInputs, setSnapGlobals } from './utils';
import builders from './builders';

declare global {
// eslint-disable-next-line @typescript-eslint/no-namespace
Expand All @@ -25,26 +26,21 @@ export function cli(argv: string[], commands: any): void {

.command(commands)

.option('verboseErrors', {
alias: ['v', 'verboseErrors'],
type: 'boolean',
describe: 'Display original errors',
required: false,
default: false,
})
.option('verboseErrors', builders.verboseErrors)

.option('suppressWarnings', {
alias: ['sw', 'suppressWarnings'],
type: 'boolean',
describe: 'Suppress warnings',
required: false,
default: false,
})
.option('suppressWarnings', builders.suppressWarnings)

.strict()

.middleware((yargsArgv) => {
assignGlobals(yargsArgv);
.middleware(async (yargsArgv) => {
// Some globals affect error logging, and applyConfig may error.
// Therefore, we set globals from the yargs argv object before applying
// defaults from the config, and then set the globals again after, to
// ensure that inline options are preferred over any config files.
// This is ugly, but cheap.
setSnapGlobals(yargsArgv);
await applyConfig(yargsArgv);
setSnapGlobals(yargsArgv);
sanitizeInputs(yargsArgv);
})

Expand Down
4 changes: 1 addition & 3 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#!/usr/bin/env node
import { cli } from './cli';
import { applyConfig } from './utils';
import commands from './cmds';

global.snaps = {
Expand All @@ -12,7 +11,6 @@ global.snaps = {
main();

// application
async function main(): Promise<void> {
await applyConfig();
function main(): void {
cli(process.argv, commands);
}
31 changes: 15 additions & 16 deletions src/types/package.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,19 @@ export interface NodePackageManifest {
web3Wallet?: ManifestWalletProperty;
}

export interface Builder {
[key: string]: Options;
src: Options;
dist: Options;
bundle: Options;
root: Options;
port: Options;
sourceMaps: Options;
stripComments: Options;
outfileName: Options;
manifest: Options;
populate: Options;
eval: Options;
verboseErrors: Options;
suppressWarnings: Options;
environment: Options;
export interface Builders {
readonly src: Readonly<Options>;
readonly dist: Readonly<Options>;
readonly bundle: Readonly<Options>;
readonly root: Readonly<Options>;
readonly port: Readonly<Options>;
readonly sourceMaps: Readonly<Options>;
readonly stripComments: Readonly<Options>;
readonly outfileName: Readonly<Options>;
readonly manifest: Readonly<Options>;
readonly populate: Readonly<Options>;
readonly eval: Readonly<Options>;
readonly verboseErrors: Readonly<Options>;
readonly suppressWarnings: Readonly<Options>;
readonly environment: Readonly<Options>;
}
15 changes: 5 additions & 10 deletions src/utils/misc.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import yargs from 'yargs';
import { Arguments } from 'yargs';

export const permRequestKeys = [
'@context',
Expand All @@ -20,10 +20,9 @@ export const CONFIG_PATHS = [
*
* @param {Argument} argv - arguments as an object generated by yargs
*/
export function assignGlobals(argv: yargs.Arguments<{
verboseErrors: boolean;
} & {
suppressWarnings: boolean;
export function setSnapGlobals(argv: Arguments<{
verboseErrors: unknown;
suppressWarnings: unknown;
}>) {
if (['w', 'watch'].includes(argv._[0] as string)) {
global.snaps.isWatching = true;
Expand All @@ -43,11 +42,7 @@ export function assignGlobals(argv: yargs.Arguments<{
*
* @param {Argument} argv - arguments as an object generated by yargs
*/
export function sanitizeInputs(argv: yargs.Arguments<{
verboseErrors: boolean;
} & {
suppressWarnings: boolean;
}>) {
export function sanitizeInputs(argv: Arguments) {
Object.keys(argv).forEach((key) => {
if (typeof argv[key] === 'string') {
if (argv[key] === './') {
Expand Down
11 changes: 6 additions & 5 deletions src/utils/snap-config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { promises as fs } from 'fs';
import { Arguments } from 'yargs';
import builders from '../builders';
import { logError } from './misc';
import { CONFIG_PATHS } from '.';
Expand All @@ -9,29 +10,29 @@ const INVALID_CONFIG_FILE = 'Invalid config file.';
* Attempts to read the config file and apply the config to
* globals.
*/
export async function applyConfig(): Promise<void> {
export async function applyConfig(argv: Arguments): Promise<void> {
let pkg: any;

// first, attempt to read and apply config from package.json
try {
pkg = JSON.parse(await fs.readFile('package.json', 'utf8'));

if (pkg.main) {
builders.src.default = pkg.main;
argv.src = pkg.main;
}

if (pkg.web3Wallet) {
const { bundle } = pkg.web3Wallet;
if (bundle?.local) {
const { local: bundlePath } = bundle;
builders.bundle.default = bundlePath;
argv.bundle = bundlePath;
let dist: string;
if (bundlePath.indexOf('/') === -1) {
dist = '.';
} else {
dist = bundlePath.substr(0, bundlePath.indexOf('/') + 1);
}
builders.dist.default = dist;
argv.dist = dist;
}
}
} catch (err) {
Expand Down Expand Up @@ -67,7 +68,7 @@ export async function applyConfig(): Promise<void> {
if (cfg && typeof cfg === 'object' && !Array.isArray(cfg)) {
for (const key of Object.keys(cfg)) {
if (Object.hasOwnProperty.call(builders, key)) {
builders[key].default = cfg[key];
argv[key] = cfg[key];
} else {
logError(
`Error: Encountered unrecognized config file property "${key}" in config file "${usedConfigPath as string}".`,
Expand Down
8 changes: 4 additions & 4 deletions test/utils/misc.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const { trimPathString, logError, logWarning, sanitizeInputs, assignGlobals } = require('../../dist/src/utils/misc');
const { trimPathString, logError, logWarning, sanitizeInputs, setSnapGlobals } = require('../../dist/src/utils/misc');

describe('misc', () => {
global.snaps = {
Expand Down Expand Up @@ -115,16 +115,16 @@ describe('misc', () => {
delete global.snaps;
});

describe('assignGlobals', () => {
describe('setSnapGlobals', () => {
it('sets global variables correctly', () => {
assignGlobals(exampleArgv);
setSnapGlobals(exampleArgv);
expect(global.snaps.isWatching).toStrictEqual(true);
expect(global.snaps.verboseErrors).toStrictEqual(true);
expect(global.snaps.suppressWarnings).toStrictEqual(true);
});

it('doesnt set global variables incorrectly', () => {
assignGlobals(defaultArgv);
setSnapGlobals(defaultArgv);
expect(global.snaps.isWatching).toStrictEqual(false);
expect(global.snaps.verboseErrors).toStrictEqual(false);
expect(global.snaps.suppressWarnings).toStrictEqual(false);
Expand Down
98 changes: 43 additions & 55 deletions test/utils/snap-config.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,6 @@ const { default: builders } = require('../../dist/src/builders');
const { applyConfig } = require('../../dist/src/utils/snap-config');
const misc = require('../../dist/src/utils/misc');

const originalBuilders = Object.keys(builders).reduce((snapshot, key) => {
snapshot[key] = builders[key];
return builders[key];
}, {});

const getDefaultWeb3Wallet = () => {
return {
'bundle': {
Expand Down Expand Up @@ -37,6 +32,22 @@ const getDefaultSnapConfig = () => {
};
};

const getArgv = ({
bundle = builders.bundle.default,
dist = builders.dist.default,
outfileName = builders.outfileName.default,
port = builders.port.default,
src = builders.src.default,
} = {}) => {
return {
bundle,
dist,
outfileName,
port,
src,
};
};

describe('snap-config', () => {
let fsMock;

Expand All @@ -59,9 +70,6 @@ describe('snap-config', () => {
});

afterEach(() => {
Object.keys(originalBuilders).forEach((key) => {
builders[key] = originalBuilders[key];
});
fsMock.mockRestore();
fsMock = null;
delete global.snaps;
Expand All @@ -75,10 +83,12 @@ describe('snap-config', () => {
return {};
});

await applyConfig();
expect(builders.src.default).toStrictEqual('index.js');
expect(builders.bundle.default).toStrictEqual('dist/foo.js');
expect(builders.dist.default).toStrictEqual('dist/');
const argv = getArgv();
await applyConfig(argv);

expect(argv.src).toStrictEqual(builders.src.default);
expect(argv.bundle).toStrictEqual('dist/foo.js');
expect(argv.dist).toStrictEqual('dist/');
});

it('sets web3wallet with no local property correctly', async () => {
Expand All @@ -98,10 +108,12 @@ describe('snap-config', () => {
return {};
});

await applyConfig();
expect(builders.src.default).toStrictEqual(main);
expect(builders.bundle.default).toStrictEqual(builders.bundle.default);
expect(builders.dist.default).toStrictEqual(builders.dist.default);
const argv = getArgv();
await applyConfig(argv);

expect(argv.src).toStrictEqual(main);
expect(argv.bundle).toStrictEqual(builders.bundle.default);
expect(argv.dist).toStrictEqual(builders.dist.default);
});

it('sets dist field correctly in edge case', async () => {
Expand All @@ -122,10 +134,12 @@ describe('snap-config', () => {
return {};
});

await applyConfig();
expect(builders.src.default).toStrictEqual(main);
expect(builders.bundle.default).toStrictEqual(web3Wallet.bundle.local);
expect(builders.dist.default).toStrictEqual('.');
const argv = getArgv();
await applyConfig(argv);

expect(argv.src).toStrictEqual(main);
expect(argv.bundle).toStrictEqual(web3Wallet.bundle.local);
expect(argv.dist).toStrictEqual('.');
});

it('package.json read error is handled correctly', async () => {
Expand All @@ -137,7 +151,7 @@ describe('snap-config', () => {
throw new Error('foo');
});

await applyConfig();
await applyConfig(getArgv());
expect(mockLogError).toHaveBeenCalled();
expect(process.exit).toHaveBeenCalledWith(1);
});
Expand All @@ -149,9 +163,11 @@ describe('snap-config', () => {
.mockImplementationOnce(async () => getPackageJson())
.mockImplementationOnce(async () => getDefaultSnapConfig());

await applyConfig();
expect(builders.port.default).toStrictEqual(8084);
expect(builders.outfileName.default).toStrictEqual('test.js');
const argv = getArgv();
await applyConfig(argv);

expect(argv.port).toStrictEqual(8084);
expect(argv.outfileName).toStrictEqual('test.js');
});

it('config file read error is handled correctly', async () => {
Expand All @@ -164,7 +180,7 @@ describe('snap-config', () => {
throw new Error('foo');
});

await applyConfig();
await applyConfig(getArgv());
expect(mockLogError).toHaveBeenCalled();
expect(process.exit).toHaveBeenCalledWith(1);
});
Expand All @@ -177,7 +193,7 @@ describe('snap-config', () => {
.mockImplementationOnce(async () => getPackageJson())
.mockImplementationOnce(async () => 'foo');

await applyConfig();
await applyConfig(getArgv());
expect(mockLogError).toHaveBeenCalled();
expect(process.exit).toHaveBeenCalledWith(1);
});
Expand All @@ -192,37 +208,9 @@ describe('snap-config', () => {
return { foo: 'bar' };
});

await applyConfig();
await applyConfig(getArgv());
expect(mockLogError).toHaveBeenCalled();
expect(process.exit).toHaveBeenCalledWith(1);
});
});

describe('applyConfig', () => {
it('sets default values correctly', async () => {
fsMock = jest.spyOn(fs, 'readFile')
.mockImplementationOnce(async () => getPackageJson())
.mockImplementationOnce(async () => {
return {};
});

await applyConfig();
expect(builders.src.default).toStrictEqual('index.js');
expect(builders.bundle.default).toStrictEqual('dist/foo.js');
expect(builders.dist.default).toStrictEqual('dist/');
});

it('config file overrides package.json fields', async () => {
const customConfig = {
'src': 'custom.js',
};

fsMock = jest.spyOn(fs, 'readFile')
.mockImplementationOnce(async () => getPackageJson())
.mockImplementationOnce(async () => customConfig);

await applyConfig();
expect(builders.src.default).toStrictEqual('custom.js');
});
});
Comment on lines -200 to -227
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Upon review, these test cases were redundant.

});