schema-dsl 1.1.0 → 1.1.2

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/STATUS.md CHANGED
@@ -1,13 +1,15 @@
1
1
  # schema-dsl 项目状态
2
2
 
3
- > **最后更新**: 2026-01-04
4
- > **当前版本**: v1.0.9
5
- > **项目状态**: ✅ 全部完成,测试100%通过(725个测试)
3
+ > **最后更新**: 2026-01-06
4
+ > **当前版本**: v1.1.1
5
+ > **项目状态**: ✅ 全部完成,测试100%通过(921个测试)
6
6
 
7
7
  ---
8
8
 
9
9
  ## 📋 目录
10
10
 
11
+ - [v1.1.1](#v111) - 2026-01-06 ✅ 已完成
12
+ - [v1.1.0](#v110) - 2026-01-05 ✅ 已完成
11
13
  - [v1.0.9](#v109) - 2026-01-04 ✅ 已完成
12
14
  - [v1.0.8](#v108) - 2026-01-04 ✅ 已完成
13
15
  - [v1.0.7](#v107) - 2026-01-04 ✅ 已完成
@@ -23,6 +25,66 @@
23
25
 
24
26
  ## 版本发布计划
25
27
 
28
+ ### v1.1.1
29
+
30
+ **发布日期**: 2026-01-06
31
+ **状态**: ✅ 已完成
32
+ **类型**: 🎉 新功能 - ConditionalBuilder 独立消息 + I18nError 多语言错误
33
+ **进度**: 100%完成 | 测试: 921个通过 | 新增: 52个测试
34
+
35
+ | 需求标题 | 状态 | 优先级 | 详细 |
36
+ |---------|------|--------|------|
37
+ | ConditionalBuilder 独立消息 | ✅ 完成 | P1 | `.and()/.or()` 后可调用 `.message()` |
38
+ | I18nError 多语言错误 | ✅ 完成 | P1 | 统一的多语言错误抛出机制 |
39
+ | dsl.error 快捷方法 | ✅ 完成 | P1 | create/throw/assert 三个方法 |
40
+ | TypeScript 类型定义 | ✅ 完成 | P0 | I18nError + dsl.error 类型 |
41
+ | 测试用例 | ✅ 完成 | P0 | 52个新测试(24+28) |
42
+ | 文档更新 | ✅ 完成 | P0 | README + CHANGELOG + examples |
43
+ | 语言包扩充 | ✅ 完成 | P1 | 中英文 20+ 错误消息 |
44
+
45
+ **实现状态统计**:
46
+ - ✅ 完成: 7个
47
+ - 🔄 进行中: 0个
48
+ - ⏳ 待完成: 0个
49
+
50
+ **核心变更**:
51
+ - ✅ **新增**: ConditionalBuilder 支持 `.and()/.or()` 独立消息
52
+ - ✅ **新增**: I18nError 类 (lib/errors/I18nError.js)
53
+ - ✅ **新增**: dsl.error 快捷方法 (create/throw/assert)
54
+ - ✅ **新增**: 20+ 内置错误代码(通用/账户/用户/订单)
55
+ - ✅ **新增**: examples/i18n-error.examples.js 示例文件
56
+ - ✅ **更新**: README FAQ Q7/Q8
57
+ - ✅ **更新**: CHANGELOG v1.1.1 完整记录
58
+ - ✅ **更新**: index.d.ts TypeScript 类型定义
59
+
60
+ ---
61
+
62
+ ### v1.1.0
63
+
64
+ **发布日期**: 2026-01-05
65
+ **状态**: ✅ 已完成
66
+ **类型**: 🎉 重大功能 - 跨类型联合验证 + 插件系统增强
67
+ **进度**: 100%完成
68
+
69
+ | 需求标题 | 状态 | 优先级 | 详细 |
70
+ |---------|------|--------|------|
71
+ | 跨类型联合验证 | ✅ 完成 | P1 | `types:string|number` 语法 |
72
+ | 插件 DSL 类型注册 | ✅ 完成 | P1 | 插件可注册自定义 DSL 类型 |
73
+ | DslBuilder.registerType | ✅ 完成 | P0 | 静态方法供插件使用 |
74
+ | 文档更新 | ✅ 完成 | P0 | README + CHANGELOG |
75
+
76
+ **实现状态统计**:
77
+ - ✅ 完成: 4个
78
+ - 🔄 进行中: 0个
79
+ - ⏳ 待完成: 0个
80
+
81
+ **核心变更**:
82
+ - ✅ **新增**: `types:` 语法支持跨类型联合验证
83
+ - ✅ **增强**: 插件系统支持 DSL 类型注册
84
+ - ✅ **新增**: DslBuilder.registerType() 静态方法
85
+
86
+ ---
87
+
26
88
  ### v1.0.9
27
89
 
28
90
  **发布日期**: 2026-01-04
@@ -1,7 +1,7 @@
1
1
  # 链式条件 API - ConditionalBuilder
2
2
 
3
- > **版本**: v1.1.0
4
- > **更新日期**: 2026-01-05
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
- .then('email!')
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
- **逻辑**: `(condition1 AND condition2)`
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
- **逻辑**: `(condition1 OR condition2)`
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
- **行为**: 不满足条件时自动抛出此错误(无需 `.throwError()`)
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.0 (2026-01-05)
1260
+ ### v1.1.1 (2026-01-05)
1015
1261
 
1016
1262
  - ✅ 新增 `ConditionalBuilder` 类
1017
1263
  - ✅ 新增 `dsl.if()` 链式条件 API