前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >创建发布一个cli工具

创建发布一个cli工具

作者头像
刘嘿哈
发布2022-10-25 14:22:01
2.2K0
发布2022-10-25 14:22:01
举报
文章被收录于专栏:js笔记js笔记

1.初始化项目

代码语言:javascript
复制
npm init -y

2.创建目录bin,里面创建inde.js

代码语言:javascript
复制
#!/usr/bin/env node
// 上面的不是注释,非常重要,告诉命令使用node环境运行本文件
console.log("hellow cli...")

3.package.json中配置bin命令

代码语言:javascript
复制
...
"main": "index.js",
"bin": {
  "kun": "./bin/index.js"
},
...

4.执行命令,创建软链接,把bin目录的路径暴露出来

代码语言:javascript
复制
npm link

成功后,在命令行尝试执行

代码语言:javascript
复制
kun

控制台打印 hellow cli...

  1. 安装辅助的依赖 ,commander node.js命令行界面的完整解决方案
代码语言:javascript
复制
npm install commander -S

修改bin/index.js

代码语言:javascript
复制
#!/usr/bin/env node
// 上面的不是注释,非常重要,告诉命令使用node环境运行本文件
const program=require('commander');
program.version(require('./../package.json').version);
program.command("create <name>")

    .description("create a koa project")
    .action((name)=>{
        console.log("name: "+name)        
    })
// 这行代码是解析参数
program.parse(process.argv)

执行kun create hellow,打印name: hellow。 现在支持 kun create <name>,kun -V,而且action中可以执行一下操作,并且能得到用户传入的参数。 6.安装 chalk.js 控制台粉笔工具,方便改变打印的颜色

代码语言:javascript
复制
npm install chalk -S

修改/bin/index.js,action中的function换成init导出的function

代码语言:javascript
复制
...
   .description("create a koa project")
   .action(require('./init'))
program.parse(process.argv)

根目录创建init.js ,主要功能就是创建一个文件夹,里面创建一个index.js和一个package.json。

代码语言:javascript
复制
const fs = require("fs");
const chalk = require("chalk");
const path = require("path");
const createLog = (type) => (content) => console.log(chalk[type](content));
const success = createLog("green");
const errorLog = createLog("red");
function getFilePath(name) {
  return `./${name}`;
}
// 删除目录
function delDir(path) {
  let files = [];

  if (fs.existsSync(path)) {
    files = fs.readdirSync(path);

    files.forEach((file) => {
      let curPath = path + "/" + file;

      if (fs.statSync(curPath).isDirectory()) {
        delDir(curPath); //递归删除文件夹
      } else {
        fs.unlinkSync(curPath); //删除文件
      }
    });

    fs.rmdirSync(path);
  }
}
// 这个name值是index.js中,`program.parse(argv)`解析的
module.exports = async (name) => {
  const basePath = getFilePath(name);
  if (fs.existsSync(basePath)) {
    errorLog("同名文件已经存在");
    return false;
  }
  //   创建目录
  fs.mkdirSync(basePath);
  try {
    fs.writeFileSync(`${basePath}/index.js`, "index");
    fs.writeFileSync(`${basePath}/package.json`,'package');
    success("创建成功");
  } catch (error) {
    //   删除目录及文件
    delDir(basePath);
    errorLog("创建失败!");
  }
};

7.有内味了。就是文件生成的确实low b点。安装ejs高效的嵌入式 JavaScript 模板引擎 首先要创建模板目录template。里面创建index.ejs和package.ejs

代码语言:javascript
复制
//index.ejs
const Koa = require('koa');

<% if (middleware.router) { %>    
const Router = require('koa-router');
<% } %>
<% if (middleware.static) { %>    
const serve = require("koa-static");
<% } %>
<% if (middleware.views) { %>    
const views = require("koa-views");
<% } %>
<% if (middleware.body) { %>    
const body = require('koa-body');
<% } %>

const app = new Koa();

<% if (middleware.static) { %>
app.use(serve(__dirname, '/static'));

<% } %>
<% if (middleware.views) { %>    
app.use(views(__dirname, '/views'), {
    extension: 'pug'
})
<% } %>

<% if (middleware.body) { %>    
app.use(body({
    multipart: true
}))
<% } %>

<% if (middleware.router) { %>    
const router = new Router();
router.get('/', ctx => {
    ctx.body = "hellow world"
})
app.use(router.routes());
<% } %>


app.listen(<%= port %>, () => {
    console.log("服务启动在localhost:<%= port %>")
})
代码语言:javascript
复制
//package.ejs
{
"name": "template",
"version": "1.0.0",
"description": "",
"main": "<%= packageName %>.js",
    "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
    },
    "keywords": [],
    "author": "",
    "license": "ISC",
    "dependencies": {
    "koa": "^2.13.1"
    <% if (middleware.body) { %>
        ,"koa-body": "^4.2.0"
        <% } %>
            <% if (middleware.router) { %>
                , "koa-router": "^10.0.0"
                <% } %>
                    <% if (middleware.static) { %>
                        ,"koa-static": "^5.0.0"
                        <% } %>
                            <% if (middleware.views) { %>
                                ,"koa-views": "^7.0.1"
                                <% } %>
                                    }
                                    }

创建目录createCode ,里面创建文件 inde.jscreateIndexPage.jscreatePackagePage.js

代码语言:javascript
复制
//index.js
const createIndexPage =require('./createIndexPage')
const createPackagePage =require('./createPackagePage')
module.exports.createIndexPage=createIndexPage
module.exports.createPackagePage=createPackagePage
代码语言:javascript
复制
//createIndexPage.js
const ejs = require("ejs");
const fs = require("fs");
const path = require("path");
module.exports = () => {
 const content = fs
   .readFileSync(path.join(__dirname, "../template/index.ejs"))
   .toString();
 const code = ejs.render(content, { middleware: {}, port: 3000 });
 return code;
};
代码语言:javascript
复制
// createPackagePage.js
const ejs = require("ejs");
const fs = require("fs");
const path=require('path');
module.exports = () => {
  const content = fs
    .readFileSync(path.join(__dirname, "./../template/package.ejs"))
    .toString();
  const code = ejs.render(content, { middleware: {}, packageName: 3000 });
  return code;
};

init.js稍微修改一下,改变文件写入的字符

代码语言:javascript
复制
const { createIndexPage, createPackagePage } = require("./createCode");

...
  try {
    fs.writeFileSync(`${basePath}/index.js`, createIndexPage());
    fs.writeFileSync(`${basePath}/package.json`,createPackagePage());
    success("创建成功");
  } catch (error) {
...

8.来点交互更加炫酷 安装 inquirer 一个用户与命令行交互的工具

代码语言:javascript
复制
npm install inquirer -S

创建目录question,里面创建文件index.jspackageName.jsport.jsmiddleware.js

代码语言:javascript
复制
//index.js 
const inquirer = require("inquirer");
function getPromptList(name) {
  return [
    // 具体交互内容
    require("./packageName.js")(name),
    require("./port.js")(),
    require("./middleware.js")(),
  ];
}
module.exports = (name) => {
  return inquirer.prompt(getPromptList(name));
};
代码语言:javascript
复制
// packageName.js
module.exports = (name) => ({
  type: "input",
  name: "packageName",
  message: "设置项目名称",
  validate(val) {
    if (!val) {
      return "请输入项目名称";
    } else {
      return true;
    }
  },
  default() {
    return name;
  },
});

//middleware.js
module.exports = (name) => ({
  type: "checkbox",
  name: "middleware",
  message: "请选择使用的中间件",
  choices: [
    {
      name: "KoaBody",
    },
    {
      name: "Koaviews",
    },
    {
      name: "KoaStatic",
    },
    {
      name: "KoaRouter",
    },
  ],
});

// port.js
module.exports = () => ({
  type: "input",
  name: "port",
  message: "设置服务端口号",
  default() {
    return 8000;
  },
  validate: function (val) {
    if (val > 3000 && val < 65535) {
      // 校验位数
      return true;
    }
    return "端口号范围应为:3000-65535";
  },
});

init.js中执行交互,并且将用户的选择传入到生成代码的函数

代码语言:javascript
复制
const question = require("./question");


...
  const data = await question();
  console.log(data);
  var config = {
    packageName: data.packageName,
    port: data.port,
    middleware: {
      body: data.middleware.indexOf("KoaBody") !== -1,
      views: data.middleware.indexOf("KoaViews") !== -1,
      static: data.middleware.indexOf("KoaStatic") !== -1,
      router: data.middleware.indexOf("KoaRouter") !== -1,
    },
  };
   //   创建目录
  fs.mkdirSync(basePath);
  try {
    fs.writeFileSync(`${basePath}/index.js`, createIndexPage(config));
    fs.writeFileSync(`${basePath}/package.json`, createPackagePage(config));
....
  1. 项目创建完成,贴心的帮用户安装依赖。就是用代码执行npm install。安装 execa将process_child pipe到主进程
代码语言:javascript
复制
npm install execa -S

init.js

代码语言:javascript
复制
const fs = require("fs");
const chalk = require("chalk");
const execa = require("execa");
const { createIndexPage, createPackagePage } = require("./createCode");
const question = require("./question");
const createLog = (type) => (content) => console.log(chalk[type](content));
const success = createLog("green");
const errorLog = createLog("red");
function getFilePath(name) {
  return `./${name}`;
}
// 删除目录
function delDir(path) {
  let files = [];
  if (fs.existsSync(path)) {
    files = fs.readdirSync(path);
    files.forEach((file) => {
      let curPath = path + "/" + file;
      if (fs.statSync(curPath).isDirectory()) {
        delDir(curPath); //递归删除文件夹
      } else {
        fs.unlinkSync(curPath); //删除文件
      }
    });
    fs.rmdirSync(path);
  }
}

module.exports = async (name) => {
  const basePath = getFilePath(name);
  if (fs.existsSync(basePath)) {
    errorLog("同名文件已经存在");
    return false;
  }
  const data = await question(name);
  var config = {
    packageName: data.packageName,
    port: data.port,
    middleware: {
      body: data.middleware.indexOf("KoaBody") !== -1,
      views: data.middleware.indexOf("KoaViews") !== -1,
      static: data.middleware.indexOf("KoaStatic") !== -1,
      router: data.middleware.indexOf("KoaRouter") !== -1,
    },
  };
  //   创建目录
  fs.mkdirSync(basePath);
  try {
    fs.writeFileSync(`${basePath}/index.js`, createIndexPage(config));
    fs.writeFileSync(`${basePath}/package.json`, createPackagePage(config));
    await execa("npm", ["install"], { cwd: `./${name}`, stdio: [2, 2, 2] });
    success(`
恭喜!!!小项目创建完毕
-----------------------------------------------
***********************************************


cd ./${name}

npm run serve


===============================================
`);
  } catch (error) {
    //   删除目录及文件
    delDir(basePath);
    errorLog("创建失败!");
  }
};
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-06-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
消息队列 TDMQ
消息队列 TDMQ (Tencent Distributed Message Queue)是腾讯基于 Apache Pulsar 自研的一个云原生消息中间件系列,其中包含兼容Pulsar、RabbitMQ、RocketMQ 等协议的消息队列子产品,得益于其底层计算与存储分离的架构,TDMQ 具备良好的弹性伸缩以及故障恢复能力。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档