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/validate.md CHANGED
@@ -1,486 +1,506 @@
1
- # validate 方法详细文档
2
-
3
- ## 📑 目录
4
-
5
- ### 基础概念
6
- - [概述](#概述) - validate 方法介绍
7
- - [方法签名](#方法签名) - API 定义
8
-
9
- ### 参数详解
10
- - [参数详解](#参数详解)
11
- - [schema 参数](#schema-参数)
12
- - [options 对象属性](#options-对象属性)
13
- - [返回值详解](#返回值详解)
14
- - [valid (Boolean)](#valid-boolean)
15
- - [errors (Array)](#errors-array)
16
- - [data (Any)](#data-any)
17
-
18
- ### 使用示例
19
- - [基础示例](#基础示例)
20
- - [示例 1: 验证简单对象](#示例-1-验证简单对象)
21
- - [示例 2: 验证复杂对象](#示例-2-验证复杂对象)
22
- - [示例 3: 处理验证错误](#示例-3-处理验证错误)
23
- - [示例 4: 使用默认值](#示例-4-使用默认值)
24
-
25
- ### 高级功能
26
- - [高级用法](#高级用法)
27
- - [批量验证](#批量验证)
28
- - [自定义错误格式](#自定义错误格式)
29
- - [性能优化](#性能优化)
30
-
31
- ### 参考资料
32
- - [相关文档](#相关文档)
33
- - [API 参考](#api-参考)
34
-
35
- ---
36
-
37
- ## 概述
38
-
39
- `validate` 是 Validator 类的核心方法,用于验证数据是否符合 JSON Schema 定义。基于高性能的 ajv 验证器实现。
40
-
41
- ---
42
-
43
- ## 方法签名
44
-
45
- ```javascript
46
- validator.validate(schema, data, options = {})
47
- ```
48
-
49
- **参数说明**:
50
- - `schema` (Object|Function): JSON Schema 对象或已编译的验证函数
51
- - `data` (Any): 待验证的数据
52
- - `options` (Object): 验证选项(可选)
53
-
54
- **返回值**:
55
- ```javascript
56
- {
57
- valid: Boolean, // 是否有效
58
- errors: Array, // 错误列表
59
- data: Any // 验证后的数据(可能被 useDefaults 修改)
60
- }
61
- ```
62
-
63
- ---
64
-
65
- ## 参数详解
66
-
67
- ### schema 参数
68
-
69
- JSON Schema 对象,支持 JSON Schema Draft 7 标准。
70
-
71
- | 参数类型 | 说明 | 来源 |
72
- |---------|------|------|
73
- | Object | JSON Schema 对象 | JSON Schema 标准 ✅ |
74
- | Function | 已编译的验证函数(通过 `compile()` 生成) | ajv ✅ |
75
-
76
- ### options 对象属性
77
-
78
- | 参数 | 类型 | 必填 | 默认值 | 说明 |
79
- |------|------|------|--------|------|
80
- | `format` | Boolean | 否 | `true` | 是否格式化错误信息 |
81
-
82
- **图例说明**:
83
- - ✅ **标准功能**: 该参数来自 JSON Schema 或 ajv 标准
84
-
85
- ---
86
-
87
- ## 返回值详解
88
-
89
- ### valid (Boolean)
90
-
91
- 表示数据是否通过验证。
92
-
93
- ```javascript
94
- result.valid === true // 验证通过
95
- result.valid === false // 验证失败
96
- ```
97
-
98
- ### errors (Array)
99
-
100
- 验证错误列表,当 `valid` 为 `false` 时包含详细错误信息。
101
-
102
- **错误对象结构**:
103
- ```javascript
104
- {
105
- path: String, // 错误字段路径,如 'user.email'
106
- message: String, // 错误描述信息
107
- keyword: String, // 触发的 Schema 关键字
108
- params: Object // 错误相关参数
109
- }
110
- ```
111
-
112
- ### data (Any)
113
-
114
- 验证后的数据。如果 Validator 配置了 `useDefaults: true`,则会应用 Schema 中定义的默认值。
115
-
116
- ---
117
-
118
- ## 基础示例
119
-
120
- ### 示例 1: 验证简单对象
121
-
122
- ```javascript
123
- const { Validator } = require('schema-dsl');
124
-
125
- const validator = new Validator();
126
-
127
- const schema = {
128
- type: 'object',
129
- properties: {
130
- name: { type: 'string' },
131
- age: { type: 'number' }
132
- },
133
- required: ['name']
134
- };
135
-
136
- const result = validator.validate(schema, {
137
- name: 'John',
138
- age: 25
139
- });
140
-
141
- console.log(result.valid); // true
142
- console.log(result.errors); // []
143
- ```
144
-
145
- ### 示例 2: 处理验证失败
146
-
147
- ```javascript
148
- const result = validator.validate(schema, {
149
- age: 'invalid'
150
- });
151
-
152
- console.log(result.valid); // false
153
- console.log(result.errors);
154
- // [
155
- // { path: '', message: "must have required property 'name'" },
156
- // { path: 'age', message: 'must be number' }
157
- // ]
158
- ```
159
-
160
- ---
161
-
162
- ## 高级示例
163
-
164
- ### 示例 3: 验证字符串约束
165
-
166
- ```javascript
167
- const schema = {
168
- type: 'string',
169
- minLength: 3,
170
- maxLength: 32,
171
- pattern: '^[a-zA-Z0-9]+$'
172
- };
173
-
174
- // 有效数据
175
- console.log(validator.validate(schema, 'john123').valid); // true
176
-
177
- // 太短
178
- console.log(validator.validate(schema, 'ab').valid); // false
179
-
180
- // 包含非法字符
181
- console.log(validator.validate(schema, 'john-123').valid); // false
182
- ```
183
-
184
- ### 示例 4: 验证数字范围
185
-
186
- ```javascript
187
- const schema = {
188
- type: 'number',
189
- minimum: 0,
190
- maximum: 100
191
- };
192
-
193
- console.log(validator.validate(schema, 50).valid); // true
194
- console.log(validator.validate(schema, -1).valid); // false
195
- console.log(validator.validate(schema, 101).valid); // false
196
- ```
197
-
198
- ### 示例 5: 验证邮箱格式
199
-
200
- ```javascript
201
- const schema = {
202
- type: 'string',
203
- format: 'email'
204
- };
205
-
206
- console.log(validator.validate(schema, 'test@example.com').valid); // true
207
- console.log(validator.validate(schema, 'invalid-email').valid); // false
208
- ```
209
-
210
- ### 示例 6: 验证枚举值
211
-
212
- ```javascript
213
- const schema = {
214
- type: 'string',
215
- enum: ['active', 'inactive', 'pending']
216
- };
217
-
218
- console.log(validator.validate(schema, 'active').valid); // true
219
- console.log(validator.validate(schema, 'invalid').valid); // false
220
- ```
221
-
222
- ### 示例 7: 验证嵌套对象
223
-
224
- ```javascript
225
- const schema = {
226
- type: 'object',
227
- properties: {
228
- user: {
229
- type: 'object',
230
- properties: {
231
- name: { type: 'string' },
232
- email: { type: 'string', format: 'email' }
233
- },
234
- required: ['name', 'email']
235
- }
236
- }
237
- };
238
-
239
- const data = {
240
- user: {
241
- name: 'John',
242
- email: 'john@example.com'
243
- }
244
- };
245
-
246
- const result = validator.validate(schema, data);
247
- console.log(result.valid); // true
248
- ```
249
-
250
- ### 示例 8: 验证数组
251
-
252
- ```javascript
253
- const schema = {
254
- type: 'array',
255
- items: { type: 'string' },
256
- minItems: 1,
257
- maxItems: 10
258
- };
259
-
260
- console.log(validator.validate(schema, ['a', 'b', 'c']).valid); // true
261
- console.log(validator.validate(schema, []).valid); // false (minItems)
262
- console.log(validator.validate(schema, [1, 2, 3]).valid); // false (type)
263
- ```
264
-
265
- ---
266
-
267
- ## 使用默认值
268
-
269
- Validator 配置了 `useDefaults: true` 时,会自动应用 Schema 中的默认值。
270
-
271
- ```javascript
272
- const validator = new Validator({ useDefaults: true });
273
-
274
- const schema = {
275
- type: 'object',
276
- properties: {
277
- name: { type: 'string' },
278
- status: { type: 'string', default: 'active' }
279
- }
280
- };
281
-
282
- const result = validator.validate(schema, { name: 'John' });
283
-
284
- console.log(result.valid); // true
285
- console.log(result.data); // { name: 'John', status: 'active' }
286
- console.log(result.data.status); // 'active' (自动应用默认值)
287
- ```
288
-
289
- ---
290
-
291
- ## 使用已编译的验证函数
292
-
293
- 为了提高性能,可以先编译 Schema,然后重复使用编译后的验证函数。
294
-
295
- ```javascript
296
- // 编译 Schema
297
- const validateFn = validator.compile(schema);
298
-
299
- // 重复使用(性能更好)
300
- const result1 = validator.validate(validateFn, data1);
301
- const result2 = validator.validate(validateFn, data2);
302
- const result3 = validator.validate(validateFn, data3);
303
- ```
304
-
305
- ---
306
-
307
- ## 错误处理最佳实践
308
-
309
- ### 实践 1: 展示用户友好的错误信息
310
-
311
- ```javascript
312
- const result = validator.validate(schema, data);
313
-
314
- if (!result.valid) {
315
- // 格式化错误信息
316
- result.errors.forEach(err => {
317
- console.log(`字段 "${err.path}": ${err.message}`);
318
- });
319
-
320
- // 或者整体提示
321
- console.log(`验证失败,共 ${result.errors.length} 个错误`);
322
- }
323
- ```
324
-
325
- ### 实践 2: API 响应中返回错误
326
-
327
- ```javascript
328
- const result = validator.validate(schema, req.body);
329
-
330
- if (!result.valid) {
331
- return res.status(400).json({
332
- success: false,
333
- message: '数据验证失败',
334
- errors: result.errors.map(err => ({
335
- field: err.path,
336
- message: err.message
337
- }))
338
- });
339
- }
340
-
341
- // 验证通过,继续处理
342
- processData(result.data);
343
- ```
344
-
345
- ### 实践 3: 抛出异常
346
-
347
- ```javascript
348
- const result = validator.validate(schema, data);
349
-
350
- if (!result.valid) {
351
- const error = new ValidationError('数据验证失败');
352
- error.errors = result.errors;
353
- throw error;
354
- }
355
- ```
356
-
357
- ---
358
-
359
- ## 性能优化建议
360
-
361
- ### 建议 1: 复用 Validator 实例
362
-
363
- ```javascript
364
- // 好:复用实例
365
- const validator = new Validator();
366
-
367
- app.post('/api/users', (req, res) => {
368
- const result = validator.validate(userSchema, req.body);
369
- // ...
370
- });
371
-
372
- // ❌ 不好:每次创建新实例
373
- app.post('/api/users', (req, res) => {
374
- const validator = new Validator(); // 不推荐
375
- const result = validator.validate(userSchema, req.body);
376
- // ...
377
- });
378
- ```
379
-
380
- ### 建议 2: 预编译 Schema
381
-
382
- ```javascript
383
- // 应用启动时预编译
384
- const validateUser = validator.compile(userSchema);
385
- const validateProduct = validator.compile(productSchema);
386
-
387
- // 使用时直接验证(更快)
388
- app.post('/api/users', (req, res) => {
389
- const result = validator.validate(validateUser, req.body);
390
- // ...
391
- });
392
- ```
393
-
394
- ### 建议 3: 使用缓存
395
-
396
- ```javascript
397
- // 使用缓存键
398
- const result = validator.validate(
399
- schema,
400
- data,
401
- { cacheKey: 'user-schema' } // 自动缓存编译结果
402
- );
403
- ```
404
-
405
- ---
406
-
407
- ## 常见问题
408
-
409
- ### Q1: 如何验证可选字段?
410
-
411
- 不在 `required` 数组中的字段自动为可选:
412
-
413
- ```javascript
414
- const schema = {
415
- type: 'object',
416
- properties: {
417
- name: { type: 'string' },
418
- age: { type: 'number' } // age 是可选的
419
- },
420
- required: ['name'] // 只有 name 是必填的
421
- };
422
- ```
423
-
424
- ### Q2: 如何允许额外字段?
425
-
426
- JSON Schema 默认允许额外字段。如果要禁止额外字段:
427
-
428
- ```javascript
429
- const schema = {
430
- type: 'object',
431
- properties: {
432
- name: { type: 'string' }
433
- },
434
- additionalProperties: false // 禁止额外字段
435
- };
436
- ```
437
-
438
- ### Q3: 如何验证多种类型?
439
-
440
- 使用 `anyOf` `oneOf`:
441
-
442
- ```javascript
443
- const schema = {
444
- type: 'object',
445
- properties: {
446
- value: {
447
- anyOf: [
448
- { type: 'string' },
449
- { type: 'number' }
450
- ]
451
- }
452
- }
453
- };
454
- ```
455
-
456
- ### Q4: 性能如何?
457
-
458
- 基于 ajv,业界最快的 JSON Schema 验证器:
459
- - 验证速度 >15,000 ops/s
460
- - 内置编译缓存
461
- - 支持批量验证优化
462
-
463
- ---
464
-
465
- ## 相关文档
466
-
467
- - [Validator 类概述](./validator.md)
468
- - [compile 方法](./compile.md) - 编译 Schema 提升性能
469
- - [validateBatch 方法](./validate-batch.md) - 批量验证
470
- - [addKeyword 方法](./add-keyword.md) - 添加自定义验证
471
- - [JSON Schema 基础](./json-schema-basics.md)
472
-
473
- ---
474
-
475
- ## 外部参考
476
-
477
- - [JSON Schema 官方文档](https://json-schema.org/)
478
- - [ajv 文档](https://ajv.js.org/)
479
- - [JSON Schema Validator](https://www.jsonschemavalidator.net/) - 在线测试工具
480
-
481
- ---
482
-
483
-
484
- **最后更新**: 2025-12-24
485
-
486
-
1
+ # validate 方法详细文档
2
+
3
+ ## 📑 目录
4
+
5
+ ### 基础概念
6
+ - [概述](#概述) - validate 方法介绍
7
+ - [方法签名](#方法签名) - API 定义
8
+
9
+ ### 参数详解
10
+ - [参数详解](#参数详解)
11
+ - [schema 参数](#schema-参数)
12
+ - [options 对象属性](#options-对象属性)
13
+ - [返回值详解](#返回值详解)
14
+ - [valid (Boolean)](#valid-boolean)
15
+ - [errors (Array)](#errors-array)
16
+ - [data (Any)](#data-any)
17
+
18
+ ### 使用示例
19
+ - [基础示例](#基础示例)
20
+ - [示例 1: 验证简单对象](#示例-1-验证简单对象)
21
+ - [示例 2: 验证复杂对象](#示例-2-验证复杂对象)
22
+ - [示例 3: 处理验证错误](#示例-3-处理验证错误)
23
+ - [示例 4: 使用默认值](#示例-4-使用默认值)
24
+
25
+ ### 高级功能
26
+ - [高级用法](#高级用法)
27
+ - [批量验证](#批量验证)
28
+ - [自定义错误格式](#自定义错误格式)
29
+ - [性能优化](#性能优化)
30
+
31
+ ### 参考资料
32
+ - [相关文档](#相关文档)
33
+ - [API 参考](#api-参考)
34
+
35
+ ---
36
+
37
+ ## 概述
38
+
39
+ `validate` 是 Validator 类的核心方法,用于验证数据是否符合 JSON Schema 定义。基于高性能的 ajv 验证器实现。
40
+
41
+ ---
42
+
43
+ ## 方法签名
44
+
45
+ ```javascript
46
+ validator.validate(schema, data, options = {})
47
+ ```
48
+
49
+ **参数说明**:
50
+ - `schema` (Object|Function): JSON Schema 对象或已编译的验证函数
51
+ - `data` (Any): 待验证的数据
52
+ - `options` (Object): 验证选项(可选)
53
+
54
+ **返回值**:
55
+ ```javascript
56
+ {
57
+ valid: Boolean, // 是否有效
58
+ errors: Array, // 成功时为空数组,失败时为错误列表
59
+ data: Any // 当前实现会返回本次验证数据(可能被 useDefaults 修改)
60
+ }
61
+ ```
62
+
63
+ 当前实现中,`data` 与 `errors` 都会随结果一并返回:成功时 `errors` 为空数组,验证失败时仍会保留 `data` 以便排查输入。
64
+
65
+ ---
66
+
67
+ ## 参数详解
68
+
69
+ ### schema 参数
70
+
71
+ JSON Schema 对象,支持 JSON Schema Draft 7 标准。
72
+
73
+ | 参数类型 | 说明 | 来源 |
74
+ |---------|------|------|
75
+ | Object | JSON Schema 对象 | JSON Schema 标准 ✅ |
76
+ | Function | 已编译的验证函数(通过 `compile()` 生成) | ajv ✅ |
77
+
78
+ ### options 对象属性
79
+
80
+ `validator.validate(schema, data, options)` 当前按本次调用实际读取以下参数:
81
+
82
+ | 参数 | 类型 | 必填 | 默认值 | 说明 |
83
+ |------|------|------|--------|------|
84
+ | `format` | Boolean | 否 | `true` | 是否格式化错误信息 |
85
+ | `locale` | String | 否 | — | 动态指定语言,如 `'zh-CN'`、`'en-US'`、`'ja-JP'` |
86
+ | `messages` | Object | 否 | — | 自定义错误消息覆盖 |
87
+
88
+ ### 相关配置入口
89
+
90
+ 以下能力**不属于** `validator.validate(schema, data, options)` 的逐次调用参数:
91
+
92
+ | 能力 | 正确入口 | 说明 |
93
+ |------|----------|------|
94
+ | `allErrors` / `useDefaults` / `coerceTypes` / `removeAdditional` / `cache` | `new Validator(options)` | 这些配置在创建 `Validator` 实例时注入到底层 AJV / 缓存层 |
95
+ | `strict` | Schema 本身 | 如果需要禁止额外字段,请在 schema 层使用 `DslBuilder.strict()` 或等价的 schema 级约束 |
96
+ | `coerce` | 顶层 `validate()` / `validateAsync()` 便捷函数 | 顶层 helper 默认会做字符串 → 数字 / 布尔值的便捷转换,传 `{ coerce: false }` 可关闭 |
97
+
98
+ 如果你需要在**单次调用**中覆盖错误输出,请使用上表中的 `format`、`locale`、`messages`;如果你需要调整验证器行为,请优先在 `Validator` 构造阶段配置。
99
+
100
+ ---
101
+
102
+ ## 返回值详解
103
+
104
+ ### valid (Boolean)
105
+
106
+ 表示数据是否通过验证。
107
+
108
+ ```javascript
109
+ result.valid === true // 验证通过
110
+ result.valid === false // 验证失败
111
+ ```
112
+
113
+ ### errors (Array)
114
+
115
+ 验证错误列表。当前实现成功时返回空数组,验证失败时包含详细错误信息。
116
+
117
+ **错误对象结构**:
118
+ ```javascript
119
+ {
120
+ path: String, // 错误字段路径,如 'user.email'
121
+ message: String, // 错误描述信息
122
+ keyword: String, // 触发的 Schema 关键字
123
+ params: Object // 错误相关参数
124
+ }
125
+ ```
126
+
127
+ ### data (Any)
128
+
129
+ 验证后的数据。当前实现即使在验证失败时也会保留本次验证数据,便于排查输入;如果 Validator 配置了 `useDefaults: true`,则也可能反映 Schema 中应用后的默认值。
130
+
131
+ ---
132
+
133
+ ## 基础示例
134
+
135
+ ### 示例 1: 验证简单对象
136
+
137
+ ```javascript
138
+ const { Validator } = require('schema-dsl');
139
+
140
+ const validator = new Validator();
141
+
142
+ const schema = {
143
+ type: 'object',
144
+ properties: {
145
+ name: { type: 'string' },
146
+ age: { type: 'number' }
147
+ },
148
+ required: ['name']
149
+ };
150
+
151
+ const result = validator.validate(schema, {
152
+ name: 'John',
153
+ age: 25
154
+ });
155
+
156
+ console.log(result.valid); // true
157
+ console.log(result.errors); // []
158
+ ```
159
+
160
+ ### 示例 2: 处理验证失败
161
+
162
+ ```javascript
163
+ const result = validator.validate(schema, {
164
+ age: 'invalid'
165
+ });
166
+
167
+ console.log(result.valid); // false
168
+ console.log(result.errors);
169
+ // 当前实现返回格式化后的错误列表:
170
+ // [
171
+ // { path: 'name', message: 'name不能为空' },
172
+ // { path: 'age', message: 'age应该是 number 类型' }
173
+ // ]
174
+ ```
175
+
176
+ ---
177
+
178
+ ## 高级示例
179
+
180
+ ### 示例 3: 验证字符串约束
181
+
182
+ ```javascript
183
+ const schema = {
184
+ type: 'string',
185
+ minLength: 3,
186
+ maxLength: 32,
187
+ pattern: '^[a-zA-Z0-9]+$'
188
+ };
189
+
190
+ // 有效数据
191
+ console.log(validator.validate(schema, 'john123').valid); // true
192
+
193
+ // 太短
194
+ console.log(validator.validate(schema, 'ab').valid); // false
195
+
196
+ // 包含非法字符
197
+ console.log(validator.validate(schema, 'john-123').valid); // false
198
+ ```
199
+
200
+ ### 示例 4: 验证数字范围
201
+
202
+ ```javascript
203
+ const schema = {
204
+ type: 'number',
205
+ minimum: 0,
206
+ maximum: 100
207
+ };
208
+
209
+ console.log(validator.validate(schema, 50).valid); // true
210
+ console.log(validator.validate(schema, -1).valid); // false
211
+ console.log(validator.validate(schema, 101).valid); // false
212
+ ```
213
+
214
+ ### 示例 5: 验证邮箱格式
215
+
216
+ ```javascript
217
+ const schema = {
218
+ type: 'string',
219
+ format: 'email'
220
+ };
221
+
222
+ console.log(validator.validate(schema, 'test@example.com').valid); // true
223
+ console.log(validator.validate(schema, 'invalid-email').valid); // false
224
+ ```
225
+
226
+ ### 示例 6: 验证枚举值
227
+
228
+ ```javascript
229
+ const schema = {
230
+ type: 'string',
231
+ enum: ['active', 'inactive', 'pending']
232
+ };
233
+
234
+ console.log(validator.validate(schema, 'active').valid); // true
235
+ console.log(validator.validate(schema, 'invalid').valid); // false
236
+ ```
237
+
238
+ ### 示例 7: 验证嵌套对象
239
+
240
+ ```javascript
241
+ const schema = {
242
+ type: 'object',
243
+ properties: {
244
+ user: {
245
+ type: 'object',
246
+ properties: {
247
+ name: { type: 'string' },
248
+ email: { type: 'string', format: 'email' }
249
+ },
250
+ required: ['name', 'email']
251
+ }
252
+ }
253
+ };
254
+
255
+ const data = {
256
+ user: {
257
+ name: 'John',
258
+ email: 'john@example.com'
259
+ }
260
+ };
261
+
262
+ const result = validator.validate(schema, data);
263
+ console.log(result.valid); // true
264
+ ```
265
+
266
+ ### 示例 8: 验证数组
267
+
268
+ ```javascript
269
+ const schema = {
270
+ type: 'array',
271
+ items: { type: 'string' },
272
+ minItems: 1,
273
+ maxItems: 10
274
+ };
275
+
276
+ console.log(validator.validate(schema, ['a', 'b', 'c']).valid); // true
277
+ console.log(validator.validate(schema, []).valid); // false (minItems)
278
+ console.log(validator.validate(schema, [1, 2, 3]).valid); // false (type)
279
+ ```
280
+
281
+ ---
282
+
283
+ ## 使用默认值
284
+
285
+ Validator 配置了 `useDefaults: true` 时,会自动应用 Schema 中的默认值。
286
+
287
+ ```javascript
288
+ const validator = new Validator({ useDefaults: true });
289
+
290
+ const schema = {
291
+ type: 'object',
292
+ properties: {
293
+ name: { type: 'string' },
294
+ status: { type: 'string', default: 'active' }
295
+ }
296
+ };
297
+
298
+ const result = validator.validate(schema, { name: 'John' });
299
+
300
+ console.log(result.valid); // true
301
+ console.log(result.data); // { name: 'John', status: 'active' }
302
+ console.log(result.data.status); // 'active' (自动应用默认值)
303
+ ```
304
+
305
+ ---
306
+
307
+ ## 使用已编译的验证函数
308
+
309
+ 为了提高性能,可以先编译 Schema,然后重复使用编译后的验证函数。
310
+
311
+ ```javascript
312
+ // 编译 Schema
313
+ const validateFn = validator.compile(schema);
314
+
315
+ // 重复使用(性能更好)
316
+ const result1 = validator.validate(validateFn, data1);
317
+ const result2 = validator.validate(validateFn, data2);
318
+ const result3 = validator.validate(validateFn, data3);
319
+ ```
320
+
321
+ ---
322
+
323
+ ## 错误处理最佳实践
324
+
325
+ ### 实践 1: 展示用户友好的错误信息
326
+
327
+ ```javascript
328
+ const result = validator.validate(schema, data);
329
+
330
+ if (!result.valid) {
331
+ // 格式化错误信息
332
+ result.errors.forEach(err => {
333
+ console.log(`字段 "${err.path}": ${err.message}`);
334
+ });
335
+
336
+ // 或者整体提示
337
+ console.log(`验证失败,共 ${result.errors.length} 个错误`);
338
+ }
339
+ ```
340
+
341
+ ### 实践 2: API 响应中返回错误
342
+
343
+ ```javascript
344
+ const result = validator.validate(schema, req.body);
345
+
346
+ if (!result.valid) {
347
+ return res.status(400).json({
348
+ success: false,
349
+ message: '数据验证失败',
350
+ errors: result.errors.map(err => ({
351
+ field: err.path,
352
+ message: err.message
353
+ }))
354
+ });
355
+ }
356
+
357
+ // 验证通过,继续处理
358
+ processData(result.data);
359
+ ```
360
+
361
+ ### 实践 3: 抛出异常
362
+
363
+ ```javascript
364
+ const result = validator.validate(schema, data);
365
+
366
+ if (!result.valid) {
367
+ const error = new ValidationError(result.errors, data);
368
+ throw error;
369
+ }
370
+ ```
371
+
372
+ ---
373
+
374
+ ## 性能优化建议
375
+
376
+ ### 建议 1: 复用 Validator 实例
377
+
378
+ ```javascript
379
+ // ✅ 好:复用实例
380
+ const validator = new Validator();
381
+
382
+ app.post('/api/users', (req, res) => {
383
+ const result = validator.validate(userSchema, req.body);
384
+ // ...
385
+ });
386
+
387
+ // ❌ 不好:每次创建新实例
388
+ app.post('/api/users', (req, res) => {
389
+ const validator = new Validator(); // 不推荐
390
+ const result = validator.validate(userSchema, req.body);
391
+ // ...
392
+ });
393
+ ```
394
+
395
+ ### 建议 2: 预编译 Schema
396
+
397
+ ```javascript
398
+ // 应用启动时预编译
399
+ const validateUser = validator.compile(userSchema);
400
+ const validateProduct = validator.compile(productSchema);
401
+
402
+ // 使用时直接验证(更快)
403
+ app.post('/api/users', (req, res) => {
404
+ const result = validator.validate(validateUser, req.body);
405
+ // ...
406
+ });
407
+ ```
408
+
409
+ ### 建议 3: 使用缓存
410
+
411
+ ```javascript
412
+ // 显式编译并复用缓存键
413
+ const validateUser = validator.compile(schema, 'user-schema');
414
+
415
+ console.log(validateUser(data));
416
+ ```
417
+
418
+ ---
419
+
420
+ ## 常见问题
421
+
422
+ ---
423
+
424
+ ## 对应示例文件
425
+
426
+ **示例入口**: [validate.ts](https://github.com/vextjs/schema-dsl/blob/main/examples/docs/validate.ts)
427
+ **说明**: 覆盖顶层 `validate()` 的成功/失败路径、默认类型转换,以及关闭 `coerce` 后的行为差异。
428
+
429
+ ### Q1: 如何验证可选字段?
430
+
431
+ 不在 `required` 数组中的字段自动为可选:
432
+
433
+ ```javascript
434
+ const schema = {
435
+ type: 'object',
436
+ properties: {
437
+ name: { type: 'string' },
438
+ age: { type: 'number' } // age 是可选的
439
+ },
440
+ required: ['name'] // 只有 name 是必填的
441
+ };
442
+ ```
443
+
444
+ ### Q2: 如何允许额外字段?
445
+
446
+ JSON Schema 默认允许额外字段。如果要禁止额外字段:
447
+
448
+ ```javascript
449
+ const schema = {
450
+ type: 'object',
451
+ properties: {
452
+ name: { type: 'string' }
453
+ },
454
+ additionalProperties: false // 禁止额外字段
455
+ };
456
+ ```
457
+
458
+ ### Q3: 如何验证多种类型?
459
+
460
+ 使用 `anyOf` 或 `oneOf`:
461
+
462
+ ```javascript
463
+ const schema = {
464
+ type: 'object',
465
+ properties: {
466
+ value: {
467
+ anyOf: [
468
+ { type: 'string' },
469
+ { type: 'number' }
470
+ ]
471
+ }
472
+ }
473
+ };
474
+ ```
475
+
476
+ ### Q4: 性能如何?
477
+
478
+ 基于 ajv,业界最快的 JSON Schema 验证器:
479
+ - 验证速度 >15,000 ops/s
480
+ - 内置编译缓存
481
+ - 支持批量验证优化
482
+
483
+ ---
484
+
485
+ ## 相关文档
486
+
487
+ - [Validator 类概述](./validator.md)
488
+ - [compile 方法](./compile.md) - 编译 Schema 提升性能
489
+ - [validateBatch 方法](./validate-batch.md) - 批量验证
490
+ - [addKeyword 方法](./add-keyword.md) - 添加自定义验证
491
+ - [JSON Schema 基础](./json-schema-basics.md)
492
+
493
+ ---
494
+
495
+ ## 外部参考
496
+
497
+ - [JSON Schema 官方文档](https://json-schema.org/)
498
+ - [ajv 文档](https://ajv.js.org/)
499
+ - [JSON Schema Validator](https://www.jsonschemavalidator.net/) - 在线测试工具
500
+
501
+ ---
502
+
503
+
504
+ **最后更新**: 2025-12-24
505
+
506
+