-
Notifications
You must be signed in to change notification settings - Fork 0
Conversation
.option("json", { | ||
type: "boolean" | ||
}) | ||
.group(['token', 'json'], 'Global Options:') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is cool
@@ -7,7 +10,9 @@ const printOutput = require("../lib/helpers/print-output"); | |||
* @param {import('yargs').Yargs} yargs - Instance of yargs | |||
*/ | |||
const builder = yargs => { | |||
return yargs | |||
const baseOptions = flow([withToken, withJson]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I read up on flow
but I may not get it. Are these functions that are being called after you pass in the column and PR options?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Like what would be the alternative way of doing this - without using lodash?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great question! The alternative would be:
return withJson(withToken(yargs))
.option("column", {
describe: "Project column ID",
demandOption: true,
type: "number"
})
.option("pull-request", {
describe: "Pull request ID",
demandOption: true,
type: "number"
});
Right now, this isn't terrible, but as we move options out into these shared helpers it would end up super nested e.g.
withAnotherThing(withSomethingElse(withSomething(withJson(withToken(yargs)))))
Lodash's flow
method helps us out like this:
- It accepts an array of functions e.g.
const baseOptions = flow([withToken, withJson]);
- It returns a function that we can pass an argument into e.g.
baseOptions(yargs)
- This function, when called, executes each function serially (one after another), taking the return value from the function it has just called and using that as the argument that it passes to the next function
In our case, our with*
helper methods accept yargs
as an argument and they also return that same object. return yargs.option(...)
gives us the instance of yargs
as yargs
implements a fluent interface. You can see that in the code for yargs
, the option()
method returns self
, which is the same object that the option()
method itself is being defined on (self.option
): https://github.com/yargs/yargs/blob/51876e69c71e9861fb09847530eeaec9be534f5f/yargs.js#L577-L687
This leads us to...
const baseOptions = flow([withToken, withJson]);
// Calling this function that `flow` has returned has the following effect:
// baseOptions(yargs)
// -> withToken(argumentGivenTo_baseOptions)
// -> withJson(returnValueFrom_withToken)
const result = baseOptions(yargs);
// `result` is the return value from `withJson`, the last function in the chain of functions
// that `flow` called. In our case here, that is `yargs`, so we can go and chain other
// `.option()` calls on to it, yay!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this directly replaceable with the proposed pipeline operator
Which would be
const result = yargs
|> baseOptions
|> withToken
|> withJson;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@leggsimon Yep! Bring it on (although the syntax isn't the nicest). In this case it would actually be:
const baseOptions = yargs
|> withToken
|> withJson;
As baseOptions
was just the identifier for the function returned by Lodash's flow
method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes that makes so much more sense and I totally understand why using flow
is right for this situation! Thanks so much Simon, this was so friggin' helpful.
Every command now explicitly adds the `--json` option in its yargs builder method.
05f41d8
to
ae98baa
Compare
Having the
--json
option configured at a global level withyargs
didn't feel particularly good in terms of making this project's codebase accessible to other developers ("where does the json option that this command uses actually come from?"), so I've followed the approach that Ebi takes, and each command now explicitly defines the options that it accepts.Resolves #38.