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
@@ -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)