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

Use an alias system instead of camelCase function #3101

Merged
merged 2 commits into from
Apr 20, 2017
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
32 changes: 0 additions & 32 deletions __tests__/cli/aliases.js

This file was deleted.

32 changes: 32 additions & 0 deletions __tests__/cli/unsupported-aliases.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/* @flow */

import unsupportedAliases from '../../src/cli/unsupported-aliases.js';

test('shorthands and affordances', () => {
expect(unsupportedAliases['run-script']).toBe('run');
expect(unsupportedAliases['c']).toBe('config');
expect(unsupportedAliases['i']).toBe('install');
expect(unsupportedAliases['ls']).toBe('list');
expect(unsupportedAliases['rb']).toBe('rebuild');
expect(unsupportedAliases['runScript']).toBe('run');
expect(unsupportedAliases['t']).toBe('test');
expect(unsupportedAliases['tst']).toBe('test');
expect(unsupportedAliases['un']).toBe('remove');
expect(unsupportedAliases['up']).toBe('upgrade');
expect(unsupportedAliases['v']).toBe('version');
expect(unsupportedAliases['add-user']).toBe('login');
expect(unsupportedAliases['dist-tag']).toBe('tag');
expect(unsupportedAliases['dist-tags']).toBe('tag');
expect(unsupportedAliases['adduser']).toBe('login');
expect(unsupportedAliases['author']).toBe('owner');
expect(unsupportedAliases['isntall']).toBe('install');
expect(unsupportedAliases['la']).toBe('list');
expect(unsupportedAliases['ll']).toBe('list');
expect(unsupportedAliases['r']).toBe('remove');
expect(unsupportedAliases['rm']).toBe('remove');
expect(unsupportedAliases['show']).toBe('info');
expect(unsupportedAliases['uninstall']).toBe('remove');
expect(unsupportedAliases['update']).toBe('upgrade');
expect(unsupportedAliases['verison']).toBe('version');
expect(unsupportedAliases['view']).toBe('info');
});
5 changes: 5 additions & 0 deletions __tests__/fixtures/index/run-generate-lock-entry/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "test_generate_lock_entry",
"version": "1.0.0",
"license": "UNLICENSED"
}
45 changes: 43 additions & 2 deletions __tests__/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -211,20 +211,26 @@ test.concurrent('should not output JSON activity/progress if given --no-progress
});
});

test.concurrent('should interpolate aliases', async () => {
test.concurrent('should interpolate unsopported aliases', async () => {
await expectAnErrorMessage(
execCommand('i', [], 'run-add', true),
'Did you mean `yarn install`?',
);
});

test.concurrent('should display correct documentation link for aliases', async () => {
test.concurrent('should display correct documentation link for unsopported aliases', async () => {
await expectAnInfoMessageAfterError(
execCommand('i', [], 'run-add', true),
'Visit https://yarnpkg.com/en/docs/cli/install for documentation about this command.',
);
});

test.concurrent('should show help and ignore unsopported aliases', async () => {
Copy link
Member

Choose a reason for hiding this comment

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

unsopported? :p

(same typo on 214 and 221 :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

aaaah thanks and sorry XD

const stdout = await execCommand('i', ['--help'], 'run-help');
expect(stdout[stdout.length - 1])
.toEqual('Visit https://yarnpkg.com/en/docs/cli/install for documentation about this command.');
});

test.concurrent('should run help of run command if --help is before --', async () => {
const stdout = await execCommand('run', ['custom-script', '--help', '--'], 'run-custom-script-with-arguments');
expect(stdout[0]).toEqual('Usage: yarn [command] [flags]');
Expand Down Expand Up @@ -286,3 +292,38 @@ test.concurrent('should throws missing command for constructor command', async (
'Command \"constructor\" not found',
);
});

test.concurrent('should show help and ignore constructor command', async () => {
const stdout = await execCommand('constructor', ['--help'], 'run-help');
expectHelpOutput(stdout);
});

test.concurrent('should run command with hyphens', async () => {
const stdout = await execCommand('generate-lock-entry', [], 'run-generate-lock-entry');
expect(stdout[0]).toMatch(/# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY./);
expect(stdout[1]).toMatch(/# yarn lockfile v1/);
});

test.concurrent('should run camelised command for command with hyphens', async () => {
const stdout = await execCommand('generateLockEntry', [], 'run-generate-lock-entry');
expect(stdout[0]).toMatch(/# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY./);
expect(stdout[1]).toMatch(/# yarn lockfile v1/);
});

test.concurrent('should run help for command with hyphens', async () => {
const stdout = await execCommand('generate-lock-entry', ['--help'], 'run-generate-lock-entry');
const lastLines = stdout.slice(stdout.length - 4);
expect(lastLines[0]).toMatch(/yarn generate-lock-entry/);
expect(lastLines[1]).toMatch(/yarn generate-lock-entry --use-manifest .\/package.json/);
expect(lastLines[2]).toMatch(/yarn generate-lock-entry --resolved local-file.tgz#hash/);
expect(lastLines[3]).toMatch(/Visit https:\/\/yarnpkg.com\/en\/docs\/cli\/generate-lock-entry/);
});

test.concurrent('should run help for camelised command', async () => {
const stdout = await execCommand('generateLockEntry', ['--help'], 'run-generate-lock-entry');
const lastLines = stdout.slice(stdout.length - 4);
expect(lastLines[0]).toMatch(/yarn generate-lock-entry/);
expect(lastLines[1]).toMatch(/yarn generate-lock-entry --use-manifest .\/package.json/);
expect(lastLines[2]).toMatch(/yarn generate-lock-entry --resolved local-file.tgz#hash/);
expect(lastLines[3]).toMatch(/Visit https:\/\/yarnpkg.com\/en\/docs\/cli\/generate-lock-entry/);
});
39 changes: 3 additions & 36 deletions src/cli/aliases.js
Original file line number Diff line number Diff line change
@@ -1,39 +1,6 @@
/* @flow */

const shorthands: { [key: string]: string } = {
c: 'config',
i: 'install',
la: 'list',
ll: 'list',
ln: 'link',
ls: 'list',
r: 'remove',
rb: 'rebuild',
rm: 'remove',
t: 'test',
tst: 'test',
un: 'remove',
up: 'upgrade',
v: 'version',
};

const affordances: { [key: string]: string } = {
'add-user': 'login',
adduser: 'login',
author: 'owner',
'dist-tag': 'tag',
'dist-tags': 'tag',
isntall: 'install',
'run-script': 'run',
runScript: 'run',
show: 'info',
uninstall: 'remove',
update: 'upgrade',
verison: 'version',
view: 'info',
};

export default ({
...shorthands,
...affordances,
export default({
'upgrade-interactive': 'upgradeInteractive',
'generate-lock-entry': 'generateLockEntry',
}: { [key: string]: string });
17 changes: 6 additions & 11 deletions src/cli/commands/help.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
/* @flow */

import * as commands from './index.js';
import commands from './index.js';
import * as constants from '../../constants.js';
import type {Reporter} from '../../reporters/index.js';
import type Config from '../../config.js';
import {sortAlpha, hyphenate, camelCase} from '../../util/misc.js';
import {sortAlpha, hyphenate} from '../../util/misc.js';
const chalk = require('chalk');

export function hasWrapper(): boolean {
Expand All @@ -19,15 +19,10 @@ export function run(
commander: Object,
args: Array<string>,
): Promise<void> {
const getDocsLink = (name) => `${constants.YARN_DOCS}${name || ''}`;
const getDocsInfo = (name) => 'Visit ' + chalk.bold(getDocsLink(name)) + ' for documentation about this command.';

if (args.length) {
const commandName = camelCase(args.shift());

if (commandName) {
const commandName = args.shift();
if (Object.prototype.hasOwnProperty.call(commands, commandName)) {
const command = commands[commandName];

if (command) {
command.setFlags(commander);
const examples: Array<string> = (command && command.examples) || [];
Expand All @@ -40,15 +35,15 @@ export function run(
console.log();
});
}
commander.on('--help', () => console.log(' ' + getDocsInfo(commandName) + '\n'));

commander.on('--help', () => console.log(' ' + command.getDocsInfo + '\n'));
commander.help();
return Promise.resolve();
}
}
}

commander.on('--help', () => {
const getDocsLink = (name) => `${constants.YARN_DOCS}${name || ''}`;
console.log(' Commands:\n');
for (const name of Object.keys(commands).sort(sortAlpha)) {
if (commands[name].useless) {
Expand Down
111 changes: 75 additions & 36 deletions src/cli/commands/index.js
Original file line number Diff line number Diff line change
@@ -1,49 +1,88 @@
/* @flow */
import {ConsoleReporter, JSONReporter} from '../../reporters/index.js';
import * as constants from '../../constants.js';
import {MessageError} from '../../errors.js';
import Config from '../../config.js';

import * as access from './access.js'; export {access};
import * as add from './add.js'; export {add};
import * as bin from './bin.js'; export {bin};
import * as cache from './cache.js'; export {cache};
import * as check from './check.js'; export {check};
import * as clean from './clean.js'; export {clean};
import * as config from './config.js'; export {config};
import * as generateLockEntry from './generate-lock-entry.js'; export {generateLockEntry};
import * as global from './global.js'; export {global};
import * as help from './help.js'; export {help};
import * as import_ from './import.js'; export {import_ as import};
import * as info from './info.js'; export {info};
import * as init from './init.js'; export {init};
import * as install from './install.js'; export {install};
import * as licenses from './licenses.js'; export {licenses};
import * as link from './link.js'; export {link};
import * as login from './login.js'; export {login};
import * as logout from './logout.js'; export {logout};
import * as list from './list.js'; export {list};
import * as outdated from './outdated.js'; export {outdated};
import * as owner from './owner.js'; export {owner};
import * as pack from './pack.js'; export {pack};
import * as publish from './publish.js'; export {publish};
import * as remove from './remove.js'; export {remove};
import * as run from './run.js'; export {run};
import * as tag from './tag.js'; export {tag};
import * as team from './team.js'; export {team};
import * as unlink from './unlink.js'; export {unlink};
import * as upgrade from './upgrade.js'; export {upgrade};
import * as version from './version.js'; export {version};
import * as versions from './versions.js'; export {versions};
import * as why from './why.js'; export {why};
import * as upgradeInteractive from './upgrade-interactive.js'; export {upgradeInteractive};
const chalk = require('chalk');

const getDocsLink = (name) => `${constants.YARN_DOCS}${name || ''}`;
const getDocsInfo = (name) => 'Visit ' + chalk.bold(getDocsLink(name)) + ' for documentation about this command.';

const commands = {};

import * as access from './access.js'; commands['access'] = access;
import * as add from './add.js'; commands['add'] = add;
import * as bin from './bin.js'; commands['bin'] = bin;
import * as cache from './cache.js'; commands['cache'] = cache;
import * as check from './check.js'; commands['check'] = check;
import * as clean from './clean.js'; commands['clean'] = clean;
import * as config from './config.js'; commands['config'] = config;
import * as generateLockEntry from './generate-lock-entry.js'; commands['generateLockEntry'] = generateLockEntry;
import * as global from './global.js'; commands['global'] = global;
import * as help from './help.js'; commands['help'] = help;
import * as import_ from './import.js'; commands['import'] = import_;
import * as info from './info.js'; commands['info'] = info;
import * as init from './init.js'; commands['init'] = init;
import * as install from './install.js'; commands['install'] = install;
import * as licenses from './licenses.js'; commands['licenses'] = licenses;
import * as link from './link.js'; commands['link'] = link;
import * as login from './login.js'; commands['login'] = login;
import * as logout from './logout.js'; commands['logout'] = logout;
import * as list from './list.js'; commands['list'] = list;
import * as outdated from './outdated.js'; commands['outdated'] = outdated;
import * as owner from './owner.js'; commands['owner'] = owner;
import * as pack from './pack.js'; commands['pack'] = pack;
import * as publish from './publish.js'; commands['publish'] = publish;
import * as remove from './remove.js'; commands['remove'] = remove;
import * as run from './run.js'; commands['run'] = run;
import * as tag from './tag.js'; commands['tag'] = tag;
import * as team from './team.js'; commands['team'] = team;
import * as unlink from './unlink.js'; commands['unlink'] = unlink;
import * as upgrade from './upgrade.js'; commands['upgrade'] = upgrade;
import * as version from './version.js'; commands['version'] = version;
import * as versions from './versions.js'; commands['versions'] = versions;
import * as why from './why.js'; commands['why'] = why;
import * as upgradeInteractive from './upgrade-interactive.js'; commands['upgradeInteractive'] = upgradeInteractive;
Copy link
Member

Choose a reason for hiding this comment

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

It might be clearer to do something like this:

import * as bar from './bar';
import * as foo from './foo';
...

let commands = {
    bar,
    foo,
    ...
};

What do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think is A LOT clearer; i will change it!


import buildUseless from './_useless.js';

export const lockfile = buildUseless(
commands['lockfile'] = buildUseless(
"The lockfile command isn't necessary. `yarn install` will produce a lockfile.",
);

export const dedupe = buildUseless(
commands['dedupe'] = buildUseless(
"The dedupe command isn't necessary. `yarn install` will already dedupe.",
);

export const prune = buildUseless(
commands['prune'] = buildUseless(
"The prune command isn't necessary. `yarn install` will prune extraneous packages.",
);

for (const key in commands) {
commands[key].getDocsInfo = getDocsInfo(key);
}

import aliases from '../aliases.js';

for (const key in aliases) {
commands[key] = commands[aliases[key]];
commands[key].getDocsInfo = getDocsInfo(key);
}

import unsupportedAliases from '../unsupported-aliases.js';

for (const key in unsupportedAliases) {
commands[key] = {
run(config: Config, reporter: ConsoleReporter | JSONReporter): Promise<void> {
throw new MessageError(`Did you mean \`yarn ${unsupportedAliases[key]}\`?`);
},
setFlags: () => {},
hasWrapper: () => true,
getDocsInfo: getDocsInfo(unsupportedAliases[key]),
};
}

export default ({
...commands,
}: { [key: string]: Object });
Loading