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

@loneship/zup

v1.0.0

Published

一个用于发布本地的前后端目录或可执行文件的命令行工具,负责优雅地替换和部署(仅支持pm2部署的产品),并能自动备份旧版本。

Readme

zup

zup 是一个通过 SSH 部署本地构建产物的 CLI。它适合两类场景:

  • 上传目录并以原子切换方式发布,例如前端 dist
  • 上传单个文件并在发布后执行 pm2 reload

使用者只需要安装 Node.js,不需要 TypeScript。

安装

npm install -g @loneship/zup

也可以直接使用:

npx @loneship/zup

配置文件

默认读取当前目录下的 zup.config.json,也可以通过 --config 指定。

目录模式

适合前端构建目录发布。

{
  "ssh": {
    "host": "example.com",
    "port": 22,
    "username": "root",
    "password": "your-password"
  },
  "paths": {
    "local": "./dist",
    "remote": "/var/www/app"
  },
  "deployment": {
    "mode": "directory",
    "preDeployCommand": "npm run build",
    "keepBackups": 10
  }
}

私钥登录

适合使用 SSH key 的服务器。

{
  "ssh": {
    "host": "example.com",
    "port": 22,
    "username": "deploy",
    "privateKeyPath": "./keys/id_ed25519",
    "passphrase": "your-key-passphrase"
  },
  "paths": {
    "local": "./dist",
    "remote": "/var/www/app"
  },
  "deployment": {
    "mode": "directory",
    "preDeployCommand": "npm run build",
    "keepBackups": 10
  }
}

文件模式

适合单个 Node.js 脚本、Rust 可执行文件等发布。

{
  "ssh": {
    "host": "example.com",
    "port": 22,
    "username": "root",
    "password": "your-password"
  },
  "paths": {
    "local": "./target/release/my-service",
    "remote": "/srv/my-service/current"
  },
  "deployment": {
    "mode": "file",
    "preDeployCommand": "cargo build --release",
    "keepBackups": 5,
    "pm2": {
      "appName": "my-service"
    }
  }
}

配置项说明

  • ssh.host 远端主机地址。
  • ssh.port SSH 端口。
  • ssh.username SSH 用户名。
  • ssh.password SSH 密码,可与私钥认证二选一或同时提供。
  • ssh.privateKey 私钥内容,适合直接通过配置注入。
  • ssh.privateKeyPath 私钥文件路径。相对路径会基于配置文件所在目录解析,例如 ./keys/id_ed25519
  • ssh.passphrase 私钥解密口令,仅在使用 ssh.privateKeyssh.privateKeyPath 时有效。
  • paths.local 本地待发布路径。相对路径会基于配置文件所在目录解析。
  • paths.remote 远端正式路径,必须是绝对路径。
  • deployment.mode 必填,支持 directoryfile
  • deployment.preDeployCommand 可选。本地前置命令,在上传前执行。失败时直接中止部署。
  • deployment.keepBackups 保留的最近备份数量,默认 10,允许为 0
  • deployment.pm2.appNamefile 模式可用。切换成功后执行 pm2 reload <appName>,等待 5 秒,再执行 pm2 list

使用命令

使用默认配置文件:

zup

指定配置文件:

zup --config ./deploy/zup.config.json

执行流程

目录模式

  1. 可选执行本地前置命令,例如 npm run build
  2. 连接 SSH 服务器
  3. 上传到 remote.tmp.时间戳
  4. 如果正式目录已存在,先备份到 remote.old.时间戳
  5. 将临时目录原子重命名为正式目录
  6. 清理超出 keepBackups 的旧备份

文件模式

  1. 可选执行本地前置命令,例如 cargo build --release
  2. 连接 SSH 服务器
  3. 上传到 remote.tmp.时间戳
  4. 如果正式文件已存在,先备份到 remote.old.时间戳
  5. 将临时文件原子重命名为正式文件
  6. 如果正式文件不是 .js.cjs.mjs,自动执行 chmod 755
  7. 如果配置了 pm2.appName,执行 pm2 reload <appName>,等待 5 秒,再执行 pm2 list
  8. 清理超出 keepBackups 的旧备份

前置命令

deployment.preDeployCommand 适合用来先做本地构建,例如:

  • npm run build
  • pnpm build
  • cargo build --release

规则:

  • 在配置文件所在目录执行
  • 失败时直接中止部署
  • 失败时不会继续 SSH 上传

日志

CLI 会输出带颜色的分层日志,包含:

  • 主阶段
  • 子步骤
  • 文件级上传明细
  • 错误详情

典型输出:

[zup] === 开始执行原子部署
[zup]   | 部署模式:          directory
[zup]   | 本地路径:          /path/to/dist
[zup]   | 正式路径:          /var/www/app
[zup]   | 临时路径:          /var/www/app.tmp.2026-04-10_15.30.00
[zup]   | 备份路径:          /var/www/app.old.2026-04-10_15.30.00

[zup] ==> 上传临时目录
[zup]  -> 递归上传 /path/to/dist -> /var/www/app.tmp.2026-04-10_15.30.00
[zup]   | file assets/index.js -> /var/www/app.tmp.2026-04-10_15.30.00/assets/index.js

[zup] === 部署完成

远端环境要求

  • Linux shell 环境
  • 支持常见命令:mkdirmvrmlstest
  • 文件模式如需自动加执行权限,还需要支持 chmod
  • 文件模式如配置了 pm2,远端还需要安装并可用 pm2
  • paths.remote 的父目录需要对当前 SSH 用户可写

常见失败场景

本地路径不存在

  • directory 模式要求 paths.local 是目录
  • file 模式要求 paths.local 是文件

本地前置命令失败

  • 例如 npm run buildcargo build --release 执行失败
  • 这种情况下不会继续连接服务器

SSH 连接失败

  • 主机、端口、用户名、密码、私钥或私钥口令配置错误
  • 网络不可达
  • 服务器禁止当前认证方式

上传失败

  • 远端磁盘空间不足
  • 远端目录无写权限
  • SFTP 传输中断

备份或切换失败

  • 同名临时路径或备份路径已存在
  • 远端权限不足
  • 目标路径被其他进程占用

PM2 reload 失败

  • pm2 未安装
  • pm2.appName 配置错误
  • reload 后服务启动失败

说明:

  • pm2 reload 失败会让部署失败
  • pm2 list 失败只会告警,不会让部署失败