schema-dsl 2.3.0
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/.eslintignore +10 -0
- package/.eslintrc.json +27 -0
- package/.github/CODE_OF_CONDUCT.md +45 -0
- package/.github/ISSUE_TEMPLATE/bug_report.md +57 -0
- package/.github/ISSUE_TEMPLATE/config.yml +11 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +45 -0
- package/.github/ISSUE_TEMPLATE/question.md +31 -0
- package/.github/PULL_REQUEST_TEMPLATE.md +70 -0
- package/.github/SECURITY.md +184 -0
- package/.github/workflows/ci.yml +35 -0
- package/CHANGELOG.md +633 -0
- package/CONTRIBUTING.md +368 -0
- package/LICENSE +21 -0
- package/README.md +1122 -0
- package/STATUS.md +273 -0
- package/docs/FEATURE-INDEX.md +521 -0
- package/docs/INDEX.md +224 -0
- package/docs/api-reference.md +1098 -0
- package/docs/best-practices.md +672 -0
- package/docs/cache-manager.md +336 -0
- package/docs/design-philosophy.md +602 -0
- package/docs/dsl-syntax.md +654 -0
- package/docs/dynamic-locale.md +552 -0
- package/docs/error-handling.md +703 -0
- package/docs/export-guide.md +459 -0
- package/docs/faq.md +576 -0
- package/docs/frontend-i18n-guide.md +290 -0
- package/docs/i18n-user-guide.md +488 -0
- package/docs/label-vs-description.md +262 -0
- package/docs/markdown-exporter.md +398 -0
- package/docs/mongodb-exporter.md +279 -0
- package/docs/multi-type-support.md +319 -0
- package/docs/mysql-exporter.md +257 -0
- package/docs/plugin-system.md +542 -0
- package/docs/postgresql-exporter.md +290 -0
- package/docs/quick-start.md +761 -0
- package/docs/schema-helper.md +340 -0
- package/docs/schema-utils.md +492 -0
- package/docs/string-extensions.md +480 -0
- package/docs/troubleshooting.md +471 -0
- package/docs/type-converter.md +319 -0
- package/docs/type-reference.md +219 -0
- package/docs/validate.md +486 -0
- package/docs/validation-guide.md +484 -0
- package/examples/array-dsl-example.js +227 -0
- package/examples/custom-extension.js +85 -0
- package/examples/dsl-match-example.js +74 -0
- package/examples/dsl-style.js +118 -0
- package/examples/dynamic-locale-configuration.js +348 -0
- package/examples/dynamic-locale-example.js +287 -0
- package/examples/export-demo.js +130 -0
- package/examples/i18n-full-demo.js +310 -0
- package/examples/i18n-memory-safety.examples.js +268 -0
- package/examples/markdown-export.js +71 -0
- package/examples/middleware-usage.js +93 -0
- package/examples/password-reset/README.md +153 -0
- package/examples/password-reset/schema.js +26 -0
- package/examples/password-reset/test.js +101 -0
- package/examples/plugin-system.examples.js +205 -0
- package/examples/simple-example.js +122 -0
- package/examples/string-extensions.js +297 -0
- package/examples/user-registration/README.md +156 -0
- package/examples/user-registration/routes.js +92 -0
- package/examples/user-registration/schema.js +150 -0
- package/examples/user-registration/server.js +74 -0
- package/index.d.ts +1999 -0
- package/index.js +270 -0
- package/index.mjs +30 -0
- package/lib/adapters/DslAdapter.js +653 -0
- package/lib/adapters/index.js +20 -0
- package/lib/config/constants.js +286 -0
- package/lib/config/patterns/creditCard.js +9 -0
- package/lib/config/patterns/idCard.js +9 -0
- package/lib/config/patterns/index.js +8 -0
- package/lib/config/patterns/licensePlate.js +4 -0
- package/lib/config/patterns/passport.js +4 -0
- package/lib/config/patterns/phone.js +9 -0
- package/lib/config/patterns/postalCode.js +5 -0
- package/lib/core/CacheManager.js +376 -0
- package/lib/core/DslBuilder.js +740 -0
- package/lib/core/ErrorCodes.js +233 -0
- package/lib/core/ErrorFormatter.js +342 -0
- package/lib/core/JSONSchemaCore.js +347 -0
- package/lib/core/Locale.js +119 -0
- package/lib/core/MessageTemplate.js +89 -0
- package/lib/core/PluginManager.js +448 -0
- package/lib/core/StringExtensions.js +209 -0
- package/lib/core/Validator.js +316 -0
- package/lib/exporters/MarkdownExporter.js +420 -0
- package/lib/exporters/MongoDBExporter.js +162 -0
- package/lib/exporters/MySQLExporter.js +212 -0
- package/lib/exporters/PostgreSQLExporter.js +289 -0
- package/lib/exporters/index.js +24 -0
- package/lib/locales/en-US.js +65 -0
- package/lib/locales/es-ES.js +66 -0
- package/lib/locales/fr-FR.js +66 -0
- package/lib/locales/index.js +8 -0
- package/lib/locales/ja-JP.js +66 -0
- package/lib/locales/zh-CN.js +93 -0
- package/lib/utils/LRUCache.js +174 -0
- package/lib/utils/SchemaHelper.js +240 -0
- package/lib/utils/SchemaUtils.js +313 -0
- package/lib/utils/TypeConverter.js +245 -0
- package/lib/utils/index.js +13 -0
- package/lib/validators/CustomKeywords.js +203 -0
- package/lib/validators/index.js +11 -0
- package/package.json +70 -0
- package/plugins/custom-format.js +101 -0
- package/plugins/custom-validator.js +200 -0
package/docs/faq.md
ADDED
|
@@ -0,0 +1,576 @@
|
|
|
1
|
+
# 常见问题解答 (FAQ)
|
|
2
|
+
|
|
3
|
+
> **更新时间**: 2025-12-25
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## 📑 目录
|
|
9
|
+
|
|
10
|
+
- [基础问题](#基础问题)
|
|
11
|
+
- [DSL 语法问题](#dsl-语法问题)
|
|
12
|
+
- [验证问题](#验证问题)
|
|
13
|
+
- [性能问题](#性能问题)
|
|
14
|
+
- [设计理念](#设计理念)
|
|
15
|
+
- [错误处理](#错误处理)
|
|
16
|
+
- [数据库导出](#数据库导出)
|
|
17
|
+
- [TypeScript 支持](#typescript-支持)
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## 基础问题
|
|
22
|
+
|
|
23
|
+
### Q: SchemaIO 和 Joi、Yup 有什么区别?
|
|
24
|
+
|
|
25
|
+
**A**: SchemaIO 采用 DSL 语法,更简洁:
|
|
26
|
+
|
|
27
|
+
```javascript
|
|
28
|
+
// SchemaIO - 简洁
|
|
29
|
+
const schema = dsl({
|
|
30
|
+
username: 'string:3-32!',
|
|
31
|
+
email: 'email!'
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
// Joi - 繁琐
|
|
35
|
+
const schema = Joi.object({
|
|
36
|
+
username: Joi.string().min(3).max(32).required(),
|
|
37
|
+
email: Joi.string().email().required()
|
|
38
|
+
});
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
**主要区别**:
|
|
42
|
+
- 更简洁的 DSL 语法
|
|
43
|
+
- 支持数据库 Schema 导出
|
|
44
|
+
- 内置常见验证器(username、password、phone)
|
|
45
|
+
- 基于 JSON Schema 标准
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
### Q: 如何安装 SchemaIO?
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
npm install schema-dsl
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
**Node.js 版本要求**:>= 12.0.0
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
### Q: 支持 ES Modules 吗?
|
|
60
|
+
|
|
61
|
+
**A**: 支持。
|
|
62
|
+
|
|
63
|
+
```javascript
|
|
64
|
+
// CommonJS
|
|
65
|
+
const { dsl, validate } = require('schema-dsl');
|
|
66
|
+
|
|
67
|
+
// ES Modules
|
|
68
|
+
import { dsl, validate } from 'schema-dsl';
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## DSL 语法问题
|
|
74
|
+
|
|
75
|
+
### Q: `'string:3-32!'` 是什么意思?
|
|
76
|
+
|
|
77
|
+
**A**: 这是 DSL 语法:
|
|
78
|
+
- `string` - 类型
|
|
79
|
+
- `3-32` - 长度范围(最小3,最大32)
|
|
80
|
+
- `!` - 必填
|
|
81
|
+
|
|
82
|
+
更多示例:
|
|
83
|
+
```javascript
|
|
84
|
+
'string:10' // 最大长度10
|
|
85
|
+
'string:3-' // 最小长度3
|
|
86
|
+
'number:0-100' // 数值范围0-100
|
|
87
|
+
'email!' // 必填邮箱
|
|
88
|
+
'a|b|c' // 枚举值
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
### Q: 如何定义数组?
|
|
94
|
+
|
|
95
|
+
**A**: 使用 `array` 类型:
|
|
96
|
+
|
|
97
|
+
```javascript
|
|
98
|
+
// 简单数组
|
|
99
|
+
tags: 'array'
|
|
100
|
+
|
|
101
|
+
// 带长度约束
|
|
102
|
+
tags: 'array:1-10' // 1-10个元素
|
|
103
|
+
tags: 'array!1-10' // 必填,1-10个元素
|
|
104
|
+
|
|
105
|
+
// 带元素类型
|
|
106
|
+
tags: 'array<string>' // 字符串数组
|
|
107
|
+
tags: 'array<number>' // 数字数组
|
|
108
|
+
tags: 'array<string:1-20>' // 带约束的字符串数组
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
### Q: 如何定义嵌套对象?
|
|
114
|
+
|
|
115
|
+
**A**: 直接嵌套即可:
|
|
116
|
+
|
|
117
|
+
```javascript
|
|
118
|
+
const schema = dsl({
|
|
119
|
+
user: {
|
|
120
|
+
name: 'string!',
|
|
121
|
+
address: {
|
|
122
|
+
city: 'string!',
|
|
123
|
+
zip: 'string:5-10!'
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
### Q: 如何使用 String 扩展?
|
|
132
|
+
|
|
133
|
+
**A**: 字符串可以直接链式调用方法:
|
|
134
|
+
|
|
135
|
+
```javascript
|
|
136
|
+
const schema = dsl({
|
|
137
|
+
email: 'email!'
|
|
138
|
+
.label('邮箱地址')
|
|
139
|
+
.messages({
|
|
140
|
+
'required': '{{#label}}不能为空',
|
|
141
|
+
'format': '请输入有效的{{#label}}'
|
|
142
|
+
}),
|
|
143
|
+
|
|
144
|
+
username: 'string:3-32!'
|
|
145
|
+
.pattern(/^[a-z0-9_]+$/)
|
|
146
|
+
.label('用户名')
|
|
147
|
+
.username('medium')
|
|
148
|
+
});
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## 验证问题
|
|
154
|
+
|
|
155
|
+
### Q: 如何验证数据?
|
|
156
|
+
|
|
157
|
+
**A**: 使用 `validate()` 函数或 `Validator` 类:
|
|
158
|
+
|
|
159
|
+
```javascript
|
|
160
|
+
// 方式1:便捷函数
|
|
161
|
+
const { dsl, validate } = require('schema-dsl');
|
|
162
|
+
const result = validate(schema, data);
|
|
163
|
+
|
|
164
|
+
// 方式2:Validator 实例
|
|
165
|
+
const { Validator } = require('schema-dsl');
|
|
166
|
+
const validator = new Validator();
|
|
167
|
+
const result = validator.validate(schema, data);
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
### Q: 验证结果的格式是什么?
|
|
173
|
+
|
|
174
|
+
**A**: 返回对象包含:
|
|
175
|
+
|
|
176
|
+
```javascript
|
|
177
|
+
{
|
|
178
|
+
valid: true/false, // 是否通过
|
|
179
|
+
errors: [], // 错误数组(如果有)
|
|
180
|
+
data: {}, // 验证后的数据(可能包含默认值)
|
|
181
|
+
performance: { // 性能信息
|
|
182
|
+
duration: 1.5 // 验证耗时(毫秒)
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
### Q: 如何获取所有错误而不是只有第一个?
|
|
190
|
+
|
|
191
|
+
**A**: 默认就是返回所有错误。如果只需要第一个:
|
|
192
|
+
|
|
193
|
+
```javascript
|
|
194
|
+
const validator = new Validator({ allErrors: false });
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
### Q: 如何使用默认值?
|
|
200
|
+
|
|
201
|
+
**A**: 使用 `.default()` 方法:
|
|
202
|
+
|
|
203
|
+
```javascript
|
|
204
|
+
const schema = dsl({
|
|
205
|
+
status: 'string'.default('active'),
|
|
206
|
+
count: 'integer'.default(0)
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
const result = validate(schema, {});
|
|
210
|
+
console.log(result.data);
|
|
211
|
+
// { status: 'active', count: 0 }
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## 性能问题
|
|
217
|
+
|
|
218
|
+
### Q: Schema-DSL 的性能怎么样?
|
|
219
|
+
|
|
220
|
+
**A**: 性能优秀,排名第3:
|
|
221
|
+
|
|
222
|
+
| 库名 | 每秒操作数 | 排名 |
|
|
223
|
+
|------|-----------|------|
|
|
224
|
+
| Ajv | 2,000,000 ops/s | 🥇 第1 |
|
|
225
|
+
| Zod | 526,316 ops/s | 🥈 第2 |
|
|
226
|
+
| **Schema-DSL** | **277,778 ops/s** | 🥉 **第3** |
|
|
227
|
+
| Joi | 97,087 ops/s | 第4 |
|
|
228
|
+
| Yup | 60,241 ops/s | 第5 |
|
|
229
|
+
|
|
230
|
+
**结论**:
|
|
231
|
+
- ✅ 比 Joi 快 **2.86倍**
|
|
232
|
+
- ✅ 比 Yup 快 **4.61倍**
|
|
233
|
+
- ✅ 对大多数应用足够(27万+ ops/s)
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
### Q: 为什么比 Zod 慢?
|
|
238
|
+
|
|
239
|
+
**A**: 因为 Schema-DSL 使用**运行时解析 DSL**,而 Zod 是**编译时构建**。
|
|
240
|
+
|
|
241
|
+
**权衡**:
|
|
242
|
+
```
|
|
243
|
+
损失: 比 Zod 慢 1.9倍
|
|
244
|
+
换来:
|
|
245
|
+
✅ 代码量减少 65%
|
|
246
|
+
✅ 完全动态的验证规则
|
|
247
|
+
✅ 多租户/配置驱动支持
|
|
248
|
+
✅ 前后端共享规则
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
---
|
|
252
|
+
|
|
253
|
+
### Q: 什么时候性能会成为瓶颈?
|
|
254
|
+
|
|
255
|
+
**A**: 以下场景才可能成为瓶颈:
|
|
256
|
+
|
|
257
|
+
1. **API 网关**(每秒 >50万次验证)
|
|
258
|
+
2. **高并发服务**(每秒 >50万次请求)
|
|
259
|
+
3. **实时数据处理**(毫秒级延迟要求)
|
|
260
|
+
|
|
261
|
+
**大多数应用**(每秒 <10万次验证)不会遇到性能瓶颈。
|
|
262
|
+
|
|
263
|
+
---
|
|
264
|
+
|
|
265
|
+
### Q: 验证速度慢怎么办?
|
|
266
|
+
|
|
267
|
+
**A**: 使用预编译和缓存:
|
|
268
|
+
|
|
269
|
+
```javascript
|
|
270
|
+
// 1. 使用预编译
|
|
271
|
+
const validator = new Validator();
|
|
272
|
+
const validateUser = validator.compile(userSchema);
|
|
273
|
+
|
|
274
|
+
// 2. 启用缓存(v2.3.0)
|
|
275
|
+
const validator = new Validator({
|
|
276
|
+
cache: {
|
|
277
|
+
maxSize: 5000, // 缓存5000个Schema
|
|
278
|
+
ttl: 3600000 // 1小时过期
|
|
279
|
+
}
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
// 3. 复用 Validator 实例
|
|
283
|
+
// ❌ 错误:每次都创建新实例
|
|
284
|
+
app.post('/api/users', (req, res) => {
|
|
285
|
+
const validator = new Validator(); // 慢
|
|
286
|
+
// ...
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
// ✅ 正确:复用实例
|
|
290
|
+
const validator = new Validator();
|
|
291
|
+
app.post('/api/users', (req, res) => {
|
|
292
|
+
const result = validator.validate(schema, req.body); // 快
|
|
293
|
+
// ...
|
|
294
|
+
});
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
---
|
|
298
|
+
|
|
299
|
+
### Q: 缓存如何工作?
|
|
300
|
+
|
|
301
|
+
**A**: SchemaIO 内置 LRU 缓存(v2.3.0):
|
|
302
|
+
|
|
303
|
+
```javascript
|
|
304
|
+
const validator = new Validator({
|
|
305
|
+
cache: {
|
|
306
|
+
maxSize: 5000, // 最大缓存5000条
|
|
307
|
+
ttl: 3600000 // 1小时过期
|
|
308
|
+
}
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
// 缓存统计
|
|
312
|
+
const stats = validator.cache.getStats();
|
|
313
|
+
console.log(stats);
|
|
314
|
+
// {
|
|
315
|
+
// size: 150, // 当前缓存数
|
|
316
|
+
// hits: 8500, // 缓存命中次数
|
|
317
|
+
// misses: 150, // 缓存未命中次数
|
|
318
|
+
// evictions: 0 // 驱逐次数
|
|
319
|
+
// }
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
---
|
|
323
|
+
|
|
324
|
+
### Q: 如何批量验证?
|
|
325
|
+
|
|
326
|
+
**A**: 使用 `validateBatch()`:
|
|
327
|
+
|
|
328
|
+
```javascript
|
|
329
|
+
const results = validator.validateBatch(schema, [data1, data2, data3]);
|
|
330
|
+
// 返回结果数组
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
---
|
|
334
|
+
|
|
335
|
+
## 设计理念
|
|
336
|
+
|
|
337
|
+
### Q: 为什么选择运行时解析而不是编译时构建?
|
|
338
|
+
|
|
339
|
+
**A**: 这是有意的设计选择,优先考虑**灵活性**而非**极致性能**。
|
|
340
|
+
|
|
341
|
+
**运行时解析的优势**:
|
|
342
|
+
1. ✅ **完全动态** - 可从配置/数据库动态生成规则
|
|
343
|
+
2. ✅ **多租户支持** - 每个租户不同规则,零代码修改
|
|
344
|
+
3. ✅ **可序列化** - 可存储、传输、共享
|
|
345
|
+
4. ✅ **前后端共享** - 一套规则,两端使用
|
|
346
|
+
5. ✅ **低代码基础** - 可视化配置表单验证
|
|
347
|
+
|
|
348
|
+
**编译时构建的限制**:
|
|
349
|
+
- ❌ Schema 固定,无法动态调整
|
|
350
|
+
- ❌ 无法序列化和传输
|
|
351
|
+
- ❌ 多租户困难
|
|
352
|
+
- ❌ 无法从数据库读取规则
|
|
353
|
+
|
|
354
|
+
**详细说明**: [设计理念文档](design-philosophy.md)
|
|
355
|
+
|
|
356
|
+
---
|
|
357
|
+
|
|
358
|
+
### Q: Schema-DSL 适合什么场景?
|
|
359
|
+
|
|
360
|
+
**A**: ✅ **最适合的场景**:
|
|
361
|
+
|
|
362
|
+
1. **多租户 SaaS 系统** - 每个租户不同验证规则
|
|
363
|
+
2. **后台管理系统** - 管理员配置表单验证
|
|
364
|
+
3. **配置驱动开发** - 验证规则存储在配置/数据库
|
|
365
|
+
4. **低代码/无代码平台** - 可视化表单构建器
|
|
366
|
+
5. **快速原型开发** - 5分钟上手,代码量最少
|
|
367
|
+
6. **前后端共享验证** - 一套规则,两端使用
|
|
368
|
+
|
|
369
|
+
⚠️ **不适合的场景**:
|
|
370
|
+
1. 极致性能要求(>50万 ops/s)→ 推荐 **Zod** 或 **Ajv**
|
|
371
|
+
2. TypeScript 强类型推断 → 推荐 **Zod**
|
|
372
|
+
3. 静态验证规则 → 推荐 **Zod**
|
|
373
|
+
|
|
374
|
+
---
|
|
375
|
+
|
|
376
|
+
### Q: 为什么不做成像 Zod 那样的编译时库?
|
|
377
|
+
|
|
378
|
+
**A**: 因为会失去核心价值:
|
|
379
|
+
|
|
380
|
+
**失去的能力**:
|
|
381
|
+
```javascript
|
|
382
|
+
// ❌ 无法从数据库读取规则
|
|
383
|
+
const rules = await db.findOne({ entity: 'user' });
|
|
384
|
+
const schema = dsl(rules);
|
|
385
|
+
|
|
386
|
+
// ❌ 无法多租户动态规则
|
|
387
|
+
function getTenantSchema(tenantId) {
|
|
388
|
+
return dsl(tenantConfig[tenantId]);
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
// ❌ 无法通过 API 传输
|
|
392
|
+
res.json({ validationRules: rules });
|
|
393
|
+
|
|
394
|
+
// ❌ 无法后台配置表单验证
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
**保留的能力**:
|
|
398
|
+
```javascript
|
|
399
|
+
// ✅ 完全动态
|
|
400
|
+
const schema = dsl({
|
|
401
|
+
username: `string:${config.min}-${config.max}!`
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
// ✅ 可序列化
|
|
405
|
+
JSON.stringify({ username: 'string:3-32!' });
|
|
406
|
+
|
|
407
|
+
// ✅ 前后端共享
|
|
408
|
+
// 后端定义 → API传输 → 前端使用
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
---
|
|
412
|
+
|
|
413
|
+
### Q: 性能和灵活性如何平衡?
|
|
414
|
+
|
|
415
|
+
**A**: Schema-DSL 的设计优先级:
|
|
416
|
+
|
|
417
|
+
```
|
|
418
|
+
灵活性 > 易用性 > 性能
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
**权衡结果**:
|
|
422
|
+
- 损失:比 Zod 慢 1.9倍
|
|
423
|
+
- 换来:完全的动态性 + 代码量减少 65%
|
|
424
|
+
- 结论:对大多数应用(<10万 ops/s)足够
|
|
425
|
+
|
|
426
|
+
**如果需要极致性能**: 推荐使用 Zod(526k ops/s)或 Ajv(2M ops/s)
|
|
427
|
+
|
|
428
|
+
---
|
|
429
|
+
|
|
430
|
+
## 错误处理
|
|
431
|
+
|
|
432
|
+
### Q: 如何自定义错误消息?
|
|
433
|
+
|
|
434
|
+
**A**: 使用 `.messages()` 方法:
|
|
435
|
+
|
|
436
|
+
```javascript
|
|
437
|
+
username: 'string:3-32!'
|
|
438
|
+
.label('用户名')
|
|
439
|
+
.messages({
|
|
440
|
+
'min': '{{#label}}太短了',
|
|
441
|
+
'max': '{{#label}}太长了',
|
|
442
|
+
'required': '请输入{{#label}}'
|
|
443
|
+
})
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
---
|
|
447
|
+
|
|
448
|
+
### Q: 如何支持多语言?
|
|
449
|
+
|
|
450
|
+
**A**: 使用 `Locale` 类:
|
|
451
|
+
|
|
452
|
+
```javascript
|
|
453
|
+
const { Locale } = require('schema-dsl');
|
|
454
|
+
|
|
455
|
+
// 添加语言包
|
|
456
|
+
Locale.addLocale('zh-CN', {
|
|
457
|
+
'required': '{{#label}}不能为空',
|
|
458
|
+
'min': '{{#label}}长度不能少于{{#limit}}'
|
|
459
|
+
});
|
|
460
|
+
|
|
461
|
+
// 验证时指定语言
|
|
462
|
+
validator.validate(schema, data, { locale: 'zh-CN' });
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
---
|
|
466
|
+
|
|
467
|
+
### Q: 错误路径格式是什么?
|
|
468
|
+
|
|
469
|
+
**A**: JSON Pointer 格式:
|
|
470
|
+
|
|
471
|
+
```javascript
|
|
472
|
+
'/username' // 顶层字段
|
|
473
|
+
'/user/name' // 嵌套字段
|
|
474
|
+
'/items/0/name' // 数组元素
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
---
|
|
478
|
+
|
|
479
|
+
## 数据库导出
|
|
480
|
+
|
|
481
|
+
### Q: 如何导出为 MongoDB Schema?
|
|
482
|
+
|
|
483
|
+
```javascript
|
|
484
|
+
const { exporters } = require('schema-dsl');
|
|
485
|
+
|
|
486
|
+
const exporter = new exporters.MongoDBExporter();
|
|
487
|
+
const mongoSchema = exporter.export(schema);
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
---
|
|
491
|
+
|
|
492
|
+
### Q: 如何导出为 MySQL DDL?
|
|
493
|
+
|
|
494
|
+
```javascript
|
|
495
|
+
const exporter = new exporters.MySQLExporter();
|
|
496
|
+
const ddl = exporter.export('table_name', schema);
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
---
|
|
500
|
+
|
|
501
|
+
### Q: 如何导出为 PostgreSQL DDL?
|
|
502
|
+
|
|
503
|
+
```javascript
|
|
504
|
+
const exporter = new exporters.PostgreSQLExporter({ schema: 'public' });
|
|
505
|
+
const ddl = exporter.export('table_name', schema);
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
---
|
|
509
|
+
|
|
510
|
+
### Q: 导出时如何添加注释?
|
|
511
|
+
|
|
512
|
+
**A**: 使用 `.description()`:
|
|
513
|
+
|
|
514
|
+
```javascript
|
|
515
|
+
username: 'string:3-32!'
|
|
516
|
+
.description('用户登录名,只能包含字母数字')
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
MySQL 会生成 `COMMENT`,PostgreSQL 会生成 `COMMENT ON COLUMN`。
|
|
520
|
+
|
|
521
|
+
---
|
|
522
|
+
|
|
523
|
+
## TypeScript 支持
|
|
524
|
+
|
|
525
|
+
### Q: SchemaIO 支持 TypeScript 吗?
|
|
526
|
+
|
|
527
|
+
**A**: 支持,类型定义在 `index.d.ts`:
|
|
528
|
+
|
|
529
|
+
```typescript
|
|
530
|
+
import { dsl, validate, DslBuilder, Validator } from 'schema-dsl';
|
|
531
|
+
|
|
532
|
+
const schema = dsl({
|
|
533
|
+
username: 'string:3-32!',
|
|
534
|
+
email: 'email!'
|
|
535
|
+
});
|
|
536
|
+
|
|
537
|
+
const result = validate(schema, data);
|
|
538
|
+
if (result.valid) {
|
|
539
|
+
console.log(result.data);
|
|
540
|
+
}
|
|
541
|
+
```
|
|
542
|
+
|
|
543
|
+
---
|
|
544
|
+
|
|
545
|
+
### Q: 如何获得 String 扩展的类型提示?
|
|
546
|
+
|
|
547
|
+
**A**: 类型定义包含全局 String 扩展:
|
|
548
|
+
|
|
549
|
+
```typescript
|
|
550
|
+
// TypeScript 会识别这些方法
|
|
551
|
+
const schema = dsl({
|
|
552
|
+
email: 'email!'.label('邮箱').messages({ ... })
|
|
553
|
+
});
|
|
554
|
+
```
|
|
555
|
+
|
|
556
|
+
---
|
|
557
|
+
|
|
558
|
+
## 更多问题
|
|
559
|
+
|
|
560
|
+
如果您有其他问题:
|
|
561
|
+
|
|
562
|
+
1. 查看 [完整文档](INDEX.md)
|
|
563
|
+
2. 查看 [DSL 语法指南](dsl-syntax.md)
|
|
564
|
+
3. 查看 [API 参考](api-reference.md)
|
|
565
|
+
4. 提交 [GitHub Issue](https://github.com/schema-dsl/schema-dsl/issues)
|
|
566
|
+
|
|
567
|
+
---
|
|
568
|
+
|
|
569
|
+
## 相关文档
|
|
570
|
+
|
|
571
|
+
- [快速开始](quick-start.md)
|
|
572
|
+
- [DSL 语法](dsl-syntax.md)
|
|
573
|
+
- [验证指南](validation-guide.md)
|
|
574
|
+
- [导出指南](export-guide.md)
|
|
575
|
+
- [错误处理](error-handling.md)
|
|
576
|
+
|