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

@daiyu-5577/buildsystem

v1.3.1

Published

CLI tool to build projects based on git changes

Readme

BuildSystem

基于 Git 变更的自动化构建系统,提供 CLI 构建命令和 Web 可视化构建管理界面,支持增量构建、并发控制、实时消息推送、版本回退、Webhook 通知和多用户权限管理。

功能概览

  • CLI 构建 — 命令行一键触发构建,支持指定分支、目录、commit 区间
  • Web 管理界面 — 实时构建状态监控、聊天室、日志查看、版本回退、用户权限管理
  • 增量构建 — 通过 git diff 识别变更项目,仅构建受影响的包
  • 并发控制 — 可配置最大并发构建数(MAX_CONCURRENCY
  • 实时推送 — Socket.IO 双向通信,构建日志实时流式推送
  • Webhook 通知 — 构建完成自动通知外部系统
  • 版本回退 — 构建前自动备份,支持一键回退
  • 定时清理 — Cron 定时清理旧日志和备份
  • 多用户认证 — Token 加密鉴权,支持邀请注册
  • 角色权限 — 三级角色体系(Super / Admin / User),细粒度权限控制

目录结构

buildSystem/
├── src/                          # 后端(Node.js + TypeScript + ESM)
│   ├── cli.ts                    # CLI 入口(commander)
│   ├── commands/
│   │   ├── build.ts              # build 命令:纯 CLI 构建
│   │   └── server.ts             # server 命令:启动 Web 服务
│   ├── server/
│   │   ├── index.ts              # Express + Socket.IO 服务主类
│   │   ├── routes.ts             # REST API 路由(含用户管理接口)
│   │   └── websocket.ts          # WebSocket 处理器 & 命令系统
│   ├── queue.ts                  # 构建任务队列(并发控制、增量构建)
│   ├── git.ts                    # Git 异步操作(checkout/pull/diff/clean)
│   ├── pm.ts                     # 包管理器检测(npm/yarn/pnpm)
│   ├── artifact.ts               # 构建产物备份与复制
│   ├── notifier.ts               # 通知系统(Socket.IO + Webhook)
│   ├── cron.ts                   # Cron 定时任务
│   ├── crypto.ts                 # AES-256-CBC 加解密
│   ├── database/
│   │   ├── index.ts              # JSON 文件数据库
│   │   └── types.ts              # 数据库类型(User/Message/Invite)
│   ├── config.ts                 # 集中配置(环境变量 + 路径)
│   ├── types.ts                  # 公共类型定义
│   ├── logger.ts                 # Winston 日志(http / socket 分离)
│   ├── fsHelpers.ts              # 文件系统工具
│   ├── utils.ts                  # 通用工具函数
│   └── custError.ts              # 自定义错误
│
├── web/                          # 前端(React + Vite + Less)
│   ├── src/
│   │   ├── main.tsx              # 入口(Router + AuthGuard)
│   │   ├── pages/
│   │   │   ├── Home.tsx          # 主页(构建面板 + 聊天室 + 用户操作)
│   │   │   ├── Login.tsx         # 登录/注册页
│   │   │   ├── InviteModal.tsx   # 邀请码弹窗
│   │   │   ├── PermissionModal.tsx # 权限管理弹窗
│   │   │   ├── UserInfoModal.tsx   # 用户信息弹窗
│   │   │   └── *.module.less     # 页面级样式
│   │   ├── components/
│   │   │   ├── Modal/            # 模态框体系(StackModal/Toast/Confirm/ImagePreview)
│   │   │   ├── Select/           # 下拉选择器
│   │   │   ├── SuggestMenu/      # 命令建议菜单
│   │   │   └── UserAvatar/       # 用户头像下拉组件
│   │   ├── hooks/
│   │   │   ├── useSocket.ts      # Socket.IO 连接 + 消息管理
│   │   │   └── useScrollToBottom.ts
│   │   ├── utils/
│   │   │   └── api.ts            # API 封装(带 token)
│   │   └── index.css             # 全局样式 & CSS 变量
│   └── vite.config.ts
│
├── .buildsystemCatch/            # 运行时缓存(自动创建)
│   ├── webBackup/                # 构建产物备份
│   ├── buildLog/                 # 构建日志
│   ├── database/                 # JSON 数据库
│   ├── log/                      # HTTP 日志
│   └── images/                   # 聊天图片
│
├── .env.example                  # 环境变量模板
├── package.json
└── tsconfig.json

架构

┌──────────────────────────────────────────────────────────────┐
│                    Browser                                    │
│  ┌──────────┐  ┌──────────┐  ┌───────────────────────────┐  │
│  │ Login    │  │ Home     │  │ Modal/Select/UserAvatar   │  │
│  │ (React)  │  │ (React)  │  │ (React Components)        │  │
│  └────┬─────┘  └────┬─────┘  └─────────────┬─────────────┘  │
│       │              │                       │                │
│       └──────┬───────┴───────────────────────┘                │
│              │ REST API + Socket.IO                           │
└──────────────┼────────────────────────────────────────────────┘
               │
┌──────────────┼────────────────────────────────────────────────┐
│         BuildServer (Express)                                 │
│  ┌───────────┴───────────┐                                    │
│  │  routes.ts (REST API) │  websocket.ts (Socket.IO)          │
│  │  - 构建任务管理        │  - 实时消息推送                     │
│  │  - 用户与权限管理      │  - 聊天室 & 快捷命令               │
│  │  - 邀请码管理          │  - 构建日志订阅                    │
│  └───────────┬───────────┘──────────┬─────────────────────────┘
│              │                       │                         │
│  ┌───────────┴───────────────────────┴────────────────────────┐ │
│  │              BuildTaskQueue                                │ │
│  │  ┌─────────┐  ┌──────────┐  ┌───────────────────────────┐ │ │
│  │  │  git.ts  │  │  pm.ts   │  │   artifact.ts             │ │ │
│  │  │ checkout │  │ npm ci   │  │  backup / copy / restore  │ │ │
│  │  │ pull     │  │ yarn     │  │                           │ │ │
│  │  │ diff     │  │ pnpm     │  └───────────────────────────┘ │ │
│  │  └─────────┘  └──────────┘                                │ │
│  └───────────────────────────────────────────────────────────┘ │
│  ┌─────────────┐  ┌───────────┐  ┌──────────────────────────┐  │
│  │ notifier.ts │  │  cron.ts  │  │  database/               │  │
│  │ webhook     │  │ 定时清理  │  │  User / Message / Invite │  │
│  └─────────────┘  └───────────┘  └──────────────────────────┘  │
└────────────────────────────────────────────────────────────────┘

快速开始

前置要求

  • Node.js >= 16
  • 项目根目录包含 package.json(含 build 脚本)

使用方式

buildSystem 支持两种使用场景:作为全局 CLI 工具直接使用,或从源码开发。

全局安装

npm install @daiyu-5577/buildsystem -g
# 构建项目,指定分支为 master
buildsystem build -b master

# 启动 Web 服务
# 启动后访问 `http://localhost:3000/buildsystem` 进入后台 Web 界面
# 账号/密码:root/123456
buildsystem server --port 3000

# 启动 Web 服务,并托管网站。静态文件根路径为 /path/to/dist,网站路由前缀为 /page
# 启动后访问 `http://localhost:3000/page/app` 进入静态托管的 Web 界面
buildsystem server --port 3000 --website /path/to/dist --website-prefix /page

CLI 命令参考

build 命令 — 纯 CLI 构建,不启动 Web 服务

buildsystem build -b <branch> [-p <paths...>] [-c <commit>] [-n <notify>]

| 参数 | 说明 | 示例 | |------|------|------| | -b, --branch | 目标分支(必填) | master | | -p, --packagePaths | 指定构建目录 | packages/app1 packages/app2 | | -c, --commit | commit 区间,增量构建 | abc123..def456 | | -n, --notify | 构建通知地址 | https://hooks.example.com/notify |

server 命令 — 启动 Web 管理界面 + REST API + Socket.IO

buildsystem server [--port <number>] [--website <path>] [--website-prefix <prefix>]

| 参数 | 说明 | 默认值 | |------|------|--------| | --port | 端口号 | 3000 | | --website | 托管的网站静态文件路径 | 空 | | --website-prefix | 网站路由前缀(挂载点) | /page |

Nginx 反向代理配置

当自定义了 BASE_ROUTE 环境变量,并通过nginx匹配该路径location BASE_ROUTE,需要通过反向代理将所有匹配的路径统一转发到后端服务:

server {
    listen 80;
    server_name example.com;

    # 匹配自定义 BASE_ROUTE 路径下的所有请求,全部转发到后端
    location /$BASE_ROUTE/ {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

    # 匹配 /buildsystem 路径下的所有请求,全部转发到后端
    # 启动后访问 `http://localhost:3000/buildsystem` 进入后台 Web 界面
    location /buildsystem/ {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

如果使用 --website-prefix /page 托管另一个站点,则需添加对应的 location block:

location /page/ {
    proxy_pass http://127.0.0.1:3000;
    # ... 同上 header
}

这样无论前端如何路由,所有请求都会到达 Express,由 findIndexHtmlexpress.static 正确处理 SPA 的 fallback 逻辑。

网站托管(--website / --website-prefix

通过 server --website <path> --website-prefix <prefix> 可在指定 URL 路径下托管任意静态网站:

buildsystem server \
  --website /data/sites/app \
  --website-prefix /app

| 参数 | 作用 | 示例 | |------|------|------| | --website | 静态文件实际所在的绝对路径 | /data/sites/app | | --website-prefix | URL 匹配前缀(挂载点) | /app |

访问 http://example.com/app → 返回 /data/sites/app/index.html 访问 http://example.com/app/login → 返回 /data/sites/app/login/index.html

多层级目录结构

假设 website-root 目录如下:

/data/sites/app/
├── index.html              # /app → 命中
├── login/index.html        # /app/login → 命中
├── vue/index.html     # /app/vue → 命中
│   └── assets/
└── react/index.html   # /app/react → 命中
    └── assets/

只需启动一次服务,所有子路径自动生效。无需为每个站点单独配置 --website-path

| 客户端访问 | 查找逻辑 | 结果 | |-----------|---------|------| | /app | /data/sites/app/index.html | ✅ | | /app/login | /data/sites/app/login/index.html | ✅ | | /app/vue/assets/logo.png | express.static 直接提供静态资源 | ✅ | | /app/vue/non-existent | 逐级 fallback 查找 index.html | 找到最近的父级或根 |

findIndexHtml 逐级查找算法

当请求无文件扩展名(SPA History 模式)时,服务端从长到短逐级尝试匹配:

请求路径: /app/vue/deep/page
匹配路径: /app
websiteRoot: /data/sites/app

1. /data/sites/app + /vue/deep/page + /index.html  → 不存在
2.            /vue/deep + /index.html               → 不存在
3.                  /vue + /index.html              → ✅ 命中
  • --website-prefix 仅作为 Express 的 use 前缀过滤,不参与最终文件路径拼接
  • 拼接公式:websiteRoot + 请求路径的前缀 + /index.html
  • 逐级向上 fallback 直到根目录的 index.html

注意事项

| 要点 | 说明 | |------|------| | 位置顺序 | location前缀匹配优先级从高到低排列,较长前缀应放在较之前,否则短前缀会先匹配拦截请求 | | /buildsystem/ | 这是前端 Vite 构建产物所在的路径,对应代码中 base: '/buildsystem' | | /app/vue//app/react/ | 通过 server --website-prefix /app 启动后,所有 /app/** 请求都会被 Express 代理处理 | | WebSocket 头 | Socket.IO 依赖 Upgrade + Connection 头部做协议升级,务必添加这两行 |

Vite 配置详解

前端使用 Vite 6 开发,配置文件位于 web/vite.config.ts

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  base: '/buildsystem',       // ① 前端资源路径前缀,与 Nginx 的 location 和 Express 的静态文件路径对应
  plugins: [react()],          // ② React JSX 转换插件
  server: {
    port: 5173,                // ③ 开发服务器端口
    proxy: {                   // ④ 开发环境代理:将 /api、/ws 请求转发到后端 :3000
      '/api': {                //    - /api → Express REST API(用户认证、任务管理等)
        target: 'http://localhost:3000',
        changeOrigin: true,    //    - 修改 Host 头为目标地址,避免 CORS 问题
      },
      '/ws': {                 //    - /ws → Socket.IO 实时通信端点
        target: 'http://localhost:3000',
        ws: true,              //    - 启用 WebSocket 代理
      },
    },
  },
  build: {
    outDir: '../dist/web',     // ⑤ 生产构建输出目录(相对于 web/ 即项目根目录的 dist/web)
    emptyOutDir: true,         // ⑥ 构建前先清空输出目录,避免残留旧文件
  },
})

| 字段 | 作用 | 注意事项 | |------|------|----------| | base | 定义前端资源(JS/CSS/HTML)访问路径的前缀 | 设为 /buildsystem 表示所有请求 URL 以 /buildsystem/ 开头;若改为 / 则表示直接部署在域名根路径下 | | server.proxy | 仅开发环境生效,解决前后端同源策略 | 生产环境需通过 Nginx 反向代理或后端统一端口解决 | | build.outDir | 指定编译产出放置位置 | 默认会覆盖整个目录,配合 emptyOutDir 保证干净构建 | | build.emptyOutDir | 确保每次构建都是全新产物 | 如果希望保留某些文件可设为 false,但通常建议开启 |

环境变量

| 变量 | 说明 | 默认值 | |------|------|--------| | NODE_ENV | 运行环境 | development | | BASE_ROUTE | REST API 路由前缀(即 express 中 /api/... 的前缀) | 空 | | CATCH_ROOT | 缓存根目录 | .buildsystemCatch | | DIST_ROOT | 构建产物目录 | dist | | MAX_CONCURRENCY | 最大并发构建数 | 1 | | CRYPTO_SALT | AES 加密 salt | 生产环境必须设置 | | CRYPTO_SECRET | AES 加密 secret | 生产环境必须设置 | | WEBHOOK_URL | Webhook 通知地址 | 空 |

用户权限体系

系统采用三级角色体系:

| 角色 | 权限 | |------|------| | Super | 全部权限:可以分配 Super/Admin/User 角色、生成邀请码 | | Admin | 管理权限:可以分配 Admin/User 角色、查看所有构建 | | User | 普通用户:仅可查看构建状态、发送聊天消息 |

邀请注册流程

  1. 管理员(Super/Admin)生成邀请码
  2. 将邀请码分享给新用户
  3. 用户在登录页切换至"注册"Tab,输入用户名、密码和邀请码完成注册

权限管理

  • 点击右上角头像打开下拉菜单,选择"权限管理"(需 Admin 或以上角色)
  • 搜索用户后通过下拉框修改其角色
  • Admin 不能降级或提升 Super 角色的用户

API

启动 Server 后,主要接口位于 /api/ 路径下(若设置了 BASE_ROUTE,则为 <BASE_ROUTE>/api/...):

| 方法 | 路径 | 说明 | |------|------|------| | POST | /api/login | 用户登录 | | POST | /api/register | 用户注册(需邀请码) | | POST | /api/addTask | 添加构建任务 | | POST | /api/cancelTask | 取消构建任务 | | GET | /api/getAllTask | 获取任务列表 | | GET | /api/getAllPackage | 获取可构建项目列表 | | GET | /api/refreshPackages | 刷新可构建项目列表(Admin/Super) | | GET | /api/getAllLog | 获取日志列表 | | GET | /api/getAllBackup | 获取备份列表 | | POST | /api/restore | 版本回退 | | GET | /api/getNoticeList | 获取通知配置 | | POST | /api/notify | Webhook 回调(构建通知) | | GET | /api/getUserInfo | 获取当前/指定用户信息 | | GET | /api/getAllUsers | 获取所有用户列表(Admin/Super) | | POST | /api/updateUserRole | 更新用户角色(Admin/Super) | | GET | /api/inviteCodes | 获取当前用户的邀请码列表(Super) | | POST | /api/generateInviteCode | 生成新邀请码(Super) |

构建流程

添加任务 → 入队列 → 并发调度 → 执行:
  1. git checkout <branch> + git pull
  2. 检测包管理器 → npm ci / yarn install / pnpm install
  3. npm run build
  4. 备份旧产物 → 复制新产物到 dist/
  5. git clean(还原工作区)
  → 成功/失败 → Webhook 通知 + Socket.IO 推送

技术栈

后端:Node.js · TypeScript · ESM · Express 5 · Socket.IO · Commander · Winston · dayjs · fs-extra

前端:React 19 · Vite 6 · TypeScript · React Router 6 · Socket.IO Client · Less (CSS Modules)

License

MIT