Skip to content

Commit

Permalink
refactor(yargs-factory)!: refactor yargs-factory to use class (#1895)
Browse files Browse the repository at this point in the history
refactor!: implicitly private methods are now actually private
refactor!: deprecated reset() method is now private (call yargs() instead).
  • Loading branch information
bcoe committed Mar 31, 2021
1 parent ade29b8 commit 376f892
Show file tree
Hide file tree
Showing 19 changed files with 1,808 additions and 1,806 deletions.
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

0 comments on commit 376f892

Please sign in to comment.