1. 程式人生 > >Building a Command-line Interface in JavaScript with OClif

Building a Command-line Interface in JavaScript with OClif

$ npm init #will create a new package.json file with the data you provide for the current directory
$ npm install oclif #will install the oclif package into your current directory
$ npm remove config #will remove the config package from your current directory
$ npm publish
$ buttercms generate:blog --for=express
Figure 1: Expected output from the new ButterCMS tool

documentation

$ npm install -g oclif
$ oclif multi your-command
$ ./bin/run hello
$ ./bin/run hello
hello world from ./src/commands/hello.ts!
$ ./bin/run help
USAGE
  $ mynewcli [COMMAND]

COMMANDS
  hello  describe the command here
  help   display help for mynewcli
$ ./bin/run help hello
describe the command here

USAGE
  $ mynewcli hello [FILE]

OPTIONS
  -f, --force
  -n, --name=name  name to print

EXAMPLES
  $ mynewcli hello
  hello world from ./src/hello.ts!
$ oclif multi buttercms
'use strict'

const {Command, flags} = require('@oclif/command')
const requiredir = require("require-dir")
const BlogGenerators = requiredir("../../generators/blog")

class BlogCommand extends Command {
        async run() {
                const {flags} = this.parse(BlogCommand)
                const targetGeneration = flags.for.toLowerCase().trim()

                //error handling
                if(BlogCommand.flags.for.options.indexOf(targetGeneration) == -1) {
                        return this.error (`Target not found '${targetGeneration}', please try one of the valid ones - ${BlogCommand.flags.for.options.join(",")} - `)
                }

                const gen = new BlogGenerators[targetGeneration]()
                gen.run();
        }
}
//Adding for auto-documentation purposes thanks to OClif
BlogCommand.flags = {
        for: flags.string({
                description: 'Target destination for the generator command',
                options: ['express'] //valid options
        })
}

module.exports = BlogCommand
$ ./bin/run generate:blog --for=express
const {flags} = this.parse(BlogCommand)
const targetGeneration = flags.for.toLowerCase().trim()
'use strict'

const {Command} = require('@oclif/command')
const inquirer = require("inquirer")
const chalk  = require("chalk")
const fs = require("fs")
const ncp = require("ncp").ncp

const SOURCEEXPRESSBLOG = __dirname + "/express-template"

module.exports = class ExpressBlogGenerator extends Command{
        prompts() {
                this.log(`The following list of files will be created: 
${chalk.green(
        ['app',
           '- /public/javascripts/',
           '- /public/images/',
           '- /public/stylesheets/',
           '- /public/stylesheets/style.css',
           ' ',
           '- /routes/index.js',
           '- /routes/authors.js',
           '- /routes/categories.js',
           '- /routes/blog.js',
           ' ',

           '- /views/error.jade',
           '- /views/index.jade',
           '- /views/layout.jade',
           '- /views/authors.jade',
           '- /views/categories.jade',
           '- /views/feeds.jade',
           '- /views/posts.jade',
           '- /views/post.jade',

           ' ',
           '- /app.js',
           '- /package.json',
           '- /bin/www'
].join("\n")
)} 
Also the following routes will be availabe for you:
${chalk.green("- GET")} /categories/:slug
${chalk.green("- GET")} /authors/:slug

${chalk.green("- GET")} /blog/rss
${chalk.green("- GET")} /blog/atom

${chalk.green("- GET")} /blog/pages/:page
${chalk.green("- GET")} /blog
${chalk.green("- GET")} /blog/:slug
`)

                return inquirer.prompt([{
                                type: "confirm",
                                name: "continue",
                                message: "Are you sure you wish to continue?",
                                choices: "Y/n",
                                default: "Y"
                        },{
                                when: response => response.continue,
                                type: "string",
                                name: "appname",
                                message: "What's the name of your blog?"
                        }])
                        .then( answer => answer) 
                        .catch( err => false)
        }

        cleanAppName(appname) {
                return appname.trim().toLowerCase().replace(/[^a-zA-Z0-9]/g,"")
        }
        printSuccessMessage(folderName) {
                this.log(chalk.green(`
== CONGRATS == 
Your blog is ready for you to start pumping code into it!

Now you can:
1- cd ./${folderName}
2- npm install
3- npm start 
                        `))
        }
        
        /*
        Create the destination folder using the application name given,
        and copy the blog files into it
        */
        copyFiles(appname) {
                const folderName = this.cleanAppName(appname)
                fs.mkdir(folderName, (err) => {
                        if(err) { 
                                return this.log("There was a problem creating your blog's folder: " + chalk.red(err.toString()))
                        }
                        this.log("Folder - " + chalk.bold(folderName) + " -  " + chalk.green("successfully created!"))
                        ncp(SOURCEEXPRESSBLOG, folderName, (err) => {
                                if(err) {
                                        return this.log("There was a problem while copying your files: " + chalk.red(err))
                                }
                                this.printSuccessMessage(folderName)
                        })
                })
        }

        execute(answer) {
                if(!answer.continue){
                        return this.log("OK then, see you later!")
                }
                this.copyFiles(answer.appname)
        }

        async run() {
                this
                        .prompts() //ask the questions
                        .then(this.execute.bind(this)) //execute the command
        }
}
$ npm link
$ npm start
Found this guide helpful? Get more delivered straight to your inbox.