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