@app-public/weaverbird-debug
v1.0.5
Published
WeaverBird CI 开放 CLI — 本地调试环境
Readme
WeaverBird CLI
WeaverBird CI 开放 CLI,通过 OAuth 2.0 登录后访问 CI 平台 API。与 CI 流水线共用同一 OAuth 应用,凭证按环境配置在 config/profiles/ 中。
设计说明见飞书文档:CI 系统 2.5 版本方案设计 — CI 开放 Cli 认证
环境要求
- Node.js >= 16
安装
cd cli
npm install全局联调(可选):
npm link或从 npm 安装(发布后,按环境选择包,scope 为 @app-public):
npm install -g @app-public/weaverbird # 线上(命令仍为 weaverbird)
npm install -g @app-public/weaverbird-debug # 本地调试
npm install -g @app-public/weaverbird-test # 测试环境scoped 包
@app-public/weaverbird与公共 npm 上无 scope 的weaverbird(Vue 查询构建器)是不同包,不会冲突。
CLI 命令
| 操作 | 命令 |
|------|------|
| 顶层帮助 | weaverbird --help |
| cli 子命令帮助 | weaverbird cli --help |
| token 帮助 | weaverbird cli token --help |
| token set 参数 | weaverbird cli token set --help |
| 版本 | weaverbird --version |
| OAuth 登录 | weaverbird cli login |
| 退出登录 | weaverbird cli logout |
| 登录状态 | weaverbird cli status |
| 自更新 | weaverbird update |
| 设置 Figma token | weaverbird cli token set --type figma <token> |
update 可在顶层或 cli 下执行,二者等价。token set 的 <token> 是位置参数,放在命令最后;--type figma 必填。
token set 示例
weaverbird cli token set --type figma figd_xxxxxxxxxxxxxxxx
weaverbird cli token set -t figma figd_xxxxxxxxxxxxxxxx需先 weaverbird cli login。Figma token:Settings → Security → Personal access tokens。
login 流程
- 本地启动
http://localhost:3333/callback回调服务 - CLI 调用
POST /v1/api/ci/oauth/createAuthorizeSession创建一次性、5 分钟有效的授权会话 - 自动打开浏览器访问
{WEAVERBIRD_URL}/weaverbird/oauth/authorize?session=...(链接不可复制复用) - 用户授权后回调带
code,CLI 调用POST /v1/api/ci/oauth/token换取 token - token 写入
~/.weaverbird/token.{env}.json(如token.release.json)
status 输出示例
已登录:
{
"logged_in": true,
"env": "debug",
"ci_base_url": "http://10.25.72.141:16644",
"token_path": "C:\\Users\\xxx\\.weaverbird\\token.debug.json",
"user_id": "abc123",
"user_name": "张三",
"token": {
"access_token": "eyJxxx",
"token_type": "Bearer",
"expires_in": 7200,
"refresh_token": "xxx",
"user": {
"id": "abc123",
"name": "zhangsan",
"realname": "张三"
}
}
}未登录:
{
"logged_in": false,
"env": "debug",
"ci_base_url": "http://10.25.72.141:16644",
"token_path": "C:\\Users\\xxx\\.weaverbird\\token.debug.json",
"user_id": null,
"user_name": null,
"token": null
}多环境配置
CLI 通过命令名区分环境(weaverbird / weaverbird-debug / weaverbird-test),配置与后端 core/config/config.py 对齐,位于 config/profiles/:
| 命令 | 环境 | CI_BASE_URL(SERVER_HOST) | WEAVERBIRD_URL |
|------|------|------------------------------|------------------|
| weaverbird | release | https://apphost.vesync.cn | https://apphost.vesync.cn |
| weaverbird-debug | debug | http://10.25.72.141:16644 | http://10.25.72.141:18833 |
| weaverbird-test | test | http://192.168.10.191:16644 | http://192.168.10.191:18833 |
校验 profile
npm run config -- --env=release
npm run config:debug
npm run config:test
npm run config:release构建(profile 校验 + 语法检查 + 单元测试)
npm run build发布
发布前自动执行 prepublishOnly(构建与测试)。按环境发布为 @app-public scope 下的独立包(自动 --access public):
| 脚本 | npm 包名 | 全局命令 |
|------|----------|----------|
| npm run publish:release | @app-public/weaverbird | weaverbird |
| npm run publish:debug | @app-public/weaverbird-debug | weaverbird-debug |
| npm run publish:test | @app-public/weaverbird-test | weaverbird-test |
| npm run publish:all | 依次发布以上三个包 | — |
npm run publish:release # 发布线上包
npm run publish:debug # 发布调试包
npm run publish:test # 发布测试包
npm run publish:all # 一次性发布三个包(版本号需一致)
# 透传 npm publish 参数
npm run publish:release -- --dry-run
npm run publish:test -- --tag beta本地
package.json为私有工作区包(weaverbird-cli,private: true),不可直接npm publish。publish:*脚本会临时改写为对应环境的独立包名与 bin,发布完成后自动还原。
三个环境对应三个不同的 scoped 包名,互不影响、可独立发版:
| 环境 | npm 包名 |
|------|----------|
| 线上 | @app-public/weaverbird |
| 调试 | @app-public/weaverbird-debug |
| 测试 | @app-public/weaverbird-test |
运行时环境变量覆盖
生成 config.js 在运行时按命令名加载 profile;仍可通过环境变量覆盖部分配置(便于本地调试):
| 变量 | 说明 |
|------|------|
| WEAVERBIRD_ENV | 环境标识(debug / test / release) |
| WEAVERBIRD_CI_URL | CI API 根地址 |
| WEAVERBIRD_URL | WeaverBird 前端地址 |
| WEAVERBIRD_CLIENT_ID | OAuth 应用 ID |
| WEAVERBIRD_CLIENT_SECRET | OAuth 应用密钥 |
| WEAVERBIRD_REDIRECT_URI | OAuth 回调地址,默认 http://localhost:3333/callback |
| WEAVERBIRD_CALLBACK_PORT | 本地回调端口,默认 3333 |
| WEAVERBIRD_SCOPE | OAuth scope,默认 read write |
OAuth 凭证配置
凭证由服务端 oauth_client 表统一生成与管理(每个 PocketBase 库各一条应用记录)。环境不写在表里,而是通过 core/config 连接不同数据库(debug / test / release)自然隔离。
CLI 侧在 config/profiles/{debug,test,release}.js 中配置各环境 API 地址,并从对应环境数据库初始化脚本输出的 CLIENT_ID / CLIENT_SECRET 填入 profile。
初始化 WeaverBird CLI 应用
在目标环境的 PocketBase 建好 oauth_client 表后,用对应环境启动脚本执行(与后端一致,如 python main.py test 或 release):
python util/data_server_update/maintain_260615/main.py每个数据库只会创建一条 name=WeaverBird CLI 的记录;首次创建时打印明文 clientSecret,写入该环境对应的 cli/config/profiles/*.js。
注意: 不要将真实 CLIENT_SECRET 提交到公开仓库;CI/CD 发布时建议通过环境变量注入。
OAuth 客户端应用表(oauth_client)
PocketBase 集合名:oauth_client
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| name | text | 是 | 应用名称,如 WeaverBird CLI |
| clientId | text | 是 | OAuth CLIENT_ID,格式 cli_ + 32 位 hex,全局唯一 |
| clientSecret | text | 是 | AES 加密存储的 CLIENT_SECRET,不可明文回显 |
| redirectUris | json | 是 | 允许的回调地址列表,默认 ["http://localhost:3333/callback"] |
| scopes | text | 是 | 授权范围,默认 read write |
| grantTypes | json | 是 | 默认 ["authorization_code","refresh_token"] |
| isInvalid | bool | 否 | 是否禁用,默认 false |
| description | text | 否 | 备注 |
环境隔离:不在表中存
env/key。debug、test、release 各自连独立 PocketBase(见core/config/config.py的POCKETBASE_BASE_URL),各库维护各自的oauth_client记录。
凭证生成规则
后端 OAuthClientExtLogic(logic/ext/oauth_client.py):
| 方法 | 说明 |
|------|------|
| generate_client_id() | cli_{secrets.token_hex(16)} |
| generate_client_secret() | secrets.token_urlsafe(32) |
| create_oauth_client(name, ...) | 创建应用,仅返回时展示一次明文 secret |
| create_or_get_weaverbird_cli() | 若已有 WeaverBird CLI 则返回首条,否则新建 |
| get_by_client_id | 按 clientId 查询(唯一键) |
| verify_client(client_id, secret) | OAuth token 端校验客户端 |
clientSecret 使用 Encrypt.encrypt_with_salt 加密,salt 为 clientId。
与 CLI profile 的关系
| 后端环境(core/config) | PocketBase | CLI profile |
|-------------------------|------------|-------------|
| debug | 10.25.72.141:17760 | config/profiles/debug.js |
| test | 192.168.10.191:17760 | config/profiles/test.js |
| release | apphost.vesync.cn | config/profiles/release.js |
各环境分别在对应库执行初始化脚本,将输出的凭证填入同名 profile 即可。
关联表(OAuth 完整链路,后续实现)
| 表名 | 用途 |
|------|------|
| oauth_authorization_code | 授权码:code、clientId、userId、redirectUri、scope、expiresTime(兑换后删除) |
| oauth_access_token | 访问令牌:可复用现有 token 表扩展,或独立存储 accessToken、refreshToken、clientId、userId、expiresAt |
目录结构
cli/
├── index.js # CLI 入口(bin: weaverbird / weaverbird-debug / weaverbird-test)
├── config.js # 运行时按命令名加载 profile
├── config/
│ └── profiles/ # 各环境 profile(与 core/config 对齐)
├── login.js # OAuth 登录逻辑
├── tokenStore.js # ~/.weaverbird/token.json 读写
├── api.js # Bearer 请求与 refresh_token 刷新
├── scripts/
│ ├── build-config.js # 校验 profile
│ ├── run-build.js # build 入口
│ └── run-publish.js # 按环境发布 npm 包
├── test/
└── package.json开发
npm run build # 完整构建
npm run publish:release # 发布线上包(示例)后端依赖
CLI 依赖服务端 OAuth 接口(均为 POST JSON,响应格式与项目统一 { code, msg, data }):
| 接口 | 说明 |
|------|------|
| /v1/api/ci/oauth/createOauthClient | 管理员创建 OAuth 应用(header token) |
| /v1/api/ci/oauth/createAuthorizeSession | CLI 创建授权页一次性会话(需 client_secret) |
| /v1/api/ci/oauth/getAuthorizeSession | Web 查询授权会话状态(pending/expired/invalid) |
| /v1/api/ci/oauth/authorize | 签发 authorization code(需 session_token + header token) |
| /v1/api/ci/oauth/token | 换取/刷新 access_token |
| /v1/api/ci/open/setToken | CLI 设置第三方 token(如 figma),需 cli_token header |
授权页由前端 {WEAVERBIRD_URL}/weaverbird/oauth/authorize?session=... 实现;会话 5 分钟过期、一次性使用,过期或已用后 Web 会拦截并提示重新执行 weaverbird cli login。
业务 API 请求头:cli_token header(OAuth 换取的 access_token,与网页 token 独立)。
PocketBase 需创建的表
oauth_client— OAuth 应用oauth_authorize_session— 授权页会话(字段:sessionToken, clientId, redirectUri, responseType, scope, state, expiresTime;使用后删除)oauth_authorization_code— 授权码(字段:code, clientId, userId, redirectUri, scope, expiresTime;兑换后删除)oauth_refresh_token— 刷新令牌(字段:refreshToken, clientId, userId, scope, expiresTime, isInvalid)
