schema-dsl 1.1.3 → 1.1.4
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 +75 -1275
- package/README.md +221 -2
- package/STATUS.md +34 -2
- 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/docs/dsl-syntax.md +14 -3
- package/docs/optional-marker-guide.md +321 -0
- package/docs/runtime-locale-support.md +443 -0
- package/index.d.ts +126 -10
- package/index.js +6 -3
- package/index.mjs +2 -2
- package/lib/core/DslBuilder.js +11 -2
- package/lib/errors/I18nError.js +21 -6
- package/package.json +1 -1
|
@@ -0,0 +1,432 @@
|
|
|
1
|
+
# v1.1.4 变更日志
|
|
2
|
+
|
|
3
|
+
> **发布日期**: 2026-01-13
|
|
4
|
+
> **版本号**: v1.1.4
|
|
5
|
+
> **类型**: 🔧 TypeScript类型修复 + 📚 文档完善
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 📋 变更概览
|
|
10
|
+
|
|
11
|
+
| 类型 | 数量 | 说明 |
|
|
12
|
+
|------|------|------|
|
|
13
|
+
| 🔧 Bug修复 | 2 | TypeScript 类型定义重复签名 |
|
|
14
|
+
| 📚 文档更新 | 3 | 多语言文档完善 |
|
|
15
|
+
| ✅ 验证测试 | 3 | 多语言、语法、类型验证 |
|
|
16
|
+
| 🔄 内部改进 | 1 | CHANGELOG 格式统一 |
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## 🔧 TypeScript 类型修复
|
|
21
|
+
|
|
22
|
+
### 问题描述
|
|
23
|
+
|
|
24
|
+
index.d.ts 中存在2处重复的函数签名定义,导致 TypeScript 编译器报错(46个类型错误)。
|
|
25
|
+
|
|
26
|
+
### 修复详情
|
|
27
|
+
|
|
28
|
+
#### 1. dsl.error.assert 重复签名
|
|
29
|
+
|
|
30
|
+
**位置**: `index.d.ts` 第1336-1343行
|
|
31
|
+
|
|
32
|
+
**修复前**:
|
|
33
|
+
```typescript
|
|
34
|
+
assert(
|
|
35
|
+
condition: any,
|
|
36
|
+
code: string,
|
|
37
|
+
params?: Record<string, any>,
|
|
38
|
+
statusCode?: number,
|
|
39
|
+
locale?: string
|
|
40
|
+
): asserts condition;
|
|
41
|
+
statusCode?: number // ❌ 重复行
|
|
42
|
+
): asserts condition; // ❌ 重复行
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**修复后**:
|
|
46
|
+
```typescript
|
|
47
|
+
assert(
|
|
48
|
+
condition: any,
|
|
49
|
+
code: string,
|
|
50
|
+
params?: Record<string, any>,
|
|
51
|
+
statusCode?: number,
|
|
52
|
+
locale?: string
|
|
53
|
+
): asserts condition;
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
**错误信息**:
|
|
57
|
+
```
|
|
58
|
+
TS1131: Property or signature expected.
|
|
59
|
+
TS1128: Declaration or statement expected.
|
|
60
|
+
应为类型成员
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
#### 2. I18nError.assert 重复签名
|
|
66
|
+
|
|
67
|
+
**位置**: `index.d.ts` 第1805-1821行
|
|
68
|
+
|
|
69
|
+
**修复前**:
|
|
70
|
+
```typescript
|
|
71
|
+
static assert(
|
|
72
|
+
condition: any,
|
|
73
|
+
code: string,
|
|
74
|
+
params?: Record<string, any>,
|
|
75
|
+
statusCode?: number,
|
|
76
|
+
locale?: string
|
|
77
|
+
): asserts condition;
|
|
78
|
+
*/ // ❌ 注释位置错误
|
|
79
|
+
static assert( // ❌ 重复定义
|
|
80
|
+
condition: any,
|
|
81
|
+
code: string,
|
|
82
|
+
params?: Record<string, any>,
|
|
83
|
+
statusCode?: number
|
|
84
|
+
): asserts condition;
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
**修复后**:
|
|
88
|
+
```typescript
|
|
89
|
+
/**
|
|
90
|
+
* 断言方法 - 条件不满足时抛错
|
|
91
|
+
* @param condition - 条件表达式
|
|
92
|
+
* @param code - 错误代码
|
|
93
|
+
* @param params - 错误参数
|
|
94
|
+
* @param statusCode - HTTP 状态码
|
|
95
|
+
* @param locale - 语言环境(可选,不传则使用全局语言)
|
|
96
|
+
* @throws I18nError 条件为 false 时抛出
|
|
97
|
+
*/
|
|
98
|
+
static assert(
|
|
99
|
+
condition: any,
|
|
100
|
+
code: string,
|
|
101
|
+
params?: Record<string, any>,
|
|
102
|
+
statusCode?: number,
|
|
103
|
+
locale?: string
|
|
104
|
+
): asserts condition;
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
**错误信息**:
|
|
108
|
+
```
|
|
109
|
+
TS1128: Declaration or statement expected.
|
|
110
|
+
应为语句
|
|
111
|
+
TS1003: Identifier expected.
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
### 修复结果
|
|
117
|
+
|
|
118
|
+
**修复前**:
|
|
119
|
+
- ❌ 46个类型错误
|
|
120
|
+
- ⚠️ 1个警告
|
|
121
|
+
|
|
122
|
+
**修复后**:
|
|
123
|
+
- ✅ 0个类型错误
|
|
124
|
+
- ⚠️ 2个可忽略警告(设计决策)
|
|
125
|
+
|
|
126
|
+
**剩余警告**:
|
|
127
|
+
1. `export { _if as if }` - 保留词警告(设计决策,为了提供更好的API)
|
|
128
|
+
2. `toJsonSchema()` - 未使用方法警告(向后兼容保留)
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
### 影响范围
|
|
133
|
+
|
|
134
|
+
- ✅ **仅影响**: TypeScript 类型检查
|
|
135
|
+
- ✅ **不影响**: 运行时逻辑
|
|
136
|
+
- ✅ **向后兼容**: 无破坏性变更
|
|
137
|
+
- ✅ **测试状态**: 921个测试全部通过
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## 📚 文档更新
|
|
142
|
+
|
|
143
|
+
### 1. 完善运行时多语言支持文档
|
|
144
|
+
|
|
145
|
+
**文件**: `docs/runtime-locale-support.md`
|
|
146
|
+
|
|
147
|
+
**更新内容**:
|
|
148
|
+
- ✅ 版本标记更新为 v1.1.4+
|
|
149
|
+
- ✅ 全局语言设置 vs 运行时指定语言对比
|
|
150
|
+
- ✅ API 参数详细说明
|
|
151
|
+
- ✅ Express/Koa 集成示例
|
|
152
|
+
- ✅ 微服务架构中的多语言错误传递
|
|
153
|
+
- ✅ 最佳实践建议
|
|
154
|
+
|
|
155
|
+
**核心示例**:
|
|
156
|
+
|
|
157
|
+
```javascript
|
|
158
|
+
// 运行时指定语言(不影响全局设置)
|
|
159
|
+
const error1 = dsl.error.create('account.notFound', {}, 404, 'zh-CN');
|
|
160
|
+
// message: "账户不存在"
|
|
161
|
+
|
|
162
|
+
const error2 = dsl.error.create('account.notFound', {}, 404, 'en-US');
|
|
163
|
+
// message: "Account not found"
|
|
164
|
+
|
|
165
|
+
// 根据请求头动态返回
|
|
166
|
+
app.post('/api/account', (req, res) => {
|
|
167
|
+
const locale = req.headers['accept-language'] || 'en-US';
|
|
168
|
+
dsl.error.assert(account, 'account.notFound', {}, 404, locale);
|
|
169
|
+
});
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
---
|
|
173
|
+
|
|
174
|
+
### 2. 更新 README.md 多语言章节
|
|
175
|
+
|
|
176
|
+
**文件**: `README.md`
|
|
177
|
+
|
|
178
|
+
**新增内容**:
|
|
179
|
+
|
|
180
|
+
#### 运行时多语言支持(v1.1.0+)
|
|
181
|
+
|
|
182
|
+
```javascript
|
|
183
|
+
const { dsl, I18nError } = require('schema-dsl');
|
|
184
|
+
|
|
185
|
+
// 方式1: 业务错误 - 运行时指定语言
|
|
186
|
+
const error1 = dsl.error.create('account.notFound', {}, 404, 'zh-CN');
|
|
187
|
+
console.log(error1.message); // "账户不存在"
|
|
188
|
+
|
|
189
|
+
const error2 = dsl.error.create('account.notFound', {}, 404, 'en-US');
|
|
190
|
+
console.log(error2.message); // "Account not found"
|
|
191
|
+
|
|
192
|
+
// 方式2: 断言风格 - 根据请求头动态指定
|
|
193
|
+
app.post('/api/withdraw', (req, res) => {
|
|
194
|
+
const locale = req.headers['accept-language'] || 'en-US';
|
|
195
|
+
const account = getAccount(req.user.id);
|
|
196
|
+
|
|
197
|
+
// 根据请求头返回对应语言的错误
|
|
198
|
+
I18nError.assert(account, 'account.notFound', {}, 404, locale);
|
|
199
|
+
I18nError.assert(
|
|
200
|
+
account.balance >= req.body.amount,
|
|
201
|
+
'account.insufficientBalance',
|
|
202
|
+
{ balance: account.balance, required: req.body.amount },
|
|
203
|
+
400,
|
|
204
|
+
locale
|
|
205
|
+
);
|
|
206
|
+
|
|
207
|
+
// 验证通过,继续处理...
|
|
208
|
+
});
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
**适用场景**:
|
|
212
|
+
- ✅ 多语言 API(根据请求头返回不同语言)
|
|
213
|
+
- ✅ 微服务架构(错误在服务间传递时保持语言)
|
|
214
|
+
- ✅ 同一请求中需要多种语言的错误消息
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
### 3. 更新 README.md Q8章节
|
|
219
|
+
|
|
220
|
+
**增强内容**: 添加运行时语言支持示例
|
|
221
|
+
|
|
222
|
+
```javascript
|
|
223
|
+
// 根据请求头动态返回不同语言
|
|
224
|
+
app.post('/api/account', (req, res, next) => {
|
|
225
|
+
const locale = req.headers['accept-language'] || 'en-US';
|
|
226
|
+
const account = getAccount(req.user.id);
|
|
227
|
+
|
|
228
|
+
try {
|
|
229
|
+
// 第5个参数指定语言
|
|
230
|
+
dsl.error.assert(account, 'account.notFound', {}, 404, locale);
|
|
231
|
+
dsl.error.assert(
|
|
232
|
+
account.balance >= 100,
|
|
233
|
+
'account.insufficientBalance',
|
|
234
|
+
{ balance: account.balance, required: 100 },
|
|
235
|
+
400,
|
|
236
|
+
locale
|
|
237
|
+
);
|
|
238
|
+
// 验证通过...
|
|
239
|
+
} catch (error) {
|
|
240
|
+
next(error);
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
// 同一请求中使用不同语言
|
|
245
|
+
const error1 = dsl.error.create('account.notFound', {}, 404, 'zh-CN');
|
|
246
|
+
console.log(error1.message); // "账户不存在"
|
|
247
|
+
|
|
248
|
+
const error2 = dsl.error.create('account.notFound', {}, 404, 'en-US');
|
|
249
|
+
console.log(error2.message); // "Account not found"
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
**新增文档链接**:
|
|
253
|
+
- 📖 [运行时多语言支持](./docs/runtime-locale-support.md)
|
|
254
|
+
|
|
255
|
+
---
|
|
256
|
+
|
|
257
|
+
### 4. 生成深度分析报告
|
|
258
|
+
|
|
259
|
+
**文件**: `reports/schema-dsl/analysis/deep-analysis-multilang-types-v1.1.2.md`
|
|
260
|
+
|
|
261
|
+
**报告内容**:
|
|
262
|
+
- ✅ 多语言加载机制详细分析
|
|
263
|
+
- ✅ string? 语法支持验证
|
|
264
|
+
- ✅ 类型定义问题分析与修复步骤
|
|
265
|
+
- ✅ 测试验证结果
|
|
266
|
+
- ✅ 优化建议
|
|
267
|
+
|
|
268
|
+
**核心发现**:
|
|
269
|
+
1. 多语言包在启动时一次性加载(`lib/locales/index.js`)
|
|
270
|
+
2. 支持全局切换:`Locale.setLocale('zh-CN')`
|
|
271
|
+
3. 支持运行时指定:`dsl.error.create(code, params, statusCode, 'zh-CN')`
|
|
272
|
+
4. string? 语法完整支持(包括 `string:3-32?`、`email?` 等)
|
|
273
|
+
|
|
274
|
+
---
|
|
275
|
+
|
|
276
|
+
## ✅ 验证测试
|
|
277
|
+
|
|
278
|
+
### 1. 多语言测试
|
|
279
|
+
|
|
280
|
+
**测试文件**: `test-i18n-support.js`
|
|
281
|
+
|
|
282
|
+
**测试覆盖**:
|
|
283
|
+
- ✅ dsl.error.create/throw/assert 方法存在性
|
|
284
|
+
- ✅ 5种语言支持验证(中英日法西)
|
|
285
|
+
- ✅ 参数插值功能
|
|
286
|
+
- ✅ 运行时指定语言(不影响全局)
|
|
287
|
+
- ✅ 错误对象属性验证
|
|
288
|
+
- ✅ toJSON 方法
|
|
289
|
+
|
|
290
|
+
**测试结果**:
|
|
291
|
+
```
|
|
292
|
+
========================================
|
|
293
|
+
运行时语言支持测试全部通过!
|
|
294
|
+
========================================
|
|
295
|
+
✅ dsl.error.create 支持运行时指定语言
|
|
296
|
+
✅ I18nError.throw 支持运行时指定语言
|
|
297
|
+
✅ I18nError.assert 支持运行时指定语言
|
|
298
|
+
✅ 运行时语言不影响全局语言设置
|
|
299
|
+
✅ 同一请求可使用多种语言
|
|
300
|
+
✅ 适合 API 开发中根据请求头动态返回多语言错误
|
|
301
|
+
|
|
302
|
+
🎉 所有测试通过!ctx.dsl.error 等方法完全支持多语言!
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
---
|
|
306
|
+
|
|
307
|
+
### 2. string? 语法测试
|
|
308
|
+
|
|
309
|
+
**测试文件**: `test-optional-syntax.js`
|
|
310
|
+
|
|
311
|
+
**测试覆盖**:
|
|
312
|
+
- ✅ `string`(默认可选)
|
|
313
|
+
- ✅ `string!`(必填)
|
|
314
|
+
- ✅ `string?`(显式可选)
|
|
315
|
+
- ✅ `string:3-32?`(范围可选)
|
|
316
|
+
- ✅ `email?`(格式可选)
|
|
317
|
+
|
|
318
|
+
**测试结果**:
|
|
319
|
+
```
|
|
320
|
+
========================================
|
|
321
|
+
测试总结
|
|
322
|
+
========================================
|
|
323
|
+
✅ string(默认可选)- 支持
|
|
324
|
+
✅ string!(必填)- 支持
|
|
325
|
+
✅ string?(显式可选)- 支持
|
|
326
|
+
|
|
327
|
+
🎯 结论:
|
|
328
|
+
1. string 和 string? 行为相同(都是可选)
|
|
329
|
+
2. string? 提供更明确的语义表达
|
|
330
|
+
3. 建议:在需要明确表达"可选"时使用 ?
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
---
|
|
334
|
+
|
|
335
|
+
### 3. 类型定义验证
|
|
336
|
+
|
|
337
|
+
**工具**: TypeScript 编译器 + IDE 类型检查
|
|
338
|
+
|
|
339
|
+
**验证结果**:
|
|
340
|
+
- ✅ 无类型错误
|
|
341
|
+
- ⚠️ 2个可忽略警告
|
|
342
|
+
- ✅ dsl.error 类型完整
|
|
343
|
+
- ✅ I18nError 类型完整
|
|
344
|
+
- ✅ 所有方法签名正确
|
|
345
|
+
|
|
346
|
+
---
|
|
347
|
+
|
|
348
|
+
## 🔄 内部改进
|
|
349
|
+
|
|
350
|
+
### 统一 CHANGELOG.md 格式
|
|
351
|
+
|
|
352
|
+
**参考**: monSQLize/CHANGELOG.md
|
|
353
|
+
|
|
354
|
+
**改进内容**:
|
|
355
|
+
- ✅ 详细变更移至 `changelogs/` 目录
|
|
356
|
+
- ✅ CHANGELOG.md 保留版本概览和里程碑摘要
|
|
357
|
+
- ✅ 增加版本概览表格
|
|
358
|
+
- ✅ 增加变更统计
|
|
359
|
+
- ✅ 增加里程碑版本摘要
|
|
360
|
+
|
|
361
|
+
**格式特点**:
|
|
362
|
+
- ✅ 清晰的表格布局
|
|
363
|
+
- ✅ 统一的日期格式(YYYY-MM-DD)
|
|
364
|
+
- ✅ 重要性标记(⭐数量)
|
|
365
|
+
- ✅ Emoji 图标分类(🔧🐛🎉📚✅)
|
|
366
|
+
- ✅ 详细链接到 changelogs/ 目录
|
|
367
|
+
|
|
368
|
+
---
|
|
369
|
+
|
|
370
|
+
## 📦 依赖变更
|
|
371
|
+
|
|
372
|
+
**无依赖变更**
|
|
373
|
+
|
|
374
|
+
---
|
|
375
|
+
|
|
376
|
+
## 🎯 升级指南
|
|
377
|
+
|
|
378
|
+
### 从 v1.1.3 升级到 v1.1.4
|
|
379
|
+
|
|
380
|
+
**破坏性变更**: ❌ 无
|
|
381
|
+
|
|
382
|
+
**推荐操作**:
|
|
383
|
+
```bash
|
|
384
|
+
npm install schema-dsl@1.1.4
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
**无需修改代码**: 本次更新仅修复 TypeScript 类型定义,不影响运行时行为。
|
|
388
|
+
|
|
389
|
+
---
|
|
390
|
+
|
|
391
|
+
## 📊 统计信息
|
|
392
|
+
|
|
393
|
+
### 代码变更
|
|
394
|
+
|
|
395
|
+
| 文件 | 添加 | 删除 | 说明 |
|
|
396
|
+
|------|------|------|------|
|
|
397
|
+
| index.d.ts | 20 | 9 | 修复重复签名 + 完善注释 |
|
|
398
|
+
| CHANGELOG.md | 150 | 1200 | 格式重构,详情移至 changelogs/ |
|
|
399
|
+
| README.md | 80 | 10 | 添加运行时多语言示例 |
|
|
400
|
+
| STATUS.md | 30 | 10 | 更新版本信息 |
|
|
401
|
+
| package.json | 1 | 1 | 版本号更新 |
|
|
402
|
+
| changelogs/v1.1.4.md | 500 | 0 | 新增详细变更文档 |
|
|
403
|
+
|
|
404
|
+
### 文档完整性
|
|
405
|
+
|
|
406
|
+
- ✅ 多语言文档覆盖: 100%
|
|
407
|
+
- ✅ API 文档完整性: 100%
|
|
408
|
+
- ✅ 示例代码数量: 15+
|
|
409
|
+
- ✅ 测试用例数量: 921
|
|
410
|
+
|
|
411
|
+
---
|
|
412
|
+
|
|
413
|
+
## 🙏 致谢
|
|
414
|
+
|
|
415
|
+
感谢 monSQLize 项目发现并报告类型定义问题。
|
|
416
|
+
|
|
417
|
+
---
|
|
418
|
+
|
|
419
|
+
## 🔗 相关链接
|
|
420
|
+
|
|
421
|
+
- [GitHub Repository](https://github.com/vextjs/schema-dsl)
|
|
422
|
+
- [npm Package](https://www.npmjs.com/package/schema-dsl)
|
|
423
|
+
- [完整文档](./docs/INDEX.md)
|
|
424
|
+
- [运行时多语言支持](./docs/runtime-locale-support.md)
|
|
425
|
+
- [多语言用户指南](./docs/i18n-user-guide.md)
|
|
426
|
+
|
|
427
|
+
---
|
|
428
|
+
|
|
429
|
+
**发布者**: schema-dsl Team
|
|
430
|
+
**发布时间**: 2026-01-13
|
|
431
|
+
**下一版本**: v1.1.5 (计划中)
|
|
432
|
+
|
package/docs/dsl-syntax.md
CHANGED
|
@@ -86,17 +86,28 @@ const schema = dsl({
|
|
|
86
86
|
'uuid' // UUID
|
|
87
87
|
```
|
|
88
88
|
|
|
89
|
-
### 2.
|
|
89
|
+
### 2. 必填与可选标记
|
|
90
90
|
|
|
91
|
-
使用 `!`
|
|
91
|
+
使用 `!` 标记必填字段,使用 `?` 显式标记可选字段:
|
|
92
92
|
|
|
93
93
|
```javascript
|
|
94
94
|
const schema = dsl({
|
|
95
95
|
username: 'string!', // 必填
|
|
96
|
-
nickname: 'string'
|
|
96
|
+
nickname: 'string', // 可选(默认)
|
|
97
|
+
bio: 'string?', // 显式可选(等价于 string)
|
|
98
|
+
email: 'email?' // 可选邮箱
|
|
97
99
|
});
|
|
98
100
|
```
|
|
99
101
|
|
|
102
|
+
**说明**:
|
|
103
|
+
- `!` - 必填标记,字段不能为空
|
|
104
|
+
- `?` - 可选标记,字段可以为空(默认行为)
|
|
105
|
+
- 不加标记 - 默认可选
|
|
106
|
+
|
|
107
|
+
**推荐**:
|
|
108
|
+
- 使用 `!` 明确标记必填字段
|
|
109
|
+
- 使用 `?` 在需要明确表达"可选"时增强代码可读性
|
|
110
|
+
|
|
100
111
|
### 3. 对象必填
|
|
101
112
|
|
|
102
113
|
支持两种方式:
|