schema-dsl 1.2.4 → 2.0.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.
Files changed (242) hide show
  1. package/CHANGELOG.md +87 -210
  2. package/README.md +391 -2249
  3. package/dist/DslBuilder-DQDN0ZxZ.d.cts +341 -0
  4. package/dist/DslBuilder-DkLaOo9Q.d.ts +341 -0
  5. package/dist/Validator-C7GsVQOH.d.cts +192 -0
  6. package/dist/Validator-hFWKGxir.d.ts +192 -0
  7. package/dist/index.cjs +6594 -0
  8. package/dist/index.d.cts +1145 -0
  9. package/dist/index.d.ts +1145 -0
  10. package/dist/index.js +6528 -0
  11. package/dist/plugin-CIKtTMtS.d.cts +246 -0
  12. package/dist/plugin-CIKtTMtS.d.ts +246 -0
  13. package/dist/plugins/custom-format.cjs +3802 -0
  14. package/dist/plugins/custom-format.d.cts +12 -0
  15. package/dist/plugins/custom-format.d.ts +12 -0
  16. package/dist/plugins/custom-format.js +3772 -0
  17. package/dist/plugins/custom-type-example.cjs +3795 -0
  18. package/dist/plugins/custom-type-example.d.cts +8 -0
  19. package/dist/plugins/custom-type-example.d.ts +8 -0
  20. package/dist/plugins/custom-type-example.js +3765 -0
  21. package/dist/plugins/custom-validator.cjs +146 -0
  22. package/dist/plugins/custom-validator.d.cts +10 -0
  23. package/dist/plugins/custom-validator.d.ts +10 -0
  24. package/dist/plugins/custom-validator.js +121 -0
  25. package/docs/FEATURE-INDEX.md +102 -68
  26. package/docs/add-custom-locale.md +48 -35
  27. package/docs/add-keyword.md +24 -0
  28. package/docs/api-reference.md +396 -154
  29. package/docs/api.md +13 -0
  30. package/docs/best-practices-project-structure.md +19 -10
  31. package/docs/best-practices.md +93 -53
  32. package/docs/cache-manager.md +23 -15
  33. package/docs/compile.md +45 -0
  34. package/docs/conditional-api.md +40 -11
  35. package/docs/custom-extensions-guide.md +80 -152
  36. package/docs/design-philosophy.md +76 -71
  37. package/docs/doc-index.md +324 -0
  38. package/docs/dsl-syntax.md +69 -19
  39. package/docs/dynamic-locale.md +24 -14
  40. package/docs/enum.md +12 -5
  41. package/docs/error-handling.md +53 -44
  42. package/docs/export-guide.md +47 -8
  43. package/docs/export-limitations.md +27 -11
  44. package/docs/faq.md +86 -67
  45. package/docs/frontend-i18n-guide.md +26 -12
  46. package/docs/i18n-user-guide.md +60 -47
  47. package/docs/i18n.md +51 -32
  48. package/docs/index.md +48 -0
  49. package/docs/json-schema-basics.md +40 -0
  50. package/docs/label-vs-description.md +12 -3
  51. package/docs/markdown-exporter.md +15 -6
  52. package/docs/mongodb-exporter.md +11 -4
  53. package/docs/multi-language.md +26 -0
  54. package/docs/multi-type-support.md +26 -33
  55. package/docs/mysql-exporter.md +9 -2
  56. package/docs/number-operators.md +12 -5
  57. package/docs/optional-marker-guide.md +28 -23
  58. package/docs/performance-guide.md +49 -0
  59. package/docs/plugin-system.md +205 -366
  60. package/docs/plugin-type-registration.md +34 -0
  61. package/docs/postgresql-exporter.md +9 -2
  62. package/docs/public/favicon.svg +5 -0
  63. package/docs/quick-start.md +37 -363
  64. package/docs/runtime-locale-support.md +20 -9
  65. package/docs/schema-helper.md +10 -5
  66. package/docs/schema-utils-advanced-issues.md +23 -0
  67. package/docs/schema-utils-best-practices.md +20 -0
  68. package/docs/schema-utils-chaining.md +7 -0
  69. package/docs/schema-utils.md +76 -42
  70. package/docs/security-checklist.md +20 -0
  71. package/docs/string-extensions.md +17 -9
  72. package/docs/troubleshooting.md +36 -21
  73. package/docs/type-converter.md +41 -50
  74. package/docs/type-reference.md +38 -15
  75. package/docs/typescript-guide.md +53 -42
  76. package/docs/union-type-guide.md +11 -1
  77. package/docs/union-types.md +10 -3
  78. package/docs/validate-async.md +36 -25
  79. package/docs/validate-batch.md +49 -0
  80. package/docs/validate-dsl-object-support.md +33 -28
  81. package/docs/validate.md +36 -16
  82. package/docs/validation-guide.md +25 -7
  83. package/docs/validator.md +39 -0
  84. package/package.json +85 -27
  85. package/plugins/custom-format.cjs +8 -0
  86. package/plugins/custom-type-example.cjs +8 -0
  87. package/plugins/custom-validator.cjs +8 -0
  88. package/src/adapters/DslAdapter.ts +111 -0
  89. package/src/adapters/index.ts +1 -0
  90. package/src/config/constants.ts +83 -0
  91. package/src/config/index.ts +2 -0
  92. package/src/config/patterns.ts +77 -0
  93. package/src/core/CacheManager.ts +159 -0
  94. package/src/core/ConditionalBuilder.ts +382 -0
  95. package/src/core/ConditionalRuntime.ts +28 -0
  96. package/src/core/ConditionalValidator.ts +255 -0
  97. package/src/core/DslBuilder.ts +677 -0
  98. package/src/core/ErrorCodes.ts +38 -0
  99. package/src/core/ErrorFormatter.ts +271 -0
  100. package/src/core/JSONSchemaCore.ts +65 -0
  101. package/src/core/Locale.ts +187 -0
  102. package/src/core/MessageTemplate.ts +42 -0
  103. package/src/core/ObjectDslBuilder.ts +64 -0
  104. package/src/core/PluginManager.ts +326 -0
  105. package/src/core/StringExtensions.ts +140 -0
  106. package/src/core/TemplateEngine.ts +44 -0
  107. package/src/core/Validator.ts +448 -0
  108. package/src/errors/I18nError.ts +159 -0
  109. package/src/errors/ValidationError.ts +105 -0
  110. package/src/exporters/BaseExporter.ts +60 -0
  111. package/src/exporters/MarkdownExporter.ts +305 -0
  112. package/src/exporters/MongoDBExporter.ts +126 -0
  113. package/src/exporters/MySQLExporter.ts +155 -0
  114. package/src/exporters/PostgreSQLExporter.ts +222 -0
  115. package/src/exporters/index.ts +18 -0
  116. package/src/index.ts +633 -0
  117. package/{lib/locales/en-US.js → src/locales/en-US.ts} +21 -37
  118. package/{lib/locales/es-ES.js → src/locales/es-ES.ts} +63 -16
  119. package/{lib/locales/fr-FR.js → src/locales/fr-FR.ts} +74 -27
  120. package/src/locales/index.ts +103 -0
  121. package/{lib/locales/ja-JP.js → src/locales/ja-JP.ts} +59 -17
  122. package/src/locales/types.ts +156 -0
  123. package/{lib/locales/zh-CN.js → src/locales/zh-CN.ts} +21 -38
  124. package/src/parser/ConstraintParser.ts +101 -0
  125. package/src/parser/DslParser.ts +470 -0
  126. package/src/parser/SchemaCompiler.ts +66 -0
  127. package/src/parser/TypeRegistry.ts +250 -0
  128. package/src/parser/index.ts +6 -0
  129. package/src/plugins/custom-format.ts +126 -0
  130. package/src/plugins/custom-type-example.ts +108 -0
  131. package/src/plugins/custom-validator.ts +140 -0
  132. package/src/types/conditional.ts +28 -0
  133. package/src/types/config.ts +59 -0
  134. package/src/types/dsl.ts +131 -0
  135. package/src/types/error.ts +60 -0
  136. package/src/types/index.ts +17 -0
  137. package/src/types/infer.ts +128 -0
  138. package/src/types/plugin.ts +58 -0
  139. package/src/types/safe-regex.d.ts +9 -0
  140. package/src/types/schema.ts +66 -0
  141. package/src/types/validate.ts +71 -0
  142. package/src/utils/SchemaHelper.ts +196 -0
  143. package/src/utils/SchemaUtils.ts +346 -0
  144. package/src/utils/TypeConverter.ts +215 -0
  145. package/src/utils/index.ts +10 -0
  146. package/src/validators/CustomKeywords.ts +477 -0
  147. package/.eslintignore +0 -11
  148. package/.eslintrc.json +0 -27
  149. package/CONTRIBUTING.md +0 -368
  150. package/STATUS.md +0 -491
  151. package/changelogs/v1.0.0.md +0 -328
  152. package/changelogs/v1.0.9.md +0 -367
  153. package/changelogs/v1.1.0.md +0 -389
  154. package/changelogs/v1.1.1.md +0 -308
  155. package/changelogs/v1.1.2.md +0 -183
  156. package/changelogs/v1.1.3.md +0 -161
  157. package/changelogs/v1.1.4.md +0 -432
  158. package/changelogs/v1.1.5.md +0 -493
  159. package/changelogs/v1.1.6.md +0 -211
  160. package/changelogs/v1.1.8.md +0 -376
  161. package/changelogs/v1.2.3.md +0 -124
  162. package/docs/INDEX.md +0 -252
  163. package/docs/issues-resolved-summary.md +0 -196
  164. package/docs/performance-benchmark-report.md +0 -179
  165. package/docs/performance-quick-reference.md +0 -123
  166. package/docs/user-questions-answered.md +0 -353
  167. package/docs/validation-rules-v1.0.2.md +0 -1608
  168. package/examples/README.md +0 -81
  169. package/examples/array-dsl-example.js +0 -227
  170. package/examples/conditional-example.js +0 -288
  171. package/examples/conditional-non-object.js +0 -129
  172. package/examples/conditional-validate-example.js +0 -321
  173. package/examples/custom-extension.js +0 -85
  174. package/examples/dsl-match-example.js +0 -74
  175. package/examples/dsl-style.js +0 -118
  176. package/examples/dynamic-locale-configuration.js +0 -348
  177. package/examples/dynamic-locale-example.js +0 -287
  178. package/examples/enum.examples.js +0 -324
  179. package/examples/export-demo.js +0 -130
  180. package/examples/express-integration.js +0 -376
  181. package/examples/i18n-error-handling-complete.js +0 -381
  182. package/examples/i18n-error-handling-quickstart.md +0 -0
  183. package/examples/i18n-error.examples.js +0 -181
  184. package/examples/i18n-full-demo.js +0 -301
  185. package/examples/i18n-memory-safety.examples.js +0 -268
  186. package/examples/markdown-export.js +0 -71
  187. package/examples/middleware-usage.js +0 -93
  188. package/examples/new-features-comparison.js +0 -315
  189. package/examples/password-reset/README.md +0 -153
  190. package/examples/password-reset/schema.js +0 -26
  191. package/examples/password-reset/test.js +0 -101
  192. package/examples/plugin-system.examples.js +0 -205
  193. package/examples/schema-utils-chaining.examples.js +0 -250
  194. package/examples/simple-example.js +0 -122
  195. package/examples/slug.examples.js +0 -179
  196. package/examples/string-extensions.js +0 -297
  197. package/examples/union-type-example.js +0 -127
  198. package/examples/union-types-example.js +0 -77
  199. package/examples/user-registration/README.md +0 -156
  200. package/examples/user-registration/routes.js +0 -92
  201. package/examples/user-registration/schema.js +0 -150
  202. package/examples/user-registration/server.js +0 -74
  203. package/index.d.ts +0 -3540
  204. package/index.js +0 -457
  205. package/index.mjs +0 -60
  206. package/lib/adapters/DslAdapter.js +0 -871
  207. package/lib/adapters/index.js +0 -20
  208. package/lib/config/constants.js +0 -286
  209. package/lib/config/patterns/common.js +0 -47
  210. package/lib/config/patterns/creditCard.js +0 -9
  211. package/lib/config/patterns/idCard.js +0 -9
  212. package/lib/config/patterns/index.js +0 -9
  213. package/lib/config/patterns/licensePlate.js +0 -4
  214. package/lib/config/patterns/passport.js +0 -4
  215. package/lib/config/patterns/phone.js +0 -9
  216. package/lib/config/patterns/postalCode.js +0 -5
  217. package/lib/core/CacheManager.js +0 -376
  218. package/lib/core/ConditionalBuilder.js +0 -503
  219. package/lib/core/DslBuilder.js +0 -1400
  220. package/lib/core/ErrorCodes.js +0 -233
  221. package/lib/core/ErrorFormatter.js +0 -445
  222. package/lib/core/JSONSchemaCore.js +0 -347
  223. package/lib/core/Locale.js +0 -130
  224. package/lib/core/MessageTemplate.js +0 -98
  225. package/lib/core/PluginManager.js +0 -448
  226. package/lib/core/StringExtensions.js +0 -240
  227. package/lib/core/Validator.js +0 -654
  228. package/lib/errors/I18nError.js +0 -328
  229. package/lib/errors/ValidationError.js +0 -191
  230. package/lib/exporters/MarkdownExporter.js +0 -420
  231. package/lib/exporters/MongoDBExporter.js +0 -162
  232. package/lib/exporters/MySQLExporter.js +0 -212
  233. package/lib/exporters/PostgreSQLExporter.js +0 -289
  234. package/lib/exporters/index.js +0 -24
  235. package/lib/locales/index.js +0 -8
  236. package/lib/utils/LRUCache.js +0 -174
  237. package/lib/utils/SchemaHelper.js +0 -240
  238. package/lib/utils/SchemaUtils.js +0 -445
  239. package/lib/utils/TypeConverter.js +0 -245
  240. package/lib/utils/index.js +0 -13
  241. package/lib/validators/CustomKeywords.js +0 -616
  242. package/lib/validators/index.js +0 -11
@@ -0,0 +1,23 @@
1
+ # SchemaUtils 深入问题分析
2
+
3
+ ## 常见问题
4
+
5
+ ### 内部字段泄漏
6
+
7
+ 链式 DSL 会产生 `_label`、`_customMessages`、`_required` 等内部字段。面向 OpenAPI 或外部系统时,应在 Builder 阶段使用 `toJsonSchema()` 输出纯净 JSON Schema。
8
+
9
+ ### required 同步
10
+
11
+ 使用 `pick()`、`omit()`、`partial()` 后应检查 `required` 是否符合预期,当前实现会同步处理顶层 required。
12
+
13
+ ### 深拷贝限制
14
+
15
+ `SchemaUtils.clone()` 基于 JSON 序列化,不保留函数、`RegExp` 实例等非 JSON 值。
16
+
17
+ ---
18
+
19
+ ## 对应示例文件
20
+
21
+ **示例入口**: [schema-utils-advanced-issues.ts](https://github.com/vextjs/schema-dsl/blob/main/examples/docs/schema-utils-advanced-issues.ts)
22
+ **说明**: 覆盖内部字段泄漏、`required` 同步和 `clone()` 深拷贝边界三个最容易踩坑的点。
23
+
@@ -0,0 +1,20 @@
1
+ # SchemaUtils 最佳实践
2
+
3
+ ## 推荐用法
4
+
5
+ - 使用 `SchemaUtils.reusable()` 封装可复用字段工厂。
6
+ - 使用 `SchemaUtils.extend()` 组合基础 Schema 与业务扩展字段。
7
+ - 使用 `pick()` / `omit()` / `partial()` 生成派生 Schema,避免手写重复定义。
8
+
9
+ ## 注意事项
10
+
11
+ - 派生 Schema 后仍需用 `validate()` 或 `Validator` 做回归验证。
12
+ - 对外导出标准 JSON Schema 时,优先在 Builder 阶段使用 `toJsonSchema()`,或在导出前显式清理内部字段。
13
+
14
+ ---
15
+
16
+ ## 对应示例文件
17
+
18
+ **示例入口**: [schema-utils-best-practices.ts](https://github.com/vextjs/schema-dsl/blob/main/examples/docs/schema-utils-best-practices.ts)
19
+ **说明**: 以创建、公开返回、局部更新三个场景展示字段库复用与派生 schema 的推荐组织方式。
20
+
@@ -140,4 +140,11 @@ app.patch('/users/:id', async (req, res, next) => {
140
140
  ### extend(schema, extensions)
141
141
  扩展字段
142
142
 
143
+ ---
144
+
145
+ ## 对应示例文件
146
+
147
+ **示例入口**: [schema-utils-chaining.ts](https://github.com/vextjs/schema-dsl/blob/main/examples/docs/schema-utils-chaining.ts)
148
+ **说明**: 覆盖 `omit()`、`extend()`、`pick()`、`partial()` 的链式组合,以及派生 schema 的成功/失败验证路径。
149
+
143
150
 
@@ -113,32 +113,33 @@ const registerSchema = dsl({
113
113
 
114
114
  ## Schema 合并
115
115
 
116
- ### merge() - 合并多个Schema
116
+ ### createLibrary() - 创建片段库
117
117
 
118
118
  ```javascript
119
119
  const { SchemaUtils, dsl } = require('schema-dsl');
120
120
 
121
- // 基础Schema
122
- const baseUser = dsl({
123
- name: 'string:1-50!',
124
- email: 'email!'
121
+ const fields = SchemaUtils.createLibrary({
122
+ email: () => 'email!'.label('邮箱地址'),
123
+ phone: () => dsl('string!').phone('cn').label('手机号'),
124
+ profile: () => ({
125
+ bio: 'string:500',
126
+ avatar: 'url'
127
+ })
125
128
  });
126
129
 
127
- // 扩展Schema
128
- const withAge = dsl({
129
- age: 'number:18-120',
130
- gender: 'male|female|other'
130
+ const registerSchema = dsl({
131
+ email: fields.email(),
132
+ phone: fields.phone(),
133
+ password: dsl('string!').password('strong')
131
134
  });
132
135
 
133
- // 扩展
134
- const fullUser = SchemaUtils.extend(baseUser, {
135
- age: 'number:18-120',
136
- bio: 'string:500',
137
- avatar: 'url'
136
+ const profileSchema = dsl({
137
+ ...fields.profile(),
138
+ email: fields.email()
138
139
  });
139
140
  ```
140
141
 
141
- **说明**: 扩展字段,合并 properties 和 required 数组
142
+ **说明**: `createLibrary()` 只是返回片段工厂集合,适合在大型项目中集中管理字段和组合片段。
142
143
 
143
144
  ---
144
145
 
@@ -206,6 +207,32 @@ const safeUser = SchemaUtils.omit(fullUser, ['password']);
206
207
 
207
208
  ---
208
209
 
210
+ ### partial() - 将字段改为可选
211
+
212
+ ```javascript
213
+ const updateSchema = SchemaUtils.partial(dsl({
214
+ name: 'string!',
215
+ email: 'email!',
216
+ age: 'number:18-120'
217
+ }));
218
+
219
+ // 结果中 required 会被移除,适合 PATCH / 局部更新场景
220
+ ```
221
+
222
+ 也可以只对部分字段做可选化:
223
+
224
+ ```javascript
225
+ const schema = dsl({
226
+ name: 'string!',
227
+ email: 'email!',
228
+ age: 'number:18-120'
229
+ });
230
+
231
+ const partialContact = SchemaUtils.partial(schema, ['name', 'email']);
232
+ ```
233
+
234
+ ---
235
+
209
236
  ## Schema 导出
210
237
 
211
238
  ### toMarkdown() - 导出为Markdown文档
@@ -218,10 +245,7 @@ const schema = dsl({
218
245
  });
219
246
 
220
247
  const markdown = SchemaUtils.toMarkdown(schema, {
221
- title: '用户注册Schema',
222
- showRequired: true,
223
- showType: true,
224
- showConstraints: true
248
+ title: '用户注册Schema'
225
249
  });
226
250
 
227
251
  console.log(markdown);
@@ -246,8 +270,7 @@ console.log(markdown);
246
270
 
247
271
  ```javascript
248
272
  const html = SchemaUtils.toHTML(schema, {
249
- title: '用户注册Schema',
250
- theme: 'bootstrap' // 或 'default'
273
+ title: '用户注册Schema'
251
274
  });
252
275
 
253
276
  // 生成HTML表格,可以嵌入文档
@@ -259,10 +282,10 @@ const html = SchemaUtils.toHTML(schema, {
259
282
 
260
283
  ## 性能监控
261
284
 
262
- ### validateBatch() - 批量验证
285
+ ### validateBatch() - 批量验证统计
263
286
 
264
287
  ```javascript
265
- const { Validator } = require('schema-dsl');
288
+ const { SchemaUtils, Validator, dsl } = require('schema-dsl');
266
289
 
267
290
  const schema = dsl({
268
291
  email: 'email!',
@@ -277,44 +300,46 @@ const items = [
277
300
  { email: 'user2@example.com', age: 30 }
278
301
  ];
279
302
 
280
- const results = validator.validateBatch(schema, items);
303
+ const batch = SchemaUtils.validateBatch(schema, items, validator.getAjv());
281
304
 
282
- console.log(results);
305
+ console.log(batch);
283
306
  // {
284
307
  // results: [
285
- // { valid: true, ... },
286
- // { valid: false, errors: [...] },
287
- // { valid: true, ... }
308
+ // { index: 0, valid: true, errors: null, data: {...} },
309
+ // { index: 1, valid: false, errors: [...], data: null },
310
+ // { index: 2, valid: true, errors: null, data: {...} }
288
311
  // ],
289
- // stats: {
312
+ // summary: {
290
313
  // total: 3,
291
314
  // valid: 2,
292
315
  // invalid: 1,
293
- // duration: '5.2ms'
316
+ // duration: 5,
317
+ // averageTime: 1.67
294
318
  // }
295
319
  // }
296
320
  ```
297
321
 
298
- **用途**: 批量验证数据,获取性能统计
322
+ **说明**:
323
+ - 如果你只需要“每条是否通过”的结果,可直接使用 `validator.validateBatch(schema, items)`
324
+ - 如果你还需要汇总统计信息,再使用 `SchemaUtils.validateBatch(schema, items, validator.getAjv())`
299
325
 
300
326
  ---
301
327
 
302
- ### 性能监控(自动)
328
+ ### withPerformance() - 给 Validator 添加性能包装
303
329
 
304
330
  ```javascript
305
- const validator = new Validator({ performance: true });
331
+ const validator = SchemaUtils.withPerformance(new Validator());
306
332
 
307
333
  const result = validator.validate(schema, data);
308
334
 
309
335
  console.log(result.performance);
310
336
  // {
311
- // duration: '2.1ms',
312
- // compileDuration: '1.5ms',
313
- // validateDuration: '0.6ms'
337
+ // duration: 2,
338
+ // timestamp: '2026-05-06T12:34:56.789Z'
314
339
  // }
315
340
  ```
316
341
 
317
- **用途**: 监控验证性能
342
+ **用途**: 在不改业务调用方式的前提下,为验证结果附加耗时信息
318
343
 
319
344
  ---
320
345
 
@@ -344,6 +369,8 @@ cloned.properties.user.properties.name.maxLength = 100;
344
369
  ### validateNestingDepth() - 检查嵌套深度
345
370
 
346
371
  ```javascript
372
+ const { dsl, DslBuilder } = require('schema-dsl');
373
+
347
374
  const schema = dsl({
348
375
  level1: {
349
376
  level2: {
@@ -354,15 +381,15 @@ const schema = dsl({
354
381
  }
355
382
  });
356
383
 
357
- const depth = schema.validateNestingDepth(10);
358
- // 返回: 4
384
+ const result = DslBuilder.validateNestingDepth(schema, 10);
385
+ // 返回: { valid: true, depth: 4, path: 'level1.level2.level3', message: '...' }
359
386
 
360
- if (depth > 5) {
387
+ if (result.depth > 5) {
361
388
  console.warn('嵌套层级过深,建议扁平化');
362
389
  }
363
390
  ```
364
391
 
365
- **用途**: 防止过深嵌套
392
+ **说明**: 这个能力属于 `DslBuilder` 静态方法,不是 `SchemaUtils` 的成员;这里一并列出是因为它常与 Schema 工具链一起使用。
366
393
 
367
394
  ---
368
395
 
@@ -485,6 +512,13 @@ const schema = dsl({
485
512
 
486
513
  ---
487
514
 
488
- **最后更新**: 2025-12-25
515
+ ## 对应示例文件
516
+
517
+ **示例入口**: [schema-utils.ts](https://github.com/vextjs/schema-dsl/blob/main/examples/docs/schema-utils.ts)
518
+ **说明**: 覆盖 `reusable()`、`createLibrary()`、`extend()`、`validateBatch()`、`withPerformance()` 和 `clone()` 的最小工作流。
519
+
520
+ ---
521
+
522
+ **最后更新**: 2026-05-08
489
523
 
490
524
 
@@ -0,0 +1,20 @@
1
+ # 安全检查清单
2
+
3
+ ## 发布前检查
4
+
5
+ - 运行 `npm audit --audit-level=moderate`。
6
+ - 确认文档示例不包含真实密钥、Token 或密码。
7
+ - 自定义正则应避免灾难性回溯。
8
+ - 自定义 validator 不应执行不可信输入生成的代码。
9
+
10
+ ## 当前建议
11
+
12
+ 依赖升级后应重新运行完整测试与构建验证。
13
+
14
+ ---
15
+
16
+ ## 对应示例文件
17
+
18
+ **示例入口**: [security-checklist.ts](https://github.com/vextjs/schema-dsl/blob/main/examples/docs/security-checklist.ts)
19
+ **说明**: 使用占位 token、受限字符集和显式 URL 校验,示范文档中“不要暴露真实凭据”“正则要有界”的落地写法。
20
+
@@ -1,6 +1,6 @@
1
1
  # String 扩展文档
2
2
 
3
- > **更新时间**: 2025-12-25
3
+ > **更新时间**: 2026-05-22
4
4
 
5
5
  ---
6
6
 
@@ -63,7 +63,7 @@ const schema = dsl({
63
63
  | `.label(text)` | 字段标签 | `'email!'.label('邮箱地址')` |
64
64
  | `.messages(obj)` | 自定义消息 | `'string!'.messages({...})` |
65
65
  | `.description(text)` | 描述 | `'url'.description('主页')` |
66
- | `.custom(fn)` | 自定义验证 | `'string!'.custom(async...)` |
66
+ | `.custom(fn)` | 自定义同步验证 | `'string!'.custom(value => value !== "admin")` |
67
67
  | `.default(value)` | 默认值 | `'string'.default('guest')` |
68
68
  | `.username(range?)` | 用户名验证 | `'string!'.username('5-20')` |
69
69
  | `.phone(country)` | 手机号验证 | `'string!'.phone('cn')` |
@@ -179,9 +179,8 @@ const schema = dsl({
179
179
  const schema = dsl({
180
180
  // 最优雅:只在失败时返回错误消息
181
181
  username: 'string:3-32!'
182
- .custom(async (value) => {
183
- const exists = await checkUsernameExists(value);
184
- if (exists) return '用户名已被占用';
182
+ .custom((value) => {
183
+ if (value === 'admin') return '用户名已被占用';
185
184
  // 成功时无需返回
186
185
  })
187
186
  .label('用户名'),
@@ -197,6 +196,8 @@ const schema = dsl({
197
196
  });
198
197
  ```
199
198
 
199
+ ⚠️ `.custom()` 当前仅支持同步函数;需要异步查库或远程调用时,请在 `validate()` / `validateAsync()` 通过后于业务层单独执行。
200
+
200
201
  **支持的返回值**:
201
202
  - 不返回/`undefined` → 验证通过 ✅
202
203
  - 返回字符串 → 验证失败(错误消息)
@@ -206,8 +207,8 @@ const schema = dsl({
206
207
  - 返回 `false` → 验证失败(默认消息)
207
208
 
208
209
  **注意**:
209
- - 异步验证器(async)需要使用 `validator.validateAsync()`(计划中)或在外部处理。
210
- - 目前 `validator.validate()` 是同步的,如果 `.custom()` 返回 Promise,会抛出错误提示。
210
+ - 当前版本**不支持**在 `.custom()` 中直接返回 `Promise`;即使调用 `validateAsync()`,异步 custom validator 仍会报 `同步验证不支持异步操作`。
211
+ - 需要异步校验时,请改为:① 先用 `schema-dsl` 做同步结构校验;② 再在业务层执行异步检查。
211
212
 
212
213
 
213
214
  ---
@@ -471,10 +472,17 @@ const schema = dsl({
471
472
  - [DSL 语法](./dsl-syntax.md)
472
473
  - [API 参考](./api-reference.md)
473
474
  - [多语言支持](./multi-language.md)
474
- - [示例代码](../examples/string-extensions.js)
475
+ - [示例代码](https://github.com/vextjs/schema-dsl/blob/main/examples/docs/string-extensions.ts)
476
+
477
+ ---
478
+
479
+ ## 对应示例文件
480
+
481
+ **示例入口**: [string-extensions.ts](https://github.com/vextjs/schema-dsl/blob/main/examples/docs/string-extensions.ts)
482
+ **说明**: 覆盖 String.prototype 扩展的安装/卸载、链式 `.label()` / `.messages()` / `.pattern()` 调用,以及校验成功/失败路径。
475
483
 
476
484
  ---
477
485
 
478
- **最后更新**: 2025-12-25
486
+ **最后更新**: 2026-05-08
479
487
 
480
488
 
@@ -1,6 +1,6 @@
1
1
  # 常见问题排查指南
2
2
 
3
- > **用途**: 快速解决 SchemaI-DSL 使用中的常见问题
3
+ > **用途**: 快速解决 schema-dsl 使用中的常见问题
4
4
  > **更新**: 2025-12-26
5
5
 
6
6
  ---
@@ -41,10 +41,10 @@ const validator = new Validator({ verbose: true });
41
41
  const result = validator.validate(schema, data);
42
42
  ```
43
43
 
44
- 3. **使用 Schema 分析工具**
44
+ 3. **使用 Schema 摘要工具**
45
45
  ```javascript
46
- const { SchemaUtils } = require('schema-dsl');
47
- console.log(SchemaUtils.analyze(schema));
46
+ const { SchemaHelper } = require('schema-dsl');
47
+ console.log(SchemaHelper.summarizeSchema(schema));
48
48
  ```
49
49
 
50
50
  4. **检查字段名是否正确**
@@ -79,14 +79,20 @@ email: 'email!'.custom(async (value) => {
79
79
  // ❌ 错误:在 validate() 中使用异步验证器
80
80
  const result = validate(schema, data); // 同步模式
81
81
 
82
- // 解决1:使用 validateAsync()
83
- const result = await validateAsync(schema, data);
82
+ // 误区:validateAsync() 也不会让 .custom(async fn) 生效
83
+ await validateAsync(schema, data); // 仍会抛“同步验证不支持异步操作”
84
84
 
85
- // ✅ 解决2:使用同步验证器
85
+ // ✅ 正确:使用同步验证器
86
86
  email: 'email!'.custom((value) => {
87
87
  // 同步代码
88
88
  if (checkSync(value)) return '邮箱已被占用';
89
89
  })
90
+
91
+ // ✅ 或者:把异步检查放到 schema-dsl 之外
92
+ const result = validate(schema, data);
93
+ if (result.valid) {
94
+ await checkEmailUniqueness(data.email);
95
+ }
90
96
  ```
91
97
 
92
98
  #### 原因2: custom() 返回值不正确
@@ -258,13 +264,15 @@ console.log(Object.keys(Locale.locales));
258
264
  // 应该包含: ['zh-CN', 'en-US', 'ja-JP', ...]
259
265
  ```
260
266
 
261
- #### 2. 检查 Validator 配置
267
+ #### 2. 检查验证调用是否传入 locale
262
268
  ```javascript
263
- // ❌ 未指定语言
269
+ // ❌ 构造函数不会设置本次验证语言
264
270
  const validator = new Validator();
265
271
 
266
- // ✅ 指定语言
267
- const validator = new Validator({ locale: 'zh-CN' });
272
+ // ✅ 在 validate 时按次指定语言
273
+ const result = validator.validate(schema, data, {
274
+ locale: 'zh-CN'
275
+ });
268
276
  ```
269
277
 
270
278
  #### 3. 动态切换语言
@@ -378,7 +386,7 @@ db.createCollection('users', {
378
386
 
379
387
  **解决方案**:
380
388
  ```javascript
381
- // SchemaI-DSL 默认会自动安装 String 扩展
389
+ // schema-dsl 默认会自动安装 String 扩展
382
390
  // 如果未生效,手动安装:
383
391
  const { installStringExtensions } = require('schema-dsl');
384
392
  installStringExtensions();
@@ -405,15 +413,15 @@ console.log(JSON.stringify(schema, null, 2));
405
413
  // 查看实际生成的 JSON Schema 结构
406
414
  ```
407
415
 
408
- ### 技巧2: 使用 Schema 分析工具
416
+ ### 技巧2: 使用 Schema 摘要工具
409
417
 
410
418
  ```javascript
411
- const { SchemaUtils } = require('schema-dsl');
419
+ const { SchemaHelper } = require('schema-dsl');
412
420
 
413
- // 分析 Schema 结构
414
- const analysis = SchemaUtils.analyze(schema);
415
- console.log(analysis);
416
- // 输出字段列表、约束信息、嵌套深度等
421
+ // 查看 Schema 结构摘要
422
+ const summary = SchemaHelper.summarizeSchema(schema);
423
+ console.log(summary);
424
+ // 输出字段列表、required 数量、复杂度等
417
425
  ```
418
426
 
419
427
  ### 技巧3: 启用详细日志
@@ -458,13 +466,20 @@ describe('User Schema', () => {
458
466
 
459
467
  如果以上方法无法解决你的问题:
460
468
 
461
- 1. **查看文档**: [完整文档索引](INDEX.md)
462
- 2. **查看示例**: [examples/](../examples/) 目录
463
- 3. **GitHub Issues**: [提交问题](https://github.com/schema-dsl/schema-dsl/issues)
469
+ 1. **查看文档**: [完整文档索引](doc-index.md)
470
+ 2. **查看示例**: [troubleshooting.ts](https://github.com/vextjs/schema-dsl/blob/main/examples/docs/troubleshooting.ts)
471
+ 3. **GitHub Issues**: [提交问题](https://github.com/vextjs/schema-dsl/issues)
464
472
  4. **常见问题**: [FAQ.md](faq.md)
465
473
 
466
474
  ---
467
475
 
476
+ ## 对应示例文件
477
+
478
+ **示例入口**: [troubleshooting.ts](https://github.com/vextjs/schema-dsl/blob/main/examples/docs/troubleshooting.ts)
479
+ **说明**: 演示如何用 `validate()` 和 `compile()` 复现错误、查看路径/关键字/消息,并快速定位失败原因。
480
+
481
+ ---
482
+
468
483
  ## 贡献
469
484
 
470
485
  发现了新的常见问题?欢迎提交 PR 补充本文档!