nodebbs 0.1.0 → 0.3.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +65 -310
- package/dist/commands/db/import.d.ts +1 -2
- package/dist/commands/db/import.js +73 -45
- package/dist/commands/pack/index.js +60 -44
- package/dist/commands/restart/index.js +13 -7
- package/dist/commands/start/index.d.ts +1 -1
- package/dist/commands/start/index.js +83 -73
- package/dist/commands/upgrade/index.d.ts +8 -0
- package/dist/commands/upgrade/index.js +39 -0
- package/dist/interactive.js +1 -1
- package/dist/templates/docker-compose.build.yml +10 -0
- package/dist/templates/docker-compose.lowmem.yml +25 -14
- package/dist/templates/docker-compose.prod.yml +89 -0
- package/dist/templates/docker-compose.yml +34 -93
- package/dist/templates/dockerignore +120 -0
- package/dist/templates/env +11 -30
- package/dist/utils/docker.d.ts +1 -1
- package/dist/utils/docker.js +46 -10
- package/dist/utils/env.d.ts +6 -1
- package/dist/utils/env.js +90 -16
- package/dist/utils/selection.d.ts +3 -1
- package/dist/utils/selection.js +22 -23
- package/oclif.manifest.json +103 -80
- package/package.json +1 -1
- package/dist/commands/rebuild/index.d.ts +0 -6
- package/dist/commands/rebuild/index.js +0 -11
package/README.md
CHANGED
|
@@ -7,15 +7,17 @@
|
|
|
7
7
|
|
|
8
8
|
## 📖 简介
|
|
9
9
|
|
|
10
|
-
NodeBBS CLI 是一个专为全栈开发者设计的命令行工具,用于简化 NodeBBS
|
|
10
|
+
NodeBBS CLI 是一个专为全栈开发者设计的命令行工具,用于简化 NodeBBS 项目的开发、部署和管理流程。它能够自动识别 **源码项目** 和 **纯净镜像部署** 两种场景,并提供开箱即用的 Docker 容器管理能力。
|
|
11
11
|
|
|
12
12
|
### 特性
|
|
13
13
|
|
|
14
|
-
-
|
|
14
|
+
- ️ **交互式菜单** - 支持键盘导航的可视化命令选择
|
|
15
|
+
- 🧠 **智能识别** - 自动检测源码模式或镜像模式
|
|
16
|
+
- 🔄 **平滑升级** - 一个命令完成更新(自动选择重建或拉取镜像)
|
|
15
17
|
- 🎯 **全栈友好** - 命令设计贴近开发者思维
|
|
16
18
|
- 📊 **实时日志** - 方便查看各服务日志
|
|
17
19
|
- 💾 **数据库管理** - 内置数据库迁移和管理工具
|
|
18
|
-
- 🌐 **内置模板** -
|
|
20
|
+
- 🌐 **内置模板** - 无需本地配置文件即可使用
|
|
19
21
|
|
|
20
22
|
## 📦 安装
|
|
21
23
|
|
|
@@ -45,210 +47,63 @@ npx nodebbs [command]
|
|
|
45
47
|
```bash
|
|
46
48
|
npx nodebbs
|
|
47
49
|
```
|
|
48
|
-
- **start**: 开始部署(首次使用推荐选择此项)
|
|
49
|
-
- **rebuild**: 更新并重启(Pull & Restart,代码/镜像更新后使用)
|
|
50
|
-
|
|
51
|
-
## 📚 命令参考
|
|
52
|
-
|
|
53
|
-
#### `nodebbs start`
|
|
54
|
-
开始部署
|
|
55
|
-
|
|
56
|
-
```bash
|
|
57
|
-
# 交互式启动
|
|
58
|
-
npx nodebbs start
|
|
59
|
-
|
|
60
|
-
# 指定环境启动
|
|
61
|
-
npx nodebbs start -e production
|
|
62
|
-
|
|
63
|
-
**参数**:
|
|
64
|
-
- `-e, --env` - 部署环境(production, lowmem)
|
|
65
|
-
- `-t, --tag` - 镜像版本 tag (默认: latest)
|
|
66
|
-
|
|
67
|
-
启动流程包含:
|
|
68
|
-
- Docker 环境检查
|
|
69
|
-
- 环境变量验证
|
|
70
|
-
- 拉取最新镜像
|
|
71
|
-
- 服务启动
|
|
72
|
-
- 健康检查(默认开启)
|
|
73
|
-
- 数据库初始化(默认开启)
|
|
74
|
-
|
|
75
|
-
#### `nodebbs rebuild`
|
|
76
|
-
拉取最新镜像并重启服务 (Update & Restart)
|
|
77
|
-
|
|
78
|
-
```bash
|
|
79
|
-
npx nodebbs rebuild
|
|
80
|
-
```
|
|
81
|
-
> 此命令是 `start` 的别名,用于快速更新部署。
|
|
82
|
-
|
|
83
|
-
#### `nodebbs restart`
|
|
84
|
-
重启所有服务(不更新镜像,支持环境选择)
|
|
85
|
-
|
|
86
|
-
```bash
|
|
87
|
-
npx nodebbs restart
|
|
88
|
-
npx nodebbs restart -e production
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
#### `nodebbs stop`
|
|
92
|
-
停止服务(支持环境选择)
|
|
93
|
-
|
|
94
|
-
```bash
|
|
95
|
-
npx nodebbs stop
|
|
96
|
-
npx nodebbs stop -e production
|
|
97
|
-
|
|
98
|
-
# 停止服务并删除数据卷(危险!)
|
|
99
|
-
npx nodebbs stop --volumes
|
|
100
|
-
npx nodebbs stop -v
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
**参数**:
|
|
104
|
-
- `-v, --volumes` - 同时删除数据卷
|
|
105
|
-
|
|
106
|
-
#### `nodebbs status`
|
|
107
|
-
查看服务状态
|
|
108
|
-
|
|
109
|
-
```bash
|
|
110
|
-
npx nodebbs status
|
|
111
|
-
# 查看指定环境状态
|
|
112
|
-
npx nodebbs status -e production
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
### 日志管理
|
|
116
|
-
|
|
117
|
-
#### `nodebbs logs`
|
|
118
|
-
查看服务日志
|
|
119
|
-
|
|
120
|
-
```bash
|
|
121
|
-
# 查看所有日志
|
|
122
|
-
npx nodebbs logs
|
|
123
|
-
# 查看指定环境日志
|
|
124
|
-
npx nodebbs logs -e production
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
#### `nodebbs logs:api`
|
|
128
|
-
查看 API 服务日志
|
|
129
|
-
|
|
130
|
-
```bash
|
|
131
|
-
npx nodebbs logs:api
|
|
132
|
-
```
|
|
133
50
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
####
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
npx nodebbs shell:web
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
#### `nodebbs shell:db`
|
|
189
|
-
进入数据库(自动启动 psql)
|
|
190
|
-
|
|
191
|
-
```bash
|
|
192
|
-
npx nodebbs shell:db
|
|
193
|
-
```
|
|
194
|
-
|
|
195
|
-
#### `nodebbs shell:redis`
|
|
196
|
-
进入 Redis(自动启动 redis-cli)
|
|
197
|
-
|
|
198
|
-
```bash
|
|
199
|
-
npx nodebbs shell:redis
|
|
200
|
-
```
|
|
201
|
-
|
|
202
|
-
### 数据库管理
|
|
203
|
-
|
|
204
|
-
#### `nodebbs db:push`
|
|
205
|
-
推送数据库 schema
|
|
206
|
-
|
|
207
|
-
```bash
|
|
208
|
-
npx nodebbs db:push
|
|
209
|
-
```
|
|
210
|
-
|
|
211
|
-
#### `nodebbs db:seed`
|
|
212
|
-
初始化数据库数据
|
|
213
|
-
|
|
214
|
-
```bash
|
|
215
|
-
npx nodebbs db:seed
|
|
216
|
-
```
|
|
217
|
-
|
|
218
|
-
#### `nodebbs db:reset`
|
|
219
|
-
重置并重新初始化数据(危险!)
|
|
220
|
-
|
|
221
|
-
```bash
|
|
222
|
-
npx nodebbs db:reset
|
|
223
|
-
```
|
|
224
|
-
|
|
225
|
-
#### `nodebbs db:backup`
|
|
226
|
-
备份数据库
|
|
227
|
-
|
|
228
|
-
```bash
|
|
229
|
-
npx nodebbs db:backup
|
|
230
|
-
npx nodebbs db:backup -o backup.sql
|
|
231
|
-
```
|
|
232
|
-
|
|
233
|
-
#### `nodebbs clean`
|
|
234
|
-
清理 Docker 缓存和残留资源
|
|
235
|
-
|
|
236
|
-
```bash
|
|
237
|
-
# 交互式选择清理项目
|
|
238
|
-
npx nodebbs clean
|
|
239
|
-
|
|
240
|
-
# 自动清理所有(构建缓存、无用镜像、网络)
|
|
241
|
-
npx nodebbs clean -a
|
|
242
|
-
|
|
243
|
-
# 仅清理构建缓存
|
|
244
|
-
npx nodebbs clean --cache
|
|
245
|
-
```
|
|
246
|
-
|
|
247
|
-
## 🎯 使用场景
|
|
51
|
+
- **start**: 开始部署(首次使用推荐选择此项)
|
|
52
|
+
- **upgrade**: 升级并重启(自动检测更新策略)
|
|
53
|
+
|
|
54
|
+
## 📚 部署模式
|
|
55
|
+
|
|
56
|
+
CLI 会自动根据当前目录内容判断部署模式:
|
|
57
|
+
|
|
58
|
+
1. **源码模式 (Source Mode)**
|
|
59
|
+
- 检测到 `package.json`。
|
|
60
|
+
- 行为:使用本地源码执行 `docker build` 构建镜像。
|
|
61
|
+
- 适用:开发环境、二次开发。
|
|
62
|
+
|
|
63
|
+
2. **镜像模式 (Image Mode)**
|
|
64
|
+
- 未检测到源码。
|
|
65
|
+
- 行为:直接从远程仓库拉取预构建镜像。
|
|
66
|
+
- 适用:生产环境部署、快速体验。
|
|
67
|
+
- **配置**:首次启动时会提示输入镜像版本(默认为 `latest`),并自动写入 `.env`。
|
|
68
|
+
|
|
69
|
+
## 🛠️ 常用命令
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
$ nodebbs
|
|
73
|
+
? 选择命令:
|
|
74
|
+
❯ start 启动服务
|
|
75
|
+
stop 停止服务
|
|
76
|
+
restart 重启服务
|
|
77
|
+
upgrade 升级服务
|
|
78
|
+
status 查看服务状态
|
|
79
|
+
logs 查看服务日志 [+]
|
|
80
|
+
shell 进入容器终端 [+]
|
|
81
|
+
db 数据库操作 (备份, 迁移, 种子数据等) [+]
|
|
82
|
+
pack 生成离线部署包
|
|
83
|
+
clean 清理 Docker 缓存和残留资源
|
|
84
|
+
help 显示帮助信息
|
|
85
|
+
❌ 退出
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
#### 命令说明
|
|
89
|
+
|
|
90
|
+
| 命令 | 说明 |
|
|
91
|
+
|------|---------|
|
|
92
|
+
| **start** | 启动服务(根据当前配置环境)|
|
|
93
|
+
| **stop** | 停止所有服务 |
|
|
94
|
+
| **restart** | 重启服务(相当于 `docker compose up --force-recreate`)|
|
|
95
|
+
| **upgrade** | 升级服务(拉取最新 Docker 镜像或重新构建本地镜像)|
|
|
96
|
+
| **status** | 查看所有容器的运行状态和健康检查结果 |
|
|
97
|
+
| **logs** | 查看服务日志(支持选择特定服务 API/Web/DB/Redis)|
|
|
98
|
+
| **shell** | 进入容器终端进行调试(支持选择特定服务)|
|
|
99
|
+
| **db** | 数据库高级操作:<br>• 备份 (backup)<br>• 恢复 (import)<br>• 迁移 (migrate)<br>• 种子数据 (seed) |
|
|
100
|
+
| **pack** | 生成离线部署包(**仅限源码模式**),方便在无网环境部署 |
|
|
101
|
+
| **clean** | 清理工具(删除未使用镜像、容器、卷,释放磁盘空间)|
|
|
248
102
|
|
|
249
103
|
### 离线服务器部署
|
|
250
104
|
|
|
251
105
|
1. **在开发机打包**:
|
|
106
|
+
> 注意:此命令需要在 **源码模式** 下运行(项目根目录包含 package.json)。
|
|
252
107
|
```bash
|
|
253
108
|
# 生成离线包
|
|
254
109
|
npx nodebbs pack
|
|
@@ -270,129 +125,29 @@ vi .env
|
|
|
270
125
|
./install.sh
|
|
271
126
|
```
|
|
272
127
|
|
|
273
|
-
|
|
274
|
-
|
|
275
128
|
## ⚙️ 环境配置
|
|
276
129
|
|
|
277
130
|
### 支持的环境
|
|
278
131
|
|
|
279
|
-
- **
|
|
280
|
-
- **
|
|
132
|
+
- **production** - 生产环境(推荐,启用资源限制与安全配置)
|
|
133
|
+
- **lowmem** - 低配环境(适用于 1C2G 服务器)
|
|
134
|
+
- **basic** - 基础环境(测试用,无资源限制)
|
|
281
135
|
|
|
282
136
|
### 环境变量
|
|
283
137
|
|
|
284
|
-
|
|
138
|
+
CLI 首次运行时会引导生成 `.env` 文件。
|
|
139
|
+
在 **镜像模式** 下,会额外生成:
|
|
285
140
|
|
|
286
141
|
```env
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
POSTGRES_DB=nodebbs
|
|
290
|
-
|
|
291
|
-
# Redis 配置
|
|
292
|
-
REDIS_PASSWORD=your_redis_password
|
|
293
|
-
|
|
294
|
-
# JWT 配置
|
|
295
|
-
JWT_SECRET=your_jwt_secret
|
|
296
|
-
|
|
297
|
-
# 应用配置
|
|
298
|
-
APP_URL=http://localhost:3100
|
|
299
|
-
API_URL=http://localhost:7100
|
|
300
|
-
|
|
301
|
-
# CORS 配置
|
|
302
|
-
CORS_ORIGIN=*
|
|
303
|
-
```
|
|
304
|
-
|
|
305
|
-
> **提示**:可以使用 `openssl rand -hex 32` 命令生成安全的随机密钥。
|
|
306
|
-
|
|
307
|
-
### 环境持久化
|
|
308
|
-
|
|
309
|
-
CLI 会自动记住您上次启动的环境:
|
|
310
|
-
|
|
311
|
-
1. 当您运行 `nodebbs start` 并选择环境(如 `production`)后,CLI 会在当前目录创建 `.nodebbs-env` 文件记录该选择。
|
|
312
|
-
2. 后续运行 `nodebbs logs`, `nodebbs status` 等命令时,会自动使用该环境,无需再次指定 `-e production`。
|
|
313
|
-
3. 运行 `nodebbs stop` 成功停止服务后,会自动删除 `.nodebbs-env` 文件。
|
|
314
|
-
|
|
315
|
-
**注意**:如果您需要临时操作其他环境,仍然可以使用 `-e` 参数强制指定,例如 `nodebbs logs -e lowmem`。
|
|
316
|
-
|
|
317
|
-
## 🛠️ 高级用法
|
|
318
|
-
|
|
319
|
-
### 内置模板
|
|
320
|
-
|
|
321
|
-
NodeBBS CLI 内置了 Docker Compose 配置文件,即使项目中没有这些文件,也可以直接使用:
|
|
322
|
-
|
|
323
|
-
```bash
|
|
324
|
-
# 在任何目录运行
|
|
325
|
-
npx nodebbs start
|
|
326
|
-
```
|
|
327
|
-
|
|
328
|
-
CLI 会自动:
|
|
329
|
-
1. 检查当前目录是否有 `docker-compose.yml`
|
|
330
|
-
2. 如果没有,使用内置模板
|
|
331
|
-
3. 使用当前目录作为项目目录
|
|
332
|
-
|
|
333
|
-
### 自定义配置
|
|
334
|
-
|
|
335
|
-
如果需要自定义配置,在项目根目录创建:
|
|
336
|
-
- `docker-compose.yml` - 基础/生产环境配置
|
|
337
|
-
- `docker-compose.lowmem.yml` - 低配环境配置 (Override)
|
|
338
|
-
|
|
339
|
-
CLI 会优先使用本地配置文件。
|
|
340
|
-
|
|
341
|
-
## 🐛 故障排除
|
|
342
|
-
|
|
343
|
-
### 服务启动失败
|
|
344
|
-
|
|
345
|
-
```bash
|
|
346
|
-
# 查看日志
|
|
347
|
-
npx nodebbs logs
|
|
348
|
-
|
|
349
|
-
# 查看特定服务日志
|
|
350
|
-
npx nodebbs logs:api
|
|
351
|
-
|
|
352
|
-
# 检查服务状态
|
|
353
|
-
npx nodebbs status
|
|
354
|
-
```
|
|
355
|
-
|
|
356
|
-
### 数据库连接问题
|
|
357
|
-
|
|
358
|
-
```bash
|
|
359
|
-
# 进入数据库检查
|
|
360
|
-
npx nodebbs shell:db
|
|
361
|
-
|
|
362
|
-
# 重置数据库
|
|
363
|
-
npx nodebbs db:reset
|
|
364
|
-
```
|
|
365
|
-
|
|
366
|
-
### 端口冲突
|
|
367
|
-
|
|
368
|
-
检查以下端口是否被占用:
|
|
369
|
-
- 3100 - Web 前端
|
|
370
|
-
- 7100 - API 服务
|
|
371
|
-
- 5432 - PostgreSQL
|
|
372
|
-
- 6379 - Redis
|
|
373
|
-
|
|
374
|
-
### 清理环境
|
|
375
|
-
|
|
376
|
-
```bash
|
|
377
|
-
# 停止所有服务
|
|
378
|
-
npx nodebbs stop
|
|
379
|
-
|
|
380
|
-
# 停止并删除所有数据(危险!)
|
|
381
|
-
npx nodebbs stop --volumes
|
|
142
|
+
API_IMAGE=ghcr.io/aiprojecthub/nodebbs-api:latest
|
|
143
|
+
WEB_IMAGE=ghcr.io/aiprojecthub/nodebbs-web:latest
|
|
382
144
|
```
|
|
383
145
|
|
|
146
|
+
如需升级至特定版本,修改 `.env` 中的版本号后运行 `nodebbs upgrade` 即可。
|
|
384
147
|
## 🔗 相关链接
|
|
385
148
|
|
|
386
149
|
- [NodeBBS 项目](https://github.com/aiprojecthub/nodebbs)
|
|
387
150
|
- [问题反馈](https://github.com/aiprojecthub/nodebbs/issues)
|
|
388
|
-
|
|
389
|
-
## 💡 提示
|
|
390
|
-
|
|
391
|
-
- 使用 `npx nodebbs --help` 查看所有可用命令
|
|
392
|
-
- 使用 `npx nodebbs [command] --help` 查看特定命令的帮助
|
|
393
|
-
- 所有命令都支持 `--help` 参数
|
|
394
|
-
- 建议在生产环境使用前先在测试环境验证
|
|
395
|
-
|
|
396
151
|
---
|
|
397
152
|
|
|
398
153
|
Made with ❤️ by NodeBBS Team
|
|
@@ -3,8 +3,7 @@ export default class DbImport extends Command {
|
|
|
3
3
|
static description: string;
|
|
4
4
|
static flags: {
|
|
5
5
|
env: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
6
|
-
|
|
7
|
-
yes: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
6
|
+
input: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
8
7
|
};
|
|
9
8
|
run(): Promise<void>;
|
|
10
9
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Command, Flags } from '@oclif/core';
|
|
2
|
-
import { confirm } from '@inquirer/prompts';
|
|
3
2
|
import { getComposeFiles } from '../../utils/docker.js';
|
|
4
3
|
import { logger } from '../../utils/logger.js';
|
|
5
4
|
import { execa } from 'execa';
|
|
@@ -7,72 +6,101 @@ import fs from 'node:fs';
|
|
|
7
6
|
import path from 'node:path';
|
|
8
7
|
import dotenv from 'dotenv';
|
|
9
8
|
import { EnvFlag, selectEnvironment } from '../../utils/selection.js';
|
|
9
|
+
import { confirm, select, input } from '@inquirer/prompts';
|
|
10
10
|
export default class DbImport extends Command {
|
|
11
|
-
static description = '导入数据库 (
|
|
11
|
+
static description = '导入数据库 (从 SQL 文件恢复)';
|
|
12
12
|
static flags = {
|
|
13
13
|
env: EnvFlag,
|
|
14
|
-
|
|
15
|
-
char: '
|
|
16
|
-
description: '
|
|
17
|
-
required: true,
|
|
18
|
-
}),
|
|
19
|
-
yes: Flags.boolean({
|
|
20
|
-
char: 'y',
|
|
21
|
-
description: '跳过确认提示',
|
|
22
|
-
default: false,
|
|
14
|
+
input: Flags.string({
|
|
15
|
+
char: 'i',
|
|
16
|
+
description: '输入文件路径',
|
|
23
17
|
}),
|
|
24
18
|
};
|
|
25
19
|
async run() {
|
|
26
20
|
const { flags } = await this.parse(DbImport);
|
|
27
21
|
// 1. 选择环境
|
|
28
22
|
const env = await selectEnvironment(flags.env);
|
|
29
|
-
// 2.
|
|
30
|
-
|
|
23
|
+
// 2. 确定输入文件
|
|
24
|
+
let inputFile = flags.input;
|
|
25
|
+
if (!inputFile) {
|
|
26
|
+
// 尝试自动查找当前目录下的 .sql 文件
|
|
27
|
+
const files = fs.readdirSync(process.cwd())
|
|
28
|
+
.filter(f => f.endsWith('.sql'))
|
|
29
|
+
.sort((a, b) => {
|
|
30
|
+
// 尝试按时间倒序 (虽然文件名可能有时间戳,但用文件修改时间更准)
|
|
31
|
+
const statA = fs.statSync(a);
|
|
32
|
+
const statB = fs.statSync(b);
|
|
33
|
+
return statB.mtime.getTime() - statA.mtime.getTime();
|
|
34
|
+
});
|
|
35
|
+
if (files.length > 0) {
|
|
36
|
+
const choices = files.map(f => ({
|
|
37
|
+
name: `${f} (${(fs.statSync(f).size / 1024 / 1024).toFixed(2)} MB)`,
|
|
38
|
+
value: f
|
|
39
|
+
}));
|
|
40
|
+
choices.push({ name: '手动输入路径', value: '__MANUAL__' });
|
|
41
|
+
const selection = await select({
|
|
42
|
+
message: '请选择导入文件:',
|
|
43
|
+
choices: choices,
|
|
44
|
+
});
|
|
45
|
+
if (selection === '__MANUAL__') {
|
|
46
|
+
inputFile = await input({ message: '请输入文件路径:' });
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
inputFile = selection;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
inputFile = await input({ message: '未找到 SQL 文件,请输入路径:' });
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
// 确保绝对路径并检查是否存在
|
|
57
|
+
const inputPath = path.resolve(process.cwd(), inputFile);
|
|
31
58
|
if (!fs.existsSync(inputPath)) {
|
|
32
|
-
logger.error(
|
|
59
|
+
logger.error(`文件未找到: ${inputPath}`);
|
|
33
60
|
this.exit(1);
|
|
34
61
|
}
|
|
35
|
-
// 3.
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
}
|
|
62
|
+
// 3. 危险操作确认
|
|
63
|
+
logger.warning('警告: 此操作将清空当前数据库的所有数据并从备份恢复!');
|
|
64
|
+
logger.warning(`目标文件: ${inputPath}`);
|
|
65
|
+
const isConfirmed = await confirm({
|
|
66
|
+
message: '确认继续?(数据丢失不可撤销)',
|
|
67
|
+
default: false
|
|
68
|
+
});
|
|
69
|
+
if (!isConfirmed) {
|
|
70
|
+
logger.info('操作已取消');
|
|
71
|
+
this.exit(0);
|
|
46
72
|
}
|
|
47
73
|
// 4. 获取 Compose 文件
|
|
48
74
|
const { files, isBuiltIn } = await getComposeFiles(env);
|
|
49
|
-
logger.info(`正在从文件恢复数据库: ${inputPath}`);
|
|
50
|
-
logger.info('环境: ' + env);
|
|
51
|
-
// 加载环境配置
|
|
52
|
-
const envConfig = dotenv.config().parsed || {};
|
|
53
|
-
const dbUser = envConfig.POSTGRES_USER || 'postgres';
|
|
54
|
-
const dbName = envConfig.POSTGRES_DB || 'nodebbs';
|
|
55
|
-
const dbPassword = envConfig.POSTGRES_PASSWORD;
|
|
56
|
-
// 5. 构建 Compose 参数
|
|
57
75
|
const composeArgs = files.flatMap(f => ['-f', f]);
|
|
58
76
|
if (isBuiltIn) {
|
|
59
77
|
composeArgs.push('--project-directory', process.cwd());
|
|
60
78
|
}
|
|
61
|
-
//
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
}
|
|
69
|
-
importArgs.push('postgres', 'psql', '-U', dbUser, '-d', dbName);
|
|
79
|
+
// 加载环境配置获取数据库信息 (用于可能的连接参数,虽然 docker exec 默认用 postgres 用户通常足够)
|
|
80
|
+
const envConfig = dotenv.config().parsed || {};
|
|
81
|
+
const dbUser = envConfig.POSTGRES_USER || 'postgres';
|
|
82
|
+
const dbName = envConfig.POSTGRES_DB || 'nodebbs';
|
|
83
|
+
const dbPassword = envConfig.POSTGRES_PASSWORD;
|
|
84
|
+
// 5. 执行恢复
|
|
85
|
+
logger.info('正在准备恢复数据库...');
|
|
70
86
|
try {
|
|
71
|
-
|
|
87
|
+
// 步骤 A: 重置 Schema (Drop & Create public)
|
|
88
|
+
// 这样做比单纯导入更干净,因为 pg_dump 默认可能不包含 DROP TABLE
|
|
89
|
+
logger.info('正在重置数据库 Schema...');
|
|
90
|
+
const resetCmd = [...composeArgs, 'exec', '-T', 'postgres', 'psql', '-U', dbUser, '-d', dbName, '-c', 'DROP SCHEMA public CASCADE; CREATE SCHEMA public;'];
|
|
91
|
+
// 如果有密码
|
|
92
|
+
const envs = process.env;
|
|
93
|
+
if (dbPassword)
|
|
94
|
+
envs.PGPASSWORD = dbPassword;
|
|
95
|
+
await execa('docker', ['compose', ...resetCmd], { env: envs });
|
|
96
|
+
logger.success('数据库 Schema 已重置');
|
|
97
|
+
// 步骤 B: 导入数据
|
|
98
|
+
logger.info(`正在导入数据 from ${path.basename(inputPath)}...`);
|
|
99
|
+
const importCmd = [...composeArgs, 'exec', '-T', 'postgres', 'psql', '-U', dbUser, '-d', dbName];
|
|
100
|
+
const subprocess = execa('docker', ['compose', ...importCmd], {
|
|
101
|
+
env: envs,
|
|
72
102
|
input: fs.createReadStream(inputPath)
|
|
73
103
|
});
|
|
74
|
-
// subprocess.stdout?.pipe(process.stdout)
|
|
75
|
-
// subprocess.stderr?.pipe(process.stderr)
|
|
76
104
|
await subprocess;
|
|
77
105
|
logger.success('数据库导入成功!');
|
|
78
106
|
}
|