befly 3.9.11 → 3.9.13

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/docs/config.md ADDED
@@ -0,0 +1,638 @@
1
+ # 配置系统指南
2
+
3
+ > 本文档详细介绍 Befly 框架的配置系统,包括配置文件结构、加载优先级、配置项说明及最佳实践。
4
+
5
+ ## 目录
6
+
7
+ - [配置系统指南](#配置系统指南)
8
+ - [目录](#目录)
9
+ - [概述](#概述)
10
+ - [核心特性](#核心特性)
11
+ - [配置文件结构](#配置文件结构)
12
+ - [文件位置](#文件位置)
13
+ - [加载优先级](#加载优先级)
14
+ - [合并规则](#合并规则)
15
+ - [配置项说明](#配置项说明)
16
+ - [核心参数](#核心参数)
17
+ - [日志配置 (logger)](#日志配置-logger)
18
+ - [数据库配置 (db)](#数据库配置-db)
19
+ - [Redis 配置 (redis)](#redis-配置-redis)
20
+ - [认证配置 (auth)](#认证配置-auth)
21
+ - [CORS 配置 (cors)](#cors-配置-cors)
22
+ - [禁用配置](#禁用配置)
23
+ - [Addon 配置 (addons)](#addon-配置-addons)
24
+ - [环境变量](#环境变量)
25
+ - [完整配置示例](#完整配置示例)
26
+ - [befly.common.json](#beflycmmonjson)
27
+ - [befly.dev.json](#befldevjson)
28
+ - [befly.prod.json](#beflprodjson)
29
+ - [befly.local.json](#befllocaljson)
30
+ - [访问配置](#访问配置)
31
+ - [最佳实践](#最佳实践)
32
+ - [常见问题](#常见问题)
33
+
34
+ ---
35
+
36
+ ## 概述
37
+
38
+ Befly 配置系统采用分层配置设计,支持环境分离和本地覆盖,所有配置文件使用 JSON 格式。
39
+
40
+ ### 核心特性
41
+
42
+ - **分层配置**:支持通用配置 + 环境配置 + 本地配置
43
+ - **环境分离**:自动根据 NODE_ENV 加载对应环境配置
44
+ - **深度合并**:配置项支持深度合并,后加载的覆盖先加载的
45
+ - **默认值**:所有配置项都有合理的默认值
46
+ - **类型安全**:完整的 TypeScript 类型定义
47
+
48
+ ---
49
+
50
+ ## 配置文件结构
51
+
52
+ ### 文件位置
53
+
54
+ 配置文件存放在项目根目录的 `configs/` 目录下:
55
+
56
+ ```
57
+ 项目根目录/
58
+ └── configs/
59
+ ├── befly.common.json # 通用配置(所有环境共享)
60
+ ├── befly.dev.json # 开发环境配置
61
+ ├── befly.prod.json # 生产环境配置
62
+ └── befly.local.json # 本地配置(不提交到 Git)
63
+ ```
64
+
65
+ ### 加载优先级
66
+
67
+ 配置按以下顺序加载,后加载的覆盖先加载的:
68
+
69
+ ```
70
+ 默认配置(代码内置)
71
+
72
+ befly.common.json(通用配置)
73
+
74
+ befly.dev.json 或 befly.prod.json(环境配置)
75
+
76
+ befly.local.json(本地配置,最高优先级)
77
+ ```
78
+
79
+ **环境判断**:
80
+
81
+ - `NODE_ENV=production` → 加载 `befly.prod.json`
82
+ - 其他情况 → 加载 `befly.dev.json`
83
+
84
+ ### 合并规则
85
+
86
+ 配置采用深度合并策略:
87
+
88
+ ```json
89
+ // befly.common.json
90
+ {
91
+ "db": {
92
+ "host": "127.0.0.1",
93
+ "port": 3306,
94
+ "database": "befly"
95
+ }
96
+ }
97
+
98
+ // befly.local.json
99
+ {
100
+ "db": {
101
+ "password": "local_password"
102
+ }
103
+ }
104
+
105
+ // 最终配置
106
+ {
107
+ "db": {
108
+ "host": "127.0.0.1", // 来自 common
109
+ "port": 3306, // 来自 common
110
+ "database": "befly", // 来自 common
111
+ "password": "local_password" // 来自 local(覆盖默认值)
112
+ }
113
+ }
114
+ ```
115
+
116
+ ---
117
+
118
+ ## 配置项说明
119
+
120
+ ### 核心参数
121
+
122
+ | 配置项 | 类型 | 默认值 | 说明 |
123
+ | ------------- | ------ | ----------------- | --------------------------- |
124
+ | `nodeEnv` | string | `'development'` | 运行环境 |
125
+ | `appName` | string | `'野蜂飞舞'` | 应用名称 |
126
+ | `appPort` | number | `3000` | 应用端口 |
127
+ | `appHost` | string | `'127.0.0.1'` | 应用主机 |
128
+ | `devEmail` | string | `'dev@qq.com'` | 开发者邮箱(syncDev 使用) |
129
+ | `devPassword` | string | - | 开发者密码(syncDev 使用) |
130
+ | `bodyLimit` | number | `1048576` | 请求体大小限制(字节,1MB) |
131
+ | `tz` | string | `'Asia/Shanghai'` | 时区 |
132
+
133
+ ```json
134
+ {
135
+ "appName": "我的应用",
136
+ "appPort": 8080,
137
+ "appHost": "0.0.0.0",
138
+ "bodyLimit": 5242880
139
+ }
140
+ ```
141
+
142
+ ---
143
+
144
+ ### 日志配置 (logger)
145
+
146
+ | 配置项 | 类型 | 默认值 | 说明 |
147
+ | --------------- | ------ | ------------------------- | ------------------------------------ |
148
+ | `debug` | number | `1` | 是否开启调试模式(0: 关闭, 1: 开启) |
149
+ | `excludeFields` | string | `'password,token,secret'` | 日志中排除的敏感字段 |
150
+ | `dir` | string | `'./logs'` | 日志文件目录 |
151
+ | `console` | number | `1` | 是否输出到控制台(0: 关闭, 1: 开启) |
152
+ | `maxSize` | number | `10485760` | 单个日志文件最大大小(字节,10MB) |
153
+
154
+ ```json
155
+ {
156
+ "logger": {
157
+ "debug": 0,
158
+ "excludeFields": "password,token,secret,apiKey",
159
+ "dir": "/var/log/befly",
160
+ "console": 0,
161
+ "maxSize": 52428800
162
+ }
163
+ }
164
+ ```
165
+
166
+ ---
167
+
168
+ ### 数据库配置 (db)
169
+
170
+ | 配置项 | 类型 | 默认值 | 说明 |
171
+ | ---------- | ------ | -------------- | ----------------------------------- |
172
+ | `type` | string | `'mysql'` | 数据库类型(mysql/postgres/sqlite) |
173
+ | `host` | string | `'127.0.0.1'` | 数据库主机 |
174
+ | `port` | number | `3306` | 数据库端口 |
175
+ | `username` | string | `'root'` | 数据库用户名 |
176
+ | `password` | string | `'root'` | 数据库密码 |
177
+ | `database` | string | `'befly_demo'` | 数据库名称 |
178
+ | `poolMax` | number | `10` | 连接池最大连接数 |
179
+
180
+ ```json
181
+ {
182
+ "db": {
183
+ "type": "mysql",
184
+ "host": "localhost",
185
+ "port": 3306,
186
+ "username": "befly",
187
+ "password": "your_password",
188
+ "database": "befly_prod",
189
+ "poolMax": 20
190
+ }
191
+ }
192
+ ```
193
+
194
+ **PostgreSQL 配置**:
195
+
196
+ ```json
197
+ {
198
+ "db": {
199
+ "type": "postgres",
200
+ "host": "localhost",
201
+ "port": 5432,
202
+ "username": "postgres",
203
+ "password": "your_password",
204
+ "database": "befly_prod"
205
+ }
206
+ }
207
+ ```
208
+
209
+ ---
210
+
211
+ ### Redis 配置 (redis)
212
+
213
+ | 配置项 | 类型 | 默认值 | 说明 |
214
+ | ---------- | ------ | --------------- | ---------------- |
215
+ | `host` | string | `'127.0.0.1'` | Redis 主机 |
216
+ | `port` | number | `6379` | Redis 端口 |
217
+ | `username` | string | `''` | Redis 用户名 |
218
+ | `password` | string | `''` | Redis 密码 |
219
+ | `db` | number | `0` | Redis 数据库索引 |
220
+ | `prefix` | string | `'befly_demo:'` | Redis Key 前缀 |
221
+
222
+ ```json
223
+ {
224
+ "redis": {
225
+ "host": "localhost",
226
+ "port": 6379,
227
+ "password": "redis_password",
228
+ "db": 1,
229
+ "prefix": "myapp:"
230
+ }
231
+ }
232
+ ```
233
+
234
+ ---
235
+
236
+ ### 认证配置 (auth)
237
+
238
+ | 配置项 | 类型 | 默认值 | 说明 |
239
+ | ----------- | ------------- | ---------------- | -------------- |
240
+ | `secret` | string | `'befly-secret'` | JWT 密钥 |
241
+ | `expiresIn` | string/number | `'7d'` | Token 过期时间 |
242
+ | `algorithm` | string | `'HS256'` | 签名算法 |
243
+
244
+ ```json
245
+ {
246
+ "auth": {
247
+ "secret": "your-super-secret-key-at-least-32-chars",
248
+ "expiresIn": "30d",
249
+ "algorithm": "HS256"
250
+ }
251
+ }
252
+ ```
253
+
254
+ **过期时间格式**:
255
+
256
+ - 字符串:`'7d'`(7天)、`'24h'`(24小时)、`'60m'`(60分钟)
257
+ - 数字:秒数,如 `604800`(7天)
258
+
259
+ ---
260
+
261
+ ### CORS 配置 (cors)
262
+
263
+ | 配置项 | 类型 | 默认值 | 说明 |
264
+ | ---------------- | ------ | ---------------------------------- | ---------------------- |
265
+ | `origin` | string | `'*'` | 允许的来源 |
266
+ | `methods` | string | `'GET,HEAD,PUT,PATCH,POST,DELETE'` | 允许的方法 |
267
+ | `allowedHeaders` | string | `'Content-Type,Authorization'` | 允许的请求头 |
268
+ | `exposedHeaders` | string | `''` | 暴露的响应头 |
269
+ | `maxAge` | number | `86400` | 预检请求缓存时间(秒) |
270
+ | `credentials` | string | `'true'` | 是否允许凭证 |
271
+
272
+ ```json
273
+ {
274
+ "cors": {
275
+ "origin": "https://example.com",
276
+ "methods": "GET,POST",
277
+ "allowedHeaders": "Content-Type,Authorization,X-Custom-Header",
278
+ "credentials": "true"
279
+ }
280
+ }
281
+ ```
282
+
283
+ **多域名配置**:
284
+
285
+ ```json
286
+ {
287
+ "cors": {
288
+ "origin": "https://app.example.com,https://admin.example.com"
289
+ }
290
+ }
291
+ ```
292
+
293
+ ---
294
+
295
+ ### 禁用配置
296
+
297
+ | 配置项 | 类型 | 默认值 | 说明 |
298
+ | ---------------- | -------- | ------ | -------------- |
299
+ | `disableHooks` | string[] | `[]` | 禁用的钩子列表 |
300
+ | `disablePlugins` | string[] | `[]` | 禁用的插件列表 |
301
+ | `hiddenMenus` | string[] | `[]` | 隐藏的菜单路径 |
302
+
303
+ ```json
304
+ {
305
+ "disableHooks": ["requestLogger"],
306
+ "disablePlugins": ["redis"],
307
+ "hiddenMenus": ["/admin/debug", "/admin/test"]
308
+ }
309
+ ```
310
+
311
+ ---
312
+
313
+ ### Addon 配置 (addons)
314
+
315
+ Addon 运行时配置按 Addon 名称分组:
316
+
317
+ ```json
318
+ {
319
+ "addons": {
320
+ "admin": {
321
+ "email": {
322
+ "host": "smtp.qq.com",
323
+ "port": 465,
324
+ "secure": true,
325
+ "user": "your-email@qq.com",
326
+ "pass": "your-auth-code",
327
+ "fromName": "系统通知"
328
+ }
329
+ },
330
+ "pay": {
331
+ "wechat": {
332
+ "appId": "wx1234567890",
333
+ "mchId": "1234567890",
334
+ "apiKey": "your-api-key"
335
+ }
336
+ }
337
+ }
338
+ }
339
+ ```
340
+
341
+ **在插件中访问**:
342
+
343
+ ```typescript
344
+ const emailConfig = befly.config?.addons?.admin?.email || {};
345
+ const wechatConfig = befly.config?.addons?.pay?.wechat || {};
346
+ ```
347
+
348
+ ---
349
+
350
+ ## 环境变量
351
+
352
+ 支持通过环境变量覆盖部分配置:
353
+
354
+ | 环境变量 | 对应配置 | 说明 |
355
+ | ---------- | --------- | -------- |
356
+ | `NODE_ENV` | `nodeEnv` | 运行环境 |
357
+
358
+ ```bash
359
+ # 启动生产环境
360
+ NODE_ENV=production bun run start
361
+ ```
362
+
363
+ ---
364
+
365
+ ## 完整配置示例
366
+
367
+ ### befly.common.json
368
+
369
+ 所有环境共享的配置:
370
+
371
+ ```json
372
+ {
373
+ "appName": "我的应用",
374
+ "bodyLimit": 5242880,
375
+ "tz": "Asia/Shanghai",
376
+
377
+ "logger": {
378
+ "excludeFields": "password,token,secret,apiKey"
379
+ },
380
+
381
+ "db": {
382
+ "type": "mysql",
383
+ "database": "myapp"
384
+ },
385
+
386
+ "redis": {
387
+ "prefix": "myapp:"
388
+ },
389
+
390
+ "cors": {
391
+ "allowedHeaders": "Content-Type,Authorization,X-Request-ID"
392
+ }
393
+ }
394
+ ```
395
+
396
+ ### befly.dev.json
397
+
398
+ 开发环境配置:
399
+
400
+ ```json
401
+ {
402
+ "appPort": 3000,
403
+
404
+ "logger": {
405
+ "debug": 1,
406
+ "console": 1
407
+ },
408
+
409
+ "db": {
410
+ "host": "localhost",
411
+ "username": "root",
412
+ "password": "root"
413
+ },
414
+
415
+ "redis": {
416
+ "host": "localhost"
417
+ }
418
+ }
419
+ ```
420
+
421
+ ### befly.prod.json
422
+
423
+ 生产环境配置:
424
+
425
+ ```json
426
+ {
427
+ "appPort": 8080,
428
+ "appHost": "0.0.0.0",
429
+
430
+ "logger": {
431
+ "debug": 0,
432
+ "console": 0,
433
+ "dir": "/var/log/myapp"
434
+ },
435
+
436
+ "auth": {
437
+ "expiresIn": "7d"
438
+ },
439
+
440
+ "cors": {
441
+ "origin": "https://myapp.com"
442
+ }
443
+ }
444
+ ```
445
+
446
+ ### befly.local.json
447
+
448
+ 本地配置(不提交到 Git):
449
+
450
+ ```json
451
+ {
452
+ "db": {
453
+ "password": "my_local_password"
454
+ },
455
+
456
+ "redis": {
457
+ "password": "my_redis_password"
458
+ },
459
+
460
+ "auth": {
461
+ "secret": "my-super-secret-key-for-local-development"
462
+ },
463
+
464
+ "addons": {
465
+ "admin": {
466
+ "email": {
467
+ "user": "my-email@qq.com",
468
+ "pass": "my-auth-code"
469
+ }
470
+ }
471
+ }
472
+ }
473
+ ```
474
+
475
+ **注意**:将 `befly.local.json` 添加到 `.gitignore`:
476
+
477
+ ```gitignore
478
+ # 本地配置
479
+ configs/befly.local.json
480
+ ```
481
+
482
+ ---
483
+
484
+ ## 访问配置
485
+
486
+ ### 在 API 中访问
487
+
488
+ ```typescript
489
+ export default {
490
+ name: '示例接口',
491
+ handler: async (befly, ctx) => {
492
+ // 通过 befly.config 访问配置
493
+ const appName = befly.config.appName;
494
+ const dbType = befly.config.db?.type;
495
+ const jwtSecret = befly.config.auth?.secret;
496
+
497
+ // 访问 Addon 配置
498
+ const emailConfig = befly.config.addons?.admin?.email;
499
+
500
+ return befly.tool.Yes('成功', { appName: appName });
501
+ }
502
+ };
503
+ ```
504
+
505
+ ### 在插件中访问
506
+
507
+ ```typescript
508
+ import { beflyConfig } from '../befly.config.js';
509
+
510
+ const plugin: Plugin = {
511
+ handler: () => {
512
+ const port = beflyConfig.appPort;
513
+ const dbConfig = beflyConfig.db;
514
+ // ...
515
+ }
516
+ };
517
+ ```
518
+
519
+ ### 直接导入
520
+
521
+ ```typescript
522
+ import { beflyConfig } from 'befly-core/befly.config';
523
+
524
+ console.log(beflyConfig.appName);
525
+ ```
526
+
527
+ ---
528
+
529
+ ## 最佳实践
530
+
531
+ ### 1. 敏感信息放 local 配置
532
+
533
+ ```json
534
+ // ✅ befly.local.json(不提交)
535
+ {
536
+ "db": { "password": "real_password" },
537
+ "auth": { "secret": "real_secret" },
538
+ "redis": { "password": "real_password" }
539
+ }
540
+
541
+ // ❌ befly.common.json(会提交)
542
+ {
543
+ "db": { "password": "real_password" }
544
+ }
545
+ ```
546
+
547
+ ### 2. 环境差异放环境配置
548
+
549
+ ```json
550
+ // befly.dev.json
551
+ {
552
+ "logger": { "debug": 1, "console": 1 }
553
+ }
554
+
555
+ // befly.prod.json
556
+ {
557
+ "logger": { "debug": 0, "console": 0 }
558
+ }
559
+ ```
560
+
561
+ ### 3. 使用合理的默认值
562
+
563
+ 框架已提供合理的默认值,只需覆盖需要修改的配置项。
564
+
565
+ ### 4. JWT 密钥长度
566
+
567
+ ```json
568
+ // ✅ 推荐:至少 32 字符
569
+ {
570
+ "auth": {
571
+ "secret": "your-super-secret-key-at-least-32-chars-long"
572
+ }
573
+ }
574
+
575
+ // ❌ 避免:过短的密钥
576
+ {
577
+ "auth": {
578
+ "secret": "123456"
579
+ }
580
+ }
581
+ ```
582
+
583
+ ### 5. 生产环境关闭调试
584
+
585
+ ```json
586
+ // befly.prod.json
587
+ {
588
+ "logger": {
589
+ "debug": 0,
590
+ "console": 0
591
+ }
592
+ }
593
+ ```
594
+
595
+ ---
596
+
597
+ ## 常见问题
598
+
599
+ ### Q1: 配置文件不生效?
600
+
601
+ 1. 检查文件位置是否正确(`configs/` 目录)
602
+ 2. 检查 JSON 格式是否正确
603
+ 3. 检查配置项名称是否正确(区分大小写)
604
+ 4. 重启应用使配置生效
605
+
606
+ ### Q2: 如何查看最终配置?
607
+
608
+ ```typescript
609
+ // 在 API 中打印
610
+ befly.logger.info({ config: befly.config }, '当前配置');
611
+ ```
612
+
613
+ ### Q3: local 配置被提交了?
614
+
615
+ 添加到 `.gitignore`:
616
+
617
+ ```gitignore
618
+ configs/befly.local.json
619
+ ```
620
+
621
+ ### Q4: 如何动态修改配置?
622
+
623
+ 配置在应用启动时加载,不支持运行时动态修改。如需动态配置,建议使用数据库或 Redis 存储。
624
+
625
+ ### Q5: 数组配置如何合并?
626
+
627
+ 数组配置是覆盖而非合并:
628
+
629
+ ```json
630
+ // befly.common.json
631
+ { "disableHooks": ["hook1"] }
632
+
633
+ // befly.local.json
634
+ { "disableHooks": ["hook2"] }
635
+
636
+ // 最终结果
637
+ { "disableHooks": ["hook2"] } // 覆盖,不是合并
638
+ ```