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(cli): normalize the application of default option values #7220

Merged
merged 2 commits into from
Apr 29, 2022

Conversation

Josh-Cena
Copy link
Collaborator

Motivation

Right now, our CLI code is a bit messy, because default values are applied at different stages. Sometimes we apply default values directly in the command action; sometimes we pretend an argument of a function is optional while in practice it always exists... I decided to decouple the CLI implementation from the actual command interface, i.e. the CLI only passes the arguments down, without caring what's inside it. This should make the code much cleaner.

A big pain point of commander, though, is that its typings are quite loose. I can't find a great way to work around it at the moment.

Have you read the Contributing Guidelines on pull requests?

Yes

Test Plan

All commands work the same as before.

@Josh-Cena Josh-Cena added the pr: maintenance This PR does not produce any behavior differences to end users when upgrading. label Apr 21, 2022
@facebook-github-bot facebook-github-bot added the CLA Signed Signed Facebook CLA label Apr 21, 2022
@netlify
Copy link

netlify bot commented Apr 21, 2022

[V2]

Name Link
🔨 Latest commit 4546645
🔍 Latest deploy log https://app.netlify.com/sites/docusaurus-2/deploys/626b6d7b6d914b000b930c81
😎 Deploy Preview https://deploy-preview-7220--docusaurus-2.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site settings.

@github-actions
Copy link

github-actions bot commented Apr 21, 2022

⚡️ Lighthouse report for the changes in this PR:

Category Score
🟠 Performance 56
🟢 Accessibility 100
🟠 Best practices 83
🟢 SEO 100
🟢 PWA 90

Lighthouse ran on https://deploy-preview-7220--docusaurus-2.netlify.app/

@github-actions
Copy link

github-actions bot commented Apr 21, 2022

Size Change: 0 B

Total Size: 803 kB

ℹ️ View Unchanged
Filename Size
website/.docusaurus/globalData.json 50.1 kB
website/build/assets/css/styles.********.css 107 kB
website/build/assets/js/main.********.js 607 kB
website/build/index.html 38.8 kB

compressed-size-action

@@ -74,7 +74,9 @@ async function writePluginTranslationFiles({

export async function writeTranslations(
siteDir: string,
options: WriteTranslationsOptions & ConfigOptions & {locale?: string},
options: Partial<
Copy link
Collaborator

Choose a reason for hiding this comment

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

not fan of this kind of change 🤷‍♂️ I'd rather do the opposite and ensure all commands are never partial => handle edge cases and apply defaults at the edge of the system

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The problem is that writeTranslations should not be seen as fully internal. It's exported from the main interface and users may import @docusaurus/core and use it as a programmatic API. Therefore, I'd keep maximum compatibility with the CLI interface.

Copy link
Collaborator Author

@Josh-Cena Josh-Cena Apr 21, 2022

Choose a reason for hiding this comment

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

Related: #4841 We should always assume the existence of those users that don't interact through the CLI. Even if it's technically not documented usage, I don't see why it makes the architecture any different if we apply defaults within docusuarus.mjs or writeTranslations.ts—as long as we only apply it once. NOT doing it in docusuarus.mjs means (a) more permissive programmatic API and (b) a CLI registry that's easier to maintain in the long term because it's not intertwined with the implementation, but only a very thin wrapper around each exported function.

Copy link
Collaborator

Choose a reason for hiding this comment

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

ok, that seems reasonable

What I don't like is to have long methods receiving partial options, where there's always a risk to end up using the partial option on which default was not properly applied

Can we split the methods in 2, something like this?

function doWriteTranslations(siteDir: string, options: Options) {
	// actual code
} 

export function writeTranslations(siteDir: string, options: Partial<Options>) {
	return doWriteTranslations(siteDir, applyDefaults(options))
} 

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes, makes sense.

siteDir,
{
dir = 'build',
port = 3000,
Copy link
Collaborator

Choose a reason for hiding this comment

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

where are these default values being applied now?

isn't it convenient that the default value and the doc message mentioning it are co-located?

Why not doing the opposite instead: always apply all default values in this file, ensuring we don't have to handle partial options anywhere else in the system?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

These have always been applied internally, before and after. These default values actually only serve the purpose of being confusing & overly defensive.

Copy link
Collaborator

@slorber slorber Apr 21, 2022

Choose a reason for hiding this comment

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

as far as I understand this is the only place where 3000 is defined.

Otherwise it's the default of the underlying lib, which as you can see, can change over time (vercel/serve#680)

I'd rather keep applying these defaults explicitly so that we don't depend on underlying deps changes.

Also we can use the default options in commander help messages

  .option('-p, --port <port>', `use specified port (default: ${DefaultServeOptions.port})`)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Oh... you're sure? 😄

const basePort = portOption ? parseInt(portOption, 10) : DEFAULT_PORT;

Copy link
Collaborator

Choose a reason for hiding this comment

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

ah 😅 didn't search in utils

@Josh-Cena Josh-Cena changed the title refactor(cli): normalize default value application refactor(cli): normalize the application of default option values Apr 21, 2022
@Josh-Cena
Copy link
Collaborator Author

Actually... many of the default values are applied again in the underlying utility functions, which is a good thing, because these utility functions are re-used in multiple places where the concerns about the option values are different. The functions in src/commands are just a pipe-through, so the default values probably shouldn't be applied there. In any case, removing the default values in bin/docusaurus.mjs is a must-have since it's just very confusing that way when the utility functions would apply the default values again.

@slorber slorber merged commit 2429bfb into main Apr 29, 2022
@slorber slorber deleted the jc/normalize-cli branch April 29, 2022 10:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed Signed Facebook CLA pr: maintenance This PR does not produce any behavior differences to end users when upgrading.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants