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
package/index.d.ts DELETED
@@ -1,3540 +0,0 @@
1
- // Type definitions for schema-dsl v1.1.8
2
- // Project: https://github.com/vextjs/schema-dsl
3
- // Definitions by: schema-dsl Team
4
-
5
- // ========== 核心类型 ==========
6
-
7
- /**
8
- * 错误消息配置(字符串或对象)
9
- *
10
- * @description v1.1.5 新增:支持对象格式配置错误代码和消息
11
- *
12
- * @example 字符串格式(向后兼容)
13
- * ```typescript
14
- * const messages = {
15
- * 'user.notFound': '用户不存在'
16
- * };
17
- * ```
18
- *
19
- * @example 对象格式(v1.1.5 新增)
20
- * ```typescript
21
- * const messages = {
22
- * 'account.notFound': {
23
- * code: 'ACCOUNT_NOT_FOUND',
24
- * message: '账户不存在'
25
- * }
26
- * };
27
- * ```
28
- *
29
- * @since v1.1.5
30
- */
31
- export type ErrorMessageConfig =
32
- | string // 向后兼容:'账户不存在'
33
- | { // 新格式:{ code, message }
34
- /** 错误代码(可选,默认使用 key) */
35
- code?: string;
36
- /** 错误消息(必需) */
37
- message: string;
38
- };
39
-
40
- /**
41
- * 语言包定义
42
- *
43
- * @description 语言包对象,key 为错误代码,value 为错误消息配置
44
- *
45
- * @example
46
- * ```typescript
47
- * const zhCN: LocaleMessages = {
48
- * 'user.notFound': '用户不存在',
49
- * 'account.notFound': {
50
- * code: 'ACCOUNT_NOT_FOUND',
51
- * message: '账户不存在'
52
- * }
53
- * };
54
- * ```
55
- *
56
- * @since v1.1.5
57
- */
58
- export interface LocaleMessages {
59
- [key: string]: ErrorMessageConfig;
60
- }
61
-
62
- /**
63
- * JSON Schema 对象
64
- *
65
- * @description JSON Schema draft-07 规范的类型定义
66
- * @see https://json-schema.org/draft-07/schema
67
- *
68
- * @example
69
- * ```typescript
70
- * const schema: JSONSchema = {
71
- * type: 'object',
72
- * properties: {
73
- * username: { type: 'string', minLength: 3, maxLength: 32 },
74
- * email: { type: 'string', format: 'email' }
75
- * },
76
- * required: ['username', 'email']
77
- * };
78
- * ```
79
- */
80
- export interface JSONSchema {
81
- /** 数据类型 */
82
- type?: string | string[];
83
- /** 对象属性定义 */
84
- properties?: Record<string, JSONSchema>;
85
- /** 必填字段列表 */
86
- required?: string[];
87
- /** 字符串/数组最小长度 */
88
- minLength?: number;
89
- /** 字符串/数组最大长度 */
90
- maxLength?: number;
91
- /** 数字最小值 */
92
- minimum?: number;
93
- /** 数字最大值 */
94
- maximum?: number;
95
- /** 正则表达式验证 */
96
- pattern?: string;
97
- /** 格式验证(email, url, date等) */
98
- format?: string;
99
- /** 枚举值 */
100
- enum?: any[];
101
- /** 数组项定义 */
102
- items?: JSONSchema;
103
- /** 字段标题 */
104
- title?: string;
105
- /** 字段描述 */
106
- description?: string;
107
- /** 默认值 */
108
- default?: any;
109
- /** 示例值 */
110
- examples?: any[];
111
- /** 扩展字段 */
112
- [key: string]: any;
113
- }
114
-
115
- /**
116
- * 验证结果
117
- *
118
- * @description validate()方法的返回值类型
119
- *
120
- * @example
121
- * ```typescript
122
- * const result: ValidationResult = schema.validate({ username: 'test' });
123
- *
124
- * if (result.valid) {
125
- * console.log('验证通过', result.data);
126
- * } else {
127
- * console.log('验证失败', result.errors);
128
- * }
129
- * ```
130
- */
131
- export interface ValidationResult<T = any> {
132
- /** 是否验证通过 */
133
- valid: boolean;
134
- /** 验证错误列表(仅在valid=false时存在) */
135
- errors?: ValidationError[];
136
- /** 验证后的数据(仅在valid=true时存在) */
137
- data?: T;
138
- }
139
-
140
- /**
141
- * 验证错误
142
- *
143
- * @description 详细的验证错误信息
144
- *
145
- * @example
146
- * ```typescript
147
- * const error: ValidationError = {
148
- * message: '用户名至少需要 3 个字符',
149
- * path: 'username',
150
- * keyword: 'minLength',
151
- * params: { limit: 3 }
152
- * };
153
- * ```
154
- */
155
- export interface ValidationError {
156
- /** 错误消息 */
157
- message: string;
158
- /** 错误字段路径(使用点号分隔) */
159
- path: string;
160
- /** 验证关键字(min, max, email等) */
161
- keyword: string;
162
- /** 验证参数 */
163
- params?: Record<string, any>;
164
- /** 错误字段(别名,同path) */
165
- field?: string;
166
- }
167
-
168
- /**
169
- * 验证选项
170
- *
171
- * @description validate() 和 Validator.validate() 的配置选项
172
- *
173
- * @example
174
- * ```typescript
175
- * const options: ValidateOptions = {
176
- * format: true,
177
- * locale: 'zh-CN',
178
- * messages: {
179
- * min: '至少需要 {{#limit}} 个字符'
180
- * }
181
- * };
182
- *
183
- * const result = validate(schema, data, options);
184
- * ```
185
- */
186
- export interface ValidateOptions {
187
- /** 是否格式化错误(默认true) */
188
- format?: boolean;
189
- /** 动态指定语言(如 'zh-CN', 'en-US', 'ja-JP', 'es-ES', 'fr-FR') */
190
- locale?: string;
191
- /** 自定义错误消息 */
192
- messages?: ErrorMessages;
193
- /** 扩展选项 */
194
- [key: string]: any;
195
- }
196
-
197
- /**
198
- * 错误消息对象
199
- *
200
- * @description 自定义错误消息的配置对象
201
- *
202
- * @example
203
- * ```typescript
204
- * const messages: ErrorMessages = {
205
- * min: '至少需要 {{#limit}} 个字符',
206
- * max: '最多 {{#limit}} 个字符',
207
- * email: '邮箱格式不正确',
208
- * required: '这是必填项'
209
- * };
210
- *
211
- * const schema = dsl({ email: 'email!' }, { messages });
212
- * ```
213
- */
214
- export interface ErrorMessages {
215
- /** 最小长度/最小值错误 (v1.0.3+: 推荐使用min代替minLength) */
216
- min?: string;
217
- /** 最大长度/最大值错误 (v1.0.3+: 推荐使用max代替maxLength) */
218
- max?: string;
219
- /** 最小长度错误 (向后兼容,推荐使用min) */
220
- minLength?: string;
221
- /** 最大长度错误 (向后兼容,推荐使用max) */
222
- maxLength?: string;
223
- /** 最小值错误 (向后兼容,推荐使用min) */
224
- minimum?: string;
225
- /** 最大值错误 (向后兼容,推荐使用max) */
226
- maximum?: string;
227
- /** 数组最小长度错误 (向后兼容,推荐使用min) */
228
- minItems?: string;
229
- /** 数组最大长度错误 (向后兼容,推荐使用max) */
230
- maxItems?: string;
231
- /** 正则表达式验证错误 */
232
- pattern?: string;
233
- /** 格式验证错误 */
234
- format?: string;
235
- /** 枚举值验证错误 */
236
- enum?: string;
237
- /** 邮箱格式错误 */
238
- email?: string;
239
- /** URL格式错误 */
240
- url?: string;
241
- /** 必填项错误 */
242
- required?: string;
243
- /** 类型错误 */
244
- type?: string;
245
- /** 自定义错误消息 */
246
- [key: string]: string | undefined;
247
- }
248
-
249
- // ========== DslBuilder 类 ==========
250
-
251
- /**
252
- * DSL Builder 类
253
- *
254
- * @description 提供链式API来构建Schema定义
255
- *
256
- * @example
257
- * ```typescript
258
- * // 基础用法
259
- * const builder = new DslBuilder('email!');
260
- * builder.pattern(/custom/).label('邮箱地址');
261
- *
262
- * // 链式调用
263
- * const schema = new DslBuilder('string:3-32!')
264
- * .pattern(/^[a-zA-Z0-9_]+$/, '只能包含字母、数字和下划线')
265
- * .label('用户名')
266
- * .messages({
267
- * min: '至少3个字符',
268
- * max: '最多32个字符'
269
- * })
270
- * .toSchema();
271
- * ```
272
- */
273
- export class DslBuilder {
274
- /**
275
- * 注册自定义类型(供插件使用)
276
- * @param name - 类型名称
277
- * @param schema - JSON Schema对象或生成函数
278
- * @static
279
- * @since v1.1.0
280
- *
281
- * @example
282
- * ```typescript
283
- * // 注册自定义类型
284
- * DslBuilder.registerType('phone-cn', {
285
- * type: 'string',
286
- * pattern: '^1[3-9]\\d{9}$',
287
- * minLength: 11,
288
- * maxLength: 11
289
- * });
290
- *
291
- * // 在DSL中使用
292
- * const schema = dsl({ phone: 'phone-cn!' });
293
- * const schema2 = dsl({ contact: 'types:email|phone-cn' });
294
- * ```
295
- */
296
- static registerType(name: string, schema: JSONSchema | (() => JSONSchema)): void;
297
-
298
- /**
299
- * 检查类型是否已注册
300
- * @param type - 类型名称
301
- * @returns 是否已注册
302
- * @static
303
- * @since v1.1.0
304
- *
305
- * @example
306
- * ```typescript
307
- * DslBuilder.hasType('string'); // true (内置)
308
- * DslBuilder.hasType('phone-cn'); // false (未注册)
309
- * DslBuilder.registerType('phone-cn', { ... });
310
- * DslBuilder.hasType('phone-cn'); // true (已注册)
311
- * ```
312
- */
313
- static hasType(type: string): boolean;
314
-
315
- /**
316
- * 获取所有已注册的自定义类型
317
- * @returns 自定义类型名称数组
318
- * @static
319
- * @since v1.1.0
320
- *
321
- * @example
322
- * ```typescript
323
- * const types = DslBuilder.getCustomTypes();
324
- * console.log(types); // ['phone-cn', 'order-id', ...]
325
- * ```
326
- */
327
- static getCustomTypes(): string[];
328
-
329
- /**
330
- * 清除所有自定义类型(主要用于测试)
331
- * @static
332
- * @since v1.1.0
333
- *
334
- * @example
335
- * ```typescript
336
- * DslBuilder.clearCustomTypes();
337
- * ```
338
- */
339
- static clearCustomTypes(): void;
340
-
341
- /**
342
- * 构造函数
343
- * @param dslString - DSL字符串(如 'email!', 'string:3-32!', 'string?', 'types:string|number')
344
- *
345
- * @example 基础类型
346
- * ```typescript
347
- * const builder = new DslBuilder('email!'); // 必填邮箱
348
- * const builder2 = new DslBuilder('string:3-32'); // 可选字符串(默认)
349
- * const builder3 = new DslBuilder('string?'); // 显式可选字符串
350
- * const builder4 = new DslBuilder('email?'); // 显式可选邮箱
351
- * const builder5 = new DslBuilder('types:string|number'); // 联合类型
352
- * ```
353
- *
354
- * @example 必填与可选标记
355
- * ```typescript
356
- * new DslBuilder('string!') // 必填字符串
357
- * new DslBuilder('string') // 可选字符串(默认)
358
- * new DslBuilder('string?') // 显式可选字符串
359
- * new DslBuilder('email?') // 可选邮箱
360
- * new DslBuilder('string:3-32?') // 可选字符串,长度3-32
361
- * ```
362
- *
363
- * @example 数字类型比较运算符 (v1.1.2+)
364
- * ```typescript
365
- * // 范围约束(包括边界值)
366
- * new DslBuilder('number:0-100') // 0 <= x <= 100
367
- * new DslBuilder('number:18-') // x >= 18
368
- * new DslBuilder('number:-100') // x <= 100
369
- * new DslBuilder('number:100') // x <= 100
370
- *
371
- * // 比较运算符(v1.1.2新增)
372
- * new DslBuilder('number:>0') // x > 0 (不包括0)
373
- * new DslBuilder('number:>=18') // x >= 18
374
- * new DslBuilder('number:<100') // x < 100 (不包括100)
375
- * new DslBuilder('number:<=100') // x <= 100
376
- * new DslBuilder('number:=100') // x = 100 (精确等于)
377
- *
378
- * // 支持小数和负数
379
- * new DslBuilder('number:>0.5') // x > 0.5
380
- * new DslBuilder('number:>-10') // x > -10
381
- * new DslBuilder('number:<=99.99') // x <= 99.99
382
- *
383
- * // 配合必填标记
384
- * new DslBuilder('number:>=18!') // 必填且 >= 18
385
- * new DslBuilder('number:>0!') // 必填且 > 0
386
- * new DslBuilder('number:>0?') // 可选且 > 0(当有值时)
387
- * ```
388
- */
389
- constructor(dslString: string);
390
-
391
- /**
392
- * 添加正则验证
393
- * @param regex - 正则表达式或字符串
394
- * @param message - 自定义错误消息
395
- * @returns 当前实例(支持链式调用)
396
- *
397
- * @example
398
- * ```typescript
399
- * builder
400
- * .pattern(/^[a-zA-Z]+$/)
401
- * .pattern('^\\d{6}$', '必须是6位数字');
402
- * ```
403
- */
404
- pattern(regex: RegExp | string, message?: string): this;
405
-
406
- /**
407
- * 设置字段标签
408
- * @param text - 字段的显示名称
409
- * @returns 当前实例(支持链式调用)
410
- *
411
- * @example
412
- * ```typescript
413
- * builder.label('用户邮箱');
414
- * ```
415
- */
416
- label(text: string): this;
417
-
418
- /**
419
- * 自定义错误消息
420
- * @param messages - 错误消息对象
421
- * @returns 当前实例(支持链式调用)
422
- *
423
- * @example
424
- * ```typescript
425
- * builder.messages({
426
- * min: '至少{{#limit}}个字符',
427
- * required: '这是必填项'
428
- * });
429
- * ```
430
- */
431
- messages(messages: ErrorMessages): this;
432
-
433
- /**
434
- * 设置描述
435
- * @param text - 字段描述文本
436
- * @returns 当前实例(支持链式调用)
437
- *
438
- * @example
439
- * ```typescript
440
- * builder.description('用户的注册邮箱');
441
- * ```
442
- */
443
- description(text: string): this;
444
-
445
- /**
446
- * 添加自定义验证器
447
- * @param validator - 验证函数
448
- * @returns 当前实例(支持链式调用)
449
- *
450
- * @example
451
- * ```typescript
452
- * builder.custom((value) => {
453
- * return value.includes('@');
454
- * });
455
- *
456
- * // 异步验证
457
- * builder.custom(async (value) => {
458
- * const exists = await checkEmailExists(value);
459
- * return !exists;
460
- * });
461
- *
462
- * // 返回错误对象
463
- * builder.custom((value) => {
464
- * if (!value.includes('@')) {
465
- * return { error: 'EMAIL_INVALID', message: '邮箱格式不正确' };
466
- * }
467
- * return true;
468
- * });
469
- * ```
470
- */
471
- custom(validator: (value: any) => boolean | Promise<boolean> | { error: string; message: string }): this;
472
-
473
- /**
474
- * 条件验证
475
- * @param refField - 参考字段
476
- * @param options - 条件选项
477
- * @returns 当前实例(支持链式调用)
478
- *
479
- * @example
480
- * ```typescript
481
- * // 当userType=admin时,email必填
482
- * dsl({
483
- * userType: 'string',
484
- * email: 'email'.when('userType', {
485
- * is: 'admin',
486
- * then: dsl('email!'),
487
- * otherwise: dsl('email')
488
- * })
489
- * });
490
- * ```
491
- */
492
- // ⚠️ DEPRECATED: .when() method removed - use dsl.if() instead
493
- // when(refField: string, options: { is: any; then: DslBuilder | JSONSchema; otherwise?: DslBuilder | JSONSchema; }): this;
494
-
495
- /**
496
- * 设置默认值
497
- * @param value - 默认值
498
- * @returns 当前实例(支持链式调用)
499
- *
500
- * @example
501
- * ```typescript
502
- * builder.default('user@example.com');
503
- * ```
504
- */
505
- default(value: any): this;
506
-
507
- /**
508
- * 转为JSON Schema
509
- * @returns JSON Schema对象
510
- *
511
- * @example
512
- * ```typescript
513
- * const schema = builder.toSchema();
514
- * console.log(schema);
515
- * // { type: 'string', format: 'email', ... }
516
- * ```
517
- */
518
- toSchema(): JSONSchema;
519
-
520
- /**
521
- * 验证数据
522
- * @param data - 要验证的数据
523
- * @param context - 验证上下文(可选)
524
- * @returns 验证结果的Promise
525
- *
526
- * @example
527
- * ```typescript
528
- * const result = await builder.validate({ email: 'test@example.com' });
529
- * if (result.valid) {
530
- * console.log('验证通过');
531
- * }
532
- * ```
533
- */
534
- validate(data: any, context?: any): Promise<ValidationResult>;
535
-
536
- /**
537
- * 用户名验证(自动设置合理约束)
538
- * @param preset - 预设配置
539
- * @returns 当前实例(支持链式调用)
540
- *
541
- * @example
542
- * ```typescript
543
- * // 预设方式
544
- * builder.username('short'); // 3-16字符
545
- * builder.username('medium'); // 3-32字符
546
- * builder.username('long'); // 3-64字符
547
- *
548
- * // 范围字符串
549
- * builder.username('5-20');
550
- *
551
- * // 详细配置
552
- * builder.username({
553
- * minLength: 5,
554
- * maxLength: 20,
555
- * allowUnderscore: true,
556
- * allowNumber: true
557
- * });
558
- * ```
559
- */
560
- username(preset?: 'short' | 'medium' | 'long' | string | { minLength?: number; maxLength?: number; allowUnderscore?: boolean; allowNumber?: boolean }): this;
561
-
562
- /**
563
- * 密码强度验证
564
- * @param strength - 密码强度等级
565
- * @returns 当前实例(支持链式调用)
566
- *
567
- * @example
568
- * ```typescript
569
- * builder.password('weak'); // 6+ 字符
570
- * builder.password('medium'); // 8+ 字符,包含大小写
571
- * builder.password('strong'); // 10+ 字符,包含大小写+数字
572
- * builder.password('veryStrong'); // 12+ 字符,包含大小写+数字+特殊字符
573
- * ```
574
- */
575
- password(strength?: 'weak' | 'medium' | 'strong' | 'veryStrong'): this;
576
-
577
- /**
578
- * 手机号验证
579
- * @param country - 国家代码
580
- * @returns 当前实例(支持链式调用)
581
- *
582
- * @example
583
- * ```typescript
584
- * builder.phone('cn'); // 中国大陆 (11位)
585
- * builder.phone('us'); // 美国
586
- * builder.phone('hk'); // 香港
587
- * builder.phone('tw'); // 台湾
588
- * builder.phone('international'); // 国际号码
589
- * ```
590
- */
591
- phone(country?: 'cn' | 'us' | 'uk' | 'hk' | 'tw' | 'international'): this;
592
-
593
- /**
594
- * 设置格式
595
- * @param format - 格式名称 (email, url, uuid, date, date-time, time, ipv4, ipv6等)
596
- * @returns 当前实例(支持链式调用)
597
- *
598
- * @example
599
- * ```typescript
600
- * builder.format('email');
601
- * builder.format('uuid');
602
- * builder.format('date-time');
603
- * ```
604
- */
605
- format(format: string): this;
606
-
607
- /**
608
- * 手机号别名(phoneNumber是phone的别名)
609
- * @param country - 国家代码
610
- * @returns 当前实例(支持链式调用)
611
- *
612
- * @example
613
- * ```typescript
614
- * builder.phoneNumber('cn'); // 等同于 phone('cn')
615
- * ```
616
- */
617
- phoneNumber(country?: 'cn' | 'us' | 'uk' | 'hk' | 'tw' | 'international'): this;
618
-
619
- /**
620
- * 身份证验证
621
- * @param country - 国家代码(目前仅支持 'cn')
622
- * @returns 当前实例(支持链式调用)
623
- *
624
- * @example
625
- * ```typescript
626
- * builder.idCard('cn'); // 中国身份证18位
627
- * ```
628
- */
629
- idCard(country?: 'cn'): this;
630
-
631
- /**
632
- * URL Slug 验证(只能包含小写字母、数字和连字符)
633
- * @returns 当前实例(支持链式调用)
634
- *
635
- * @example
636
- * ```typescript
637
- * builder.slug(); // my-blog-post, hello-world-123
638
- * ```
639
- */
640
- slug(): this;
641
-
642
- /**
643
- * 信用卡验证
644
- * @param type - 卡类型
645
- * @returns 当前实例(支持链式调用)
646
- *
647
- * @example
648
- * ```typescript
649
- * builder.creditCard('visa');
650
- * builder.creditCard('mastercard');
651
- * builder.creditCard('amex');
652
- * ```
653
- */
654
- creditCard(type?: 'visa' | 'mastercard' | 'amex' | 'discover' | 'jcb' | 'unionpay'): this;
655
-
656
- /**
657
- * 车牌号验证
658
- * @param country - 国家代码
659
- * @returns 当前实例(支持链式调用)
660
- *
661
- * @example
662
- * ```typescript
663
- * builder.licensePlate('cn'); // 中国车牌号
664
- * ```
665
- */
666
- licensePlate(country?: 'cn' | 'us' | 'uk'): this;
667
-
668
- /**
669
- * 邮政编码验证
670
- * @param country - 国家代码
671
- * @returns 当前实例(支持链式调用)
672
- *
673
- * @example
674
- * ```typescript
675
- * builder.postalCode('cn'); // 中国邮政编码6位
676
- * builder.postalCode('us'); // 美国邮政编码
677
- * ```
678
- */
679
- postalCode(country?: 'cn' | 'us' | 'uk'): this;
680
-
681
- /**
682
- * 护照号码验证
683
- * @param country - 国家代码
684
- * @returns 当前实例(支持链式调用)
685
- *
686
- * @example
687
- * ```typescript
688
- * builder.passport('cn'); // 中国护照号
689
- * ```
690
- */
691
- passport(country?: 'cn' | 'us' | 'uk'): this;
692
-
693
- /**
694
- * String 最小长度(使用AJV原生minLength)
695
- * @param n - 最小长度
696
- * @returns 当前实例(支持链式调用)
697
- *
698
- * @example
699
- * ```typescript
700
- * dsl('string!').min(3); // 最少3个字符
701
- * ```
702
- */
703
- min(n: number): this;
704
-
705
- /**
706
- * String 最大长度(使用AJV原生maxLength)
707
- * @param n - 最大长度
708
- * @returns 当前实例(支持链式调用)
709
- *
710
- * @example
711
- * ```typescript
712
- * dsl('string!').max(32); // 最多32个字符
713
- * ```
714
- */
715
- max(n: number): this;
716
-
717
- /**
718
- * String 精确长度
719
- * @param n - 精确长度
720
- * @returns 当前实例(支持链式调用)
721
- *
722
- * @example
723
- * ```typescript
724
- * dsl('string!').length(11); // 必须是11个字符
725
- * ```
726
- */
727
- length(n: number): this;
728
-
729
- /**
730
- * String 只能包含字母和数字
731
- * @returns 当前实例(支持链式调用)
732
- *
733
- * @example
734
- * ```typescript
735
- * dsl('string!').alphanum(); // 只能是字母和数字
736
- * ```
737
- */
738
- alphanum(): this;
739
-
740
- /**
741
- * String 不能包含前后空格
742
- * @returns 当前实例(支持链式调用)
743
- *
744
- * @example
745
- * ```typescript
746
- * dsl('string!').trim(); // 不能有前后空格
747
- * ```
748
- */
749
- trim(): this;
750
-
751
- /**
752
- * String 必须是小写
753
- * @returns 当前实例(支持链式调用)
754
- *
755
- * @example
756
- * ```typescript
757
- * dsl('string!').lowercase(); // 必须全小写
758
- * ```
759
- */
760
- lowercase(): this;
761
-
762
- /**
763
- * String 必须是大写
764
- * @returns 当前实例(支持链式调用)
765
- *
766
- * @example
767
- * ```typescript
768
- * dsl('string!').uppercase(); // 必须全大写
769
- * ```
770
- */
771
- uppercase(): this;
772
-
773
- /**
774
- * Number 小数位数限制
775
- * @param n - 最大小数位数
776
- * @returns 当前实例(支持链式调用)
777
- *
778
- * @example
779
- * ```typescript
780
- * dsl('number!').precision(2); // 最多2位小数
781
- * ```
782
- */
783
- precision(n: number): this;
784
-
785
- /**
786
- * Number 倍数验证(使用AJV原生multipleOf)
787
- * @param n - 必须是此数的倍数
788
- * @returns 当前实例(支持链式调用)
789
- *
790
- * @example
791
- * ```typescript
792
- * dsl('number!').multiple(5); // 必须是5的倍数
793
- * ```
794
- */
795
- multiple(n: number): this;
796
-
797
- /**
798
- * Number 端口号验证(1-65535)
799
- * @returns 当前实例(支持链式调用)
800
- *
801
- * @example
802
- * ```typescript
803
- * dsl('integer!').port(); // 必须是有效端口号
804
- * ```
805
- */
806
- port(): this;
807
-
808
- /**
809
- * Object 要求所有属性都必须存在
810
- * @returns 当前实例(支持链式调用)
811
- *
812
- * @example
813
- * ```typescript
814
- * dsl({ name: 'string', age: 'number' }).requireAll();
815
- * ```
816
- */
817
- requireAll(): this;
818
-
819
- /**
820
- * Object 严格模式,不允许额外属性
821
- * @returns 当前实例(支持链式调用)
822
- *
823
- * @example
824
- * ```typescript
825
- * dsl({ name: 'string!' }).strict();
826
- * ```
827
- */
828
- strict(): this;
829
-
830
- /**
831
- * Array 不允许稀疏数组
832
- * @returns 当前实例(支持链式调用)
833
- *
834
- * @example
835
- * ```typescript
836
- * dsl('array<string>').noSparse();
837
- * ```
838
- */
839
- noSparse(): this;
840
-
841
- /**
842
- * Array 必须包含指定元素
843
- * @param items - 必须包含的元素数组
844
- * @returns 当前实例(支持链式调用)
845
- *
846
- * @example
847
- * ```typescript
848
- * dsl('array<string>').includesRequired(['admin', 'user']);
849
- * ```
850
- */
851
- includesRequired(items: any[]): this;
852
-
853
- /**
854
- * Date 自定义日期格式验证
855
- * @param fmt - 日期格式(YYYY-MM-DD, YYYY/MM/DD, DD-MM-YYYY, DD/MM/YYYY, ISO8601)
856
- * @returns 当前实例(支持链式调用)
857
- *
858
- * @example
859
- * ```typescript
860
- * dsl('string!').dateFormat('YYYY-MM-DD');
861
- * ```
862
- */
863
- dateFormat(fmt: 'YYYY-MM-DD' | 'YYYY/MM/DD' | 'DD-MM-YYYY' | 'DD/MM/YYYY' | 'ISO8601' | string): this;
864
-
865
- /**
866
- * Date 必须晚于指定日期
867
- * @param date - 比较日期
868
- * @returns 当前实例(支持链式调用)
869
- *
870
- * @example
871
- * ```typescript
872
- * dsl('date!').after('2024-01-01');
873
- * ```
874
- */
875
- after(date: string): this;
876
-
877
- /**
878
- * Date 必须早于指定日期
879
- * @param date - 比较日期
880
- * @returns 当前实例(支持链式调用)
881
- *
882
- * @example
883
- * ```typescript
884
- * dsl('date!').before('2025-12-31');
885
- * ```
886
- */
887
- before(date: string): this;
888
-
889
- /**
890
- * Pattern 域名验证
891
- * @returns 当前实例(支持链式调用)
892
- *
893
- * @example
894
- * ```typescript
895
- * dsl('string!').domain(); // example.com, sub.example.com
896
- * ```
897
- */
898
- domain(): this;
899
-
900
- /**
901
- * Pattern IP地址验证(IPv4或IPv6)
902
- * @returns 当前实例(支持链式调用)
903
- *
904
- * @example
905
- * ```typescript
906
- * dsl('string!').ip(); // 192.168.1.1 或 2001:0db8:85a3::8a2e:0370:7334
907
- * ```
908
- */
909
- ip(): this;
910
-
911
- /**
912
- * Pattern Base64编码验证
913
- * @returns 当前实例(支持链式调用)
914
- *
915
- * @example
916
- * ```typescript
917
- * dsl('string!').base64();
918
- * ```
919
- */
920
- base64(): this;
921
-
922
- /**
923
- * Pattern JWT令牌验证
924
- * @returns 当前实例(支持链式调用)
925
- *
926
- * @example
927
- * ```typescript
928
- * dsl('string!').jwt();
929
- * ```
930
- */
931
- jwt(): this;
932
-
933
- /**
934
- * Pattern JSON字符串验证
935
- * @returns 当前实例(支持链式调用)
936
- *
937
- * @example
938
- * ```typescript
939
- * dsl('string!').json();
940
- * ```
941
- */
942
- json(): this;
943
-
944
- /**
945
- * 日期大于验证
946
- * @param date - 对比日期
947
- * @returns 当前实例(支持链式调用)
948
- *
949
- * @example
950
- * ```typescript
951
- * dsl('string!').dateGreater('2025-01-01');
952
- * ```
953
- */
954
- dateGreater(date: string): this;
955
-
956
- /**
957
- * 日期小于验证
958
- * @param date - 对比日期
959
- * @returns 当前实例(支持链式调用)
960
- *
961
- * @example
962
- * ```typescript
963
- * dsl('string!').dateLess('2025-12-31');
964
- * ```
965
- */
966
- dateLess(date: string): this;
967
- }
968
-
969
- // ========== String 扩展 ==========
970
-
971
- /**
972
- * String 扩展全局接口
973
- *
974
- * ⚠️ TypeScript 用户注意事项
975
- *
976
- * 由于 TypeScript 对全局扩展的类型推导限制,在 .ts 文件中使用链式调用时,
977
- * 推荐使用 dsl() 函数包裹字符串以获得完整的类型提示:
978
- *
979
- * @example
980
- * ```typescript
981
- * // ❌ 不推荐:可能缺少类型提示
982
- * const schema = dsl({
983
- * email: 'email!'.label('邮箱') // TypeScript 可能无法推导
984
- * });
985
- *
986
- * // ✅ 推荐:使用 dsl() 包裹获得完整类型推导
987
- * const schema = dsl({
988
- * email: dsl('email!').label('邮箱').pattern(/custom/)
989
- * });
990
- *
991
- * // ✅ 也可以:先定义再使用
992
- * const emailField = dsl('email!').label('邮箱');
993
- * const schema = dsl({ email: emailField });
994
- *
995
- * // 📝 JavaScript 用户不受影响,可以直接使用
996
- * const schema = dsl({
997
- * email: 'email!'.label('邮箱') // JavaScript 中完全正常
998
- * });
999
- * ```
1000
- */
1001
-
1002
- // ========== String 扩展说明 ==========
1003
-
1004
- /**
1005
- * ⚠️ String 原型扩展的 TypeScript 限制
1006
- *
1007
- * 本库在运行时扩展了 String.prototype,允许在 JavaScript 中直接链式调用:
1008
- * ```javascript
1009
- * const schema = dsl({ email: 'email!'.label('邮箱') }); // ✅ JavaScript 中完全正常
1010
- * ```
1011
- *
1012
- * 但在 TypeScript 中,为了**避免污染全局 String 类型**(会导致原生方法如 trim() 的类型推断错误),
1013
- * 我们**不提供**全局 String 接口扩展。
1014
- *
1015
- * TypeScript 用户请使用以下方式:
1016
- *
1017
- * @example
1018
- * ```typescript
1019
- * import { dsl } from 'schema-dsl';
1020
- *
1021
- * // ✅ 推荐:使用 dsl() 函数获得完整类型提示
1022
- * const schema = dsl({
1023
- * email: dsl('email!').label('邮箱').pattern(/custom/)
1024
- * });
1025
- *
1026
- * // ✅ 或者先定义再使用
1027
- * const emailField = dsl('email!').label('邮箱');
1028
- * const schema = dsl({ email: emailField });
1029
- *
1030
- * // ❌ 避免:在 TypeScript 中直接对字符串字面量链式调用
1031
- * // 这在运行时可以工作,但 TypeScript 无法提供类型提示
1032
- * const schema = dsl({
1033
- * email: 'email!'.label('邮箱') // TypeScript: 类型错误
1034
- * });
1035
- * ```
1036
- *
1037
- * 📝 说明:
1038
- * - JavaScript 用户不受影响,可以直接使用字符串链式调用
1039
- * - TypeScript 用户应使用 dsl() 函数包裹字符串以获得类型提示
1040
- * - 移除全局 String 扩展是为了防止污染原生 String 方法的类型定义
1041
- */
1042
-
1043
- // ========== dsl() 函数 ==========
1044
-
1045
- /**
1046
- * DSL 定义对象
1047
- *
1048
- * @description 支持多种类型的Schema定义
1049
- */
1050
- export type DslDefinition = string | DslBuilder | {
1051
- [key: string]: DslDefinition;
1052
- };
1053
-
1054
- /**
1055
- * SchemaIO 配置选项
1056
- *
1057
- * @description 用于配置验证器和错误消息的选项
1058
- *
1059
- * @example
1060
- * ```typescript
1061
- * const options: SchemaIOOptions = {
1062
- * allErrors: true,
1063
- * messages: {
1064
- * min: '至少需要 {{#limit}} 个字符',
1065
- * required: '这是必填项'
1066
- * },
1067
- * locale: 'zh-CN'
1068
- * };
1069
- * ```
1070
- */
1071
- export interface SchemaIOOptions {
1072
- /** 是否返回所有错误(默认false,只返回第一个) */
1073
- allErrors?: boolean;
1074
- /** 是否启用详细模式 */
1075
- verbose?: boolean;
1076
- /** 自定义错误消息 */
1077
- messages?: ErrorMessages;
1078
- /** 语言代码 */
1079
- locale?: string;
1080
- /** 是否启用缓存 */
1081
- cache?: boolean;
1082
- /** 缓存大小限制 */
1083
- cacheSize?: number;
1084
- /** 扩展选项 */
1085
- [key: string]: any;
1086
- }
1087
-
1088
- /**
1089
- * dsl() 函数(主入口)
1090
- *
1091
- * @description schema-dsl 的核心函数,用于创建 Schema 定义
1092
- *
1093
- * @example
1094
- * ```typescript
1095
- * // 1. 字符串:返回 DslBuilder(用于进一步配置)
1096
- * const builder = dsl('email!');
1097
- * builder.label('邮箱地址').messages({ required: '必填' });
1098
- *
1099
- * // 2. 对象:返回 JSON Schema(用于验证)
1100
- * const schema = dsl({
1101
- * username: 'string:3-32!',
1102
- * email: 'email!',
1103
- * age: 'number:18-100'
1104
- * });
1105
- *
1106
- * // 3. 带选项的对象
1107
- * const schema = dsl({
1108
- * username: 'string:3-32!'
1109
- * }, {
1110
- * allErrors: true,
1111
- * messages: {
1112
- * min: '至少需要 {{#limit}} 个字符'
1113
- * }
1114
- * });
1115
- *
1116
- * // 4. 验证数据(使用顶层 validate 函数)
1117
- * const result = validate(schema, { username: 'test' });
1118
- * ```
1119
- */
1120
- export function dsl(definition: string): DslBuilder;
1121
- export function dsl(definition: Record<string, DslDefinition>, options?: SchemaIOOptions): JSONSchema;
1122
- export function dsl(definition: string | Record<string, DslDefinition>, options?: SchemaIOOptions): DslBuilder | JSONSchema;
1123
-
1124
- /**
1125
- * 全局配置
1126
- *
1127
- * @description dsl命名空间的全局配置和工具方法
1128
- *
1129
- * @remark 注意:dsl() 返回的是 JSONSchema 对象,不是类实例
1130
- * 验证时使用顶层函数 validate(schema, data) 而非 schema.validate(data)
1131
- */
1132
- export namespace dsl {
1133
- /**
1134
- * 条件规则 (if / _if)
1135
- *
1136
- * @description 支持两种方式的条件判断
1137
- *
1138
- * 注意:在 TypeScript 中因为 if 是保留字,请使用 dsl['if'] 或 dsl._if
1139
- *
1140
- * @example TypeScript 用法
1141
- * ```typescript
1142
- * // 使用字符串索引访问
1143
- * const schema = dsl({
1144
- * isVip: 'boolean',
1145
- * discount: dsl['if']('isVip', 'number:10-50!', 'number:0-10')
1146
- * });
1147
- *
1148
- * // 或使用 _if 别名
1149
- * const schema2 = dsl({
1150
- * email: dsl._if(d => d.age >= 18).then('email!').else('email')
1151
- * });
1152
- * ```
1153
- *
1154
- * @example JavaScript 用法
1155
- * ```javascript
1156
- * // JavaScript 中可以直接使用 dsl.if
1157
- * const schema = dsl({
1158
- * discount: dsl.if('isVip', 'number:10-50!', 'number:0-10')
1159
- * });
1160
- * ```
1161
- */
1162
- export { _if as if };
1163
- export function _if(condition: (data: any) => boolean): ConditionalBuilder;
1164
- export function _if(conditionField: string, thenSchema: string | DslBuilder | JSONSchema, elseSchema?: string | DslBuilder | JSONSchema): any;
1165
-
1166
- /**
1167
- * 全局配置
1168
- *
1169
- * @description 配置全局的验证规则和语言包
1170
- *
1171
- * @example
1172
- * ```typescript
1173
- * // 方式 1: 使用 i18n 配置(推荐,v1.0.4+)
1174
- * dsl.config({
1175
- * i18n: {
1176
- * locales: {
1177
- * 'zh-CN': { required: '必填' },
1178
- * 'en-US': { required: 'Required' }
1179
- * }
1180
- * }
1181
- * });
1182
- *
1183
- * // 方式 2: 使用 locales 配置(向后兼容)
1184
- * dsl.config({
1185
- * locales: {
1186
- * 'zh-CN': { required: '必填' }
1187
- * }
1188
- * });
1189
- *
1190
- * // 自定义手机号规则
1191
- * dsl.config({
1192
- * patterns: {
1193
- * phone: {
1194
- * cn: {
1195
- * pattern: /^1[3-9]\d{9}$/,
1196
- * min: 11,
1197
- * max: 11,
1198
- * key: 'phone.cn'
1199
- * }
1200
- * }
1201
- * }
1202
- * });
1203
- * ```
1204
- */
1205
- export function config(options: {
1206
- /** i18n 配置(推荐,v1.0.4+) */
1207
- i18n?: I18nConfig;
1208
- /** 缓存配置 */
1209
- cache?: CacheConfig;
1210
- /** 自定义验证规则 */
1211
- patterns?: {
1212
- /** 手机号规则 */
1213
- phone?: Record<string, { pattern: RegExp; min?: number; max?: number; key?: string }>;
1214
- /** 身份证号规则 */
1215
- idCard?: Record<string, { pattern: RegExp; min?: number; max?: number; key?: string }>;
1216
- /** 信用卡号规则 */
1217
- creditCard?: Record<string, { pattern: RegExp; msg?: string }>;
1218
- };
1219
- /** 手机号规则(兼容旧版) */
1220
- phone?: Record<string, { pattern: RegExp; min?: number; max?: number; key?: string }>;
1221
- /** 语言包配置(兼容旧版,推荐使用 i18n.locales) */
1222
- locales?: Record<string, ErrorMessages> | string;
1223
- }): void;
1224
-
1225
- /**
1226
- * 匹配规则
1227
- *
1228
- * @description 根据值匹配不同的Schema定义
1229
- *
1230
- * @example
1231
- * ```typescript
1232
- * const schema = dsl({
1233
- * userType: 'string',
1234
- * profile: dsl.match('userType', {
1235
- * 'admin': { role: 'string!', permissions: 'array' },
1236
- * 'user': { bio: 'string' }
1237
- * })
1238
- * });
1239
- * ```
1240
- */
1241
- export function match(value: any, cases: Record<string, any>): any;
1242
-
1243
- /**
1244
- * 条件规则 (if)
1245
- *
1246
- * @description 根据条件字段的值选择不同的Schema
1247
- *
1248
- * JavaScript 中使用: `dsl.if(condition, thenSchema, elseSchema)`
1249
- * TypeScript 中使用: `dsl['if'](condition, thenSchema, elseSchema)` 或 `dsl._if(...)`
1250
- *
1251
- * @param condition - 条件字段名
1252
- * @param thenSchema - 条件为 true 时的 Schema
1253
- * @param elseSchema - 条件为 false 时的 Schema(可选)
1254
- *
1255
- * @example
1256
- * ```typescript
1257
- * // TypeScript 中因为 if 是保留字,需要用字符串索引或 _if
1258
- * const schema = dsl({
1259
- * isVip: 'boolean',
1260
- * discount: dsl['if']('isVip', 'number:10-50!', 'number:0-10')
1261
- * });
1262
- *
1263
- * // 或者使用 _if 别名
1264
- * const schema2 = dsl({
1265
- * age: 'number',
1266
- * license: dsl._if('age', 'boolean!', 'boolean')
1267
- * });
1268
- * ```
1269
- *
1270
- * @example
1271
- * ```javascript
1272
- * // JavaScript 中可以直接使用 dsl.if
1273
- * const schema = dsl({
1274
- * isVip: 'boolean',
1275
- * discount: dsl.if('isVip', 'number:10-50!', 'number:0-10')
1276
- * });
1277
- * ```
1278
- */
1279
-
1280
- /**
1281
- * 便捷验证方法(dsl命名空间别名)
1282
- *
1283
- * @description 与顶层 validate 函数相同
1284
- */
1285
- export const validate: typeof import('./index').validate;
1286
-
1287
- /**
1288
- * 异步验证方法(dsl命名空间别名)
1289
- *
1290
- * @description 与顶层 validateAsync 函数相同
1291
- */
1292
- export const validateAsync: typeof import('./index').validateAsync;
1293
-
1294
- /**
1295
- * 多语言错误快捷方法 (v1.1.1+)
1296
- *
1297
- * @description 统一的多语言错误抛出机制
1298
- *
1299
- * @example
1300
- * ```typescript
1301
- * import { dsl } from 'schema-dsl';
1302
- *
1303
- * // 创建错误
1304
- * const error = dsl.error.create('account.notFound');
1305
- *
1306
- * // 直接抛出
1307
- * dsl.error.throw('account.notFound');
1308
- *
1309
- * // 断言风格
1310
- * dsl.error.assert(account, 'account.notFound');
1311
- * dsl.error.assert(
1312
- * account.balance >= 100,
1313
- * 'account.insufficientBalance',
1314
- * { balance: account.balance, required: 100 }
1315
- * );
1316
- * ```
1317
- */
1318
- export const error: {
1319
- /**
1320
- * 创建多语言错误(不抛出)
1321
- *
1322
- * @param code - 错误代码(多语言 key)
1323
- * @param paramsOrLocale - 错误参数对象 或 语言代码(智能识别,v1.1.8+)
1324
- * @param statusCode - HTTP 状态码
1325
- * @param locale - 语言环境(仅当第2个参数是对象时有效)
1326
- * @returns 错误实例
1327
- *
1328
- * @example 简化语法(v1.1.8+)
1329
- * ```typescript
1330
- * // 直接传语言参数
1331
- * const error = dsl.error.create('account.notFound', 'zh-CN');
1332
- * const error = dsl.error.create('account.notFound', 'en-US', 404);
1333
- * ```
1334
- *
1335
- * @example 标准语法(完全兼容)
1336
- * ```typescript
1337
- * // 带参数对象
1338
- * const error = dsl.error.create('account.notFound', { id: '123' }, 404, 'zh-CN');
1339
- *
1340
- * // 空参数对象
1341
- * const error = dsl.error.create('account.notFound', {}, 404, 'zh-CN');
1342
- * ```
1343
- *
1344
- * @example 全局语言
1345
- * ```typescript
1346
- * Locale.setLocale('zh-CN');
1347
- * const error = dsl.error.create('account.notFound');
1348
- * ```
1349
- *
1350
- * @example 运行时指定语言
1351
- * ```typescript
1352
- * const error1 = dsl.error.create('account.notFound', {}, 404, 'zh-CN');
1353
- * const error2 = dsl.error.create('account.notFound', {}, 404, 'en-US');
1354
- * ```
1355
- */
1356
- create(
1357
- code: string,
1358
- paramsOrLocale?: Record<string, any> | string,
1359
- statusCode?: number,
1360
- locale?: string
1361
- ): I18nError;
1362
-
1363
- /**
1364
- * 抛出多语言错误
1365
- *
1366
- * @param code - 错误代码(多语言 key)
1367
- * @param paramsOrLocale - 错误参数对象 或 语言代码(智能识别,v1.1.8+)
1368
- * @param statusCode - HTTP 状态码
1369
- * @param locale - 语言环境(仅当第2个参数是对象时有效)
1370
- * @throws I18nError
1371
- *
1372
- * @example 简化语法(v1.1.8+)
1373
- * ```typescript
1374
- * // 直接传语言参数
1375
- * dsl.error.throw('account.notFound', 'zh-CN');
1376
- * dsl.error.throw('account.notFound', 'en-US', 404);
1377
- * ```
1378
- *
1379
- * @example 标准语法(完全兼容)
1380
- * ```typescript
1381
- * // 带参数对象
1382
- * dsl.error.throw('account.notFound', { id: '123' }, 404, 'zh-CN');
1383
- *
1384
- * // 空参数对象
1385
- * dsl.error.throw('account.notFound', {}, 404, 'zh-CN');
1386
- * ```
1387
- *
1388
- * @example 全局语言
1389
- * ```typescript
1390
- * Locale.setLocale('zh-CN');
1391
- * dsl.error.throw('account.notFound');
1392
- * ```
1393
- *
1394
- * @example 运行时指定语言
1395
- * ```typescript
1396
- * dsl.error.throw('account.notFound', {}, 404, 'en-US');
1397
- * ```
1398
- */
1399
- throw(
1400
- code: string,
1401
- paramsOrLocale?: Record<string, any> | string,
1402
- statusCode?: number,
1403
- locale?: string
1404
- ): never;
1405
-
1406
- /**
1407
- * 断言方法 - 条件不满足时抛错
1408
- *
1409
- * @param condition - 条件表达式
1410
- * @param code - 错误代码(多语言 key)
1411
- * @param paramsOrLocale - 错误参数对象 或 语言代码(智能识别,v1.1.8+)
1412
- * @param statusCode - HTTP 状态码
1413
- * @param locale - 语言环境(仅当第3个参数是对象时有效)
1414
- * @throws I18nError 条件为 false 时抛出
1415
- *
1416
- * @example 简化语法(v1.1.8+)
1417
- * ```typescript
1418
- * // 直接传语言参数
1419
- * dsl.error.assert(account, 'account.notFound', 'zh-CN');
1420
- * dsl.error.assert(account, 'account.notFound', 'en-US', 404);
1421
- * ```
1422
- *
1423
- * @example 标准语法(完全兼容)
1424
- * ```typescript
1425
- * // 带参数对象
1426
- * dsl.error.assert(account, 'account.notFound', { id: '123' }, 404, 'zh-CN');
1427
- *
1428
- * // 空参数对象
1429
- * dsl.error.assert(account, 'account.notFound', {}, 404, 'zh-CN');
1430
- * ```
1431
- *
1432
- * @example 全局语言
1433
- * ```typescript
1434
- * Locale.setLocale('zh-CN');
1435
- * dsl.error.assert(account, 'account.notFound');
1436
- * ```
1437
- *
1438
- * @example 运行时指定语言
1439
- * ```typescript
1440
- * dsl.error.assert(account, 'account.notFound', {}, 404, 'en-US');
1441
- * ```
1442
- */
1443
- assert(
1444
- condition: any,
1445
- code: string,
1446
- paramsOrLocale?: Record<string, any> | string,
1447
- statusCode?: number,
1448
- locale?: string
1449
- ): asserts condition;
1450
- };
1451
- }
1452
-
1453
- // ========== Validator 类 ==========
1454
-
1455
- /**
1456
- * Validator 选项
1457
- *
1458
- * @description 验证器的配置选项
1459
- */
1460
- export interface ValidatorOptions {
1461
- /** 是否返回所有错误 */
1462
- allErrors?: boolean;
1463
- /** 是否启用详细模式 */
1464
- verbose?: boolean;
1465
- /** 自定义格式验证 */
1466
- formats?: Record<string, RegExp | ((value: any) => boolean)>;
1467
- /** 严格模式 */
1468
- strict?: boolean;
1469
- /** 扩展选项 */
1470
- [key: string]: any;
1471
- }
1472
-
1473
- /**
1474
- * 验证器类
1475
- *
1476
- * @description 基于ajv的JSON Schema验证器
1477
- *
1478
- * @example
1479
- * ```typescript
1480
- * // 创建验证器
1481
- * const validator = new Validator({ allErrors: true });
1482
- *
1483
- * // 验证数据
1484
- * const schema = dsl({ email: 'email!' }).toJsonSchema();
1485
- * const result = validator.validate(schema, { email: 'test@example.com' });
1486
- *
1487
- * if (result.valid) {
1488
- * console.log('验证通过');
1489
- * } else {
1490
- * console.log('错误:', result.errors);
1491
- * }
1492
- *
1493
- * // 获取底层ajv实例
1494
- * const ajv = validator.getAjv();
1495
- * ```
1496
- */
1497
- export class Validator {
1498
- /**
1499
- * 构造函数
1500
- * @param options - 验证器选项
1501
- */
1502
- constructor(options?: ValidatorOptions);
1503
-
1504
- /**
1505
- * 验证数据
1506
- * @param schema - JSON Schema对象
1507
- * @param data - 要验证的数据
1508
- * @param options - 验证选项
1509
- * @returns 验证结果
1510
- *
1511
- * @example
1512
- * ```typescript
1513
- * const validator = new Validator();
1514
- *
1515
- * // 使用默认语言
1516
- * const result1 = validator.validate(schema, data);
1517
- *
1518
- * // 动态指定语言
1519
- * const result2 = validator.validate(schema, data, { locale: 'zh-CN' });
1520
- *
1521
- * // 自定义错误消息
1522
- * const result3 = validator.validate(schema, data, {
1523
- * locale: 'zh-CN',
1524
- * messages: { min: '至少{{#limit}}个字符' }
1525
- * });
1526
- * ```
1527
- */
1528
- validate<T = any>(schema: JSONSchema, data: any, options?: ValidateOptions): ValidationResult<T>;
1529
-
1530
- /**
1531
- * 获取底层ajv实例
1532
- * @returns ajv实例
1533
- */
1534
- getAjv(): any;
1535
-
1536
- /**
1537
- * 添加自定义格式
1538
- * @param name - 格式名称
1539
- * @param validator - 验证函数或正则表达式
1540
- *
1541
- * @example
1542
- * ```typescript
1543
- * validator.addFormat('phone-cn', /^1[3-9]\d{9}$/);
1544
- * validator.addFormat('custom', (value) => {
1545
- * return value.startsWith('prefix-');
1546
- * });
1547
- * ```
1548
- */
1549
- addFormat(name: string, validator: RegExp | ((value: any) => boolean)): void;
1550
-
1551
- /**
1552
- * 添加自定义关键字
1553
- * @param keyword - 关键字名称
1554
- * @param definition - 关键字定义
1555
- */
1556
- addKeyword(keyword: string, definition: any): void;
1557
- }
1558
-
1559
- /**
1560
- * 便捷验证方法(同步)
1561
- *
1562
- * @description 使用默认的单例Validator,无需new
1563
- *
1564
- * @example
1565
- * ```typescript
1566
- * import { dsl, validate } from 'schema-dsl';
1567
- *
1568
- * const schema = dsl({ email: 'email!' });
1569
- *
1570
- * // 基本验证
1571
- * const result1 = validate(schema, { email: 'test@example.com' });
1572
- *
1573
- * // 指定语言
1574
- * const result2 = validate(schema, { email: 'invalid' }, { locale: 'zh-CN' });
1575
- *
1576
- * if (result2.valid) {
1577
- * console.log('验证通过');
1578
- * } else {
1579
- * console.log('错误:', result2.errors); // 中文错误消息
1580
- * }
1581
- * ```
1582
- */
1583
-
1584
- /**
1585
- * 全局配置函数
1586
- *
1587
- * @description dsl.config 的顶层导出别名,两种方式等效
1588
- *
1589
- * @example
1590
- * ```typescript
1591
- * import { config } from 'schema-dsl';
1592
- * // 或
1593
- * import { dsl } from 'schema-dsl';
1594
- *
1595
- * // 两种方式都可以
1596
- * config({ i18n: './locales' });
1597
- * dsl.config({ i18n: './locales' });
1598
- * ```
1599
- */
1600
- export const config: typeof dsl.config;
1601
-
1602
- export function validate<T = any>(
1603
- schema: JSONSchema | DslBuilder,
1604
- data: any,
1605
- options?: ValidateOptions
1606
- ): ValidationResult<T>;
1607
-
1608
- /**
1609
- * 便捷异步验证方法(推荐)
1610
- *
1611
- * @description
1612
- * - 异步验证数据,验证失败时抛出 ValidationError
1613
- * - 推荐在异步场景下使用此方法
1614
- * - 验证成功返回验证后的数据,失败抛出异常
1615
- *
1616
- * @param schema - JSON Schema对象或DslBuilder实例
1617
- * @param data - 要验证的数据
1618
- * @param options - 验证选项(可选)
1619
- * @returns 验证成功返回数据的Promise
1620
- * @throws {ValidationError} 验证失败时抛出
1621
- *
1622
- * @example
1623
- * ```typescript
1624
- * import { dsl, validateAsync, ValidationError } from 'schema-dsl';
1625
- *
1626
- * const schema = dsl({
1627
- * email: dsl('email!').label('邮箱'),
1628
- * username: dsl('string:3-32!').label('用户名')
1629
- * });
1630
- *
1631
- * try {
1632
- * const validData = await validateAsync(schema, {
1633
- * email: 'test@example.com',
1634
- * username: 'testuser'
1635
- * });
1636
- * console.log('验证通过:', validData);
1637
- * } catch (error) {
1638
- * if (error instanceof ValidationError) {
1639
- * console.log('验证失败:', error.errors);
1640
- * error.errors.forEach(err => {
1641
- * console.log(`${err.path}: ${err.message}`);
1642
- * });
1643
- * }
1644
- * }
1645
- * ```
1646
- */
1647
- export function validateAsync<T = any>(
1648
- schema: JSONSchema | DslBuilder,
1649
- data: any,
1650
- options?: ValidatorOptions
1651
- ): Promise<T>;
1652
-
1653
- /**
1654
- * 验证错误类
1655
- *
1656
- * @description 当 validateAsync 验证失败时抛出此错误
1657
- *
1658
- * @example
1659
- * ```typescript
1660
- * import { ValidationError, validateAsync, dsl } from 'schema-dsl';
1661
- *
1662
- * const schema = dsl({
1663
- * email: dsl('email!').label('邮箱'),
1664
- * age: dsl('number:18-100').label('年龄')
1665
- * });
1666
- *
1667
- * try {
1668
- * await validateAsync(schema, { email: 'invalid' });
1669
- * } catch (error) {
1670
- * if (error instanceof ValidationError) {
1671
- * // 获取所有错误
1672
- * console.log('错误列表:', error.errors);
1673
- *
1674
- * // 获取错误数量
1675
- * console.log('错误数量:', error.errors.length);
1676
- *
1677
- * // 遍历处理每个字段错误
1678
- * error.errors.forEach(err => {
1679
- * console.log(`字段 ${err.path}: ${err.message}`);
1680
- * });
1681
- *
1682
- * // 转为 JSON 格式
1683
- * const json = error.toJSON();
1684
- * console.log('JSON格式:', json);
1685
- * }
1686
- * }
1687
- * ```
1688
- */
1689
- export class ValidationError extends Error {
1690
- /** 错误名称(固定为 'ValidationError') */
1691
- readonly name: 'ValidationError';
1692
-
1693
- /** 错误消息 */
1694
- message: string;
1695
-
1696
- /** 验证错误列表 */
1697
- errors: ValidationError[];
1698
-
1699
- /**
1700
- * 构造函数
1701
- * @param errors - 验证错误数组
1702
- * @param message - 错误消息(可选)
1703
- */
1704
- constructor(errors: ValidationError[], message?: string);
1705
-
1706
- /**
1707
- * 转为 JSON 格式
1708
- * @returns JSON 对象
1709
- */
1710
- toJSON(): {
1711
- name: string;
1712
- message: string;
1713
- errors: Array<{
1714
- field: string;
1715
- message: string;
1716
- keyword: string;
1717
- params?: Record<string, any>;
1718
- }>;
1719
- };
1720
-
1721
- /**
1722
- * 获取指定字段的错误
1723
- * @param field - 字段路径
1724
- * @returns 错误对象或 null
1725
- */
1726
- getFieldError(field: string): ValidationError | null;
1727
-
1728
- /**
1729
- * 获取所有字段的错误映射
1730
- * @returns 字段错误映射对象
1731
- */
1732
- getFieldErrors(): Record<string, ValidationError>;
1733
-
1734
- /**
1735
- * 检查指定字段是否有错误
1736
- * @param field - 字段路径
1737
- * @returns 是否有错误
1738
- */
1739
- hasFieldError(field: string): boolean;
1740
-
1741
- /**
1742
- * 获取错误总数
1743
- * @returns 错误数量
1744
- */
1745
- getErrorCount(): number;
1746
- }
1747
-
1748
- /**
1749
- * I18nError - 多语言错误类
1750
- *
1751
- * @version 1.1.1
1752
- *
1753
- * @description 统一的多语言错误抛出机制,支持:
1754
- * - 多语言 key 自动翻译
1755
- * - 参数插值(如 {{#balance}}, {{#required}})
1756
- * - 自定义错误代码
1757
- * - Express/Koa 集成
1758
- *
1759
- * @example 基础用法
1760
- * ```typescript
1761
- * import { I18nError } from 'schema-dsl';
1762
- *
1763
- * // 直接抛出
1764
- * throw I18nError.create('account.notFound');
1765
- * // 中文: "账户不存在"
1766
- * // 英文: "Account not found"
1767
- * ```
1768
- *
1769
- * @example 带参数
1770
- * ```typescript
1771
- * I18nError.throw('account.insufficientBalance', {
1772
- * balance: 50,
1773
- * required: 100
1774
- * });
1775
- * // 输出: "余额不足,当前余额50,需要100"
1776
- * ```
1777
- *
1778
- * @example 断言风格
1779
- * ```typescript
1780
- * function getAccount(id: string) {
1781
- * const account = db.findAccount(id);
1782
- * I18nError.assert(account, 'account.notFound');
1783
- * I18nError.assert(
1784
- * account.balance >= 100,
1785
- * 'account.insufficientBalance',
1786
- * { balance: account.balance, required: 100 }
1787
- * );
1788
- * return account;
1789
- * }
1790
- * ```
1791
- *
1792
- * @example Express 集成
1793
- * ```typescript
1794
- * app.use((error, req, res, next) => {
1795
- * if (error instanceof I18nError) {
1796
- * return res.status(error.statusCode).json(error.toJSON());
1797
- * }
1798
- * next(error);
1799
- * });
1800
- * ```
1801
- */
1802
- export class I18nError extends Error {
1803
- /** 错误名称(固定为 'I18nError') */
1804
- readonly name: 'I18nError';
1805
-
1806
- /** 错误消息(已翻译) */
1807
- message: string;
1808
-
1809
- /** 原始 key(v1.1.5 新增) */
1810
- originalKey: string;
1811
-
1812
- /** 错误代码(从对象提取或使用 key) */
1813
- code: string;
1814
-
1815
- /** 错误参数(用于插值) */
1816
- params: Record<string, any>;
1817
-
1818
- /** HTTP 状态码 */
1819
- statusCode: number;
1820
-
1821
- /** 使用的语言环境 */
1822
- locale: string;
1823
-
1824
- /**
1825
- * 构造函数
1826
- * @param code - 错误代码(多语言 key)
1827
- * @param params - 错误参数(用于插值)
1828
- * @param statusCode - HTTP 状态码(默认 400)
1829
- * @param locale - 语言环境(默认使用当前语言)
1830
- */
1831
- constructor(
1832
- code: string,
1833
- params?: Record<string, any>,
1834
- statusCode?: number,
1835
- locale?: string
1836
- );
1837
-
1838
- /**
1839
- * 静态工厂方法 - 创建错误(不抛出)
1840
- *
1841
- * @param code - 错误代码
1842
- * @param paramsOrLocale - 错误参数对象 或 语言代码(智能识别,v1.1.8+)
1843
- * @param statusCode - HTTP 状态码
1844
- * @param locale - 语言环境(仅当第2个参数是对象时有效)
1845
- * @returns 错误实例
1846
- *
1847
- * @example 简化语法(v1.1.8+)
1848
- * ```typescript
1849
- * // 直接传语言参数
1850
- * const error = I18nError.create('account.notFound', 'zh-CN');
1851
- * const error = I18nError.create('account.notFound', 'en-US', 404);
1852
- * ```
1853
- *
1854
- * @example 标准语法(完全兼容)
1855
- * ```typescript
1856
- * // 带参数对象
1857
- * const error = I18nError.create('account.notFound', { id: '123' }, 404, 'zh-CN');
1858
- * ```
1859
- *
1860
- * @example 全局语言
1861
- * ```typescript
1862
- * Locale.setLocale('zh-CN');
1863
- * const error = I18nError.create('account.notFound');
1864
- * // message: "账户不存在"
1865
- * ```
1866
- *
1867
- * @example 运行时指定语言
1868
- * ```typescript
1869
- * const error1 = I18nError.create('account.notFound', {}, 404, 'zh-CN');
1870
- * // message: "账户不存在"
1871
- *
1872
- * const error2 = I18nError.create('account.notFound', {}, 404, 'en-US');
1873
- * // message: "Account not found"
1874
- * ```
1875
- */
1876
- static create(
1877
- code: string,
1878
- paramsOrLocale?: Record<string, any> | string,
1879
- statusCode?: number,
1880
- locale?: string
1881
- ): I18nError;
1882
-
1883
- /**
1884
- * 静态工厂方法 - 直接抛出错误
1885
- *
1886
- * @param code - 错误代码
1887
- * @param paramsOrLocale - 错误参数对象 或 语言代码(智能识别,v1.1.8+)
1888
- * @param statusCode - HTTP 状态码
1889
- * @param locale - 语言环境(仅当第2个参数是对象时有效)
1890
- * @throws I18nError
1891
- *
1892
- * @example 简化语法(v1.1.8+)
1893
- * ```typescript
1894
- * // 直接传语言参数
1895
- * I18nError.throw('account.notFound', 'zh-CN');
1896
- * I18nError.throw('account.notFound', 'en-US', 404);
1897
- * ```
1898
- *
1899
- * @example 标准语法(完全兼容)
1900
- * ```typescript
1901
- * // 带参数对象
1902
- * I18nError.throw('account.notFound', { id: '123' }, 404, 'zh-CN');
1903
- * ```
1904
- *
1905
- * @example 全局语言
1906
- * ```typescript
1907
- * Locale.setLocale('zh-CN');
1908
- * I18nError.throw('account.notFound');
1909
- * ```
1910
- *
1911
- * @example 运行时指定语言
1912
- * ```typescript
1913
- * I18nError.throw('account.notFound', {}, 404, 'en-US');
1914
- * ```
1915
- */
1916
- static throw(
1917
- code: string,
1918
- paramsOrLocale?: Record<string, any> | string,
1919
- statusCode?: number,
1920
- locale?: string
1921
- ): never;
1922
-
1923
- /**
1924
- * 断言方法 - 条件不满足时抛错
1925
- *
1926
- * @param condition - 条件表达式
1927
- * @param code - 错误代码
1928
- * @param paramsOrLocale - 错误参数对象 或 语言代码(智能识别,v1.1.8+)
1929
- * @param statusCode - HTTP 状态码
1930
- * @param locale - 语言环境(仅当第3个参数是对象时有效)
1931
- * @throws I18nError 条件为 false 时抛出
1932
- *
1933
- * @example 简化语法(v1.1.8+)
1934
- * ```typescript
1935
- * // 直接传语言参数
1936
- * I18nError.assert(account, 'account.notFound', 'zh-CN');
1937
- * I18nError.assert(account, 'account.notFound', 'en-US', 404);
1938
- * ```
1939
- *
1940
- * @example 标准语法(完全兼容)
1941
- * ```typescript
1942
- * // 带参数对象
1943
- * I18nError.assert(account, 'account.notFound', { id: '123' }, 404, 'zh-CN');
1944
- * ```
1945
- *
1946
- * @example 全局语言
1947
- * ```typescript
1948
- * Locale.setLocale('zh-CN');
1949
- * I18nError.assert(account, 'account.notFound');
1950
- * ```
1951
- *
1952
- * @example 运行时指定语言
1953
- * ```typescript
1954
- * I18nError.assert(account, 'account.notFound', {}, 404, 'en-US');
1955
- * ```
1956
- */
1957
- static assert(
1958
- condition: any,
1959
- code: string,
1960
- paramsOrLocale?: Record<string, any> | string,
1961
- statusCode?: number,
1962
- locale?: string
1963
- ): asserts condition;
1964
-
1965
- /**
1966
- * 检查错误是否为指定代码
1967
- * @param code - 错误代码
1968
- * @returns 是否匹配
1969
- */
1970
- is(code: string): boolean;
1971
-
1972
- /**
1973
- * 转为 JSON 格式(用于 API 响应)
1974
- * @returns JSON 对象
1975
- *
1976
- * @example
1977
- * ```typescript
1978
- * const json = error.toJSON();
1979
- * // {
1980
- * // error: 'I18nError',
1981
- * // originalKey: 'account.notFound', // v1.1.5 新增
1982
- * // code: 'ACCOUNT_NOT_FOUND',
1983
- * // message: '账户不存在',
1984
- * // params: {},
1985
- * // statusCode: 400,
1986
- * // locale: 'zh-CN'
1987
- * // }
1988
- * ```
1989
- *
1990
- * @since v1.1.5 - 新增 originalKey 字段
1991
- */
1992
- toJSON(): {
1993
- error: string;
1994
- originalKey: string; // v1.1.5 新增
1995
- code: string;
1996
- message: string;
1997
- params: Record<string, any>;
1998
- statusCode: number;
1999
- locale: string;
2000
- };
2001
-
2002
- /**
2003
- * 转为字符串
2004
- * @returns 格式化的错误信息
2005
- */
2006
- toString(): string;
2007
- }
2008
-
2009
- /**
2010
- * 获取默认Validator实例(单例)
2011
- *
2012
- * @description 获取全局共享的Validator实例
2013
- *
2014
- * @example
2015
- * ```typescript
2016
- * import { getDefaultValidator } from 'schema-dsl';
2017
- *
2018
- * const validator = getDefaultValidator();
2019
- * validator.addFormat('custom', /pattern/);
2020
- * ```
2021
- */
2022
- export function getDefaultValidator(): Validator;
2023
-
2024
- // ========== 导出器 ==========
2025
-
2026
- /**
2027
- * MongoDB 导出器选项
2028
- */
2029
- export interface MongoDBExporterOptions {
2030
- /** 严格模式(默认false) */
2031
- strict?: boolean;
2032
- /** 时间戳字段 */
2033
- timestamps?: boolean;
2034
- /** 集合名称 */
2035
- collectionName?: string;
2036
- }
2037
-
2038
- /**
2039
- * MongoDB 导出器
2040
- *
2041
- * @description 将JSON Schema导出为MongoDB验证规则
2042
- *
2043
- * @example
2044
- * ```typescript
2045
- * const exporter = new MongoDBExporter({ strict: true });
2046
- * const mongoSchema = exporter.export(jsonSchema);
2047
- *
2048
- * // 生成MongoDB命令
2049
- * const command = exporter.generateCommand('users', jsonSchema);
2050
- * console.log(command);
2051
- * // db.createCollection("users", { validator: { $jsonSchema: {...} } })
2052
- * ```
2053
- */
2054
- export class MongoDBExporter {
2055
- /**
2056
- * 构造函数
2057
- * @param options - 导出选项
2058
- */
2059
- constructor(options?: MongoDBExporterOptions);
2060
-
2061
- /**
2062
- * 导出为MongoDB Schema
2063
- * @param schema - JSON Schema对象
2064
- * @returns MongoDB验证规则
2065
- */
2066
- export(schema: JSONSchema): any;
2067
-
2068
- /**
2069
- * 生成MongoDB创建集合命令
2070
- * @param collectionName - 集合名称
2071
- * @param schema - JSON Schema对象
2072
- * @returns MongoDB命令字符串
2073
- */
2074
- generateCommand(collectionName: string, schema: JSONSchema): string;
2075
- }
2076
-
2077
- /**
2078
- * MySQL 导出器选项
2079
- */
2080
- export interface MySQLExporterOptions {
2081
- /** 表名 */
2082
- tableName?: string;
2083
- /** 存储引擎(默认InnoDB) */
2084
- engine?: string;
2085
- /** 字符集(默认utf8mb4) */
2086
- charset?: string;
2087
- /** 排序规则 */
2088
- collation?: string;
2089
- }
2090
-
2091
- /**
2092
- * MySQL 导出器
2093
- *
2094
- * @description 将JSON Schema导出为MySQL CREATE TABLE语句
2095
- *
2096
- * @example
2097
- * ```typescript
2098
- * const exporter = new MySQLExporter();
2099
- * const sql = exporter.export(jsonSchema, {
2100
- * tableName: 'users',
2101
- * engine: 'InnoDB',
2102
- * charset: 'utf8mb4'
2103
- * });
2104
- *
2105
- * console.log(sql);
2106
- * // CREATE TABLE `users` (
2107
- * // `id` INT PRIMARY KEY AUTO_INCREMENT,
2108
- * // `username` VARCHAR(32) NOT NULL,
2109
- * // ...
2110
- * // ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
2111
- * ```
2112
- */
2113
- export class MySQLExporter {
2114
- /**
2115
- * 构造函数
2116
- */
2117
- constructor();
2118
-
2119
- /**
2120
- * 导出为MySQL CREATE TABLE语句
2121
- * @param schema - JSON Schema对象
2122
- * @param options - 导出选项
2123
- * @returns SQL语句
2124
- */
2125
- export(schema: JSONSchema, options?: MySQLExporterOptions): string;
2126
- }
2127
-
2128
- /**
2129
- * PostgreSQL 导出器选项
2130
- */
2131
- export interface PostgreSQLExporterOptions {
2132
- /** 表名 */
2133
- tableName?: string;
2134
- /** 模式名 */
2135
- schemaName?: string;
2136
- }
2137
-
2138
- /**
2139
- * PostgreSQL 导出器
2140
- *
2141
- * @description 将JSON Schema导出为PostgreSQL CREATE TABLE语句
2142
- *
2143
- * @example
2144
- * ```typescript
2145
- * const exporter = new PostgreSQLExporter();
2146
- * const sql = exporter.export(jsonSchema, {
2147
- * tableName: 'users',
2148
- * schemaName: 'public'
2149
- * });
2150
- *
2151
- * console.log(sql);
2152
- * // CREATE TABLE public.users (
2153
- * // id SERIAL PRIMARY KEY,
2154
- * // username VARCHAR(32) NOT NULL,
2155
- * // ...
2156
- * // );
2157
- * ```
2158
- */
2159
- export class PostgreSQLExporter {
2160
- /**
2161
- * 构造函数
2162
- */
2163
- constructor();
2164
-
2165
- /**
2166
- * 导出为PostgreSQL CREATE TABLE语句
2167
- * @param schema - JSON Schema对象
2168
- * @param options - 导出选项
2169
- * @returns SQL语句
2170
- */
2171
- export(schema: JSONSchema, options?: PostgreSQLExporterOptions): string;
2172
- }
2173
-
2174
- /**
2175
- * 导出器命名空间
2176
- *
2177
- * @description 统一的导出器访问入口
2178
- *
2179
- * @example
2180
- * ```typescript
2181
- * import { exporters } from 'schema-dsl';
2182
- *
2183
- * const mongoExporter = new exporters.MongoDBExporter();
2184
- * const mysqlExporter = new exporters.MySQLExporter();
2185
- * const pgExporter = new exporters.PostgreSQLExporter();
2186
- * ```
2187
- */
2188
-
2189
- // ========== 工具函数 ==========
2190
-
2191
- /**
2192
- * 类型转换工具
2193
- *
2194
- * @description 提供多种Schema类型之间的转换
2195
- *
2196
- * @example
2197
- * ```typescript
2198
- * // 转换为JSON Schema类型
2199
- * const jsonType = TypeConverter.toJSONSchemaType('email');
2200
- * // { type: 'string', format: 'email' }
2201
- *
2202
- * // 转换为MongoDB类型
2203
- * const mongoType = TypeConverter.toMongoDBType('string');
2204
- * // 'String'
2205
- *
2206
- * // 转换为MySQL类型
2207
- * const mysqlType = TypeConverter.toMySQLType('string', { maxLength: 255 });
2208
- * // 'VARCHAR(255)'
2209
- * ```
2210
- */
2211
- export class TypeConverter {
2212
- /**
2213
- * 转换为JSON Schema类型
2214
- * @param simpleType - 简单类型名称
2215
- * @returns JSON Schema类型对象
2216
- */
2217
- static toJSONSchemaType(simpleType: string): JSONSchema;
2218
-
2219
- /**
2220
- * 转换为MongoDB类型
2221
- * @param jsonSchemaType - JSON Schema类型
2222
- * @returns MongoDB类型字符串
2223
- */
2224
- static toMongoDBType(jsonSchemaType: string): string;
2225
-
2226
- /**
2227
- * 转换为MySQL类型
2228
- * @param jsonSchemaType - JSON Schema类型
2229
- * @param constraints - 约束条件
2230
- * @returns MySQL类型字符串
2231
- */
2232
- static toMySQLType(jsonSchemaType: string, constraints?: Record<string, any>): string;
2233
-
2234
- /**
2235
- * 转换为PostgreSQL类型
2236
- * @param jsonSchemaType - JSON Schema类型
2237
- * @param constraints - 约束条件
2238
- * @returns PostgreSQL类型字符串
2239
- */
2240
- static toPostgreSQLType(jsonSchemaType: string, constraints?: Record<string, any>): string;
2241
-
2242
- /**
2243
- * 规范化属性名
2244
- * @param name - 原属性名
2245
- * @param style - 命名风格
2246
- * @returns 规范化后的属性名
2247
- *
2248
- * @example
2249
- * ```typescript
2250
- * TypeConverter.normalizePropertyName('userName', 'snake_case');
2251
- * // 'user_name'
2252
- *
2253
- * TypeConverter.normalizePropertyName('user_name', 'camelCase');
2254
- * // 'userName'
2255
- * ```
2256
- */
2257
- static normalizePropertyName(name: string, style?: 'snake_case' | 'camelCase'): string;
2258
-
2259
- /**
2260
- * 将format转换为正则表达式
2261
- * @param format - 格式名称
2262
- * @returns 正则表达式字符串或null
2263
- */
2264
- static formatToRegex(format: string): string | null;
2265
-
2266
- /**
2267
- * 合并Schema
2268
- * @param base - 基础Schema
2269
- * @param override - 覆盖Schema
2270
- * @returns 合并后的Schema
2271
- */
2272
- static mergeSchemas(base: JSONSchema, override: JSONSchema): JSONSchema;
2273
-
2274
- /**
2275
- * 提取约束条件
2276
- * @param schema - JSON Schema对象
2277
- * @returns 约束条件对象
2278
- */
2279
- static extractConstraints(schema: JSONSchema): Record<string, any>;
2280
- }
2281
-
2282
- /**
2283
- * Schema 辅助工具
2284
- *
2285
- * @description 提供Schema的基础操作方法
2286
- *
2287
- * @example
2288
- * ```typescript
2289
- * // 合并Schema
2290
- * const merged = SchemaHelper.merge(schema1, schema2);
2291
- *
2292
- * // 克隆Schema
2293
- * const cloned = SchemaHelper.clone(schema);
2294
- * ```
2295
- */
2296
- export class SchemaHelper {
2297
- /**
2298
- * 合并多个Schema
2299
- * @param schema1 - 第一个Schema
2300
- * @param schema2 - 第二个Schema
2301
- * @returns 合并后的Schema
2302
- */
2303
- static merge(schema1: JSONSchema, schema2: JSONSchema): JSONSchema;
2304
-
2305
- /**
2306
- * 克隆Schema
2307
- * @param schema - 要克隆的Schema
2308
- * @returns 克隆的Schema副本
2309
- */
2310
- static clone(schema: JSONSchema): JSONSchema;
2311
- }
2312
-
2313
- /**
2314
- * Schema 工具类 (v2.0.1+)
2315
- *
2316
- * @description 提供高级Schema操作和工具方法
2317
- *
2318
- * @example
2319
- * ```typescript
2320
- * // 创建可复用的Schema片段
2321
- * const addressFragment = SchemaUtils.reusable(() => ({
2322
- * city: 'string!',
2323
- * street: 'string!',
2324
- * zip: 'string'
2325
- * }));
2326
- *
2327
- * // 创建Schema库
2328
- * const library = SchemaUtils.createLibrary({
2329
- * user: () => ({ username: 'string!', email: 'email!' }),
2330
- * address: addressFragment
2331
- * });
2332
- *
2333
- * // 使用Schema库
2334
- * const schema = dsl({
2335
- * user: library.user(),
2336
- * address: library.address()
2337
- * });
2338
- * ```
2339
- */
2340
- export class SchemaUtils {
2341
- /**
2342
- * 创建可复用的Schema片段
2343
- * @param factory - Schema工厂函数
2344
- * @returns 可复用的工厂函数
2345
- */
2346
- static reusable<T>(factory: () => T): () => T;
2347
-
2348
- /**
2349
- * 创建Schema片段库
2350
- * @param fragments - Schema片段对象
2351
- * @returns Schema库对象
2352
- */
2353
- static createLibrary<T extends Record<string, () => any>>(fragments: T): T;
2354
-
2355
- /**
2356
- * 合并多个Schema
2357
- * @param schemas - 要合并的Schema数组
2358
- * @returns 合并后的Schema
2359
- */
2360
- static merge(...schemas: JSONSchema[]): JSONSchema;
2361
-
2362
- /**
2363
- * 扩展Schema
2364
- * @param baseSchema - 基础Schema
2365
- * @param extensions - 扩展字段
2366
- * @returns 扩展后的Schema
2367
- */
2368
- static extend(baseSchema: JSONSchema, extensions: Record<string, any>): JSONSchema;
2369
-
2370
- /**
2371
- * 挑选Schema的部分字段
2372
- * @param schema - 原Schema
2373
- * @param fields - 要挑选的字段列表
2374
- * @returns 新Schema
2375
- *
2376
- * @example
2377
- * ```typescript
2378
- * const userSchema = dsl({
2379
- * username: 'string!',
2380
- * email: 'email!',
2381
- * password: 'string!',
2382
- * age: 'number'
2383
- * });
2384
- *
2385
- * const loginSchema = SchemaUtils.pick(userSchema, ['username', 'password']);
2386
- * ```
2387
- */
2388
- static pick(schema: JSONSchema, fields: string[]): JSONSchema;
2389
-
2390
- /**
2391
- * 排除Schema的部分字段
2392
- * @param schema - 原Schema
2393
- * @param fields - 要排除的字段列表
2394
- * @returns 新Schema
2395
- *
2396
- * @example
2397
- * ```typescript
2398
- * const publicUserSchema = SchemaUtils.omit(userSchema, ['password']);
2399
- * ```
2400
- */
2401
- static omit(schema: JSONSchema, fields: string[]): JSONSchema;
2402
-
2403
- /**
2404
- * 创建带性能监控的Validator
2405
- * @param validator - 原Validator实例
2406
- * @returns 包装后的Validator
2407
- */
2408
- static withPerformance(validator: Validator): Validator;
2409
-
2410
- /**
2411
- * 批量验证
2412
- * @param schema - JSON Schema对象
2413
- * @param dataArray - 数据数组
2414
- * @param validator - Validator实例
2415
- * @returns 批量验证结果
2416
- *
2417
- * @example
2418
- * ```typescript
2419
- * const results = SchemaUtils.validateBatch(
2420
- * schema,
2421
- * [data1, data2, data3],
2422
- * validator
2423
- * );
2424
- *
2425
- * console.log(results.summary);
2426
- * // {
2427
- * // total: 3,
2428
- * // valid: 2,
2429
- * // invalid: 1,
2430
- * // duration: 15,
2431
- * // averageTime: 5
2432
- * // }
2433
- * ```
2434
- */
2435
- static validateBatch(schema: JSONSchema, dataArray: any[], validator: Validator): {
2436
- results: Array<{ index: number; valid: boolean; errors: any; data: any }>;
2437
- summary: { total: number; valid: number; invalid: number; duration: number; averageTime: number };
2438
- };
2439
-
2440
- /**
2441
- * 检查嵌套深度
2442
- * @param schema - JSON Schema对象
2443
- * @param maxDepth - 最大深度(默认10)
2444
- * @returns 检查结果
2445
- */
2446
- static validateNestingDepth(schema: JSONSchema, maxDepth?: number): {
2447
- valid: boolean;
2448
- depth: number;
2449
- path: string;
2450
- message: string;
2451
- };
2452
-
2453
- /**
2454
- * 导出为Markdown文档
2455
- * @param schema - JSON Schema对象
2456
- * @param options - 导出选项
2457
- * @returns Markdown字符串
2458
- */
2459
- static toMarkdown(schema: JSONSchema, options?: { title?: string; locale?: string }): string;
2460
-
2461
- /**
2462
- * 导出为HTML文档
2463
- * @param schema - JSON Schema对象
2464
- * @param options - 导出选项
2465
- * @returns HTML字符串
2466
- */
2467
- static toHTML(schema: JSONSchema, options?: { title?: string }): string;
2468
-
2469
- /**
2470
- * 克隆Schema
2471
- * @param schema - 要克隆的Schema
2472
- * @returns Schema副本
2473
- */
2474
- static clone(schema: JSONSchema): JSONSchema;
2475
- }
2476
-
2477
- // ========== 错误代码 ==========
2478
-
2479
- /**
2480
- * 错误代码常量
2481
- *
2482
- * @description 预定义的错误代码和消息
2483
- *
2484
- * @example
2485
- * ```typescript
2486
- * import { ErrorCodes } from 'schema-dsl';
2487
- *
2488
- * console.log(ErrorCodes.min);
2489
- * // { code: 'MIN_LENGTH', message: 'Must be at least {{#limit}} characters', zhCN: '至少需要 {{#limit}} 个字符' }
2490
- *
2491
- * console.log(ErrorCodes.email);
2492
- * // { code: 'INVALID_EMAIL', message: 'Invalid email format', zhCN: '邮箱格式不正确' }
2493
- * ```
2494
- */
2495
- export const ErrorCodes: {
2496
- /** 最小长度/最小值错误 */
2497
- min: { code: string; message: string; zhCN: string };
2498
- /** 最大长度/最大值错误 */
2499
- max: { code: string; message: string; zhCN: string };
2500
- /** 邮箱格式错误 */
2501
- email: { code: string; message: string; zhCN: string };
2502
- /** URL格式错误 */
2503
- url: { code: string; message: string; zhCN: string };
2504
- /** 正则表达式验证错误 */
2505
- pattern: { code: string; message: string; zhCN: string };
2506
- /** 必填项错误 */
2507
- required: { code: string; message: string; zhCN: string };
2508
- /** 类型错误 */
2509
- type: { code: string; message: string; zhCN: string };
2510
- /** 枚举值错误 */
2511
- enum: { code: string; message: string; zhCN: string };
2512
- };
2513
-
2514
- // ========== 多语言 ==========
2515
-
2516
- /**
2517
- * 多语言支持
2518
- *
2519
- * @description 提供国际化支持的工具类
2520
- *
2521
- * @example
2522
- * ```typescript
2523
- * import { Locale } from 'schema-dsl';
2524
- *
2525
- * // 设置语言
2526
- * Locale.setLocale('zh-CN');
2527
- *
2528
- * // 获取当前语言
2529
- * console.log(Locale.getLocale()); // 'zh-CN'
2530
- *
2531
- * // 添加自定义语言包
2532
- * Locale.addLocale('ja-JP', {
2533
- * required: '必須項目です',
2534
- * min: '{{#limit}}文字以上必要です'
2535
- * });
2536
- *
2537
- * // 获取可用语言列表
2538
- * console.log(Locale.getAvailableLocales()); // ['zh-CN', 'en-US', 'ja-JP', ...]
2539
- * ```
2540
- */
2541
- export class Locale {
2542
- /**
2543
- * 设置当前语言
2544
- * @param lang - 语言代码
2545
- */
2546
- static setLocale(lang: 'en-US' | 'zh-CN' | 'ja-JP' | 'fr-FR' | 'es-ES' | string): void;
2547
-
2548
- /**
2549
- * 获取当前语言
2550
- * @returns 语言代码
2551
- */
2552
- static getLocale(): string;
2553
-
2554
- /**
2555
- * 添加语言包
2556
- * @param locale - 语言代码
2557
- * @param messages - 错误消息
2558
- */
2559
- static addLocale(locale: string, messages: ErrorMessages): void;
2560
-
2561
- /**
2562
- * 设置当前语言包的消息
2563
- * @param messages - 错误消息
2564
- */
2565
- static setMessages(messages: ErrorMessages): void;
2566
-
2567
- /**
2568
- * 获取错误消息
2569
- * @param type - 错误类型
2570
- * @param customMessages - 自定义消息(可选)
2571
- * @returns 错误消息字符串
2572
- */
2573
- static getMessage(type: string, customMessages?: ErrorMessages): string;
2574
-
2575
- /**
2576
- * 获取可用的语言列表
2577
- * @returns 语言代码数组
2578
- */
2579
- static getAvailableLocales(): string[];
2580
- }
2581
-
2582
- // ========== JSONSchemaCore 类 ==========
2583
-
2584
- /**
2585
- * JSON Schema 核心类
2586
- *
2587
- * @description 对 JSON Schema 进行封装,提供验证和操作方法
2588
- *
2589
- * @example
2590
- * ```typescript
2591
- * const core = new JSONSchemaCore({
2592
- * type: 'string',
2593
- * minLength: 3,
2594
- * maxLength: 32
2595
- * });
2596
- *
2597
- * const result = core.validate('test');
2598
- * console.log(result.valid); // true
2599
- * ```
2600
- */
2601
- export class JSONSchemaCore {
2602
- /**
2603
- * 构造函数
2604
- * @param schema - JSON Schema 对象
2605
- */
2606
- constructor(schema: JSONSchema);
2607
-
2608
- /**
2609
- * 验证数据
2610
- * @param data - 要验证的数据
2611
- * @returns 验证结果
2612
- */
2613
- validate<T = any>(data: any): ValidationResult<T>;
2614
-
2615
- /**
2616
- * 获取 JSON Schema 对象
2617
- * @returns JSON Schema
2618
- */
2619
- toJsonSchema(): JSONSchema;
2620
- }
2621
-
2622
- // ========== ErrorFormatter 类 ==========
2623
-
2624
- /**
2625
- * 错误格式化器
2626
- *
2627
- * @description 格式化 ajv 验证错误为友好的错误消息
2628
- *
2629
- * @example
2630
- * ```typescript
2631
- * const formatter = new ErrorFormatter();
2632
- * const errors = formatter.format(ajvErrors, { locale: 'zh-CN' });
2633
- * ```
2634
- */
2635
- export class ErrorFormatter {
2636
- /**
2637
- * 格式化错误
2638
- * @param errors - ajv 错误数组
2639
- * @param options - 格式化选项
2640
- * @returns 格式化后的错误数组
2641
- */
2642
- format(errors: any[], options?: { locale?: string }): ValidationError[];
2643
- }
2644
-
2645
- // ========== MessageTemplate 类 ==========
2646
-
2647
- /**
2648
- * 消息模板类
2649
- *
2650
- * @description 处理错误消息模板和变量替换
2651
- *
2652
- * @example
2653
- * ```typescript
2654
- * const template = new MessageTemplate('至少需要{{#limit}}个字符');
2655
- * const message = template.render({ limit: 3 });
2656
- * console.log(message); // "至少需要3个字符"
2657
- * ```
2658
- */
2659
- export class MessageTemplate {
2660
- /**
2661
- * 构造函数
2662
- * @param template - 消息模板字符串
2663
- */
2664
- constructor(template: string);
2665
-
2666
- /**
2667
- * 渲染模板
2668
- * @param variables - 模板变量
2669
- * @returns 渲染后的消息
2670
- */
2671
- render(variables: Record<string, any>): string;
2672
-
2673
- /**
2674
- * 静态渲染方法
2675
- * @param template - 消息模板
2676
- * @param variables - 模板变量
2677
- * @returns 渲染后的消息
2678
- */
2679
- static render(template: string, variables: Record<string, any>): string;
2680
- }
2681
-
2682
- // ========== CacheManager 类 ==========
2683
-
2684
- /**
2685
- * 缓存管理器选项
2686
- */
2687
- export interface CacheManagerOptions {
2688
- /** 最大缓存条目数 */
2689
- maxSize?: number;
2690
- /** 缓存过期时间(毫秒) */
2691
- ttl?: number;
2692
- }
2693
-
2694
- /**
2695
- * 缓存管理器
2696
- *
2697
- * @description LRU 缓存管理器,用于缓存编译后的 Schema
2698
- *
2699
- * @example
2700
- * ```typescript
2701
- * const cache = new CacheManager({ maxSize: 1000, ttl: 60000 });
2702
- *
2703
- * // 设置缓存
2704
- * cache.set('key', value);
2705
- *
2706
- * // 获取缓存
2707
- * const value = cache.get('key');
2708
- *
2709
- * // 清空缓存
2710
- * cache.clear();
2711
- * ```
2712
- */
2713
- export class CacheManager {
2714
- /**
2715
- * 构造函数
2716
- * @param options - 缓存选项
2717
- */
2718
- constructor(options?: CacheManagerOptions);
2719
-
2720
- /**
2721
- * 缓存选项
2722
- */
2723
- options: CacheManagerOptions;
2724
-
2725
- /**
2726
- * 设置缓存
2727
- * @param key - 缓存键
2728
- * @param value - 缓存值
2729
- */
2730
- set(key: string, value: any): void;
2731
-
2732
- /**
2733
- * 获取缓存
2734
- * @param key - 缓存键
2735
- * @returns 缓存值或 undefined
2736
- */
2737
- get(key: string): any | undefined;
2738
-
2739
- /**
2740
- * 检查缓存是否存在
2741
- * @param key - 缓存键
2742
- * @returns 是否存在
2743
- */
2744
- has(key: string): boolean;
2745
-
2746
- /**
2747
- * 删除缓存
2748
- * @param key - 缓存键
2749
- */
2750
- delete(key: string): void;
2751
-
2752
- /**
2753
- * 清空所有缓存
2754
- */
2755
- clear(): void;
2756
-
2757
- /**
2758
- * 获取缓存统计信息
2759
- * @returns 统计信息对象
2760
- */
2761
- getStats(): {
2762
- size: number;
2763
- hits: number;
2764
- misses: number;
2765
- evictions: number;
2766
- };
2767
- }
2768
-
2769
- // ========== PluginManager 类 ==========
2770
-
2771
- /**
2772
- * 插件接口
2773
- */
2774
- export interface Plugin {
2775
- /** 插件名称 */
2776
- name: string;
2777
- /** 插件版本 */
2778
- version: string;
2779
- /** 插件描述 */
2780
- description?: string;
2781
- /** 安装方法 */
2782
- install(core: any, options?: any, context?: any): void;
2783
- /** 卸载方法(可选) */
2784
- uninstall?(core: any, context?: any): void;
2785
- }
2786
-
2787
- /**
2788
- * 插件管理器
2789
- *
2790
- * @description 管理验证库的插件系统
2791
- *
2792
- * @example
2793
- * ```typescript
2794
- * const pluginManager = new PluginManager();
2795
- *
2796
- * // 注册插件
2797
- * pluginManager.register({
2798
- * name: 'my-plugin',
2799
- * version: '1.0.0',
2800
- * install(core) {
2801
- * // 安装逻辑
2802
- * }
2803
- * });
2804
- *
2805
- * // 安装插件
2806
- * pluginManager.install(schemaCore);
2807
- *
2808
- * // 获取插件
2809
- * const plugin = pluginManager.get('my-plugin');
2810
- * ```
2811
- */
2812
- export class PluginManager {
2813
- /**
2814
- * 构造函数
2815
- */
2816
- constructor();
2817
-
2818
- /**
2819
- * 注册插件
2820
- * @param plugin - 插件对象
2821
- */
2822
- register(plugin: Plugin): void;
2823
-
2824
- /**
2825
- * 安装所有插件
2826
- * @param core - 核心对象
2827
- * @param options - 安装选项
2828
- */
2829
- install(core: any, options?: any): void;
2830
-
2831
- /**
2832
- * 获取插件
2833
- * @param name - 插件名称
2834
- * @returns 插件对象或 undefined
2835
- */
2836
- get(name: string): Plugin | undefined;
2837
-
2838
- /**
2839
- * 卸载插件
2840
- * @param name - 插件名称
2841
- */
2842
- uninstall(name: string): void;
2843
-
2844
- /**
2845
- * 列出所有插件
2846
- * @returns 插件名称数组
2847
- */
2848
- list(): string[];
2849
-
2850
- /**
2851
- * 清空所有插件
2852
- */
2853
- clear(): void;
2854
- }
2855
-
2856
- // ========== MarkdownExporter 类 ==========
2857
-
2858
- /**
2859
- * Markdown 导出器选项
2860
- */
2861
- export interface MarkdownExporterOptions {
2862
- /** 文档标题 */
2863
- title?: string;
2864
- /** 语言(zh-CN, en-US等) */
2865
- locale?: string;
2866
- /** 是否包含示例数据 */
2867
- includeExamples?: boolean;
2868
- }
2869
-
2870
- /**
2871
- * Markdown 导出器
2872
- *
2873
- * @description 将 JSON Schema 导出为 Markdown 文档
2874
- *
2875
- * @example
2876
- * ```typescript
2877
- * const exporter = new MarkdownExporter();
2878
- * const markdown = exporter.export(schema, {
2879
- * title: '用户注册 API',
2880
- * locale: 'zh-CN',
2881
- * includeExamples: true
2882
- * });
2883
- *
2884
- * console.log(markdown);
2885
- * // # 用户注册 API
2886
- * //
2887
- * // ## 字段列表
2888
- * // | 字段名 | 类型 | 必填 | 约束 | 说明 |
2889
- * // |--------|------|------|------|------|
2890
- * // | username | 字符串 | ✅ | 长度: 3-32 | - |
2891
- * ```
2892
- */
2893
- export class MarkdownExporter {
2894
- /**
2895
- * 构造函数
2896
- */
2897
- constructor();
2898
-
2899
- /**
2900
- * 导出为 Markdown
2901
- * @param schema - JSON Schema 对象
2902
- * @param options - 导出选项
2903
- * @returns Markdown 字符串
2904
- */
2905
- export(schema: JSONSchema, options?: MarkdownExporterOptions): string;
2906
-
2907
- /**
2908
- * 静态导出方法
2909
- * @param schema - JSON Schema 对象
2910
- * @param options - 导出选项
2911
- * @returns Markdown 字符串
2912
- */
2913
- static export(schema: JSONSchema, options?: MarkdownExporterOptions): string;
2914
- }
2915
-
2916
- // ========== CustomKeywords 类 ==========
2917
-
2918
- /**
2919
- * 自定义关键字
2920
- *
2921
- * @description 扩展 ajv 的自定义验证关键字
2922
- *
2923
- * @example
2924
- * ```typescript
2925
- * // 添加自定义关键字通常通过 Validator 的 addKeyword 方法
2926
- * const validator = new Validator();
2927
- * const ajv = validator.getAjv();
2928
-
2929
- // ========== dsl.config 选项 ==========
2930
-
2931
- /**
2932
- * i18n 配置选项
2933
- *
2934
- * @description 支持三种配置方式(v1.2.3 新增 localesPath 对象形态 + 递归子目录)
2935
- *
2936
- * @example
2937
- * ```typescript
2938
- * // 方式1: 直接传字符串路径(支持递归子目录,v1.2.3+)
2939
- * dsl.config({
2940
- * i18n: './locales'
2941
- * });
2942
- *
2943
- * // 方式2: 传入语言包对象
2944
- * dsl.config({
2945
- * i18n: {
2946
- * 'zh-CN': { required: '必填' },
2947
- * 'en-US': { required: 'Required' }
2948
- * }
2949
- * });
2950
- *
2951
- * // 方式3: 含 localesPath 的对象(v1.2.3 修复真正生效)
2952
- * dsl.config({
2953
- * i18n: { localesPath: './i18n/labels' }
2954
- * });
2955
- * ```
2956
- */
2957
- export type I18nConfig =
2958
- | string
2959
- | Record<string, ErrorMessages>
2960
- | { localesPath: string };
2961
-
2962
- /**
2963
- * 缓存配置选项(v2.3.0+)
2964
- */
2965
- export interface CacheConfig {
2966
- /** 最大缓存条目数 */
2967
- maxSize?: number;
2968
- /** 缓存过期时间(毫秒) */
2969
- ttl?: number;
2970
- }
2971
-
2972
- /**
2973
- * dsl.config() 配置选项(v2.3.0+)
2974
- *
2975
- * @description 全局配置选项,包括多语言和缓存设置
2976
- *
2977
- * @example
2978
- * ```typescript
2979
- * // 配置多语言
2980
- * dsl.config({
2981
- * i18n: {
2982
- * locales: {
2983
- * 'zh-CN': { 'username': '用户名' },
2984
- * 'en-US': { 'username': 'Username' }
2985
- * }
2986
- * }
2987
- * });
2988
- *
2989
- * // 配置缓存
2990
- * dsl.config({
2991
- * cache: {
2992
- * maxSize: 5000,
2993
- * ttl: 60000
2994
- * }
2995
- * });
2996
- *
2997
- * // 同时配置多个选项
2998
- * dsl.config({
2999
- * i18n: { locales: {...} },
3000
- * cache: { maxSize: 5000 },
3001
- * patterns: {
3002
- * phone: { cn: /^1[3-9]\d{9}$/ }
3003
- * }
3004
- * });
3005
- * ```
3006
- */
3007
- export interface DslConfigOptions {
3008
- /** i18n 配置 */
3009
- i18n?: I18nConfig;
3010
- /** 缓存配置 */
3011
- cache?: CacheConfig;
3012
- /** 自定义验证规则扩展 */
3013
- patterns?: {
3014
- /** 手机号验证规则 */
3015
- phone?: Record<string, RegExp>;
3016
- /** 身份证验证规则 */
3017
- idCard?: Record<string, RegExp>;
3018
- /** 信用卡验证规则 */
3019
- creditCard?: Record<string, RegExp>;
3020
- };
3021
- /** 向后兼容:手机号验证规则(推荐使用 patterns.phone) */
3022
- phone?: Record<string, RegExp>;
3023
- }
3024
-
3025
- // ========== exporters 对象 ==========
3026
-
3027
- /**
3028
- * 导出器集合
3029
- *
3030
- * @description 包含所有导出器的对象
3031
- *
3032
- * @example
3033
- * ```typescript
3034
- * import { exporters } from 'schema-dsl';
3035
- *
3036
- * // 使用 MongoDB 导出器
3037
- * const mongoSchema = exporters.MongoDBExporter.export(schema);
3038
- *
3039
- * // 使用 MySQL 导出器
3040
- * const mysqlDDL = new exporters.MySQLExporter().export(schema, { tableName: 'users' });
3041
- * ```
3042
- */
3043
- export const exporters: {
3044
- MongoDBExporter: typeof MongoDBExporter;
3045
- MySQLExporter: typeof MySQLExporter;
3046
- PostgreSQLExporter: typeof PostgreSQLExporter;
3047
- MarkdownExporter: typeof MarkdownExporter;
3048
- };
3049
-
3050
- // ========== String 扩展控制 ==========
3051
-
3052
- /**
3053
- * 安装 String 扩展
3054
- *
3055
- * @description 将DSL方法添加到String.prototype,使字符串支持链式调用
3056
- *
3057
- * @example
3058
- * ```typescript
3059
- * import { installStringExtensions } from 'schema-dsl';
3060
- *
3061
- * // 安装扩展
3062
- * installStringExtensions();
3063
- *
3064
- * // 现在可以在字符串上使用DSL方法
3065
- * const schema = dsl({
3066
- * email: 'email!'.label('邮箱地址').messages({ required: '必填' })
3067
- * });
3068
- * ```
3069
- */
3070
- export function installStringExtensions(): void;
3071
-
3072
- /**
3073
- * 卸载 String 扩展
3074
- *
3075
- * @description 从String.prototype移除DSL方法
3076
- *
3077
- * @example
3078
- * ```typescript
3079
- * import { uninstallStringExtensions } from 'schema-dsl';
3080
- *
3081
- * // 卸载扩展
3082
- * uninstallStringExtensions();
3083
- *
3084
- * // 字符串不再支持DSL方法
3085
- * ```
3086
- */
3087
- export function uninstallStringExtensions(): void;
3088
-
3089
- // ========== 默认导出 ==========
3090
-
3091
- // ========== 验证器扩展 ==========
3092
-
3093
- /**
3094
- * 自定义关键字
3095
- *
3096
- * @description 扩展ajv的自定义验证关键字
3097
- *
3098
- * @example
3099
- * ```typescript
3100
- * import { CustomKeywords, Validator } from 'schema-dsl';
3101
- *
3102
- * const validator = new Validator();
3103
- * const ajv = validator.getAjv();
3104
- * CustomKeywords.registerAll(ajv);
3105
- * ```
3106
- */
3107
- export const CustomKeywords: {
3108
- /**
3109
- * 注册所有自定义关键字到ajv实例
3110
- * @param ajv - ajv实例
3111
- */
3112
- registerAll(ajv: any): void;
3113
-
3114
- /**
3115
- * 注册元数据关键字
3116
- * @param ajv - ajv实例
3117
- */
3118
- registerMetadataKeywords(ajv: any): void;
3119
-
3120
- /**
3121
- * 注册字符串验证器
3122
- * @param ajv - ajv实例
3123
- */
3124
- registerStringValidators(ajv: any): void;
3125
-
3126
- /**
3127
- * 注册数字验证器
3128
- * @param ajv - ajv实例
3129
- */
3130
- registerNumberValidators(ajv: any): void;
3131
-
3132
- /**
3133
- * 注册对象验证器
3134
- * @param ajv - ajv实例
3135
- */
3136
- registerObjectValidators(ajv: any): void;
3137
-
3138
- /**
3139
- * 注册数组验证器
3140
- * @param ajv - ajv实例
3141
- */
3142
- registerArrayValidators(ajv: any): void;
3143
-
3144
- /**
3145
- * 注册日期验证器
3146
- * @param ajv - ajv实例
3147
- */
3148
- registerDateValidators(ajv: any): void;
3149
- };
3150
-
3151
- // ========== 常量 ==========
3152
-
3153
- /**
3154
- * SchemaIO 配置常量
3155
- *
3156
- * @description 所有魔法数字和配置项的统一定义
3157
- *
3158
- * @example
3159
- * ```typescript
3160
- * import { CONSTANTS } from 'schema-dsl';
3161
- *
3162
- * console.log(CONSTANTS.VALIDATION.MAX_RECURSION_DEPTH); // 100
3163
- * console.log(CONSTANTS.CACHE.SCHEMA_CACHE.MAX_SIZE); // 5000
3164
- * ```
3165
- */
3166
- export const CONSTANTS: {
3167
- /** 验证配置 */
3168
- VALIDATION: {
3169
- /** 递归深度限制 */
3170
- MAX_RECURSION_DEPTH: number;
3171
- /** 数组大小限制 */
3172
- MAX_ARRAY_SIZE: number;
3173
- /** 字符串长度限制 */
3174
- MAX_STRING_LENGTH: number;
3175
- /** 对象属性数量限制 */
3176
- MAX_OBJECT_KEYS: number;
3177
- /** 验证超时时间(ms) */
3178
- DEFAULT_TIMEOUT: number;
3179
- /** 正则表达式超时(ms) */
3180
- REGEX_TIMEOUT: number;
3181
- /** 自定义验证函数超时(ms) */
3182
- CUSTOM_VALIDATOR_TIMEOUT: number;
3183
- /** 默认选项 */
3184
- DEFAULT_OPTIONS: {
3185
- abortEarly: boolean;
3186
- stripUnknown: boolean;
3187
- convert: boolean;
3188
- presence: string;
3189
- allowUnknown: boolean;
3190
- skipFunctions: boolean;
3191
- };
3192
- };
3193
- /** 缓存配置 */
3194
- CACHE: {
3195
- /** 缓存开关 */
3196
- ENABLED: boolean;
3197
- /** Schema编译缓存 */
3198
- SCHEMA_CACHE: {
3199
- /** 最大缓存条目 */
3200
- MAX_SIZE: number;
3201
- /** 缓存过期时间(ms) */
3202
- TTL: number;
3203
- };
3204
- };
3205
- /** 格式配置 */
3206
- FORMAT: Record<string, any>;
3207
- /** 类型配置 */
3208
- TYPES: Record<string, any>;
3209
- /** 错误配置 */
3210
- ERRORS: Record<string, any>;
3211
- };
3212
-
3213
- /**
3214
- * 版本信息
3215
- *
3216
- * @description 当前schema-dsl版本号
3217
- *
3218
- * @example
3219
- * ```typescript
3220
- * import { VERSION } from 'schema-dsl';
3221
- *
3222
- * console.log(`schema-dsl version: ${VERSION}`); // schema-dsl version: 1.0.4
3223
- * ```
3224
- */
3225
- export const VERSION: string;
3226
-
3227
- /**
3228
- * 链式条件构建器
3229
- *
3230
- * @description 提供流畅的条件判断 API,类似 JavaScript if-else 语句
3231
- *
3232
- * @example
3233
- * ```typescript
3234
- * import { dsl } from 'schema-dsl';
3235
- *
3236
- * // 简单条件 + 错误消息
3237
- * const schema = dsl({
3238
- * email: dsl.if((data) => data.age >= 18)
3239
- * .message('未成年用户不能注册')
3240
- * });
3241
- *
3242
- * // 多条件 and
3243
- * const schema2 = dsl({
3244
- * email: dsl.if((data) => data.age >= 18)
3245
- * .and((data) => data.userType === 'admin')
3246
- * .then('email!')
3247
- * });
3248
- *
3249
- * // 多条件 or
3250
- * const schema3 = dsl({
3251
- * status: dsl.if((data) => data.age < 18)
3252
- * .or((data) => data.isBlocked)
3253
- * .message('不允许注册')
3254
- * });
3255
- * ```
3256
- *
3257
- * @internal
3258
- * 注意:此类不应直接导入使用。请通过 dsl.if() 或 dsl['if']() 返回实例。
3259
- *
3260
- * @example 正确用法
3261
- * ```typescript
3262
- * import { dsl } from 'schema-dsl';
3263
- *
3264
- * // TypeScript
3265
- * const builder = dsl['if'](d => d.age > 18);
3266
- * // 或
3267
- * const builder2 = dsl._if(d => d.age > 18);
3268
- *
3269
- * // JavaScript
3270
- * const builder3 = dsl.if(d => d.age > 18);
3271
- * ```
3272
- */
3273
- export class ConditionalBuilder {
3274
- /**
3275
- * 开始条件判断
3276
- * @param condition - 条件函数,接收完整数据对象
3277
- * @returns 当前实例(支持链式调用)
3278
- */
3279
- if(condition: (data: any) => boolean): this;
3280
-
3281
- /**
3282
- * 添加 AND 条件(与前一个条件组合)
3283
- *
3284
- * @version 1.1.1 支持为每个 .and() 条件设置独立的错误消息
3285
- *
3286
- * @param condition - 条件函数
3287
- * @returns 当前实例(支持链式调用)
3288
- *
3289
- * @example 基础用法(传统 AND 逻辑)
3290
- * ```typescript
3291
- * // 所有条件都为 true 才失败
3292
- * dsl.if(d => d.age >= 18)
3293
- * .and(d => d.userType === 'admin')
3294
- * .then('email!')
3295
- * ```
3296
- *
3297
- * @example v1.1.0+ 独立消息(推荐)
3298
- * ```typescript
3299
- * // 每个条件都有自己的错误消息
3300
- * dsl.if(d => !d)
3301
- * .message('ACCOUNT_NOT_FOUND')
3302
- * .and(d => d.balance < 100)
3303
- * .message('INSUFFICIENT_BALANCE')
3304
- * .assert(account);
3305
- *
3306
- * // 工作原理:链式检查模式
3307
- * // - 第一个条件失败 → 返回 'ACCOUNT_NOT_FOUND'
3308
- * // - 第二个条件失败 → 返回 'INSUFFICIENT_BALANCE'
3309
- * // - 所有条件通过 → 验证成功
3310
- * ```
3311
- *
3312
- * @example 多个 .and() 条件
3313
- * ```typescript
3314
- * dsl.if(d => !d)
3315
- * .message('NOT_FOUND')
3316
- * .and(d => d.status !== 'active')
3317
- * .message('INACTIVE')
3318
- * .and(d => d.balance < 100)
3319
- * .message('INSUFFICIENT')
3320
- * .assert(account);
3321
- * // 依次检查,第一个失败的返回其消息
3322
- * ```
3323
- */
3324
- and(condition: (data: any) => boolean): this;
3325
-
3326
- /**
3327
- * 添加 OR 条件(与前一个条件组合)
3328
- *
3329
- * @version 1.1.1 支持为 .or() 条件设置独立的错误消息
3330
- *
3331
- * @param condition - 条件函数
3332
- * @returns 当前实例(支持链式调用)
3333
- *
3334
- * @example 基础用法
3335
- * ```typescript
3336
- * // 任一条件为 true 就失败
3337
- * dsl.if((data) => data.age < 18)
3338
- * .or((data) => data.isBlocked)
3339
- * .message('不允许注册')
3340
- * ```
3341
- *
3342
- * @example v1.1.0+ 独立消息
3343
- * ```typescript
3344
- * dsl.if(d => d.age < 18)
3345
- * .message('未成年用户不能注册')
3346
- * .or(d => d.isBlocked)
3347
- * .message('账户已被封禁')
3348
- * .assert(data);
3349
- * // 哪个条件为 true 就返回哪个消息
3350
- * ```
3351
- */
3352
- or(condition: (data: any) => boolean): this;
3353
-
3354
- /**
3355
- * 添加 else-if 分支
3356
- * @param condition - 条件函数
3357
- * @returns 当前实例(支持链式调用)
3358
- */
3359
- elseIf(condition: (data: any) => boolean): this;
3360
-
3361
- /**
3362
- * 设置错误消息(支持多语言 key)
3363
- *
3364
- * @version 1.1.1 支持为 .and() 和 .or() 条件设置独立消息
3365
- *
3366
- * 条件为 true 时自动抛出此错误
3367
- *
3368
- * @param msg - 错误消息或多语言 key
3369
- * @returns 当前实例(支持链式调用)
3370
- *
3371
- * @example 基础用法
3372
- * ```typescript
3373
- * // 如果是未成年人(条件为true),抛出错误
3374
- * dsl.if((data) => data.age < 18)
3375
- * .message('未成年用户不能注册')
3376
- * ```
3377
- *
3378
- * @example v1.1.0+ 为 .and() 设置独立消息
3379
- * ```typescript
3380
- * dsl.if((data) => !data)
3381
- * .message('账户不存在')
3382
- * .and((data) => data.balance < 100)
3383
- * .message('余额不足')
3384
- * .assert(account);
3385
- * // 每个条件都有自己的错误消息
3386
- * ```
3387
- *
3388
- * @example 链式检查模式说明
3389
- * ```typescript
3390
- * // 启用条件:
3391
- * // 1. 使用 .message() 模式(不是 .then()/.else())
3392
- * // 2. root 条件有 .message()
3393
- * // 3. 有 .and() 条件
3394
- * // 4. 没有 .or() 条件
3395
- *
3396
- * // ✅ 启用链式检查
3397
- * dsl.if(d => !d).message('A').and(d => d < 100).message('B')
3398
- *
3399
- * // ❌ 不启用(有 .or())
3400
- * dsl.if(d => !d).message('A').and(d => d < 100).or(d => d > 200).message('B')
3401
- * ```
3402
- */
3403
- message(msg: string): this;
3404
-
3405
- /**
3406
- * 设置满足条件时的 Schema
3407
- * @param schema - DSL 字符串或 Schema 对象
3408
- * @returns 当前实例(支持链式调用)
3409
- */
3410
- then(schema: string | DslBuilder | JSONSchema): this;
3411
-
3412
- /**
3413
- * 设置默认 Schema(所有条件都不满足时)
3414
- * 可选:不写 else 就是不验证
3415
- * @param schema - DSL 字符串、Schema 对象或 null
3416
- * @returns 当前实例(支持链式调用)
3417
- */
3418
- else(schema: string | DslBuilder | JSONSchema | null): this;
3419
-
3420
- /**
3421
- * 快捷验证方法 - 返回完整验证结果
3422
- * @param data - 待验证的数据(任意类型)
3423
- * @param options - 验证选项(可选)
3424
- * @returns 验证结果 { valid, errors, data }
3425
- *
3426
- * @example
3427
- * ```typescript
3428
- * // 一行代码验证
3429
- * const result = dsl.if(d => d.age < 18)
3430
- * .message('未成年')
3431
- * .validate({ age: 16 });
3432
- *
3433
- * // 复用验证器
3434
- * const validator = dsl.if(d => d.age < 18).message('未成年');
3435
- * const r1 = validator.validate({ age: 16 });
3436
- * const r2 = validator.validate({ age: 20 });
3437
- * ```
3438
- */
3439
- validate<T = any>(data: T, options?: ValidateOptions): ValidationResult<T>;
3440
-
3441
- /**
3442
- * 异步验证方法 - 失败自动抛出异常
3443
- * @param data - 待验证的数据
3444
- * @param options - 验证选项(可选)
3445
- * @returns 验证通过返回数据,失败抛出异常
3446
- * @throws ValidationError 验证失败抛出异常
3447
- *
3448
- * @example
3449
- * ```typescript
3450
- * // 异步验证,失败自动抛错
3451
- * try {
3452
- * const data = await dsl.if(d => d.age < 18)
3453
- * .message('未成年')
3454
- * .validateAsync({ age: 16 });
3455
- * } catch (error) {
3456
- * console.log(error.message);
3457
- * }
3458
- *
3459
- * // Express 中间件
3460
- * app.post('/register', async (req, res, next) => {
3461
- * try {
3462
- * await dsl.if(d => d.age < 18)
3463
- * .message('未成年用户不能注册')
3464
- * .validateAsync(req.body);
3465
- * // 验证通过,继续处理...
3466
- * } catch (error) {
3467
- * next(error);
3468
- * }
3469
- * });
3470
- * ```
3471
- */
3472
- validateAsync<T = any>(data: T, options?: ValidateOptions): Promise<T>;
3473
-
3474
- /**
3475
- * 断言方法 - 同步验证,失败直接抛错
3476
- * @param data - 待验证的数据
3477
- * @param options - 验证选项(可选)
3478
- * @returns 验证通过返回数据
3479
- * @throws Error 验证失败抛出错误
3480
- *
3481
- * @example
3482
- * ```typescript
3483
- * // 断言验证,失败直接抛错
3484
- * try {
3485
- * dsl.if(d => d.age < 18)
3486
- * .message('未成年')
3487
- * .assert({ age: 16 });
3488
- * } catch (error) {
3489
- * console.log(error.message);
3490
- * }
3491
- *
3492
- * // 函数中快速断言
3493
- * function registerUser(userData: any) {
3494
- * dsl.if(d => d.age < 18)
3495
- * .message('未成年用户不能注册')
3496
- * .assert(userData);
3497
- *
3498
- * // 验证通过,继续处理...
3499
- * return createUser(userData);
3500
- * }
3501
- * ```
3502
- */
3503
- assert<T = any>(data: T, options?: ValidateOptions): T;
3504
-
3505
- /**
3506
- * 快捷检查方法 - 只返回 boolean
3507
- * @param data - 待验证的数据
3508
- * @returns 验证是否通过
3509
- *
3510
- * @example
3511
- * ```typescript
3512
- * // 快速判断
3513
- * const isValid = dsl.if(d => d.age < 18)
3514
- * .message('未成年')
3515
- * .check({ age: 16 });
3516
- * // => false
3517
- *
3518
- * // 断言场景
3519
- * if (!validator.check(userData)) {
3520
- * console.log('验证失败');
3521
- * }
3522
- * ```
3523
- */
3524
- check(data: any): boolean;
3525
- }
3526
-
3527
- /**
3528
- * 默认导出(dsl函数)
3529
- *
3530
- * @example
3531
- * ```typescript
3532
- * import schema-dsl from 'schema-dsl';
3533
- *
3534
- * const schema = schema-dsl({
3535
- * username: 'string:3-32!',
3536
- * email: 'email!'
3537
- * });
3538
- * ```
3539
- */
3540
- export default dsl;