schema-dsl 1.1.0 → 1.1.1
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/CHANGELOG.md +131 -11
- package/README.md +244 -271
- package/STATUS.md +65 -3
- package/docs/conditional-api.md +257 -11
- package/examples/i18n-error.examples.js +181 -0
- package/index.d.ts +324 -1
- package/index.js +35 -2
- package/lib/core/ConditionalBuilder.js +115 -13
- package/lib/core/Validator.js +7 -3
- package/lib/errors/I18nError.js +222 -0
- package/lib/locales/en-US.js +25 -0
- package/lib/locales/zh-CN.js +25 -0
- package/package.json +1 -1
package/docs/conditional-api.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# 链式条件 API - ConditionalBuilder
|
|
2
2
|
|
|
3
|
-
> **版本**: v1.1.
|
|
4
|
-
> **更新日期**: 2026-01-
|
|
3
|
+
> **版本**: v1.1.1
|
|
4
|
+
> **更新日期**: 2026-01-06
|
|
5
5
|
> **状态**: ✅ 稳定
|
|
6
6
|
|
|
7
7
|
---
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
## 📋 目录
|
|
10
10
|
|
|
11
11
|
- [概述](#概述)
|
|
12
|
+
- [🆕 v1.1.1 新功能](#-v110-新功能)
|
|
12
13
|
- [快速开始](#快速开始)
|
|
13
14
|
- [API 参考](#api-参考)
|
|
14
15
|
- [使用场景](#使用场景)
|
|
@@ -26,11 +27,153 @@
|
|
|
26
27
|
- ✅ **链式调用** - 流畅的 API,类似 JavaScript if-else
|
|
27
28
|
- ✅ **运行时执行** - 在验证时根据实际数据判断
|
|
28
29
|
- ✅ **多条件组合** - 支持 and/or 逻辑组合
|
|
30
|
+
- ✅ **🆕 独立消息** - v1.1.1+ 每个 .and()/.or() 可有独立错误消息
|
|
29
31
|
- ✅ **else 可选** - 不写 else 就不验证
|
|
30
32
|
- ✅ **简化设计** - message 自动抛错,无需 throwError()
|
|
31
33
|
- ✅ **完全兼容** - 不影响现有 API
|
|
32
34
|
|
|
33
|
-
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## 🆕 v1.1.1 新功能
|
|
38
|
+
|
|
39
|
+
### 独立消息支持 - `.and()/.or()` 后可调用 `.message()`
|
|
40
|
+
|
|
41
|
+
**每个条件都可以有自己的错误消息**
|
|
42
|
+
|
|
43
|
+
v1.1.1 开始,支持在 `.and()` 和 `.or()` 后调用 `.message()` 设置独立的错误消息,让错误提示更精确。
|
|
44
|
+
|
|
45
|
+
#### 基础用法
|
|
46
|
+
|
|
47
|
+
```javascript
|
|
48
|
+
const { dsl } = require('schema-dsl');
|
|
49
|
+
|
|
50
|
+
// ✅ v1.1.1+ 新功能:每个条件独立消息
|
|
51
|
+
dsl.if(d => !d)
|
|
52
|
+
.message('ACCOUNT_NOT_FOUND')
|
|
53
|
+
.and(d => d.tradable_credits < amount)
|
|
54
|
+
.message('INSUFFICIENT_TRADABLE_CREDITS')
|
|
55
|
+
.assert(account);
|
|
56
|
+
|
|
57
|
+
// 工作原理:
|
|
58
|
+
// - 第一个条件为 true → 返回 'ACCOUNT_NOT_FOUND'
|
|
59
|
+
// - 第二个条件为 true → 返回 'INSUFFICIENT_TRADABLE_CREDITS'
|
|
60
|
+
// - 所有条件为 false → 验证成功
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
#### 多个 .and() 条件
|
|
64
|
+
|
|
65
|
+
```javascript
|
|
66
|
+
// 多层验证,每层都有清晰的错误消息
|
|
67
|
+
dsl.if(d => !d)
|
|
68
|
+
.message('ACCOUNT_NOT_FOUND')
|
|
69
|
+
.and(d => d.status !== 'active')
|
|
70
|
+
.message('ACCOUNT_INACTIVE')
|
|
71
|
+
.and(d => d.tradable_credits < amount)
|
|
72
|
+
.message('INSUFFICIENT_TRADABLE_CREDITS')
|
|
73
|
+
.assert(account);
|
|
74
|
+
|
|
75
|
+
// 依次检查,第一个为 true 的条件返回其消息
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
#### .or() 条件独立消息
|
|
79
|
+
|
|
80
|
+
```javascript
|
|
81
|
+
// OR 条件也支持独立消息
|
|
82
|
+
dsl.if(d => d.age < 18)
|
|
83
|
+
.message('未成年用户不能注册')
|
|
84
|
+
.or(d => d.isBlocked)
|
|
85
|
+
.message('账户已被封禁')
|
|
86
|
+
.assert(data);
|
|
87
|
+
|
|
88
|
+
// 任一条件为 true 就失败,返回对应消息
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
#### 链式检查模式
|
|
92
|
+
|
|
93
|
+
v1.1.1 引入了**链式检查模式**,当满足以下条件时自动启用:
|
|
94
|
+
|
|
95
|
+
1. 使用 `.message()` 模式(不是 `.then()`/`.else()`)
|
|
96
|
+
2. root 条件有 `.message()`
|
|
97
|
+
3. 有 `.and()` 条件
|
|
98
|
+
4. 没有 `.or()` 条件
|
|
99
|
+
|
|
100
|
+
**链式检查模式特点**:
|
|
101
|
+
- 依次检查每个条件
|
|
102
|
+
- 第一个为 `true` 的条件失败,返回其消息
|
|
103
|
+
- 所有条件为 `false` 时验证通过
|
|
104
|
+
|
|
105
|
+
**示例对比**:
|
|
106
|
+
|
|
107
|
+
```javascript
|
|
108
|
+
// ✅ 启用链式检查(纯 AND 场景)
|
|
109
|
+
dsl.if(d => !d).message('A').and(d => d < 100).message('B')
|
|
110
|
+
|
|
111
|
+
// ❌ 不启用(有 .or(),使用传统 AND/OR 逻辑)
|
|
112
|
+
dsl.if(d => !d).message('A').and(d => d < 100).or(d => d > 200).message('B')
|
|
113
|
+
|
|
114
|
+
// ❌ 不启用(使用 .then()/.else(),不是 message 模式)
|
|
115
|
+
dsl.if(d => d.age >= 18).and(d => d.role === 'admin').then('email!')
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
#### 向后兼容性
|
|
119
|
+
|
|
120
|
+
**100% 向后兼容**,不影响现有代码:
|
|
121
|
+
|
|
122
|
+
```javascript
|
|
123
|
+
// ✅ 原有用法继续工作
|
|
124
|
+
dsl.if(d => d.age >= 18).and(d => d.role === 'admin').message('不符合条件')
|
|
125
|
+
|
|
126
|
+
// ✅ .and() 后不调用 .message() 也可以
|
|
127
|
+
dsl.if(d => !d).message('整体错误').and(d => d < 100).assert(50)
|
|
128
|
+
// → 使用整体消息 '整体错误'
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
#### 实际应用场景
|
|
132
|
+
|
|
133
|
+
**场景1:账户验证**
|
|
134
|
+
```javascript
|
|
135
|
+
function validateAccount(account, amount) {
|
|
136
|
+
dsl.if(d => !d)
|
|
137
|
+
.message('ACCOUNT_NOT_FOUND')
|
|
138
|
+
.and(d => d.status !== 'active')
|
|
139
|
+
.message('ACCOUNT_INACTIVE')
|
|
140
|
+
.and(d => d.balance < amount)
|
|
141
|
+
.message('INSUFFICIENT_BALANCE')
|
|
142
|
+
.assert(account);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// 每个失败点都有清晰的错误消息
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
**场景2:用户权限验证**
|
|
149
|
+
```javascript
|
|
150
|
+
function validateUserPermission(user) {
|
|
151
|
+
dsl.if(d => d.role !== 'admin')
|
|
152
|
+
.message('NO_ADMIN_PERMISSION')
|
|
153
|
+
.and(d => !d.isVerified)
|
|
154
|
+
.message('USER_NOT_VERIFIED')
|
|
155
|
+
.and(d => d.isBanned)
|
|
156
|
+
.message('USER_BANNED')
|
|
157
|
+
.assert(user);
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
**场景3:订单状态检查**
|
|
162
|
+
```javascript
|
|
163
|
+
function validateOrder(order) {
|
|
164
|
+
dsl.if(d => d.status !== 'paid')
|
|
165
|
+
.message('ORDER_NOT_PAID')
|
|
166
|
+
.and(d => !d.payment)
|
|
167
|
+
.message('PAYMENT_INFO_MISSING')
|
|
168
|
+
.and(d => !d.shippingAddress)
|
|
169
|
+
.message('SHIPPING_ADDRESS_MISSING')
|
|
170
|
+
.assert(order);
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## 与现有方法的区别
|
|
34
177
|
|
|
35
178
|
`dsl.if()` 提供两种使用方式,根据参数类型自动选择:
|
|
36
179
|
|
|
@@ -180,19 +323,59 @@ dsl.if((data) => data.status === 'active' && data.verified)
|
|
|
180
323
|
|
|
181
324
|
添加 AND 条件(与前一个条件组合)。
|
|
182
325
|
|
|
326
|
+
> **v1.1.1+** 支持在 `.and()` 后调用 `.message()` 设置独立的错误消息
|
|
327
|
+
|
|
183
328
|
**参数**:
|
|
184
329
|
- `condition` {Function} - 条件函数
|
|
185
330
|
|
|
186
331
|
**返回**: `this` - 支持链式调用
|
|
187
332
|
|
|
188
|
-
|
|
333
|
+
**基础示例**:
|
|
189
334
|
```javascript
|
|
335
|
+
// 传统用法:所有条件共享一个消息
|
|
190
336
|
dsl.if((data) => data.age >= 18)
|
|
191
337
|
.and((data) => data.userType === 'admin')
|
|
192
|
-
.
|
|
338
|
+
.message('不符合条件')
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
**v1.1.1+ 独立消息**:
|
|
342
|
+
```javascript
|
|
343
|
+
// ✅ 每个条件都有自己的错误消息
|
|
344
|
+
dsl.if((data) => !data)
|
|
345
|
+
.message('账户不存在')
|
|
346
|
+
.and((data) => data.balance < 100)
|
|
347
|
+
.message('余额不足')
|
|
348
|
+
.assert(account);
|
|
349
|
+
|
|
350
|
+
// 工作原理:
|
|
351
|
+
// - 第一个条件为 true → 返回 '账户不存在'
|
|
352
|
+
// - 第二个条件为 true → 返回 '余额不足'
|
|
353
|
+
// - 所有条件为 false → 验证成功
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
**多个 .and() 条件**:
|
|
357
|
+
```javascript
|
|
358
|
+
// 支持多个 .and() 条件,每个都有独立消息
|
|
359
|
+
dsl.if(d => !d)
|
|
360
|
+
.message('NOT_FOUND')
|
|
361
|
+
.and(d => d.status !== 'active')
|
|
362
|
+
.message('INACTIVE')
|
|
363
|
+
.and(d => d.balance < 100)
|
|
364
|
+
.message('INSUFFICIENT')
|
|
365
|
+
.assert(account);
|
|
366
|
+
|
|
367
|
+
// 依次检查,第一个为 true 的条件返回其消息
|
|
193
368
|
```
|
|
194
369
|
|
|
195
|
-
**逻辑**:
|
|
370
|
+
**逻辑**:
|
|
371
|
+
- 传统模式:`(condition1 AND condition2)` - 所有条件为 true 才失败
|
|
372
|
+
- 链式检查模式 (v1.1.1+):依次检查,第一个为 true 的失败
|
|
373
|
+
|
|
374
|
+
**链式检查模式触发条件**:
|
|
375
|
+
1. 使用 `.message()` 模式
|
|
376
|
+
2. root 条件有 `.message()`
|
|
377
|
+
3. 有 `.and()` 条件
|
|
378
|
+
4. 没有 `.or()` 条件
|
|
196
379
|
|
|
197
380
|
---
|
|
198
381
|
|
|
@@ -200,19 +383,41 @@ dsl.if((data) => data.age >= 18)
|
|
|
200
383
|
|
|
201
384
|
添加 OR 条件(与前一个条件组合)。
|
|
202
385
|
|
|
386
|
+
> **v1.1.1+** 支持在 `.or()` 后调用 `.message()` 设置独立的错误消息
|
|
387
|
+
|
|
203
388
|
**参数**:
|
|
204
389
|
- `condition` {Function} - 条件函数
|
|
205
390
|
|
|
206
391
|
**返回**: `this` - 支持链式调用
|
|
207
392
|
|
|
208
|
-
|
|
393
|
+
**基础示例**:
|
|
209
394
|
```javascript
|
|
395
|
+
// 传统用法:所有条件共享一个消息
|
|
210
396
|
dsl.if((data) => data.age < 18)
|
|
211
397
|
.or((data) => data.status === 'blocked')
|
|
212
398
|
.message('不允许注册')
|
|
213
399
|
```
|
|
214
400
|
|
|
215
|
-
|
|
401
|
+
**v1.1.1+ 独立消息**:
|
|
402
|
+
```javascript
|
|
403
|
+
// ✅ 每个 OR 条件都有自己的错误消息
|
|
404
|
+
dsl.if(d => d.age < 18)
|
|
405
|
+
.message('未成年用户不能注册')
|
|
406
|
+
.or(d => d.isBlocked)
|
|
407
|
+
.message('账户已被封禁')
|
|
408
|
+
.assert(data);
|
|
409
|
+
|
|
410
|
+
// 工作原理:
|
|
411
|
+
// - 第一个条件为 true → 返回 '未成年用户不能注册'
|
|
412
|
+
// - 第二个条件为 true → 返回 '账户已被封禁'
|
|
413
|
+
// - 所有条件为 false → 验证成功
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
**逻辑**: `(condition1 OR condition2)` - 任一条件为 true 就失败
|
|
417
|
+
|
|
418
|
+
**注意**:
|
|
419
|
+
- 如果有 `.or()` 条件,不会启用链式检查模式
|
|
420
|
+
- 使用传统 AND/OR 组合逻辑
|
|
216
421
|
|
|
217
422
|
---
|
|
218
423
|
|
|
@@ -242,14 +447,16 @@ dsl.if((data) => data.userType === 'admin')
|
|
|
242
447
|
|
|
243
448
|
设置错误消息(支持多语言 key)。
|
|
244
449
|
|
|
450
|
+
> **v1.1.1+** 支持为 `.and()` 和 `.or()` 条件设置独立消息
|
|
451
|
+
|
|
245
452
|
**参数**:
|
|
246
453
|
- `msg` {string} - 错误消息或多语言 key
|
|
247
454
|
|
|
248
455
|
**返回**: `this` - 支持链式调用
|
|
249
456
|
|
|
250
|
-
**行为**:
|
|
457
|
+
**行为**: 条件为 true 时自动抛出此错误(无需 `.throwError()`)
|
|
251
458
|
|
|
252
|
-
|
|
459
|
+
**基础示例**:
|
|
253
460
|
```javascript
|
|
254
461
|
dsl.if((data) => data.age >= 18)
|
|
255
462
|
.message('未成年用户不能注册')
|
|
@@ -259,6 +466,45 @@ dsl.if((data) => data.age >= 18)
|
|
|
259
466
|
.message('error.underage')
|
|
260
467
|
```
|
|
261
468
|
|
|
469
|
+
**v1.1.1+ 为 .and() 设置独立消息**:
|
|
470
|
+
```javascript
|
|
471
|
+
// ✅ 每个条件都有自己的错误消息
|
|
472
|
+
dsl.if((data) => !data)
|
|
473
|
+
.message('账户不存在')
|
|
474
|
+
.and((data) => data.balance < 100)
|
|
475
|
+
.message('余额不足')
|
|
476
|
+
.assert(account);
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
**v1.1.1+ 为 .or() 设置独立消息**:
|
|
480
|
+
```javascript
|
|
481
|
+
// ✅ OR 条件也支持独立消息
|
|
482
|
+
dsl.if(d => d.age < 18)
|
|
483
|
+
.message('未成年')
|
|
484
|
+
.or(d => d.isBlocked)
|
|
485
|
+
.message('已封禁')
|
|
486
|
+
.assert(data);
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
**链式检查模式说明** (v1.1.1+):
|
|
490
|
+
|
|
491
|
+
当满足以下条件时,自动启用链式检查模式:
|
|
492
|
+
1. 使用 `.message()` 模式(不是 `.then()`/`.else()`)
|
|
493
|
+
2. root 条件有 `.message()`
|
|
494
|
+
3. 有 `.and()` 条件
|
|
495
|
+
4. 没有 `.or()` 条件
|
|
496
|
+
|
|
497
|
+
```javascript
|
|
498
|
+
// ✅ 启用链式检查(纯 AND 场景)
|
|
499
|
+
dsl.if(d => !d).message('A').and(d => d < 100).message('B')
|
|
500
|
+
|
|
501
|
+
// ❌ 不启用(有 .or())
|
|
502
|
+
dsl.if(d => !d).message('A').and(d => d < 100).or(d => d > 200).message('B')
|
|
503
|
+
|
|
504
|
+
// ❌ 不启用(使用 .then()/.else())
|
|
505
|
+
dsl.if(d => d.age >= 18).and(d => d.role === 'admin').then('email!')
|
|
506
|
+
```
|
|
507
|
+
|
|
262
508
|
---
|
|
263
509
|
|
|
264
510
|
### .then(schema)
|
|
@@ -1011,7 +1257,7 @@ validate(contactSchema, '13800138000'); // ✅ 作为手机号验证
|
|
|
1011
1257
|
|
|
1012
1258
|
## 更新日志
|
|
1013
1259
|
|
|
1014
|
-
### v1.1.
|
|
1260
|
+
### v1.1.1 (2026-01-05)
|
|
1015
1261
|
|
|
1016
1262
|
- ✅ 新增 `ConditionalBuilder` 类
|
|
1017
1263
|
- ✅ 新增 `dsl.if()` 链式条件 API
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* I18nError 使用示例
|
|
3
|
+
*
|
|
4
|
+
* 统一的多语言错误抛出机制
|
|
5
|
+
*
|
|
6
|
+
* @version 1.1.1
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const { I18nError, dsl, Locale } = require('../index');
|
|
10
|
+
|
|
11
|
+
console.log('=== I18nError 使用示例 ===\n');
|
|
12
|
+
|
|
13
|
+
// ========== 1. 基础用法 ==========
|
|
14
|
+
console.log('1. 基础用法:');
|
|
15
|
+
try {
|
|
16
|
+
throw I18nError.create('account.notFound');
|
|
17
|
+
} catch (error) {
|
|
18
|
+
console.log('错误:', error.message); // "账户不存在"
|
|
19
|
+
console.log('代码:', error.code); // "account.notFound"
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// ========== 2. 带参数的错误 ==========
|
|
23
|
+
console.log('\n2. 带参数的错误:');
|
|
24
|
+
try {
|
|
25
|
+
throw I18nError.create('account.insufficientBalance', {
|
|
26
|
+
balance: 50,
|
|
27
|
+
required: 100
|
|
28
|
+
});
|
|
29
|
+
} catch (error) {
|
|
30
|
+
console.log('错误:', error.message); // "余额不足,当前余额50,需要100"
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// ========== 3. 使用 throw 方法 ==========
|
|
34
|
+
console.log('\n3. 使用 throw 方法(直接抛错):');
|
|
35
|
+
try {
|
|
36
|
+
I18nError.throw('user.noPermission');
|
|
37
|
+
} catch (error) {
|
|
38
|
+
console.log('错误:', error.message); // "没有管理员权限"
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// ========== 4. 使用 assert 断言 ==========
|
|
42
|
+
console.log('\n4. 使用 assert 断言:');
|
|
43
|
+
const account = { balance: 50 };
|
|
44
|
+
|
|
45
|
+
try {
|
|
46
|
+
I18nError.assert(account.balance >= 100, 'account.insufficientBalance', {
|
|
47
|
+
balance: account.balance,
|
|
48
|
+
required: 100
|
|
49
|
+
});
|
|
50
|
+
} catch (error) {
|
|
51
|
+
console.log('错误:', error.message);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// ========== 5. dsl.error 快捷方法 ==========
|
|
55
|
+
console.log('\n5. dsl.error 快捷方法:');
|
|
56
|
+
try {
|
|
57
|
+
dsl.error.throw('order.notPaid');
|
|
58
|
+
} catch (error) {
|
|
59
|
+
console.log('错误:', error.message); // "订单未支付"
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// ========== 6. 多语言支持 ==========
|
|
63
|
+
console.log('\n6. 多语言支持:');
|
|
64
|
+
try {
|
|
65
|
+
// 中文
|
|
66
|
+
Locale.setLocale('zh-CN');
|
|
67
|
+
throw I18nError.create('account.notFound');
|
|
68
|
+
} catch (error) {
|
|
69
|
+
console.log('中文:', error.message); // "账户不存在"
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
try {
|
|
73
|
+
// 英文
|
|
74
|
+
Locale.setLocale('en-US');
|
|
75
|
+
throw I18nError.create('account.notFound');
|
|
76
|
+
} catch (error) {
|
|
77
|
+
console.log('英文:', error.message); // "Account not found"
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// 恢复中文
|
|
81
|
+
Locale.setLocale('zh-CN');
|
|
82
|
+
|
|
83
|
+
// ========== 7. 实际业务场景 =========
|
|
84
|
+
console.log('\n7. 实际业务场景:');
|
|
85
|
+
|
|
86
|
+
// 场景1:账户验证函数
|
|
87
|
+
function getAccount(id) {
|
|
88
|
+
const account = id === '123' ? { id: '123', balance: 50, status: 'active' } : null;
|
|
89
|
+
|
|
90
|
+
// 断言账户存在
|
|
91
|
+
I18nError.assert(account, 'account.notFound');
|
|
92
|
+
|
|
93
|
+
// 断言账户状态
|
|
94
|
+
I18nError.assert(account.status === 'active', 'account.inactive');
|
|
95
|
+
|
|
96
|
+
// 断言余额充足
|
|
97
|
+
I18nError.assert(
|
|
98
|
+
account.balance >= 100,
|
|
99
|
+
'account.insufficientBalance',
|
|
100
|
+
{ balance: account.balance, required: 100 }
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
return account;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
try {
|
|
107
|
+
getAccount('123');
|
|
108
|
+
} catch (error) {
|
|
109
|
+
console.log('业务错误:', error.message);
|
|
110
|
+
console.log('错误代码:', error.code);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// 场景2:与 dsl.if 结合
|
|
114
|
+
console.log('\n8. 与 dsl.if 结合使用:');
|
|
115
|
+
function validateUser(user) {
|
|
116
|
+
// 使用 dsl.if 进行数据验证
|
|
117
|
+
dsl.if(d => !d)
|
|
118
|
+
.message('user.notFound')
|
|
119
|
+
.and(d => !d.isVerified)
|
|
120
|
+
.message('user.notVerified')
|
|
121
|
+
.assert(user);
|
|
122
|
+
|
|
123
|
+
// 使用 I18nError 进行业务逻辑验证
|
|
124
|
+
I18nError.assert(user.role === 'admin', 'user.noPermission');
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
try {
|
|
128
|
+
validateUser({ isVerified: true, role: 'user' });
|
|
129
|
+
} catch (error) {
|
|
130
|
+
console.log('验证错误:', error.message);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// ========== 9. Express/Koa 中间件 ==========
|
|
134
|
+
console.log('\n9. Express/Koa 错误处理:');
|
|
135
|
+
|
|
136
|
+
// Express 错误处理中间件
|
|
137
|
+
function expressErrorHandler(error, req, res, next) {
|
|
138
|
+
if (error instanceof I18nError) {
|
|
139
|
+
return res.status(error.statusCode).json(error.toJSON());
|
|
140
|
+
}
|
|
141
|
+
next(error);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// 模拟使用
|
|
145
|
+
const mockError = I18nError.create('account.notFound', {}, 404);
|
|
146
|
+
const mockRes = {
|
|
147
|
+
status: (code) => {
|
|
148
|
+
console.log('HTTP Status:', code);
|
|
149
|
+
return mockRes;
|
|
150
|
+
},
|
|
151
|
+
json: (data) => {
|
|
152
|
+
console.log('Response:', JSON.stringify(data, null, 2));
|
|
153
|
+
return mockRes;
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
expressErrorHandler(mockError, {}, mockRes, () => {});
|
|
158
|
+
|
|
159
|
+
// ========== 10. 自定义状态码 ==========
|
|
160
|
+
console.log('\n10. 自定义状态码:');
|
|
161
|
+
try {
|
|
162
|
+
throw I18nError.create('user.notFound', {}, 404);
|
|
163
|
+
} catch (error) {
|
|
164
|
+
console.log('状态码:', error.statusCode); // 404
|
|
165
|
+
console.log('错误:', error.message);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// ========== 11. 错误检查 ==========
|
|
169
|
+
console.log('\n11. 错误类型检查:');
|
|
170
|
+
try {
|
|
171
|
+
throw I18nError.create('account.notFound');
|
|
172
|
+
} catch (error) {
|
|
173
|
+
if (error instanceof I18nError) {
|
|
174
|
+
console.log('是 I18nError:', true);
|
|
175
|
+
console.log('是账户不存在:', error.is('account.notFound'));
|
|
176
|
+
console.log('是用户不存在:', error.is('user.notFound'));
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
console.log('\n=== 示例完成 ===');
|
|
181
|
+
|