npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

lwb_cli

v1.0.1

Published

## 定义

Readme

CLI 脚手架工具

定义

CLI(command-line interface)是在图形用户界面得到普及之前使用最为广泛的用户界面,它通常不支持鼠标,用户通过键盘输入指令,计算机接收到指令后,予以执行。

必备模块

常用的脚手架工具,比如 create-react-app、vue-cli、angular-cli 等等,灰常方便,他们也使用了一堆 npm 包,或者功能类似的 npm 包。

| 包名 | 功能 | | ----------------- | -------------------------------- | | Commander | 用户入参解析,如 -help | | inquirer | 常见的交互式命令行用户界面的集合 | | download-git-repo | 在 git 中下载模板 | | chalk | 改变控制台的字体颜色 | | metalsmith | 读取所有文件,实现模板渲染 | | consolidate | 统一模板引擎 |

实现功能,输入命令行,脚手架名 指令 入参: lwb-cli create myReact

准备工作

创建项目

mkdir lwb-cli

配置

npm init

链接全局包

    "bin": {
        "lwb-cli": "./bin/www"
    }

www 文件中,选择 node 环境,选择执行入口文件

    #! /usr/bin/env node
    require('../src/main.js');

开发期间链接到全局下使用

npm link

commander

命令行解析

   program
    .command("create")
    .alias("c")
    .description("新建一个项目")
    .action(() => {
        console.log("create");
    });

    // 根据不同的动作,动态引入对应模块的文件
    // path.resolve() 方法将路径或路径片段的序列解析为绝对路径。
    // process.argv 属性返回一个数组,就是用户在命令行中传入的参数。

    require(path.resolve(__dirname, action))(...process.argv.slice(3));

输出 version

version 一般存在于我们的 package 包里,包括项目名,全局变量单独存起来,新建一个 utils 文件夹,新建 constants 文件,导出 version、name

    program.version(version).parse(process.argv);

输出 help 信息

    program.on('--help', () => {
      console.log('Examples');
        Reflect.ownKeys(actionsMap).forEach((action) => {
            (actionsMap[action].examples || []).forEach((example) => {
                console.log(`  ${example}`);
            });
        });
    });

创建 create 命令

create 命令的主要作用就是去 git 仓库中拉取模板并下载对应的版本到本地,如果有模板则根据用户填写的信息渲染好模板,生成到当前运行命令的目录下~

    module.exports = async (projectName) => {
        console.log(projectName);
    };

拉项目

1、axios 2、github 的 API,获取当前组织中的所有仓库信息,https://api.github.com/orgs/项目名/repos

inquirer & ora

1、inquirer 询问式 2、ora loading 效果

    const spinner = ora('fetching repo list');
    spinner.start()
    spinner.succeed()

    const { repo } = await Inquirer.prompt({
        name: 'repo',
        type: 'list',
        message: '请选择一个项目来创建模板', choices: repos, // 选择模式
    });

下载模板 download-git-repo

这个方法不是 promise 方法、node 已经提供了现成方法

    const { promisify } = require('util');
    const downLoadGit = require('download-git-repo');
    downLoadGit = promisify(downLoadGit);

下载下来的文件,需要放到当前目录

    // 存储模板的位置
    const downloadDirectory =
        process.env[process.platform === "darwin" ? "HOME" : "USERPROFILE"]

ncp 实现文件的拷贝功能

    let ncp = require('ncp');
    ncp = promisify(ncp);
    // 将下载的文件拷贝到当前执行命令的目录下
    await ncp(target, path.join(path.resolve(), projectName));

模板编译

刚才说的是简单文件,那当然直接拷贝就好了,但是有的时候用户可以定制下载模板中的内容,拿 package.json 文件为例,用户可以根据提示给项目命名、设置描述等,在项目文件夹里增加 ask.js

    module.exports = [
    {
        type: 'confirm',
        name: 'private',
        message: 'ths resgistery is private?',
    }
]

根据对应的询问生成最终的 package.json,下载的模板中使用了 ejs 模板,核心原理就是将下载的模板文件,依次遍历根据用户填写的信息渲染模板,将渲染好的结果拷贝到执行命令的目录下

    "autor":"<%=author%>",
    "description": "<%=description%>",
    "license": "<%=license%>"

安装需要用到的模块 metalsmithn ejs consolidate

    // 下载下来的文件,如果有ask文件: 就是个复杂的模板,需要用户选择 ,然后编译模板
  if (!fs.existsSync(path.join(resultDirectory, "ask.js"))) {
    // 拿到下载到的目录之后,直接copy到当前目录下即可 ncp
    await ncp(resultDirectory, path.resolve(projectName));
    chalkSuccess(`创建项目成功 请执行\n cd ${projectName}`);
    process.exit();
  } else {
    // 1、让用户填信息
    await new Promise((resolve, reject) => {
      metalsmith(__dirname) //传入默认路径,默认遍历当前路径下的src文件夹
        .source(resultDirectory)
        //拷贝到用户指定目录下
        .destination(path.resolve(projectName))
        .use(async (files, metal, done) => {
          const asks = require(path.join(resultDirectory, "ask.js"));
          const userSelected = await Inquirer.prompt(asks);
          const meta = metal.metadata();
          Object.assign(meta, userSelected);
          delete files["ask.js"];
          done();
        })
        .use((files, metal, done) => {
          const metaData = metal.metadata();
          Reflect.ownKeys(files).forEach(async fileName => {
            //处理带 <%的命令
            if (fileName.includes("js") || fileName.includes("json")) {
              let content = files[fileName].contents.toString();
              // console.log("content: ", content)
              if (content.includes("<%")) {
                //渲染content
                content = await render(content, metaData);
                files[fileName].contents = Buffer.from(content);
              }
            }
          });
          done();
        })
        .build(err => {
          if (err) {
            chalkError(err);
            reject();
          } else {
            chalkSuccess(`创建项目成功 请执行 cd ${projectName}`);
            process.exit();
            resolve();
          }
        });
    }).catch({});
  }

项目发布

    //查看npm路径、一般都是淘宝,修改为正式的
    npm config get registry   //查看
    npm config set registry=http://registry.npm.org/ //设置

    //第一次发布需要登录

    npm login

    //发布
    npm publish