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,129 +0,0 @@
1
- /**
2
- * ConditionalBuilder 非对象类型示例
3
- *
4
- * 展示如何直接验证字符串、数组、布尔值等非对象类型
5
- */
6
-
7
- const { dsl, validate } = require('../index');
8
-
9
- console.log('========================================');
10
- console.log('ConditionalBuilder - 非对象类型示例');
11
- console.log('========================================\n');
12
-
13
- // ============================================
14
- // 示例1:直接验证字符串
15
- // ============================================
16
- console.log('【示例1】直接验证字符串');
17
- console.log('----------------------------');
18
-
19
- const stringSchema = dsl.if((data) => typeof data === 'string' && data.includes('@'))
20
- .then('email!')
21
- .else('string:1-50');
22
-
23
- const r1 = validate(stringSchema, 'test@example.com');
24
- console.log('✅ 邮箱格式:', r1.valid ? '验证通过' : '验证失败');
25
-
26
- const r2 = validate(stringSchema, 'just a text');
27
- console.log('✅ 普通文本:', r2.valid ? '验证通过' : '验证失败');
28
-
29
- // ============================================
30
- // 示例2:直接验证数组
31
- // ============================================
32
- console.log('\n【示例2】直接验证数组');
33
- console.log('----------------------------');
34
-
35
- const arraySchema = dsl.if((data) => Array.isArray(data) && data.length > 5)
36
- .message('数组最多5个元素');
37
-
38
- const r3 = validate(arraySchema, [1, 2, 3]);
39
- console.log('✅ 3个元素:', r3.valid ? '验证通过' : '验证失败');
40
-
41
- const r4 = validate(arraySchema, [1, 2, 3, 4, 5, 6]);
42
- console.log('❌ 6个元素:', r4.valid ? '验证通过' : '验证失败');
43
- if (!r4.valid) {
44
- console.log(' 错误:', r4.errors[0].message);
45
- }
46
-
47
- // ============================================
48
- // 示例3:直接验证数字
49
- // ============================================
50
- console.log('\n【示例3】直接验证数字');
51
- console.log('----------------------------');
52
-
53
- const numberSchema = dsl.if((data) => typeof data === 'number' && data < 0)
54
- .message('不允许负数')
55
- .else(null); // 不需要额外验证
56
-
57
- const r5 = validate(numberSchema, 10);
58
- console.log('✅ 正数:', r5.valid ? '验证通过' : '验证失败');
59
-
60
- const r6 = validate(numberSchema, -5);
61
- console.log('❌ 负数:', r6.valid ? '验证通过' : '验证失败');
62
- if (!r6.valid) {
63
- console.log(' 错误:', r6.errors[0].message);
64
- }
65
-
66
- // ============================================
67
- // 示例4:字符串类型判断(邮箱或手机号)
68
- // ============================================
69
- console.log('\n【示例4】自动识别邮箱或手机号');
70
- console.log('----------------------------');
71
-
72
- const contactSchema = dsl.if((data) => typeof data === 'string' && data.includes('@'))
73
- .then('email!')
74
- .else('string:11!');
75
-
76
- const r7 = validate(contactSchema, 'user@example.com');
77
- console.log('✅ 邮箱:', r7.valid ? '验证通过' : '验证失败');
78
-
79
- const r8 = validate(contactSchema, '13800138000');
80
- console.log('✅ 手机号:', r8.valid ? '验证通过' : '验证失败');
81
-
82
- const r9 = validate(contactSchema, 'invalid');
83
- console.log('❌ 无效输入:', r9.valid ? '验证通过' : '验证失败');
84
- if (!r9.valid) {
85
- console.log(' 错误:', r9.errors[0].message);
86
- }
87
-
88
- // ============================================
89
- // 示例5:复杂条件组合
90
- // ============================================
91
- console.log('\n【示例5】字符串长度 + 内容组合判断');
92
- console.log('----------------------------');
93
-
94
- const complexSchema = dsl.if((data) => typeof data === 'string' && data.length > 20)
95
- .and((data) => data.includes('@'))
96
- .then('email!')
97
- .else('string:1-50');
98
-
99
- const r10 = validate(complexSchema, 'short');
100
- console.log('✅ 短字符串:', r10.valid ? '验证通过' : '验证失败');
101
-
102
- const r11 = validate(complexSchema, 'this-is-a-long-email@example.com');
103
- console.log('✅ 长邮箱:', r11.valid ? '验证通过' : '验证失败');
104
-
105
- const r12 = validate(complexSchema, 'this is a very long string without at symbol');
106
- console.log('✅ 长文本(无@):', r12.valid ? '验证通过' : '验证失败');
107
-
108
- // ============================================
109
- // 示例6:边界值处理
110
- // ============================================
111
- console.log('\n【示例6】边界值处理');
112
- console.log('----------------------------');
113
-
114
- const boundarySchema = dsl.if((data) => data === null || data === undefined || data === '')
115
- .message('值不能为空');
116
-
117
- const r13 = validate(boundarySchema, 'valid value');
118
- console.log('✅ 有效值:', r13.valid ? '验证通过' : '验证失败');
119
-
120
- const r14 = validate(boundarySchema, '');
121
- console.log('❌ 空字符串:', r14.valid ? '验证通过' : '验证失败');
122
- if (!r14.valid) {
123
- console.log(' 错误:', r14.errors[0].message);
124
- }
125
-
126
- console.log('\n========================================');
127
- console.log('示例运行完成!');
128
- console.log('========================================');
129
-
@@ -1,321 +0,0 @@
1
- /**
2
- * ConditionalBuilder 快捷验证方法示例
3
- *
4
- * 展示 .validate() 和 .check() 方法的使用
5
- */
6
-
7
- const { dsl } = require('../index');
8
-
9
- console.log('========================================');
10
- console.log('ConditionalBuilder - 快捷验证方法示例');
11
- console.log('========================================\n');
12
-
13
- // ============================================
14
- // 示例1:一行代码验证
15
- // ============================================
16
- console.log('【示例1】一行代码验证');
17
- console.log('----------------------------');
18
-
19
- const result1 = dsl.if(d => d.age < 18)
20
- .message('未成年用户不能注册')
21
- .validate({ age: 16 });
22
-
23
- console.log('验证未成年用户:', result1.valid ? '✅ 通过' : '❌ 失败');
24
- if (!result1.valid) {
25
- console.log('错误:', result1.errors[0].message);
26
- }
27
-
28
- const result2 = dsl.if(d => d.age < 18)
29
- .message('未成年用户不能注册')
30
- .validate({ age: 20 });
31
-
32
- console.log('验证成年用户:', result2.valid ? '✅ 通过' : '❌ 失败');
33
-
34
- // ============================================
35
- // 示例2:复用验证器
36
- // ============================================
37
- console.log('\n【示例2】复用验证器');
38
- console.log('----------------------------');
39
-
40
- const ageValidator = dsl.if(d => d.age < 18).message('未成年用户不能注册');
41
-
42
- const users = [
43
- { name: '张三', age: 16 },
44
- { name: '李四', age: 20 },
45
- { name: '王五', age: 17 },
46
- { name: '赵六', age: 25 }
47
- ];
48
-
49
- users.forEach(user => {
50
- const result = ageValidator.validate(user);
51
- console.log(`${user.name}(${user.age}岁):`, result.valid ? '✅ 可以注册' : '❌ 不能注册');
52
- });
53
-
54
- // ============================================
55
- // 示例3:.check() 快速判断
56
- // ============================================
57
- console.log('\n【示例3】.check() 快速判断');
58
- console.log('----------------------------');
59
-
60
- const canRegister = dsl.if(d => d.age < 18)
61
- .or(d => d.status === 'blocked')
62
- .message('不允许注册');
63
-
64
- const testUsers = [
65
- { name: '用户A', age: 16, status: 'active' },
66
- { name: '用户B', age: 20, status: 'blocked' },
67
- { name: '用户C', age: 20, status: 'active' }
68
- ];
69
-
70
- testUsers.forEach(user => {
71
- const isValid = canRegister.check(user);
72
- console.log(`${user.name}:`, isValid ? '✅ 允许注册' : '❌ 禁止注册');
73
- });
74
-
75
- // ============================================
76
- // 示例4:then/else 动态验证
77
- // ============================================
78
- console.log('\n【示例4】then/else 动态验证');
79
- console.log('----------------------------');
80
-
81
- const emailValidator = dsl.if(d => d.userType === 'admin')
82
- .then('email!') // 管理员必填
83
- .else('email'); // 普通用户可选
84
-
85
- // 管理员有邮箱
86
- const r1 = emailValidator.validate({
87
- userType: 'admin',
88
- email: 'admin@example.com'
89
- });
90
- console.log('管理员有邮箱:', r1.valid ? '✅ 通过' : '❌ 失败');
91
-
92
- // 管理员无邮箱
93
- const r2 = emailValidator.validate({
94
- userType: 'admin',
95
- email: ''
96
- });
97
- console.log('管理员无邮箱:', r2.valid ? '✅ 通过' : '❌ 失败');
98
-
99
- // 普通用户无邮箱
100
- const r3 = emailValidator.validate({
101
- userType: 'user',
102
- email: ''
103
- });
104
- console.log('普通用户无邮箱:', r3.valid ? '✅ 通过' : '❌ 失败');
105
-
106
- // ============================================
107
- // 示例5:非对象类型验证
108
- // ============================================
109
- console.log('\n【示例5】非对象类型验证');
110
- console.log('----------------------------');
111
-
112
- // 验证字符串
113
- const stringValidator = dsl.if(d => typeof d === 'string' && d.includes('@'))
114
- .then('email!')
115
- .else('string:1-50');
116
-
117
- const r4 = stringValidator.validate('test@example.com');
118
- console.log('邮箱格式:', r4.valid ? '✅ 通过' : '❌ 失败');
119
-
120
- const r5 = stringValidator.validate('just a text');
121
- console.log('普通文本:', r5.valid ? '✅ 通过' : '❌ 失败');
122
-
123
- // 验证数组
124
- const arrayValidator = dsl.if(d => Array.isArray(d) && d.length > 5)
125
- .message('数组最多5个元素');
126
-
127
- const r6 = arrayValidator.validate([1, 2, 3]);
128
- console.log('3个元素:', r6.valid ? '✅ 通过' : '❌ 失败');
129
-
130
- const r7 = arrayValidator.validate([1, 2, 3, 4, 5, 6]);
131
- console.log('6个元素:', r7.valid ? '✅ 通过' : '❌ 失败');
132
- if (!r7.valid) {
133
- console.log('错误:', r7.errors[0].message);
134
- }
135
-
136
- // ============================================
137
- // 示例6:多语言支持
138
- // ============================================
139
- console.log('\n【示例6】多语言支持');
140
- console.log('----------------------------');
141
-
142
- const i18nValidator = dsl.if(d => d.age < 18)
143
- .message('conditional.underAge');
144
-
145
- // 中文
146
- const r8 = i18nValidator.validate({ age: 16 }, { locale: 'zh-CN' });
147
- console.log('中文:', r8.valid ? '✅ 通过' : '❌ 失败');
148
- if (!r8.valid) {
149
- console.log('错误:', r8.errors[0].message);
150
- }
151
-
152
- // 英文
153
- const r9 = i18nValidator.validate({ age: 16 }, { locale: 'en-US' });
154
- console.log('英文:', r9.valid ? '✅ 通过' : '❌ 失败');
155
- if (!r9.valid) {
156
- console.log('错误:', r9.errors[0].message);
157
- }
158
-
159
- // ============================================
160
- // 示例7:实际业务场景
161
- // ============================================
162
- console.log('\n【示例7】实际业务场景 - 用户注册');
163
- console.log('----------------------------');
164
-
165
- // 创建多个验证器
166
- const validators = {
167
- age: dsl.if(d => d.age < 18)
168
- .message('未成年用户不能注册'),
169
-
170
- email: dsl.if(d => d.userType === 'admin')
171
- .then('email!')
172
- .else('email'),
173
-
174
- phone: dsl.if(d => d.userType === 'vip')
175
- .then('string:11!')
176
- .else(null)
177
- };
178
-
179
- // 验证用户
180
- function validateUser(userData) {
181
- console.log(`\n验证用户: ${userData.username}`);
182
-
183
- // 年龄检查
184
- if (!validators.age.check(userData)) {
185
- console.log('❌ 年龄验证失败');
186
- return false;
187
- }
188
-
189
- // 邮箱检查
190
- const emailResult = validators.email.validate(userData);
191
- if (!emailResult.valid) {
192
- console.log('❌ 邮箱验证失败:', emailResult.errors[0].message);
193
- return false;
194
- }
195
-
196
- // 手机号检查
197
- const phoneResult = validators.phone.validate(userData);
198
- if (!phoneResult.valid) {
199
- console.log('❌ 手机号验证失败:', phoneResult.errors[0].message);
200
- return false;
201
- }
202
-
203
- console.log('✅ 所有验证通过');
204
- return true;
205
- }
206
-
207
- // 测试数据
208
- const userData1 = {
209
- username: 'admin1',
210
- age: 25,
211
- userType: 'admin',
212
- email: 'admin@example.com'
213
- };
214
-
215
- const userData2 = {
216
- username: 'user1',
217
- age: 16,
218
- userType: 'user',
219
- email: ''
220
- };
221
-
222
- validateUser(userData1);
223
- validateUser(userData2);
224
-
225
- // ============================================
226
- // 示例8:异步验证 - .validateAsync()
227
- // ============================================
228
- console.log('\n【示例8】异步验证 - .validateAsync()');
229
- console.log('----------------------------');
230
-
231
- async function asyncRegister() {
232
- const ageValidator = dsl.if(d => d.age < 18)
233
- .message('未成年用户不能注册');
234
-
235
- // 验证通过
236
- try {
237
- const data1 = await ageValidator.validateAsync({ age: 20, name: '张三' });
238
- console.log('✅ 验证通过:', data1.name);
239
- } catch (error) {
240
- console.log('❌ 验证失败:', error.message);
241
- }
242
-
243
- // 验证失败
244
- try {
245
- await ageValidator.validateAsync({ age: 16, name: '李四' });
246
- } catch (error) {
247
- console.log('❌ 验证失败:', error.message);
248
- }
249
- }
250
-
251
- asyncRegister();
252
-
253
- // ============================================
254
- // 示例9:断言验证 - .assert()
255
- // ============================================
256
- console.log('\n【示例9】断言验证 - .assert()');
257
- console.log('----------------------------');
258
-
259
- function createUser(userData) {
260
- try {
261
- // 断言验证,失败直接抛错
262
- dsl.if(d => d.age < 18)
263
- .message('未成年用户不能注册')
264
- .assert(userData);
265
-
266
- dsl.if(d => !d.email || d.email.length === 0)
267
- .message('邮箱不能为空')
268
- .assert(userData);
269
-
270
- console.log(`✅ 用户 ${userData.name} 创建成功`);
271
- return { success: true, user: userData };
272
- } catch (error) {
273
- console.log(`❌ 用户 ${userData.name} 创建失败: ${error.message}`);
274
- return { success: false, error: error.message };
275
- }
276
- }
277
-
278
- createUser({ name: '张三', age: 20, email: 'zhangsan@example.com' });
279
- createUser({ name: '李四', age: 16, email: 'lisi@example.com' });
280
- createUser({ name: '王五', age: 20, email: '' });
281
-
282
- // ============================================
283
- // 示例10:Express 中间件场景(模拟)
284
- // ============================================
285
- console.log('\n【示例10】Express 中间件场景(模拟)');
286
- console.log('----------------------------');
287
-
288
- // 模拟 Express 中间件
289
- async function checkPermission(req, res, next) {
290
- try {
291
- await dsl.if(d => d.role !== 'admin' && d.role !== 'moderator')
292
- .message('权限不足')
293
- .validateAsync(req.user);
294
-
295
- console.log('✅ 权限验证通过');
296
- next();
297
- } catch (error) {
298
- console.log('❌ 权限不足:', error.message);
299
- res.status = 403;
300
- res.error = error.message;
301
- }
302
- }
303
-
304
- // 模拟请求
305
- const mockReq1 = { user: { name: 'admin', role: 'admin' } };
306
- const mockReq2 = { user: { name: 'user', role: 'user' } };
307
- const mockRes = { status: 200, error: null };
308
- const mockNext = () => console.log(' 继续处理请求...');
309
-
310
- (async () => {
311
- console.log('请求1 - 管理员:');
312
- await checkPermission(mockReq1, mockRes, mockNext);
313
-
314
- console.log('请求2 - 普通用户:');
315
- await checkPermission(mockReq2, mockRes, mockNext);
316
- })();
317
-
318
- console.log('\n========================================');
319
- console.log('示例运行完成!');
320
- console.log('========================================');
321
-
@@ -1,85 +0,0 @@
1
- /**
2
- * 扩展自定义类型示例
3
- *
4
- * 演示如何在项目中扩展 SchemaIO 的功能:
5
- * 1. 扩展 DSL 方法 (DslBuilder.prototype)
6
- * 2. 添加自定义格式 (Validator.addFormat)
7
- * 3. 添加自定义关键字 (Validator.addKeyword)
8
- */
9
-
10
- const { dsl, Validator, DslBuilder } = require('../index');
11
-
12
- // ========== 1. 扩展 DSL 方法 ==========
13
-
14
- // 扩展 .zipCode() 方法
15
- DslBuilder.prototype.zipCode = function(country = 'cn') {
16
- const patterns = {
17
- cn: /^[1-9]\d{5}$/,
18
- us: /^\d{5}(-\d{4})?$/
19
- };
20
-
21
- const pattern = patterns[country];
22
- if (!pattern) throw new Error(`Unsupported country: ${country}`);
23
-
24
- return this.pattern(pattern)
25
- .messages({ 'pattern': `无效的邮政编码 (${country})` });
26
- };
27
-
28
- // 扩展 .isEven() 方法 (自定义验证逻辑)
29
- DslBuilder.prototype.isEven = function() {
30
- return this.custom(value => {
31
- if (typeof value === 'number' && value % 2 !== 0) {
32
- return '必须是偶数';
33
- }
34
- });
35
- };
36
-
37
- // ========== 2. 添加自定义格式 (Validator) ==========
38
-
39
- const validator = new Validator();
40
-
41
- // 添加 'ipv4-cidr' 格式
42
- validator.ajv.addFormat('ipv4-cidr', {
43
- type: 'string',
44
- validate: (ip) => {
45
- const parts = ip.split('/');
46
- if (parts.length !== 2) return false;
47
- const [addr, mask] = parts;
48
- // 简单验证 (实际应使用更严谨的正则)
49
- return /^\d{1,3}(\.\d{1,3}){3}$/.test(addr) &&
50
- Number(mask) >= 0 && Number(mask) <= 32;
51
- }
52
- });
53
-
54
- // ========== 3. 使用扩展功能 ==========
55
-
56
- const schema = dsl({
57
- // 使用扩展的 DSL 方法 (注意:自定义方法需要用 dsl() 包裹,或者手动扩展 String.prototype)
58
- zip: dsl('string!').zipCode('cn'),
59
- count: dsl('integer!').isEven(),
60
-
61
- // 使用自定义格式 (通过 string 类型 + format)
62
- network: 'string'.format('ipv4-cidr')
63
- });
64
-
65
- // ========== 4. 测试验证 ==========
66
-
67
- const data = {
68
- zip: '123', // 无效
69
- count: 3, // 无效 (奇数)
70
- network: 'invalid' // 无效
71
- };
72
-
73
- const result = validator.validate(schema, data);
74
-
75
- console.log('验证结果:', result.valid);
76
- if (!result.valid) {
77
- result.errors.forEach(e => console.log(`- ${e.path}: ${e.message}`));
78
- }
79
-
80
- // 输出预期:
81
- // - zip: 无效的邮政编码 (cn)
82
- // - count: 必须是偶数
83
- // - network: must match format "ipv4-cidr"
84
-
85
-
@@ -1,74 +0,0 @@
1
- /**
2
- * DSL Match 语法示例 (v2.1.0)
3
- *
4
- * 展示如何使用 dsl.match 和 dsl.if 进行条件验证
5
- */
6
-
7
- const { dsl, validate } = require('../index');
8
- const fs = require('fs');
9
-
10
- function log(msg) {
11
- console.log(msg);
12
- fs.appendFileSync('dsl-match-output.txt', msg + '\n');
13
- }
14
-
15
- log('Start example...');
16
-
17
- log('========== DSL Match 语法示例 ==========\n');
18
-
19
- // 1. 基本用法:根据类型验证格式
20
- log('✨ 1. 基本用法');
21
-
22
- const contactSchema = dsl({
23
- contactType: 'email|phone',
24
-
25
- // 根据 contactType 的值决定 contact 的验证规则
26
- contact: dsl.match('contactType', {
27
- email: 'email!',
28
- phone: 'string:11!',
29
- _default: 'string'
30
- })
31
- });
32
-
33
- const data1 = { contactType: 'email', contact: 'test@example.com' };
34
- log('Email验证: ' + (validate(contactSchema, data1).valid ? '✅ 通过' : '❌ 失败'));
35
-
36
- const data2 = { contactType: 'phone', contact: '13800138000' };
37
- log('Phone验证: ' + (validate(contactSchema, data2).valid ? '✅ 通过' : '❌ 失败'));
38
-
39
- const data3 = { contactType: 'phone', contact: '123456789012' }; // 12位,超过11
40
- log('错误验证: ' + (validate(contactSchema, data3).valid ? '✅ 通过' : '❌ 失败'));
41
- log('');
42
-
43
-
44
- // 2. 处理中文和特殊字符
45
- log('✨ 2. 中文和特殊字符');
46
-
47
- const discountSchema = dsl({
48
- level: 'string',
49
-
50
- discount: dsl.match('level', {
51
- '普通用户': 'number:0-5',
52
- 'VIP-1': 'number:0-20',
53
- '100': 'number:0-50'
54
- })
55
- });
56
-
57
- log('普通用户: ' + validate(discountSchema, { level: '普通用户', discount: 3 }).valid);
58
- log('VIP-1: ' + validate(discountSchema, { level: 'VIP-1', discount: 15 }).valid);
59
- log('');
60
-
61
-
62
- // 3. dsl.if 简单条件
63
- log('✨ 3. dsl.if 简单条件');
64
-
65
- const vipSchema = dsl({
66
- isVip: 'boolean',
67
- // 如果是VIP,折扣0-50,否则0-10
68
- discount: dsl.if('isVip', 'number:0-50', 'number:0-10')
69
- });
70
-
71
- log('VIP折扣: ' + validate(vipSchema, { isVip: true, discount: 40 }).valid);
72
- log('非VIP折扣: ' + validate(vipSchema, { isVip: false, discount: 40 }).valid); // false
73
- log('');
74
-