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

[BD-46] feat: help command for Paragon CLI #2603

Merged
merged 4 commits into from
Sep 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,16 @@ Usage on with `@edx/brand`:

Note that including fonts will affect performance. In some applications may choose not to load the custom font to keep it highly performant.

## Paragon CLI

The Paragon CLI (Command Line Interface) is a tool that provides various utility commands to automate actions within the Open edX environment.

### Available Commands

- `paragon install-theme [theme]`: Installs the specific @edx/brand package.

Use `paragon help` to see more information.

## Getting Help

Please reach out to the Paragon Working Group (PWG):
Expand Down
55 changes: 51 additions & 4 deletions bin/paragon-scripts.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,52 @@
#!/usr/bin/env node
const chalk = require('chalk');
const themeCommand = require('../lib/install-theme');
const helpCommand = require('../lib/help');

const HELP_COMMAND = '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 **********
*},
*/
'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 () => {
Expand All @@ -13,12 +55,17 @@ const COMMANDS = {

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_COMMAND) {
helpCommand(COMMANDS);
return;
viktorrusakov marked this conversation as resolved.
Show resolved Hide resolved
}

try {
await executor();
await executor.executor();
} catch (error) {
// eslint-disable-next-line no-console
console.error(chalk.red.bold('An error occurred:', error.message));
Expand Down
57 changes: 57 additions & 0 deletions lib/help.js
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));
Copy link
Contributor

Choose a reason for hiding this comment

The 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

Copy link
Contributor Author

@monteri monteri Sep 8, 2023

Choose a reason for hiding this comment

The 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.entries(commands).forEach(([command, { parameters, description, options }]) => {
console.log(` ${chalk.green.bold(command)}`);
if (description) {
console.log(` ${description}`);
}

if (parameters && parameters.length > 0) {
console.log(` ${chalk.cyan('Parameters: ')}`);
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 (options && options.length > 0) {
console.log(` ${chalk.cyan('Options: ')}`);
options.forEach(option => {
const formattedDescription = padLeft(option.description, option.name);
console.log(` ${option.name}${formattedDescription}`);
});
}

console.log();
});
}

module.exports = helpCommand;
24 changes: 22 additions & 2 deletions lib/install-theme.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
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([
{
Expand All @@ -12,6 +17,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}` : '';

Expand All @@ -20,9 +30,19 @@ 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
const userPassedThemeParameter = process.argv.length === 4;
if (userPassedThemeParameter) {
const providedTheme = process.argv[3];
installTheme(providedTheme);
} else {
const answers = await promptUserForTheme();
installTheme(answers.theme);
}
}

module.exports = themeCommand;
Loading