schema-dsl 1.1.3 → 1.1.5
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 +86 -1271
- package/README.md +366 -2
- package/STATUS.md +69 -3
- package/changelogs/v1.0.0.md +328 -0
- package/changelogs/v1.0.9.md +367 -0
- package/changelogs/v1.1.0.md +389 -0
- package/changelogs/v1.1.1.md +308 -0
- package/changelogs/v1.1.2.md +183 -0
- package/changelogs/v1.1.3.md +161 -0
- package/changelogs/v1.1.4.md +432 -0
- package/changelogs/v1.1.5.md +493 -0
- package/docs/dsl-syntax.md +14 -3
- package/docs/error-handling.md +247 -2
- package/docs/optional-marker-guide.md +321 -0
- package/docs/runtime-locale-support.md +470 -0
- package/index.d.ts +203 -12
- package/index.js +6 -3
- package/index.mjs +2 -2
- package/lib/core/DslBuilder.js +11 -2
- package/lib/core/Locale.js +28 -22
- package/lib/core/MessageTemplate.js +30 -21
- package/lib/core/Validator.js +6 -1
- package/lib/errors/I18nError.js +59 -15
- package/lib/locales/en-US.js +13 -3
- package/lib/locales/zh-CN.js +14 -3
- package/lib/validators/CustomKeywords.js +10 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -17,6 +17,29 @@
|
|
|
17
17
|
|
|
18
18
|
---
|
|
19
19
|
|
|
20
|
+
## ⚡ TL;DR(30秒快速理解)
|
|
21
|
+
|
|
22
|
+
**schema-dsl 是什么?**
|
|
23
|
+
最简洁的数据验证库,一行DSL代替10行链式调用,性能超越Zod/Joi/Yup。
|
|
24
|
+
|
|
25
|
+
**核心优势:**
|
|
26
|
+
- 🎯 **极简语法**: `'string:3-32!'` 代替 8行 Joi 代码(减少 65% 代码量)
|
|
27
|
+
- 🚀 **性能第一**: 2,879,606 ops/s,比 Zod 快 1.58倍,比 Joi 快 9.61倍
|
|
28
|
+
- 🌍 **完整多语言**: 内置5种语言,支持运行时动态切换(v1.1.0+)
|
|
29
|
+
- 🎨 **独家功能**: 从验证规则直接生成 MongoDB/MySQL/PostgreSQL Schema
|
|
30
|
+
|
|
31
|
+
**3行代码上手:**
|
|
32
|
+
```javascript
|
|
33
|
+
const { dsl, validate } = require('schema-dsl');
|
|
34
|
+
const schema = dsl({ email: 'email!', age: 'number:18-' });
|
|
35
|
+
const result = validate(schema, { email: 'test@example.com', age: 25 });
|
|
36
|
+
console.log(result.valid); // true
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
**5分钟教程**: [快速开始](#-快速开始) | **完整文档**: [docs/INDEX.md](./docs/INDEX.md) | **在线体验**: [RunKit](https://runkit.com/npm/schema-dsl)
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
20
43
|
## 🗺️ 文档导航
|
|
21
44
|
|
|
22
45
|
**新手入门**:
|
|
@@ -45,6 +68,188 @@
|
|
|
45
68
|
|
|
46
69
|
---
|
|
47
70
|
|
|
71
|
+
## 🆕 最新特性(v1.1.5)
|
|
72
|
+
|
|
73
|
+
### 🎯 错误配置对象格式支持(v1.1.5)
|
|
74
|
+
|
|
75
|
+
**统一错误代码,多语言共享,前端友好**
|
|
76
|
+
|
|
77
|
+
```javascript
|
|
78
|
+
// 语言包配置(支持对象格式)
|
|
79
|
+
const locales = {
|
|
80
|
+
'zh-CN': {
|
|
81
|
+
'account.notFound': {
|
|
82
|
+
code: 40001, // 统一的数字错误代码
|
|
83
|
+
message: '账户不存在'
|
|
84
|
+
},
|
|
85
|
+
'account.insufficientBalance': {
|
|
86
|
+
code: 40002,
|
|
87
|
+
message: '余额不足,当前{{#balance}},需要{{#required}}'
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
'en-US': {
|
|
91
|
+
'account.notFound': {
|
|
92
|
+
code: 40001, // 相同的数字 code
|
|
93
|
+
message: 'Account not found'
|
|
94
|
+
},
|
|
95
|
+
'account.insufficientBalance': {
|
|
96
|
+
code: 40002,
|
|
97
|
+
message: 'Insufficient balance: {{#balance}}, required: {{#required}}'
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
// 使用
|
|
103
|
+
try {
|
|
104
|
+
dsl.error.throw('account.notFound');
|
|
105
|
+
} catch (error) {
|
|
106
|
+
console.log(error.code); // 40001 (统一数字代码)
|
|
107
|
+
console.log(error.originalKey); // 'account.notFound' (原始key)
|
|
108
|
+
console.log(error.message); // 中文: "账户不存在" / 英文: "Account not found"
|
|
109
|
+
|
|
110
|
+
// 增强的 error.is() - 两种方式都支持
|
|
111
|
+
if (error.is('account.notFound')) { } // ✅ 使用 originalKey
|
|
112
|
+
if (error.is(40001)) { } // ✅ 使用数字 code
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// 前端统一处理
|
|
116
|
+
switch (error.code) {
|
|
117
|
+
case 40001: showNotFoundPage(); break; // 不受语言影响
|
|
118
|
+
case 40002: showTopUpDialog(); break;
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
**核心优势**:
|
|
123
|
+
- 🎯 **统一错误代码**: 不同语言使用相同的数字 `code`,便于前端统一处理
|
|
124
|
+
- 🔄 **完全向后兼容**: 字符串格式自动转换,现有代码无需修改
|
|
125
|
+
- 📊 **更好的错误追踪**: `originalKey` 和 `code` 分离,便于日志分析
|
|
126
|
+
- 🌍 **多语言友好**: 前端可以用统一的数字 code 处理,不受语言影响
|
|
127
|
+
|
|
128
|
+
📖 [完整文档](./docs/error-handling.md#v115-新功能对象格式错误配置) · [变更日志](./changelogs/v1.1.5.md)
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
### 🔗 跨类型联合验证(v1.1.0)
|
|
133
|
+
|
|
134
|
+
**一行代码支持多种类型,告别繁琐的类型判断**
|
|
135
|
+
|
|
136
|
+
```javascript
|
|
137
|
+
const schema = dsl({
|
|
138
|
+
contact: 'types:email|phone!', // 邮箱或手机号
|
|
139
|
+
price: 'types:number:0-|string:1-20', // 数字价格或"面议"
|
|
140
|
+
status: 'types:active|inactive|null' // 枚举或空值
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
validate(schema, { contact: 'test@example.com' }); // ✅ 通过
|
|
144
|
+
validate(schema, { contact: '13800138000' }); // ✅ 通过
|
|
145
|
+
validate(schema, { contact: 12345 }); // ❌ 失败
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
**实际场景**:
|
|
149
|
+
- ✅ 用户注册:支持邮箱或手机号登录
|
|
150
|
+
- ✅ 商品价格:数字或"面议"字符串
|
|
151
|
+
- ✅ 可选字段:允许null值
|
|
152
|
+
|
|
153
|
+
📖 [完整文档](./docs/union-types.md)
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
### 🌍 运行时多语言支持
|
|
158
|
+
|
|
159
|
+
**无需修改全局设置,每次调用指定语言**
|
|
160
|
+
|
|
161
|
+
```javascript
|
|
162
|
+
// 根据请求头动态返回不同语言的错误
|
|
163
|
+
app.post('/api/account', (req, res) => {
|
|
164
|
+
const locale = req.headers['accept-language'] || 'en-US';
|
|
165
|
+
|
|
166
|
+
try {
|
|
167
|
+
dsl.error.assert(account, 'account.notFound', {}, 404, locale);
|
|
168
|
+
// 中文请求返回: "账户不存在"
|
|
169
|
+
// 英文请求返回: "Account not found"
|
|
170
|
+
} catch (error) {
|
|
171
|
+
res.status(error.statusCode).json(error.toJSON());
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
**适用场景**:
|
|
177
|
+
- ✅ 多语言 API(根据请求头动态返回)
|
|
178
|
+
- ✅ 微服务架构(错误传递保持原语言)
|
|
179
|
+
- ✅ 国际化应用(同一请求多种语言)
|
|
180
|
+
|
|
181
|
+
📖 [运行时多语言文档](./docs/runtime-locale-support.md)
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
### ⚡ 其他新特性
|
|
186
|
+
|
|
187
|
+
- ✅ **错误配置对象格式**: 支持 `{ code, message }` 统一错误代码(v1.1.5)
|
|
188
|
+
- ✅ **统一错误抛出**: `I18nError` 类,支持多语言错误消息(v1.1.1)
|
|
189
|
+
- ✅ **插件系统增强**: 自定义类型注册更简单(v1.1.0)
|
|
190
|
+
- ✅ **TypeScript 类型完善**: 0个类型错误(v1.1.4)
|
|
191
|
+
|
|
192
|
+
[查看完整更新日志](./CHANGELOG.md)
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## 📦 功能清单(AI友好格式)
|
|
197
|
+
|
|
198
|
+
> 方便AI快速理解所有功能
|
|
199
|
+
|
|
200
|
+
### 核心功能
|
|
201
|
+
|
|
202
|
+
```json
|
|
203
|
+
{
|
|
204
|
+
"validation": {
|
|
205
|
+
"basic": ["string", "number", "boolean", "date", "email", "url", "phone", "idCard"],
|
|
206
|
+
"advanced": ["regex", "custom", "conditional", "nested", "array"],
|
|
207
|
+
"unionTypes": "v1.1.0+ 跨类型联合验证 (types:string|number)"
|
|
208
|
+
},
|
|
209
|
+
"i18n": {
|
|
210
|
+
"supported": ["zh-CN", "en-US", "ja-JP", "es-ES", "fr-FR"],
|
|
211
|
+
"features": ["配置加载", "运行时切换", "自定义消息", "参数插值"],
|
|
212
|
+
"runtime": "v1.1.0+ 运行时指定语言 (dsl.error.create(code, params, statusCode, locale))"
|
|
213
|
+
},
|
|
214
|
+
"database": {
|
|
215
|
+
"export": ["MongoDB", "MySQL", "PostgreSQL"],
|
|
216
|
+
"unique": "从验证规则直接生成数据库Schema"
|
|
217
|
+
},
|
|
218
|
+
"framework": {
|
|
219
|
+
"integration": ["Express", "Koa", "Fastify"],
|
|
220
|
+
"async": "validateAsync() 失败自动抛出 ValidationError"
|
|
221
|
+
},
|
|
222
|
+
"api": {
|
|
223
|
+
"main": ["dsl()", "validate()", "validateAsync()"],
|
|
224
|
+
"utils": ["SchemaUtils.pick()", "SchemaUtils.omit()", "SchemaUtils.partial()"],
|
|
225
|
+
"conditional": ["dsl.if()", "dsl.match()"],
|
|
226
|
+
"errors": ["ValidationError", "I18nError"]
|
|
227
|
+
},
|
|
228
|
+
"performance": {
|
|
229
|
+
"opsPerSecond": 2879606,
|
|
230
|
+
"vs": {
|
|
231
|
+
"Zod": "1.58x faster",
|
|
232
|
+
"Joi": "9.61x faster",
|
|
233
|
+
"Yup": "27.07x faster"
|
|
234
|
+
},
|
|
235
|
+
"optimization": ["WeakMap缓存", "智能编译", "批量验证优化"]
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### API速查
|
|
241
|
+
|
|
242
|
+
| API | 用途 | 返回值 | 文档 |
|
|
243
|
+
|-----|------|--------|------|
|
|
244
|
+
| `dsl(schema)` | 创建Schema | Schema对象 | [DSL语法](./docs/dsl-syntax.md) |
|
|
245
|
+
| `validate(schema, data)` | 同步验证 | `{valid, errors, data}` | [验证指南](./docs/validation-guide.md) |
|
|
246
|
+
| `validateAsync(schema, data)` | 异步验证 | Promise(失败抛错) | [异步验证](./docs/validate-async.md) |
|
|
247
|
+
| `dsl.if(condition)` | 条件验证 | ConditionalBuilder | [条件API](./docs/conditional-api.md) |
|
|
248
|
+
| `SchemaUtils.pick()` | 选择字段 | 新Schema | [SchemaUtils](./docs/schema-utils.md) |
|
|
249
|
+
| `I18nError.throw()` | 抛出多语言错误 | never | [I18nError示例](./examples/i18n-error.examples.js) |
|
|
250
|
+
|
|
251
|
+
---
|
|
252
|
+
|
|
48
253
|
## ✨ 为什么选择 schema-dsl?
|
|
49
254
|
|
|
50
255
|
### 🎯 极简 DSL 语法
|
|
@@ -137,9 +342,48 @@ validate(schema, { username: 'ab' }, { locale: 'ja-JP' });
|
|
|
137
342
|
// => "usernameは3文字以上である必要があります"
|
|
138
343
|
```
|
|
139
344
|
|
|
345
|
+
**🆕 运行时多语言支持(v1.1.0+)**
|
|
346
|
+
|
|
347
|
+
无需修改全局设置,可在每次调用时指定语言:
|
|
348
|
+
|
|
349
|
+
```javascript
|
|
350
|
+
const { dsl, I18nError } = require('schema-dsl');
|
|
351
|
+
|
|
352
|
+
// 方式1: 业务错误 - 运行时指定语言
|
|
353
|
+
const error1 = dsl.error.create('account.notFound', {}, 404, 'zh-CN');
|
|
354
|
+
console.log(error1.message); // "账户不存在"
|
|
355
|
+
|
|
356
|
+
const error2 = dsl.error.create('account.notFound', {}, 404, 'en-US');
|
|
357
|
+
console.log(error2.message); // "Account not found"
|
|
358
|
+
|
|
359
|
+
// 方式2: 断言风格 - 根据请求头动态指定
|
|
360
|
+
app.post('/api/withdraw', (req, res) => {
|
|
361
|
+
const locale = req.headers['accept-language'] || 'en-US';
|
|
362
|
+
const account = getAccount(req.user.id);
|
|
363
|
+
|
|
364
|
+
// 根据请求头返回对应语言的错误
|
|
365
|
+
I18nError.assert(account, 'account.notFound', {}, 404, locale);
|
|
366
|
+
I18nError.assert(
|
|
367
|
+
account.balance >= req.body.amount,
|
|
368
|
+
'account.insufficientBalance',
|
|
369
|
+
{ balance: account.balance, required: req.body.amount },
|
|
370
|
+
400,
|
|
371
|
+
locale
|
|
372
|
+
);
|
|
373
|
+
|
|
374
|
+
// 验证通过,继续处理...
|
|
375
|
+
});
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
**适用场景**:
|
|
379
|
+
- ✅ 多语言 API(根据请求头返回不同语言)
|
|
380
|
+
- ✅ 微服务架构(错误在服务间传递时保持语言)
|
|
381
|
+
- ✅ 同一请求中需要多种语言的错误消息
|
|
382
|
+
|
|
140
383
|
**内置语言**: 中文、英文、日语、法语、西班牙语
|
|
141
384
|
|
|
142
|
-
📖 [完整多语言文档](./docs/i18n.md)
|
|
385
|
+
📖 [完整多语言文档](./docs/i18n.md)
|
|
386
|
+
📖 [运行时多语言支持](./docs/runtime-locale-support.md)
|
|
143
387
|
|
|
144
388
|
### 🎨 数据库 Schema 导出
|
|
145
389
|
|
|
@@ -1901,6 +2145,125 @@ dsl.error.throw('user.noPermission');
|
|
|
1901
2145
|
dsl.error.assert(user.role === 'admin', 'user.noPermission');
|
|
1902
2146
|
```
|
|
1903
2147
|
|
|
2148
|
+
**🆕 对象格式错误配置(v1.1.5)**
|
|
2149
|
+
|
|
2150
|
+
支持统一的数字错误代码,便于前端处理:
|
|
2151
|
+
|
|
2152
|
+
```javascript
|
|
2153
|
+
// 语言包配置(lib/locales/zh-CN.js)
|
|
2154
|
+
module.exports = {
|
|
2155
|
+
// 字符串格式(向后兼容)
|
|
2156
|
+
'user.notFound': '用户不存在',
|
|
2157
|
+
|
|
2158
|
+
// 对象格式(v1.1.5 新增)- 使用数字错误码
|
|
2159
|
+
'account.notFound': {
|
|
2160
|
+
code: 40001, // 数字错误代码
|
|
2161
|
+
message: '账户不存在'
|
|
2162
|
+
},
|
|
2163
|
+
'account.insufficientBalance': {
|
|
2164
|
+
code: 40002,
|
|
2165
|
+
message: '余额不足,当前{{#balance}},需要{{#required}}'
|
|
2166
|
+
},
|
|
2167
|
+
'order.notPaid': {
|
|
2168
|
+
code: 50001,
|
|
2169
|
+
message: '订单未支付'
|
|
2170
|
+
}
|
|
2171
|
+
};
|
|
2172
|
+
|
|
2173
|
+
// lib/locales/en-US.js
|
|
2174
|
+
module.exports = {
|
|
2175
|
+
'account.notFound': {
|
|
2176
|
+
code: 40001, // 相同的数字 code
|
|
2177
|
+
message: 'Account not found'
|
|
2178
|
+
},
|
|
2179
|
+
'account.insufficientBalance': {
|
|
2180
|
+
code: 40002,
|
|
2181
|
+
message: 'Insufficient balance: {{#balance}}, required: {{#required}}'
|
|
2182
|
+
},
|
|
2183
|
+
'order.notPaid': {
|
|
2184
|
+
code: 50001,
|
|
2185
|
+
message: 'Order not paid'
|
|
2186
|
+
}
|
|
2187
|
+
};
|
|
2188
|
+
|
|
2189
|
+
// 使用
|
|
2190
|
+
try {
|
|
2191
|
+
dsl.error.throw('account.notFound');
|
|
2192
|
+
} catch (error) {
|
|
2193
|
+
error.code // 40001 (数字代码)
|
|
2194
|
+
error.originalKey // 'account.notFound' (原始key)
|
|
2195
|
+
error.message // '账户不存在'
|
|
2196
|
+
|
|
2197
|
+
// 两种判断方式
|
|
2198
|
+
error.is('account.notFound') // ✅ 使用 originalKey
|
|
2199
|
+
error.is(40001) // ✅ 使用数字 code
|
|
2200
|
+
}
|
|
2201
|
+
|
|
2202
|
+
// 前端统一处理(不受语言影响)
|
|
2203
|
+
try {
|
|
2204
|
+
await api.getAccount(id);
|
|
2205
|
+
} catch (error) {
|
|
2206
|
+
switch (error.code) {
|
|
2207
|
+
case 40001:
|
|
2208
|
+
router.push('/account-not-found');
|
|
2209
|
+
break;
|
|
2210
|
+
case 40002:
|
|
2211
|
+
showTopUpDialog(error.params.balance, error.params.required);
|
|
2212
|
+
break;
|
|
2213
|
+
case 50001:
|
|
2214
|
+
showPaymentDialog();
|
|
2215
|
+
break;
|
|
2216
|
+
}
|
|
2217
|
+
}
|
|
2218
|
+
```
|
|
2219
|
+
|
|
2220
|
+
**优势**:
|
|
2221
|
+
- ✅ 多语言共享相同的数字 `code`,前端统一处理
|
|
2222
|
+
- ✅ 完全向后兼容,字符串格式自动转换
|
|
2223
|
+
- ✅ `originalKey` 便于调试和日志追踪
|
|
2224
|
+
- ✅ 数字 code 更简洁,易于管理和文档化
|
|
2225
|
+
|
|
2226
|
+
**错误码规范建议**:
|
|
2227
|
+
- `4xxxx` - 客户端错误(账户、权限、参数等)
|
|
2228
|
+
- `5xxxx` - 业务逻辑错误(订单、支付、库存等)
|
|
2229
|
+
- `6xxxx` - 系统错误(数据库、服务不可用等)
|
|
2230
|
+
|
|
2231
|
+
📖 详细说明: [错误处理文档](./docs/error-handling.md#v115-新功能对象格式错误配置)
|
|
2232
|
+
|
|
2233
|
+
**🆕 运行时指定语言(v1.1.0+)**
|
|
2234
|
+
|
|
2235
|
+
无需修改全局语言设置,每次调用时指定:
|
|
2236
|
+
|
|
2237
|
+
```javascript
|
|
2238
|
+
// 根据请求头动态返回不同语言
|
|
2239
|
+
app.post('/api/account', (req, res, next) => {
|
|
2240
|
+
const locale = req.headers['accept-language'] || 'en-US';
|
|
2241
|
+
const account = getAccount(req.user.id);
|
|
2242
|
+
|
|
2243
|
+
try {
|
|
2244
|
+
// 第5个参数指定语言
|
|
2245
|
+
dsl.error.assert(account, 'account.notFound', {}, 404, locale);
|
|
2246
|
+
dsl.error.assert(
|
|
2247
|
+
account.balance >= 100,
|
|
2248
|
+
'account.insufficientBalance',
|
|
2249
|
+
{ balance: account.balance, required: 100 },
|
|
2250
|
+
400,
|
|
2251
|
+
locale
|
|
2252
|
+
);
|
|
2253
|
+
// 验证通过...
|
|
2254
|
+
} catch (error) {
|
|
2255
|
+
next(error);
|
|
2256
|
+
}
|
|
2257
|
+
});
|
|
2258
|
+
|
|
2259
|
+
// 同一请求中使用不同语言
|
|
2260
|
+
const error1 = dsl.error.create('account.notFound', {}, 404, 'zh-CN');
|
|
2261
|
+
console.log(error1.message); // "账户不存在"
|
|
2262
|
+
|
|
2263
|
+
const error2 = dsl.error.create('account.notFound', {}, 404, 'en-US');
|
|
2264
|
+
console.log(error2.message); // "Account not found"
|
|
2265
|
+
```
|
|
2266
|
+
|
|
1904
2267
|
**Express/Koa 集成**:
|
|
1905
2268
|
```javascript
|
|
1906
2269
|
// 错误处理中间件
|
|
@@ -1930,7 +2293,8 @@ app.post('/withdraw', (req, res) => {
|
|
|
1930
2293
|
- 用户: `user.notFound`, `user.noPermission`
|
|
1931
2294
|
- 订单: `order.notPaid`, `order.paymentMissing`
|
|
1932
2295
|
|
|
1933
|
-
📖 完整文档请查看 [examples/i18n-error.examples.js](./examples/i18n-error.examples.js)
|
|
2296
|
+
📖 完整文档请查看 [examples/i18n-error.examples.js](./examples/i18n-error.examples.js)
|
|
2297
|
+
📖 运行时多语言支持请查看 [docs/runtime-locale-support.md](./docs/runtime-locale-support.md)
|
|
1934
2298
|
|
|
1935
2299
|
---
|
|
1936
2300
|
|
package/STATUS.md
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
# schema-dsl 项目状态
|
|
2
2
|
|
|
3
|
-
> **最后更新**: 2026-01-
|
|
4
|
-
> **当前版本**: v1.1.
|
|
5
|
-
> **项目状态**: ✅ 全部完成,测试100%通过(
|
|
3
|
+
> **最后更新**: 2026-01-17
|
|
4
|
+
> **当前版本**: v1.1.5
|
|
5
|
+
> **项目状态**: ✅ 全部完成,测试100%通过(955个测试)
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
## 📋 目录
|
|
10
10
|
|
|
11
|
+
- [v1.1.5](#v115) - 2026-01-17 ✅ 已完成
|
|
12
|
+
- [v1.1.4](#v114) - 2026-01-13 ✅ 已完成
|
|
11
13
|
- [v1.1.3](#v113) - 2026-01-09 ✅ 已完成
|
|
12
14
|
- [v1.1.1](#v111) - 2026-01-06 ✅ 已完成
|
|
13
15
|
- [v1.1.0](#v110) - 2026-01-05 ✅ 已完成
|
|
@@ -26,6 +28,70 @@
|
|
|
26
28
|
|
|
27
29
|
## 版本发布计划
|
|
28
30
|
|
|
31
|
+
### v1.1.5
|
|
32
|
+
|
|
33
|
+
**发布日期**: 2026-01-17
|
|
34
|
+
**状态**: ✅ 已完成
|
|
35
|
+
**类型**: 🚀 功能增强 - 错误配置对象格式支持
|
|
36
|
+
**进度**: 100%完成 | 测试: 955个通过 (100%)
|
|
37
|
+
|
|
38
|
+
| 需求标题 | 状态 | 优先级 | 详细 |
|
|
39
|
+
|---------|------|--------|------|
|
|
40
|
+
| 实现 Locale.getMessage 对象格式支持 | ✅ 完成 | P0 | lib/core/Locale.js |
|
|
41
|
+
| 修改 I18nError 构造函数支持对象格式 | ✅ 完成 | P0 | lib/errors/I18nError.js |
|
|
42
|
+
| 新增 originalKey 字段 | ✅ 完成 | P0 | I18nError 类 |
|
|
43
|
+
| 更新 TypeScript 类型定义 | ✅ 完成 | P0 | index.d.ts |
|
|
44
|
+
| 更新语言包示例(对象格式) | ✅ 完成 | P1 | lib/locales/*.js |
|
|
45
|
+
| 新增测试用例(6个) | ✅ 完成 | P0 | test/unit/i18n-error.test.js |
|
|
46
|
+
| 更新现有测试适配对象格式 | ✅ 完成 | P0 | test/unit/*.test.js |
|
|
47
|
+
| 更新 CHANGELOG | ✅ 完成 | P0 | v1.1.5 变更记录 |
|
|
48
|
+
| 更新 STATUS | ✅ 完成 | P0 | 版本号和状态 |
|
|
49
|
+
|
|
50
|
+
**实现状态统计**:
|
|
51
|
+
- ✅ 完成: 9个
|
|
52
|
+
- 🔄 进行中: 0个
|
|
53
|
+
- ⏳ 待完成: 0个
|
|
54
|
+
|
|
55
|
+
**核心变更**:
|
|
56
|
+
- ✨ 语言包支持对象格式 `{ code, message }`
|
|
57
|
+
- ✨ I18nError 新增 `originalKey` 字段
|
|
58
|
+
- ✨ 多语言共享相同的 `code`
|
|
59
|
+
- ✅ 完全向后兼容,字符串格式自动转换
|
|
60
|
+
- ✅ `error.is()` 同时支持 code 和 originalKey 判断
|
|
61
|
+
|
|
62
|
+
**向后兼容性**: ✅ 100% 向后兼容
|
|
63
|
+
|
|
64
|
+
### v1.1.4
|
|
65
|
+
|
|
66
|
+
**发布日期**: 2026-01-13
|
|
67
|
+
**状态**: ✅ 已完成
|
|
68
|
+
**类型**: 🔧 TypeScript类型修复 + 📚 文档完善
|
|
69
|
+
**进度**: 100%完成 | 测试: 921个通过
|
|
70
|
+
|
|
71
|
+
| 需求标题 | 状态 | 优先级 | 详细 |
|
|
72
|
+
|---------|------|--------|------|
|
|
73
|
+
| 修复 dsl.error.assert 重复签名 | ✅ 完成 | P0 | index.d.ts L1336-1343 |
|
|
74
|
+
| 修复 I18nError.assert 重复签名 | ✅ 完成 | P0 | index.d.ts L1805-1821 |
|
|
75
|
+
| 完善运行时多语言文档 | ✅ 完成 | P1 | docs/runtime-locale-support.md |
|
|
76
|
+
| 更新 README.md | ✅ 完成 | P1 | 添加运行时语言支持示例 |
|
|
77
|
+
| 生成深度分析报告 | ✅ 完成 | P2 | reports/schema-dsl/analysis/ |
|
|
78
|
+
| 更新 CHANGELOG | ✅ 完成 | P0 | v1.1.4 变更记录 |
|
|
79
|
+
| 更新 STATUS | ✅ 完成 | P0 | 版本号和状态 |
|
|
80
|
+
|
|
81
|
+
**实现状态统计**:
|
|
82
|
+
- ✅ 完成: 7个
|
|
83
|
+
- 🔄 进行中: 0个
|
|
84
|
+
- ⏳ 待完成: 0个
|
|
85
|
+
|
|
86
|
+
**核心变更**:
|
|
87
|
+
- ✅ **修复**: index.d.ts 中2处重复函数签名(46个类型错误→0个错误)
|
|
88
|
+
- ✅ **文档**: 完善运行时多语言支持文档
|
|
89
|
+
- ✅ **文档**: README.md 添加运行时语言指定示例
|
|
90
|
+
- ✅ **验证**: string? 可选语法完整支持
|
|
91
|
+
- ✅ **验证**: 多语言加载机制验证
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
29
95
|
### v1.1.3
|
|
30
96
|
|
|
31
97
|
**发布日期**: 2026-01-09
|