Skip to content

CLI: refactor cli from commander to yargs #1232

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

Merged
merged 11 commits into from
Apr 23, 2025

Conversation

bcotrim
Copy link
Contributor

@bcotrim bcotrim commented Apr 17, 2025

Related issues

  • Fixes STU-355
  • Fixes STU-379

Proposed Changes

  • Refactor CLI to use yargs
  • Adjusted unit tests
  • Added locale config to CLI

You can check more details about supported locales here

Testing Instructions

  • Run npm run cli:build
  • Run npm run start and change your language in Studio
  • Run node dist/cli/main.js --help and confirm the default yargs strings are translated
  • Test other cli preview commands to ensure it's working as before

Pre-merge Checklist

  • Have you checked for TypeScript, React or other console errors?

@bcotrim bcotrim requested a review from a team April 18, 2025 17:32
@bcotrim bcotrim self-assigned this Apr 18, 2025
@bcotrim bcotrim marked this pull request as ready for review April 18, 2025 17:37
Copy link
Contributor

@fredrikekelund fredrikekelund left a comment

Choose a reason for hiding this comment

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

Core functionality works great 👍 I left a couple of small suggestion and one slightly bigger comment about printing a help page by default when no command is provided.

cli/index.ts Outdated
Comment on lines 31 to 42
} );

registerPreviewCreateCommand( program );
registerPreviewListCommand( previewCommand );
registerPreviewDeleteCommand( previewCommand );
registerPreviewUpdateCommand( previewCommand );
registerPreviewCommands( studioArgv ).strict().help();

program.parse( process.argv );
await studioArgv.argv;
Copy link
Contributor

Choose a reason for hiding this comment

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

		} )
		.demandCommand( 1, __( 'You need to specify a command' ) )
		.strict();

	registerPreviewCommands( studioArgv );

When I run the CLI script without any arguments, the help page isn't printed right now. Adding a demandCommand call fixes that.

Copy link
Contributor

Choose a reason for hiding this comment

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

Not a requirement, but I'd argue that keeping this logic in cli/index.ts makes it easier to understand the structure of all the commands provided.

} );
export const registerCommand = ( yargs: StudioArgv ) => {
return yargs.command( {
command: 'go [folder]',
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
command: 'go [folder]',
command: 'go [folder=cwd]',

While we're at it, I think this would add clarity for users.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For some reason this breaks the command. (it always uses the cwd value)

} );
export const registerCommand = ( yargs: StudioArgv ) => {
return yargs.command( {
command: 'list [folder]',
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
command: 'list [folder]',
command: 'list [folder=cwd]',

} );
export const registerCommand = ( yargs: Argv< GlobalOptions > ) => {
return yargs.command( {
command: 'update [folder]',
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
command: 'update [folder]',
command: 'update [folder=cwd]',

description: __( 'The folder to update the preview from' ),
} )
.option( 'host', {
type: 'string',
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
type: 'string',
alias: 'h',
type: 'string',

I'm not sure what I think the best approach is here, but I wanted to raise the question. -h is what we had before, but I guess you could argue that it could be confused with --help. WDYT, @bcotrim?

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 added the alias for H.
I think it makes it less likely to be confused with --help
What do you think?

Copy link
Contributor

Choose a reason for hiding this comment

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

Good call 👍

@bcotrim bcotrim force-pushed the stu-355-switch-commander-for-yargs branch from 0fb1724 to 236d026 Compare April 22, 2025 19:58
@bcotrim bcotrim requested a review from fredrikekelund April 22, 2025 20:06
Copy link
Contributor

@fredrikekelund fredrikekelund left a comment

Choose a reason for hiding this comment

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

Changes are looking good 👍 I added a few more comments, with one substantial potential change that I thought of just now. Let's also add yargs (and the types package) as a top-level dependency in package.json.

cli/index.ts Outdated
} )
.hideHelp()
);
.middleware( async () =>
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
.middleware( async () =>
.middleware( () =>

Subjective nit, but since we aren't using await inside the function, I think it's clearer which promise is relevant if we remove the async keyword. Alternatively, we could add an await in the function body.

description: __( 'The folder to update the preview from' ),
} )
.option( 'host', {
type: 'string',
Copy link
Contributor

Choose a reason for hiding this comment

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

Good call 👍

} );
export const registerCommand = ( yargs: Argv< GlobalOptions > ) => {
return yargs.command( {
command: 'delete <host>',
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
command: 'delete <host>',
command: 'preview delete <host>',

I think it would be better if all commands were printed on the top-level help page. Having to explicitly explore the preview command to understand which commands are available will be cumbersome, especially for the first release (when there are so few commands in total).

This change would also require some changes in src/index.ts.

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 couldn't make it work with "2 names commands". From my testing all the commands would register as "preview", so only the last one to be registered would be available.
I still moved to the logic to the main index, grouped under the preview command.
I explored options for displaying sub-commands in the main help output but couldn't find a clean way to do this without manually writing the help text.
I think that's worse than having the different helps for the sub-commands.
What do you think?

Copy link
Contributor

Choose a reason for hiding this comment

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

Ugh, pulling my hair over this issue 😭

I couldn't figure out a solution either, so let's stick with this approach for now.

cli/index.ts Outdated
const previewCommand = studioCommand
.command( 'preview' )
.description( __( 'Manage preview sites' ) );
registerCreateCommand( studioArgv );
Copy link
Contributor

Choose a reason for hiding this comment

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

IMO, we might as well address https://linear.app/a8c/issue/STU-379 in this PR, too, and rename this command to preview create.

@bcotrim bcotrim force-pushed the stu-355-switch-commander-for-yargs branch from 7a38a92 to 4fda597 Compare April 23, 2025 11:44
@bcotrim bcotrim requested a review from fredrikekelund April 23, 2025 11:48
Copy link
Contributor

@fredrikekelund fredrikekelund left a comment

Choose a reason for hiding this comment

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

Looking good and works as expected 👍

package.json Outdated
Copy link
Contributor

Choose a reason for hiding this comment

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

Still missing the yargs dependency here 🙂

Copy link
Contributor Author

Choose a reason for hiding this comment

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

cli/index.ts Outdated
registerPreviewListCommand( previewCommand, studioCommand );
registerPreviewDeleteCommand( previewCommand, studioCommand );
registerPreviewUpdateCommand( previewCommand, studioCommand );
.command( 'preview', 'Preview commands', ( previewYargs ) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
.command( 'preview', 'Preview commands', ( previewYargs ) => {
.command( 'preview', __( 'Manage preview sites' ), ( previewYargs ) => {

cli/index.ts Outdated
Comment on lines 35 to 40
.command( 'preview', 'Preview commands', ( previewYargs ) => {
registerCreateCommand( previewYargs );
registerListCommand( previewYargs );
registerDeleteCommand( previewYargs );
registerUpdateCommand( previewYargs );
} );
Copy link
Contributor

Choose a reason for hiding this comment

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

I also tried hard getting these commands to display in the default help output, but couldn't figure out a solution…

registerCreateCommand( previewYargs );
registerListCommand( previewYargs );
registerDeleteCommand( previewYargs );
registerUpdateCommand( previewYargs );
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
registerUpdateCommand( previewYargs );
registerUpdateCommand( previewYargs );
previewYargs.demandCommand( 1, __( 'You must provide a valid command' ) );

Forgot to add this suggestion. Without this, the help page doesn't display when passing just the preview command

cli/index.ts Outdated
registerListCommand( previewYargs );
registerDeleteCommand( previewYargs );
registerUpdateCommand( previewYargs );
} );
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
} );
} )
.demandCommand( 1, __( 'You must provide a valid command' ) )
.strict();

demandCommand needed to display the help page by default and strict seems like good practice.

@bcotrim bcotrim merged commit 5f1276a into trunk Apr 23, 2025
8 checks passed
@bcotrim bcotrim deleted the stu-355-switch-commander-for-yargs branch April 23, 2025 13:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants