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,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
-