refactor(cli): normalize the application of default option values#7220
refactor(cli): normalize the application of default option values#7220
Conversation
✅ [V2]
To edit notification comments on pull requests, go to your Netlify site settings. |
|
⚡️ Lighthouse report for the changes in this PR:
Lighthouse ran on https://deploy-preview-7220--docusaurus-2.netlify.app/ |
|
Size Change: 0 B Total Size: 803 kB ℹ️ View Unchanged
|
| export async function writeTranslations( | ||
| siteDir: string, | ||
| options: WriteTranslationsOptions & ConfigOptions & {locale?: string}, | ||
| options: Partial< |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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))
} There was a problem hiding this comment.
Yes, makes sense.
| siteDir, | ||
| { | ||
| dir = 'build', | ||
| port = 3000, |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
These have always been applied internally, before and after. These default values actually only serve the purpose of being confusing & overly defensive.
There was a problem hiding this comment.
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})`)There was a problem hiding this comment.
Oh... you're sure? 😄
There was a problem hiding this comment.
ah 😅 didn't search in utils
270aef3 to
af15be2
Compare
|
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 |
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.