-
Notifications
You must be signed in to change notification settings - Fork 69
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
[BD-46] feat: help command for Paragon CLI #2603
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,26 +1,68 @@ | ||
#!/usr/bin/env node | ||
/* eslint-disable no-console */ | ||
const chalk = require('chalk'); | ||
const themeCommand = require('../lib/install-theme'); | ||
const helpCommand = require('../lib/help'); | ||
|
||
// command: executor function | ||
const COMMANDS = { | ||
'install-theme': themeCommand, | ||
// 'command-name': { | ||
// executor: executorFunc, | ||
// | ||
// ********** Block for help command start ********** | ||
// description: 'Command description', | ||
// parameters: [ | ||
// { | ||
// name: 'paramName', | ||
// description: 'paramDescription', | ||
// defaultValue: 'paramDefaultValue', | ||
// required: true/false, | ||
// }, | ||
// ... | ||
// ], | ||
// options: [ | ||
// { | ||
// name: '--optionName', | ||
// description: 'optionDescription', | ||
// }, | ||
// ... | ||
// ], | ||
// ********** Block for help command end ********** | ||
// }, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does it make sense to use the syntax to describe JSDocs? |
||
'install-theme': { | ||
executor: themeCommand, | ||
description: 'Installs the specific @edx/brand package.', | ||
parameters: [ | ||
{ | ||
name: 'theme', | ||
description: 'The @edx/brand package to install.', | ||
defaultValue: '@edx/brand-openedx@latest', | ||
required: false, | ||
}, | ||
], | ||
}, | ||
help: { | ||
executor: helpCommand, | ||
description: 'Displays help for available commands.', | ||
}, | ||
}; | ||
|
||
(async () => { | ||
const [command] = process.argv.slice(2); | ||
const executor = COMMANDS[command]; | ||
|
||
if (!executor) { | ||
// eslint-disable-next-line no-console | ||
console.log(chalk.red.bold('Unknown command. Usage: paragon <command>')); | ||
console.log(chalk.red.bold('Unknown command. Usage: paragon <command>.')); | ||
viktorrusakov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return; | ||
} | ||
|
||
if (command === 'help') { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it necessary to move the word |
||
helpCommand(COMMANDS); | ||
return; | ||
} | ||
|
||
try { | ||
await executor(); | ||
await executor.executor(); | ||
} catch (error) { | ||
// eslint-disable-next-line no-console | ||
console.error(chalk.red.bold('An error occurred:', error.message)); | ||
process.exit(1); | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
/* eslint-disable no-console */ | ||
const chalk = require('chalk'); | ||
|
||
const DESCRIPTION_PAD = 20; | ||
|
||
/** | ||
* Pads a description string to align with a specified offset string. | ||
* | ||
* @param {string} description - The description to pad. | ||
* @param {string} offsetString - The offset string that the description should align with. | ||
* @returns {string} - The padded description. | ||
*/ | ||
function padLeft(description, offsetString) { | ||
// Calculate the necessary padding based on the offsetString length | ||
const padding = ' '.repeat(Math.max(0, DESCRIPTION_PAD - offsetString.length)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we give a meaningful name for this constant? This way you can remove the redundant comment There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it is descriptive right now. Meaningful variable name would be very long |
||
return `${padding}${description}`; | ||
} | ||
|
||
/** | ||
* Displays a help message for available commands, including descriptions, parameters, and options. | ||
* | ||
* @param {Object} commands - An object containing information about available commands. | ||
*/ | ||
function helpCommand(commands) { | ||
console.log(chalk.yellow.bold('Paragon Help')); | ||
console.log(); | ||
console.log('Available commands:'); | ||
console.log(); | ||
|
||
Object.keys(commands).forEach(command => { | ||
viktorrusakov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
console.log(` ${chalk.green.bold(command)}`); | ||
if (commands[command].description) { | ||
console.log(` ${commands[command].description}`); | ||
} | ||
|
||
if (commands[command].parameters && commands[command].parameters.length > 0) { | ||
console.log(` ${chalk.cyan('Parameters: ')}`); | ||
commands[command].parameters.forEach(parameter => { | ||
const requiredStatus = parameter.required ? 'Required' : 'Optional'; | ||
const formattedDescription = padLeft(parameter.description, parameter.name); | ||
console.log(` ${parameter.name}${formattedDescription} (${requiredStatus}, Default: ${parameter.defaultValue || 'None'})`); | ||
}); | ||
} | ||
|
||
if (commands[command].options && commands[command].options.length > 0) { | ||
console.log(` ${chalk.cyan('Options: ')}`); | ||
commands[command].options.forEach(option => { | ||
const formattedDescription = padLeft(option.description, option.name); | ||
console.log(` ${option.name}${formattedDescription}`); | ||
}); | ||
} | ||
|
||
console.log(); | ||
}); | ||
} | ||
|
||
module.exports = helpCommand; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,12 @@ | ||
/* eslint-disable no-console */ | ||
viktorrusakov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
const inquirer = require('inquirer'); | ||
const childProcess = require('child_process'); | ||
|
||
/** | ||
* Prompts the user to enter the @edx/brand package they want to install. | ||
* | ||
* @returns {Promise<Object>} - A Promise that resolves to an object containing the user's input. | ||
*/ | ||
function promptUserForTheme() { | ||
return inquirer.prompt([ | ||
{ | ||
|
@@ -12,6 +18,11 @@ function promptUserForTheme() { | |
]); | ||
} | ||
|
||
/** | ||
* Installs a specified @edx/brand package. | ||
* | ||
* @param {string} theme - The @edx/brand package to install. | ||
*/ | ||
function installTheme(theme) { | ||
const version = theme ? `npm:${theme}` : ''; | ||
|
||
|
@@ -20,9 +31,18 @@ function installTheme(theme) { | |
childProcess.execSync(installCommand, { stdio: 'inherit' }); | ||
} | ||
|
||
/** | ||
* Command handler for installing an @edx/brand package. | ||
*/ | ||
async function themeCommand() { | ||
const answers = await promptUserForTheme(); | ||
installTheme(answers.theme); | ||
// Check if the user passed a theme parameter as a command-line argument | ||
if (process.argv.length === 4) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we give a meaningful name for this expression? This way you can remove the redundant comment |
||
const providedTheme = process.argv[3]; | ||
installTheme(providedTheme); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I decided to add it in this PR since it is small and I could use newly created |
||
} else { | ||
const answers = await promptUserForTheme(); | ||
installTheme(answers.theme); | ||
} | ||
} | ||
|
||
module.exports = themeCommand; |
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.
You turned off the linter for the entire page, even though you're only using
console.log
in one place. Should I turn off the linter rule only in one place?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.
it is used twice there but I agree for two cases it is good idea.