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