-
-
Notifications
You must be signed in to change notification settings - Fork 323
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fixes: #847
- Loading branch information
Showing
32 changed files
with
443 additions
and
287 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,25 +1,30 @@ | ||
require('babel-register')({ presets: ['env'], plugins: ['transform-class-properties'] }); | ||
require('babel-polyfill'); | ||
const prog = require('caporal'); | ||
const moduleCmd = require('./cli/module'); | ||
|
||
const addModuleCommand = require('./cli/commands/addModule'); | ||
const deleteModuleCommand = require('./cli/commands/deleteModule'); | ||
const CommandInvoker = require('./cli/CommandInvoker'); | ||
|
||
const commandInvoker = new CommandInvoker(addModuleCommand, deleteModuleCommand); | ||
|
||
prog | ||
.version('1.0.0') | ||
.command('addmodule', 'Create a new Module') | ||
.argument('<module>', 'Module name') | ||
.description('Full info: https://github.com/sysgears/apollo-universal-starter-kit/wiki/Apollo-Starter-Kit-CLI') | ||
// Add module | ||
.command('addmodule', 'Create a new Module.') | ||
.argument('<moduleName>', 'Module name') | ||
.argument( | ||
'[location]', | ||
'Where should new module be created. [both, server, client]', | ||
['both', 'server', 'client'], | ||
'both' | ||
) | ||
.action((args, options, logger) => moduleCmd('addmodule', args, options, logger)) | ||
.action((args, options, logger) => commandInvoker.runAddModule(args, options, logger)) | ||
// Delete module | ||
.command('deletemodule', 'Delete a Module') | ||
.argument('<module>', 'Module name') | ||
.argument( | ||
'[location]', | ||
'Where should new module be created. [both, server, client]', | ||
['both', 'server', 'client'], | ||
'both' | ||
) | ||
.action((args, options, logger) => moduleCmd('deletemodule', args, options, logger)); | ||
.argument('<moduleName>', 'Module name') | ||
.argument('[location]', 'Where should we delete module. [both, server, client]', ['both', 'server', 'client'], 'both') | ||
.action((args, options, logger) => commandInvoker.runDeleteModule(args, options, logger)); | ||
|
||
prog.parse(process.argv); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
const { MODULE_TEMPLATES } = require('./config'); | ||
|
||
/** | ||
* Class CommandInvoker. Takes all CLI operations and calls certain CLI operation depends of variables. | ||
*/ | ||
class CommandInvoker { | ||
/** | ||
* Sets CLI operations (functions). | ||
* @constructor | ||
* | ||
* @param addModule - The function for creating a new module. | ||
* @param deleteModule - The function for deleting existing module. | ||
*/ | ||
constructor(addModule, deleteModule) { | ||
this.addModule = addModule; | ||
this.deleteModule = deleteModule; | ||
} | ||
|
||
/** | ||
* Calls CLI operation with correct location. | ||
* | ||
* @param func - The func to call. | ||
* @param location - The location for a new module [client|server|both]. | ||
* @param args - The function for deleting existing module. | ||
*/ | ||
static runCommand(func, location, ...args) { | ||
// client | ||
if (location === 'client' || location === 'both') { | ||
func(...args, 'client'); | ||
} | ||
// server | ||
if (location === 'server' || location === 'both') { | ||
func(...args, 'server'); | ||
} | ||
} | ||
|
||
/** | ||
* Runs operation (function) for creating a new module. | ||
*/ | ||
runAddModule(args, options, logger) { | ||
const { moduleName, location = 'both' } = args; | ||
CommandInvoker.runCommand(this.addModule, location, logger, MODULE_TEMPLATES, moduleName); | ||
} | ||
|
||
/** | ||
* Runs operation (function) for deleting existing module. | ||
*/ | ||
runDeleteModule(args, options, logger) { | ||
const { moduleName, location = 'both' } = args; | ||
CommandInvoker.runCommand(this.deleteModule, location, logger, moduleName); | ||
} | ||
} | ||
|
||
module.exports = CommandInvoker; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
const shell = require('shelljs'); | ||
const fs = require('fs'); | ||
const chalk = require('chalk'); | ||
const { copyFiles, renameFiles, computeModulesPath } = require('../helpers/util'); | ||
|
||
/** | ||
* Adds module in client or server and adds a new module to the Feature connector. | ||
* | ||
* @param logger - The Logger. | ||
* @param templatesPath - The path to the templates for a new module. | ||
* @param moduleName - The name of a new module. | ||
* @param location - The location for a new module [client|server|both]. | ||
* @param finished - The flag about the end of the generating process. | ||
*/ | ||
function addModule(logger, templatesPath, moduleName, location, finished = true) { | ||
logger.info(`Copying ${location} files…`); | ||
|
||
// create new module directory | ||
const destinationPath = computeModulesPath(location, moduleName); | ||
const newModule = shell.mkdir(destinationPath); | ||
|
||
// continue only if directory does not jet exist | ||
if (newModule.code !== 0) { | ||
logger.error(chalk.red(`The ${moduleName} directory is already exists.`)); | ||
process.exit(); | ||
} | ||
//copy and rename templates in destination directory | ||
copyFiles(destinationPath, templatesPath, location); | ||
renameFiles(destinationPath, moduleName); | ||
|
||
logger.info(chalk.green(`✔ The ${location} files have been copied!`)); | ||
|
||
// get index file path | ||
const modulesPath = computeModulesPath(location); | ||
const indexFullFileName = fs.readdirSync(modulesPath).find(name => name.search(/index/) >= 0); | ||
const indexPath = modulesPath + indexFullFileName; | ||
let indexContent; | ||
|
||
try { | ||
// prepend import module | ||
indexContent = `import ${moduleName} from './${moduleName}';\n` + fs.readFileSync(indexPath); | ||
} catch (e) { | ||
logger.error(chalk.red(`Failed to read ${indexPath} file`)); | ||
process.exit(); | ||
} | ||
|
||
// extract Feature modules | ||
const featureRegExp = /Feature\(([^()]+)\)/g; | ||
const [, featureModules] = featureRegExp.exec(indexContent) || ['', '']; | ||
|
||
// add module to Feature connector | ||
shell | ||
.ShellString(indexContent.replace(RegExp(featureRegExp, 'g'), `Feature(${moduleName}, ${featureModules})`)) | ||
.to(indexPath); | ||
|
||
if (finished) { | ||
logger.info(chalk.green(`✔ Module for ${location} successfully created!`)); | ||
} | ||
} | ||
|
||
module.exports = addModule; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
const shell = require('shelljs'); | ||
const fs = require('fs'); | ||
const chalk = require('chalk'); | ||
const { computeModulesPath } = require('../helpers/util'); | ||
|
||
/** | ||
* Removes the module from client, server or both locations and removes the module from the Feature connector. | ||
* | ||
* @param logger - The Logger. | ||
* @param moduleName - The name of a new module. | ||
* @param location - The location for a new module [client|server|both]. | ||
*/ | ||
function deleteModule(logger, moduleName, location) { | ||
logger.info(`Deleting ${location} files…`); | ||
const modulePath = computeModulesPath(location, moduleName); | ||
|
||
if (fs.existsSync(modulePath)) { | ||
// remove module directory | ||
shell.rm('-rf', modulePath); | ||
|
||
const modulesPath = computeModulesPath(location); | ||
|
||
// get index file path | ||
const indexFullFileName = fs.readdirSync(modulesPath).find(name => name.search(/index/) >= 0); | ||
const indexPath = modulesPath + indexFullFileName; | ||
let indexContent; | ||
|
||
try { | ||
indexContent = fs.readFileSync(indexPath); | ||
} catch (e) { | ||
logger.error(chalk.red(`Failed to read ${indexPath} file`)); | ||
process.exit(); | ||
} | ||
|
||
// extract Feature modules | ||
const featureRegExp = /Feature\(([^()]+)\)/g; | ||
const [, featureModules] = featureRegExp.exec(indexContent) || ['', '']; | ||
const featureModulesWithoutDeleted = featureModules | ||
.split(',') | ||
.filter(featureModule => featureModule.trim() !== moduleName); | ||
|
||
const contentWithoutDeletedModule = indexContent | ||
.toString() | ||
// replace features modules on features without deleted module | ||
.replace(featureRegExp, `Feature(${featureModulesWithoutDeleted.toString().trim()})`) | ||
// remove import module | ||
.replace(RegExp(`import ${moduleName} from './${moduleName}';\n`, 'g'), ''); | ||
|
||
fs.writeFileSync(indexPath, contentWithoutDeletedModule); | ||
|
||
logger.info(chalk.green(`✔ Module for ${location} successfully deleted!`)); | ||
} else { | ||
logger.info(chalk.red(`✘ Module ${location} location for ${modulePath} not found!`)); | ||
} | ||
} | ||
|
||
module.exports = deleteModule; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
const path = require('path'); | ||
|
||
const BASE_PATH = path.resolve(`${__dirname}/../..`); | ||
const TEMPLATES_DIR = `${BASE_PATH}/tools/templates`; | ||
const MODULE_TEMPLATES = `${TEMPLATES_DIR}/module`; | ||
|
||
module.exports = { | ||
BASE_PATH, | ||
TEMPLATES_DIR, | ||
MODULE_TEMPLATES | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
const shell = require('shelljs'); | ||
const { pascalize, decamelize } = require('humps'); | ||
const { startCase } = require('lodash'); | ||
const { BASE_PATH } = require('../config'); | ||
|
||
/** | ||
* Copies the templates to the destination directory. | ||
* | ||
* @param destinationPath - The destination path for a new module. | ||
* @param templatesPath - The path to the templates for a new module. | ||
* @param location - The location for a new module [client|server|both]. | ||
*/ | ||
function copyFiles(destinationPath, templatesPath, location) { | ||
shell.cp('-R', `${templatesPath}/${location}/*`, destinationPath); | ||
} | ||
|
||
/** | ||
* Renames the templates in the destination directory. | ||
* | ||
* @param destinationPath - The destination path of a new module. | ||
* @param moduleName - The name of a new module. | ||
*/ | ||
function renameFiles(destinationPath, moduleName) { | ||
const Module = pascalize(moduleName); | ||
|
||
// change to destination directory | ||
shell.cd(destinationPath); | ||
|
||
// rename files | ||
shell.ls('-Rl', '.').forEach(entry => { | ||
if (entry.isFile()) { | ||
shell.mv(entry.name, entry.name.replace('Module', Module)); | ||
} | ||
}); | ||
|
||
// replace module names | ||
shell.ls('-Rl', '.').forEach(entry => { | ||
if (entry.isFile()) { | ||
shell.sed('-i', /\$module\$/g, moduleName, entry.name); | ||
shell.sed('-i', /\$_module\$/g, decamelize(moduleName), entry.name); | ||
shell.sed('-i', /\$Module\$/g, Module, entry.name); | ||
shell.sed('-i', /\$MoDuLe\$/g, startCase(moduleName), entry.name); | ||
shell.sed('-i', /\$MODULE\$/g, moduleName.toUpperCase(), entry.name); | ||
} | ||
}); | ||
} | ||
|
||
/** | ||
* Gets the computed path of the module or modules dir path. | ||
* | ||
* @param location - The location for a new module [client|server|both]. | ||
* @param moduleName - The name of a new module. | ||
* @returns {string} - Return the computed path | ||
*/ | ||
function computeModulesPath(location, moduleName = '') { | ||
return `${BASE_PATH}/packages/${location}/src/modules/${moduleName}`; | ||
} | ||
|
||
module.exports = { | ||
renameFiles, | ||
copyFiles, | ||
computeModulesPath | ||
}; |
Oops, something went wrong.