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
@@ -1,123 +0,0 @@
1
- # Schema-DSL 性能优化快速参考
2
-
3
- ## 🚀 核心原则
4
-
5
- **生产环境:在项目启动时配置好所有 schema,避免每次请求都重复转换**
6
-
7
- ---
8
-
9
- ## ❌ 错误示例(性能差)
10
-
11
- ```javascript
12
- // ❌ 每次请求都转换(性能损失 3-5%)
13
- app.post('/api/user', (req, res) => {
14
- const result = validate(
15
- { email: 'email!', age: 'number!' }, // ❌ 每次都转换
16
- req.body
17
- );
18
- });
19
- ```
20
-
21
- ---
22
-
23
- ## ✅ 正确示例(性能最优)
24
-
25
- ### 步骤1:定义 Schema(schemas/user.js)
26
-
27
- ```javascript
28
- const { dsl } = require('schema-dsl');
29
-
30
- // ✅ 项目启动时转换一次
31
- module.exports = {
32
- register: dsl({
33
- email: 'email!',
34
- password: 'password:strong!',
35
- age: 'number:18-'
36
- }),
37
-
38
- login: dsl({
39
- email: 'email!',
40
- password: 'string!'
41
- })
42
- };
43
- ```
44
-
45
- ### 步骤2:在路由中使用(routes/user.js)
46
-
47
- ```javascript
48
- const userSchemas = require('../schemas/user');
49
- const { validate } = require('schema-dsl');
50
-
51
- // ✅ 直接使用,不再转换
52
- app.post('/api/register', (req, res) => {
53
- const result = validate(userSchemas.register, req.body);
54
- // ...
55
- });
56
-
57
- app.post('/api/login', (req, res) => {
58
- const result = validate(userSchemas.login, req.body);
59
- // ...
60
- });
61
- ```
62
-
63
- ---
64
-
65
- ## 📊 性能对比
66
-
67
- | 方式 | 1000次请求 | 转换次数 | 适用场景 |
68
- |------|-----------|---------|---------|
69
- | ❌ 每次转换 | ~3.4秒 | 1000次 | 原型、测试 |
70
- | ✅ 启动配置 | ~3.3秒 | 1次 | **生产环境** |
71
-
72
- **性能差异:约 3-5%**
73
-
74
- ---
75
-
76
- ## 📁 推荐项目结构
77
-
78
- ```
79
- your-project/
80
- ├── schemas/ # ✅ 所有 schema 定义
81
- │ ├── index.js # 统一导出
82
- │ ├── user.js
83
- │ └── order.js
84
- ├── routes/ # 路由使用 schemas/
85
- │ ├── user.js
86
- │ └── order.js
87
- └── app.js # 启动时加载 schemas
88
- ```
89
-
90
- ---
91
-
92
- ## 🎯 使用场景
93
-
94
- | 场景 | 推荐方式 |
95
- |------|---------|
96
- | 生产环境 API | ✅ 项目启动时配置 |
97
- | 高并发服务 | ✅ 项目启动时配置 |
98
- | 微服务 | ✅ 项目启动时配置 |
99
- | 单次脚本 | ✅ 直接用 DSL 对象 |
100
- | 原型开发 | ✅ 直接用 DSL 对象 |
101
- | 测试代码 | ✅ 直接用 DSL 对象 |
102
-
103
- ---
104
-
105
- ## 💡 记住
106
-
107
- **生产环境 = 启动时配置 = 性能最优**
108
-
109
- ```javascript
110
- // ✅ 这样做
111
- const schemas = require('./schemas'); // 启动时加载
112
- validate(schemas.user.register, data); // 直接使用
113
-
114
- // ❌ 不要这样
115
- validate({ email: 'email!' }, data); // 每次都转换
116
- ```
117
-
118
- ---
119
-
120
- ## 📚 完整文档
121
-
122
- - `best-practices-project-structure.md` - 完整示例
123
- - `validate-dsl-object-support.md` - 功能说明
@@ -1,353 +0,0 @@
1
- # 用户问题解答总结
2
-
3
- ## 您的三个问题
4
-
5
- ### 问题1:DSL 对象中可以使用链式调用吗?
6
-
7
- ```javascript
8
- dsl.validate(
9
- {
10
- user: {
11
- name: dsl('string:3-32!').messages({ 'string.min': '名字太短了' }),
12
- email: 'email!'
13
- }
14
- },
15
- {
16
- user: {
17
- name: 'John',
18
- email: 'john@example.com'
19
- }
20
- }
21
- )
22
- ```
23
-
24
- **答:可以!✅**
25
-
26
- - ✅ DSL 对象支持混合使用 DslBuilder 实例和 DSL 字符串
27
- - ✅ 嵌套对象中也完全支持
28
- - ✅ 自定义消息、label、pattern 等链式方法都可以使用
29
-
30
- **完整示例**:
31
-
32
- ```javascript
33
- const { dsl, validate } = require('schema-dsl');
34
-
35
- // ✅ 混合使用
36
- const result = validate(
37
- {
38
- username: dsl('string:3-32!')
39
- .pattern(/^[a-zA-Z0-9_]+$/)
40
- .messages({ 'string.pattern': '只能包含字母、数字和下划线' }),
41
- email: 'email!', // 纯 DSL 字符串
42
- age: 'number:18-',
43
- profile: {
44
- name: dsl('string!').label('姓名'),
45
- bio: 'string:0-500'
46
- }
47
- },
48
- data
49
- );
50
- ```
51
-
52
- **测试验证**:
53
-
54
- ```javascript
55
- // 测试:触发自定义错误消息
56
- const result = validate(
57
- {
58
- username: dsl('string:3-32!')
59
- .pattern(/^[a-zA-Z0-9_]+$/)
60
- .messages({ 'string.pattern': '自定义错误消息' })
61
- },
62
- { username: 'john-doe' } // 包含非法字符 -
63
- );
64
-
65
- console.log(result.errors[0].message);
66
- // 输出: "自定义错误消息"
67
- ```
68
-
69
- ---
70
-
71
- ### 问题2:直接用对象会有什么影响?
72
-
73
- **性能影响**:
74
-
75
- ```javascript
76
- // 性能测试(1000次验证)
77
- // 方式1:每次传 DSL 对象 → ~3.4秒
78
- // 方式2:复用 schema → ~3.3秒
79
- // 性能差异:约 3-5%
80
- ```
81
-
82
- **详细对比**:
83
-
84
- | 方面 | 每次传 DSL 对象 | 提前转换复用 schema |
85
- |------|----------------|-------------------|
86
- | **简洁性** | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ |
87
- | **性能** | ⭐⭐⭐⭐ (损失3-5%) | ⭐⭐⭐⭐⭐ |
88
- | **可读性** | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ |
89
- | **复用性** | ⭐⭐ (每次转换) | ⭐⭐⭐⭐⭐ |
90
-
91
- **使用建议**:
92
-
93
- ```javascript
94
- // ❌ 不推荐:高并发场景每次转换
95
- app.post('/api/user', (req, res) => {
96
- const result = validate(
97
- { email: 'email!', age: 'number!' }, // 每次都转换
98
- req.body
99
- );
100
- });
101
-
102
- // ✅ 推荐:提前转换,复用 schema
103
- const userSchema = dsl({ email: 'email!', age: 'number!' });
104
-
105
- app.post('/api/user', (req, res) => {
106
- const result = validate(userSchema, req.body); // 直接使用
107
- });
108
-
109
- // ✅ 适合:原型开发/脚本/低并发场景
110
- const result = validate({ email: 'email!' }, data); // 简洁
111
- ```
112
-
113
- **性能影响总结**:
114
-
115
- 1. **开销来源**:
116
- - DSL 对象 → JSON Schema 的转换
117
- - 对象遍历、类型检测、递归处理
118
-
119
- 2. **影响程度**:
120
- - 简单 schema(2-3个字段):3-5% 性能损失
121
- - 复杂 schema(10+字段):可能更高
122
-
123
- 3. **何时影响明显**:
124
- - ❌ 高并发 API(每秒数千请求)
125
- - ❌ 循环中重复验证(数千次)
126
- - ✅ 原型开发/脚本(可忽略)
127
- - ✅ 低并发场景(可忽略)
128
-
129
- ---
130
-
131
- ### 问题3:为什么之前不这样设计?
132
-
133
- **历史设计原因**:
134
-
135
- 1. **职责分离**(设计哲学)
136
-
137
- ```javascript
138
- // 之前的设计:明确的两个步骤
139
- const schema = dsl({ email: 'email!' }); // 步骤1:转换
140
- const result = validate(schema, data); // 步骤2:验证
141
- ```
142
-
143
- 这种设计让每个函数的职责更清晰:
144
- - `dsl()` 负责转换
145
- - `validate()` 只负责验证
146
-
147
- 2. **避免隐式转换**(最小惊喜原则)
148
-
149
- ```javascript
150
- // 用户传入什么类型,就按什么类型处理
151
- validate(jsonSchema, data); // JSON Schema
152
- validate(dslBuilder, data); // DslBuilder
153
- validate({ email: 'email!' }, data); // ❌ 会被当作 JSON Schema 报错
154
- ```
155
-
156
- 避免"魔法"行为,用户不会困惑"为什么我传入的对象被自动转换了"。
157
-
158
- 3. **类型安全考虑**(TypeScript)
159
-
160
- ```typescript
161
- // 明确的类型定义(v1.1.6)
162
- function validate(
163
- schema: JSONSchema | DslBuilder, // 明确的类型
164
- data: any
165
- ): ValidationResult;
166
-
167
- // 如果支持任意对象(v1.1.7)
168
- function validate(
169
- schema: JSONSchema | DslBuilder | Record<string, any>, // 太宽泛
170
- data: any
171
- ): ValidationResult;
172
- ```
173
-
174
- 太宽泛的类型定义会让 TypeScript 无法提供准确的类型检查。
175
-
176
- 4. **性能考虑**(避免误用)
177
-
178
- ```javascript
179
- // 避免用户不经意写出性能差的代码
180
- for (let i = 0; i < 10000; i++) {
181
- validate({ email: 'email!' }, data); // 每次都转换(性能差)
182
- }
183
- ```
184
-
185
- 强制用户显式转换,可以让他们意识到"转换是有开销的"。
186
-
187
- **为什么现在改变了?**
188
-
189
- 1. **用户反馈强烈**
190
- - 很多用户抱怨"为什么不能直接传对象"
191
- - "每次都要写 `dsl()` 太繁琐了"
192
-
193
- 2. **技术成熟**
194
- - 实现了智能检测函数 `_isDslObject()`
195
- - 可以准确区分 DSL 对象和 JSON Schema
196
-
197
- 3. **性能可接受**
198
- - 测试表明性能损失只有 3-5%
199
- - 对大多数场景可以忽略
200
-
201
- 4. **向后兼容**
202
- - 不影响现有代码
203
- - 所有原有用法都继续工作
204
-
205
- 5. **使用体验优先**
206
- - 简化常见场景的使用
207
- - 降低学习成本
208
-
209
- **设计权衡对比**:
210
-
211
- | 设计方案 | 优点 | 缺点 | 适用场景 |
212
- |---------|------|------|---------|
213
- | **显式转换**(v1.1.6) | 职责清晰<br>类型安全<br>性能最优 | 代码冗长<br>学习成本高 | 大型项目<br>类型严格 |
214
- | **自动转换**(v1.1.7) | 简洁直观<br>学习成本低 | 隐式行为<br>类型宽泛 | 原型开发<br>快速验证 |
215
-
216
- **最终选择**:**两者都支持,让用户自由选择!**
217
-
218
- ```javascript
219
- // ✅ 简单场景:直接用 DSL 对象(新增)
220
- validate({ email: 'email!' }, data);
221
-
222
- // ✅ 复杂场景:显式转换(保留)
223
- const schema = dsl({ email: 'email!' });
224
- validate(schema, data);
225
- ```
226
-
227
- ---
228
-
229
- ## 实现细节
230
-
231
- ### 智能检测函数 `_isDslObject()`
232
-
233
- ```javascript
234
- function _isDslObject(obj) {
235
- // 1. 排除非对象
236
- if (!obj || typeof obj !== 'object' || Array.isArray(obj)) {
237
- return false;
238
- }
239
-
240
- // 2. 排除 DslBuilder(顶层)
241
- if (typeof obj.toSchema === 'function') {
242
- return false;
243
- }
244
-
245
- // 3. 排除 ConditionalBuilder
246
- if (obj._isConditional) {
247
- return false;
248
- }
249
-
250
- // 4. 排除标准 JSON Schema
251
- if (obj.type && ['string', 'number', ...].includes(obj.type)) {
252
- return false;
253
- }
254
-
255
- // 5. 检测 DSL 特征
256
- const values = Object.values(obj);
257
-
258
- // 5.1 检测 DslBuilder 实例(属性值)
259
- const hasDslBuilder = values.some(v =>
260
- v && typeof v === 'object' && typeof v.toSchema === 'function'
261
- );
262
-
263
- // 5.2 检测 DSL 字符串
264
- const hasDslString = values.some(v =>
265
- typeof v === 'string' && (
266
- v.includes(':') || v.includes('!') || ...
267
- )
268
- );
269
-
270
- // 5.3 检测嵌套 DSL 对象
271
- const hasNestedDslObject = values.some(v => _isDslObject(v));
272
-
273
- return hasDslBuilder || hasDslString || hasNestedDslObject;
274
- }
275
- ```
276
-
277
- ### 自动转换流程
278
-
279
- ```javascript
280
- function validate(schema, data, options = {}) {
281
- // ✅ 自动检测并转换
282
- if (_isDslObject(schema)) {
283
- schema = DslAdapter.parseObject(schema);
284
- }
285
-
286
- const validator = new Validator(options);
287
- return validator.validate(schema, data, options);
288
- }
289
- ```
290
-
291
- ---
292
-
293
- ## 测试验证
294
-
295
- ### 功能测试(8项全部通过)
296
-
297
- ```javascript
298
- ✅ 纯 DSL 字符串对象
299
- ✅ 混合 DslBuilder 和 DSL 字符串
300
- ✅ 嵌套对象中使用 DslBuilder
301
- ✅ 触发自定义错误消息
302
- ✅ 标准 JSON Schema 仍然工作
303
- ✅ DslBuilder 实例仍然工作
304
- ✅ 复杂嵌套场景
305
- ✅ validateAsync 也支持 DSL 对象
306
- ```
307
-
308
- ### 性能测试
309
-
310
- ```
311
- 方式1: 每次传 DSL 对象: 3.412s (1000次)
312
- 方式2: 复用 schema: 3.378s (1000次)
313
- 性能差异: 约 1% (3.4ms)
314
- ```
315
-
316
- ---
317
-
318
- ## 总结
319
-
320
- ### 三个问题的答案
321
-
322
- 1. **DSL 对象中可以使用链式调用吗?**
323
- - ✅ 可以!支持混合使用 DslBuilder 实例和 DSL 字符串
324
-
325
- 2. **直接用对象会有什么影响?**
326
- - 性能损失:3-5%
327
- - 适用场景:原型开发、脚本、低并发
328
- - 高并发场景:建议提前转换复用
329
-
330
- 3. **为什么之前不这样设计?**
331
- - 设计哲学:职责分离、避免隐式转换
332
- - 现在改变:用户反馈 + 技术成熟 + 向后兼容
333
-
334
- ### 推荐使用方式
335
-
336
- ```javascript
337
- // ✅ 原型开发/脚本:直接用 DSL 对象
338
- validate({ email: 'email!' }, data);
339
-
340
- // ✅ 生产环境/高并发:提前转换
341
- const schema = dsl({ email: 'email!' });
342
- validate(schema, data);
343
-
344
- // ✅ 需要链式调用:混合使用
345
- validate({
346
- username: dsl('string:3-32!').pattern(/^[a-zA-Z0-9_]+$/),
347
- email: 'email!'
348
- }, data);
349
- ```
350
-
351
- ---
352
-
353
- **完整文档**: [validate-dsl-object-support.md](./validate-dsl-object-support.md)