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

refactor(yargs-factory)!: refactor yargs-factory to use class #1895

Merged
merged 6 commits into from Mar 31, 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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion .nycrc
Expand Up @@ -3,11 +3,12 @@
"build/test/**",
"test/**"
],
"exclude-after-remap": true,
"reporter": [
"html",
"text"
],
"lines": 100,
"branches": "96",
"statements": "100"
}
}
4 changes: 2 additions & 2 deletions browser.mjs
@@ -1,7 +1,7 @@
// Bootstrap yargs for browser:
import browserPlatformShim from './lib/platform-shims/browser.mjs';
import {YargsWithShim} from './build/lib/yargs-factory.js';
import {YargsFactory} from './build/lib/yargs-factory.js';

const Yargs = YargsWithShim(browserPlatformShim);
const Yargs = YargsFactory(browserPlatformShim);

export default Yargs;
4 changes: 2 additions & 2 deletions deno.ts
@@ -1,8 +1,8 @@
// Bootstrap yargs for Deno platform:
import denoPlatformShim from './lib/platform-shims/deno.ts';
import {YargsWithShim} from './build/lib/yargs-factory.js';
import {YargsFactory} from './build/lib/yargs-factory.js';

const WrappedYargs = YargsWithShim(denoPlatformShim);
const WrappedYargs = YargsFactory(denoPlatformShim);

function Yargs(args?: string[]) {
return WrappedYargs(args);
Expand Down
37 changes: 0 additions & 37 deletions docs/api.md
Expand Up @@ -1439,43 +1439,6 @@ usage information and exit.
The default behavior is to set the value of any key not followed by an
option value to `true`.

<a name="reset"></a>.reset() [DEPRECATED]
--------

Reset the argument object built up so far. This is useful for
creating nested command line interfaces. Use [global](#global)
to specify keys that should not be reset.

```js
var yargs = require('yargs/yargs')(process.argv.slice(2))
.usage('$0 command')
.command('hello', 'hello command')
.command('world', 'world command')
.demandCommand(1, 'must provide a valid command'),
argv = yargs.argv,
command = argv._[0];

if (command === 'hello') {
yargs.reset()
.usage('$0 hello')
.help('h')
.example('$0 hello', 'print the hello message!')
.argv

console.log('hello!');
} else if (command === 'world'){
yargs.reset()
.usage('$0 world')
.help('h')
.example('$0 world', 'print the world message!')
.argv

console.log('world!');
} else {
yargs.showHelp();
}
```

<a name="scriptName"></a>.scriptName($0)
------------------

Expand Down
6 changes: 5 additions & 1 deletion index.cjs
Expand Up @@ -11,6 +11,7 @@ module.exports = Argv;
function Argv(processArgs, cwd) {
const argv = Yargs(processArgs, cwd, require);
singletonify(argv);
// TODO(bcoe): warn if argv.parse() or argv.argv is used directly.
return argv;
}

Expand All @@ -22,7 +23,10 @@ function Argv(processArgs, cwd) {
to get a parsed version of process.argv.
*/
function singletonify(inst) {
Object.keys(inst).forEach(key => {
[
...Object.keys(inst),
...Object.getOwnPropertyNames(inst.constructor.prototype),
].forEach(key => {
if (key === 'argv') {
Argv.__defineGetter__(key, inst.__lookupGetter__(key));
} else if (typeof inst[key] === 'function') {
Expand Down
4 changes: 2 additions & 2 deletions index.mjs
Expand Up @@ -2,7 +2,7 @@

// Bootstraps yargs for ESM:
import esmPlatformShim from './lib/platform-shims/esm.mjs';
import {YargsWithShim} from './build/lib/yargs-factory.js';
import {YargsFactory} from './build/lib/yargs-factory.js';

const Yargs = YargsWithShim(esmPlatformShim);
const Yargs = YargsFactory(esmPlatformShim);
export default Yargs;
5 changes: 2 additions & 3 deletions lib/cjs.ts
Expand Up @@ -7,7 +7,7 @@ import {isPromise} from './utils/is-promise.js';
import {objFilter} from './utils/obj-filter.js';
import {parseCommand} from './parse-command.js';
import * as processArgv from './utils/process-argv.js';
import {YargsWithShim, rebase} from './yargs-factory.js';
import {YargsFactory} from './yargs-factory.js';
import {YError} from './yerror.js';
import cjsPlatformShim from './platform-shims/cjs.js';

Expand All @@ -27,7 +27,7 @@ if (process && process.version) {
}

const Parser = require('yargs-parser');
const Yargs = YargsWithShim(cjsPlatformShim);
const Yargs = YargsFactory(cjsPlatformShim);

export default {
applyExtends,
Expand All @@ -39,6 +39,5 @@ export default {
parseCommand,
Parser,
processArgv,
rebase,
YError,
};
73 changes: 45 additions & 28 deletions lib/command.ts
Expand Up @@ -207,7 +207,7 @@ export class CommandInstance {
this.handlers[command!] ||
this.handlers[this.aliasMap[command!]] ||
this.defaultCommand;
const currentContext = yargs.getContext();
const currentContext = yargs.getInternalMethods().getContext();
const parentCommands = currentContext.commands.slice();
if (command) {
currentContext.commands.push(command);
Expand Down Expand Up @@ -264,7 +264,10 @@ export class CommandInstance {
if (isCommandBuilderCallback(builder)) {
// A function can be provided, which builds
// up a yargs chain and possibly returns it.
const builderOutput = builder(yargs.reset(aliases), helpOrVersionSet);
const builderOutput = builder(
yargs.getInternalMethods().reset(aliases),
helpOrVersionSet
);
// Support the use-case of async builders:
if (isPromise(builderOutput)) {
return builderOutput.then(output => {
Expand All @@ -282,7 +285,7 @@ export class CommandInstance {
} else if (isCommandBuilderOptionDefinitions(builder)) {
// as a short hand, an object can instead be provided, specifying
// the options that a command takes.
innerYargs = yargs.reset(aliases);
innerYargs = yargs.getInternalMethods().reset(aliases);
Object.keys(commandHandler.builder).forEach(key => {
innerYargs.option(key, builder[key]);
});
Expand All @@ -307,9 +310,10 @@ export class CommandInstance {
// A null command indicates we are running the default command,
// if this is the case, we should show the root usage instructions
// rather than the usage instructions for the nested default command:
if (!command) innerYargs.getUsageInstance().unfreeze();
if (!command) innerYargs.getInternalMethods().getUsageInstance().unfreeze();
if (this.shouldUpdateUsage(innerYargs)) {
innerYargs
.getInternalMethods()
.getUsageInstance()
.usage(
this.usageFromParentCommandsCommandHandler(
Expand All @@ -319,22 +323,24 @@ export class CommandInstance {
commandHandler.description
);
}
const innerArgv = innerYargs._parseArgs(
null,
undefined,
true,
commandIndex,
helpOnly
);
const innerArgv = innerYargs
.getInternalMethods()
.runYargsParserAndExecuteCommands(
null,
undefined,
true,
commandIndex,
helpOnly
);
return {
aliases: (innerYargs.parsed as DetailedArguments).aliases,
innerArgv: innerArgv as Arguments,
};
}
private shouldUpdateUsage(yargs: YargsInstance) {
return (
!yargs.getUsageInstance().getUsageDisabled() &&
yargs.getUsageInstance().getUsage().length === 0
!yargs.getInternalMethods().getUsageInstance().getUsageDisabled() &&
yargs.getInternalMethods().getUsageInstance().getUsage().length === 0
);
}
private usageFromParentCommandsCommandHandler(
Expand Down Expand Up @@ -364,7 +370,7 @@ export class CommandInstance {
// execute middleware or handlers (these may perform expensive operations
// like creating a DB connection).
if (helpOnly) return innerArgv;
if (!yargs._hasOutput()) {
if (!yargs.getInternalMethods().getHasOutput()) {
positionalMap = this.populatePositionals(
commandHandler,
innerArgv as Arguments,
Expand All @@ -380,27 +386,31 @@ export class CommandInstance {

// we apply validation post-hoc, so that custom
// checks get passed populated positional arguments.
if (!yargs._hasOutput()) {
const validation = yargs._runValidation(
aliases,
positionalMap,
(yargs.parsed as DetailedArguments).error,
!command
);
if (!yargs.getInternalMethods().getHasOutput()) {
const validation = yargs
.getInternalMethods()
.runValidation(
aliases,
positionalMap,
(yargs.parsed as DetailedArguments).error,
!command
);
innerArgv = maybeAsyncResult<Arguments>(innerArgv, result => {
validation(result);
return result;
});
}

if (commandHandler.handler && !yargs._hasOutput()) {
yargs._setHasOutput();
if (commandHandler.handler && !yargs.getInternalMethods().getHasOutput()) {
yargs.getInternalMethods().setHasOutput();
// to simplify the parsing of positionals in commands,
// we temporarily populate '--' rather than _, with arguments
const populateDoubleDash = !!yargs.getOptions().configuration[
'populate--'
];
yargs._postProcess(innerArgv, populateDoubleDash, false, false);
yargs
.getInternalMethods()
.postProcess(innerArgv, populateDoubleDash, false, false);

innerArgv = applyMiddleware(innerArgv, yargs, middlewares, false);
innerArgv = maybeAsyncResult<Arguments>(innerArgv, result => {
Expand All @@ -412,11 +422,14 @@ export class CommandInstance {
}
});

yargs.getUsageInstance().cacheHelpMessage();
if (isPromise(innerArgv) && !yargs._hasParseCallback()) {
yargs.getInternalMethods().getUsageInstance().cacheHelpMessage();
if (
isPromise(innerArgv) &&
!yargs.getInternalMethods().hasParseCallback()
) {
innerArgv.catch(error => {
try {
yargs.getUsageInstance().fail(null, error);
yargs.getInternalMethods().getUsageInstance().fail(null, error);
} catch (_err) {
// If .fail(false) is not set, and no parse cb() has been
// registered, run usage's default fail method.
Expand Down Expand Up @@ -560,7 +573,10 @@ export class CommandInstance {
);

if (parsed.error) {
yargs.getUsageInstance().fail(parsed.error.message, parsed.error);
yargs
.getInternalMethods()
.getUsageInstance()
.fail(parsed.error.message, parsed.error);
} else {
// only copy over positional keys (don't overwrite
// flag arguments that were already parsed).
Expand All @@ -587,6 +603,7 @@ export class CommandInstance {
? this.defaultCommand.original
: this.defaultCommand.original.replace(/^[^[\]<>]*/, '$0 ');
yargs
.getInternalMethods()
.getUsageInstance()
.usage(commandString, this.defaultCommand.description);
}
Expand Down
5 changes: 3 additions & 2 deletions lib/completion.ts
Expand Up @@ -57,7 +57,7 @@ export class Completion implements CompletionInstance {
if (handlers[args[i]] && handlers[args[i]].builder) {
const builder = handlers[args[i]].builder;
if (isCommandBuilderCallback(builder)) {
const y = this.yargs.reset();
const y = this.yargs.getInternalMethods().reset();
builder(y, true);
return y.argv;
}
Expand All @@ -77,7 +77,8 @@ export class Completion implements CompletionInstance {
args: string[],
current: string
) {
const parentCommands = this.yargs.getContext().commands;
const parentCommands = this.yargs.getInternalMethods().getContext()
.commands;
if (
!current.match(/^-/) &&
parentCommands[parentCommands.length - 1] !== current
Expand Down
26 changes: 12 additions & 14 deletions lib/usage.ts
@@ -1,11 +1,6 @@
// this file handles outputting usage instructions,
// failures, etc. keeps logging in one place.
import {
Dictionary,
assertNotStrictEqual,
PlatformShim,
Y18N,
} from './typings/common-types.js';
import {Dictionary, PlatformShim} from './typings/common-types.js';
import {objFilter} from './utils/obj-filter.js';
import {YargsInstance} from './yargs-factory.js';
import {YError} from './yerror.js';
Expand All @@ -16,8 +11,8 @@ function isBoolean(fail: FailureFunction | boolean): fail is boolean {
return typeof fail === 'boolean';
}

export function usage(yargs: YargsInstance, y18n: Y18N, shim: PlatformShim) {
const __ = y18n.__;
export function usage(yargs: YargsInstance, shim: PlatformShim) {
const __ = shim.y18n.__;
const self = {} as UsageInstance;

// methods for ouputting/building failure message.
Expand All @@ -42,7 +37,7 @@ export function usage(yargs: YargsInstance, y18n: Y18N, shim: PlatformShim) {

let failureOutput = false;
self.fail = function fail(msg, err) {
const logger = yargs._getLoggerInstance();
const logger = yargs.getInternalMethods().getLoggerInstance();

if (fails.length) {
for (let i = fails.length - 1; i >= 0; --i) {
Expand Down Expand Up @@ -74,7 +69,7 @@ export function usage(yargs: YargsInstance, y18n: Y18N, shim: PlatformShim) {
err = err || new YError(msg);
if (yargs.getExitProcess()) {
return yargs.exit(1);
} else if (yargs._hasParseCallback()) {
} else if (yargs.getInternalMethods().hasParseCallback()) {
return yargs.exit(1, err);
} else {
throw err;
Expand Down Expand Up @@ -239,12 +234,15 @@ export function usage(yargs: YargsInstance, y18n: Y18N, shim: PlatformShim) {
if (commands.length > 1 || (commands.length === 1 && !commands[0][2])) {
ui.div(__('Commands:'));

const context = yargs.getContext();
const context = yargs.getInternalMethods().getContext();
const parentCommands = context.commands.length
? `${context.commands.join(' ')} `
: '';

if (yargs.getParserConfiguration()['sort-commands'] === true) {
if (
yargs.getInternalMethods().getParserConfiguration()['sort-commands'] ===
true
) {
commands = commands.sort((a, b) => a[0].localeCompare(b[0]));
}

Expand Down Expand Up @@ -603,7 +601,7 @@ export function usage(yargs: YargsInstance, y18n: Y18N, shim: PlatformShim) {
}

self.showHelp = (level: 'error' | 'log' | ((message: string) => void)) => {
const logger = yargs._getLoggerInstance();
const logger = yargs.getInternalMethods().getLoggerInstance();
if (!level) level = 'error';
const emit = typeof level === 'function' ? level : logger[level];
emit(self.help());
Expand Down Expand Up @@ -675,7 +673,7 @@ export function usage(yargs: YargsInstance, y18n: Y18N, shim: PlatformShim) {
};

self.showVersion = level => {
const logger = yargs._getLoggerInstance();
const logger = yargs.getInternalMethods().getLoggerInstance();
if (!level) level = 'error';
const emit = typeof level === 'function' ? level : logger[level];
emit(version);
Expand Down