Skip to content

Commit

Permalink
feat: add help command for Paragon CLI (#2603)
Browse files Browse the repository at this point in the history
* feat: help command for Paragon CLI

* feat: remove console log

* feat: PR comments update

* feat: update commands code

---------

Co-authored-by: monteri <lansevermore>
  • Loading branch information
monteri authored Sep 20, 2023
1 parent 1b9d1f0 commit c778061
Show file tree
Hide file tree
Showing 4 changed files with 140 additions and 6 deletions.
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>.'));
return;
}

if (command === HELP_COMMAND) {
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));
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));
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;

0 comments on commit c778061

Please sign in to comment.