schema-dsl 1.2.4 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (242) hide show
  1. package/CHANGELOG.md +87 -210
  2. package/README.md +391 -2249
  3. package/dist/DslBuilder-DQDN0ZxZ.d.cts +341 -0
  4. package/dist/DslBuilder-DkLaOo9Q.d.ts +341 -0
  5. package/dist/Validator-C7GsVQOH.d.cts +192 -0
  6. package/dist/Validator-hFWKGxir.d.ts +192 -0
  7. package/dist/index.cjs +6594 -0
  8. package/dist/index.d.cts +1145 -0
  9. package/dist/index.d.ts +1145 -0
  10. package/dist/index.js +6528 -0
  11. package/dist/plugin-CIKtTMtS.d.cts +246 -0
  12. package/dist/plugin-CIKtTMtS.d.ts +246 -0
  13. package/dist/plugins/custom-format.cjs +3802 -0
  14. package/dist/plugins/custom-format.d.cts +12 -0
  15. package/dist/plugins/custom-format.d.ts +12 -0
  16. package/dist/plugins/custom-format.js +3772 -0
  17. package/dist/plugins/custom-type-example.cjs +3795 -0
  18. package/dist/plugins/custom-type-example.d.cts +8 -0
  19. package/dist/plugins/custom-type-example.d.ts +8 -0
  20. package/dist/plugins/custom-type-example.js +3765 -0
  21. package/dist/plugins/custom-validator.cjs +146 -0
  22. package/dist/plugins/custom-validator.d.cts +10 -0
  23. package/dist/plugins/custom-validator.d.ts +10 -0
  24. package/dist/plugins/custom-validator.js +121 -0
  25. package/docs/FEATURE-INDEX.md +102 -68
  26. package/docs/add-custom-locale.md +48 -35
  27. package/docs/add-keyword.md +24 -0
  28. package/docs/api-reference.md +396 -154
  29. package/docs/api.md +13 -0
  30. package/docs/best-practices-project-structure.md +19 -10
  31. package/docs/best-practices.md +93 -53
  32. package/docs/cache-manager.md +23 -15
  33. package/docs/compile.md +45 -0
  34. package/docs/conditional-api.md +40 -11
  35. package/docs/custom-extensions-guide.md +80 -152
  36. package/docs/design-philosophy.md +76 -71
  37. package/docs/doc-index.md +324 -0
  38. package/docs/dsl-syntax.md +69 -19
  39. package/docs/dynamic-locale.md +24 -14
  40. package/docs/enum.md +12 -5
  41. package/docs/error-handling.md +53 -44
  42. package/docs/export-guide.md +47 -8
  43. package/docs/export-limitations.md +27 -11
  44. package/docs/faq.md +86 -67
  45. package/docs/frontend-i18n-guide.md +26 -12
  46. package/docs/i18n-user-guide.md +60 -47
  47. package/docs/i18n.md +51 -32
  48. package/docs/index.md +48 -0
  49. package/docs/json-schema-basics.md +40 -0
  50. package/docs/label-vs-description.md +12 -3
  51. package/docs/markdown-exporter.md +15 -6
  52. package/docs/mongodb-exporter.md +11 -4
  53. package/docs/multi-language.md +26 -0
  54. package/docs/multi-type-support.md +26 -33
  55. package/docs/mysql-exporter.md +9 -2
  56. package/docs/number-operators.md +12 -5
  57. package/docs/optional-marker-guide.md +28 -23
  58. package/docs/performance-guide.md +49 -0
  59. package/docs/plugin-system.md +205 -366
  60. package/docs/plugin-type-registration.md +34 -0
  61. package/docs/postgresql-exporter.md +9 -2
  62. package/docs/public/favicon.svg +5 -0
  63. package/docs/quick-start.md +37 -363
  64. package/docs/runtime-locale-support.md +20 -9
  65. package/docs/schema-helper.md +10 -5
  66. package/docs/schema-utils-advanced-issues.md +23 -0
  67. package/docs/schema-utils-best-practices.md +20 -0
  68. package/docs/schema-utils-chaining.md +7 -0
  69. package/docs/schema-utils.md +76 -42
  70. package/docs/security-checklist.md +20 -0
  71. package/docs/string-extensions.md +17 -9
  72. package/docs/troubleshooting.md +36 -21
  73. package/docs/type-converter.md +41 -50
  74. package/docs/type-reference.md +38 -15
  75. package/docs/typescript-guide.md +53 -42
  76. package/docs/union-type-guide.md +11 -1
  77. package/docs/union-types.md +10 -3
  78. package/docs/validate-async.md +36 -25
  79. package/docs/validate-batch.md +49 -0
  80. package/docs/validate-dsl-object-support.md +33 -28
  81. package/docs/validate.md +36 -16
  82. package/docs/validation-guide.md +25 -7
  83. package/docs/validator.md +39 -0
  84. package/package.json +85 -27
  85. package/plugins/custom-format.cjs +8 -0
  86. package/plugins/custom-type-example.cjs +8 -0
  87. package/plugins/custom-validator.cjs +8 -0
  88. package/src/adapters/DslAdapter.ts +111 -0
  89. package/src/adapters/index.ts +1 -0
  90. package/src/config/constants.ts +83 -0
  91. package/src/config/index.ts +2 -0
  92. package/src/config/patterns.ts +77 -0
  93. package/src/core/CacheManager.ts +159 -0
  94. package/src/core/ConditionalBuilder.ts +382 -0
  95. package/src/core/ConditionalRuntime.ts +28 -0
  96. package/src/core/ConditionalValidator.ts +255 -0
  97. package/src/core/DslBuilder.ts +677 -0
  98. package/src/core/ErrorCodes.ts +38 -0
  99. package/src/core/ErrorFormatter.ts +271 -0
  100. package/src/core/JSONSchemaCore.ts +65 -0
  101. package/src/core/Locale.ts +187 -0
  102. package/src/core/MessageTemplate.ts +42 -0
  103. package/src/core/ObjectDslBuilder.ts +64 -0
  104. package/src/core/PluginManager.ts +326 -0
  105. package/src/core/StringExtensions.ts +140 -0
  106. package/src/core/TemplateEngine.ts +44 -0
  107. package/src/core/Validator.ts +448 -0
  108. package/src/errors/I18nError.ts +159 -0
  109. package/src/errors/ValidationError.ts +105 -0
  110. package/src/exporters/BaseExporter.ts +60 -0
  111. package/src/exporters/MarkdownExporter.ts +305 -0
  112. package/src/exporters/MongoDBExporter.ts +126 -0
  113. package/src/exporters/MySQLExporter.ts +155 -0
  114. package/src/exporters/PostgreSQLExporter.ts +222 -0
  115. package/src/exporters/index.ts +18 -0
  116. package/src/index.ts +633 -0
  117. package/{lib/locales/en-US.js → src/locales/en-US.ts} +21 -37
  118. package/{lib/locales/es-ES.js → src/locales/es-ES.ts} +63 -16
  119. package/{lib/locales/fr-FR.js → src/locales/fr-FR.ts} +74 -27
  120. package/src/locales/index.ts +103 -0
  121. package/{lib/locales/ja-JP.js → src/locales/ja-JP.ts} +59 -17
  122. package/src/locales/types.ts +156 -0
  123. package/{lib/locales/zh-CN.js → src/locales/zh-CN.ts} +21 -38
  124. package/src/parser/ConstraintParser.ts +101 -0
  125. package/src/parser/DslParser.ts +470 -0
  126. package/src/parser/SchemaCompiler.ts +66 -0
  127. package/src/parser/TypeRegistry.ts +250 -0
  128. package/src/parser/index.ts +6 -0
  129. package/src/plugins/custom-format.ts +126 -0
  130. package/src/plugins/custom-type-example.ts +108 -0
  131. package/src/plugins/custom-validator.ts +140 -0
  132. package/src/types/conditional.ts +28 -0
  133. package/src/types/config.ts +59 -0
  134. package/src/types/dsl.ts +131 -0
  135. package/src/types/error.ts +60 -0
  136. package/src/types/index.ts +17 -0
  137. package/src/types/infer.ts +128 -0
  138. package/src/types/plugin.ts +58 -0
  139. package/src/types/safe-regex.d.ts +9 -0
  140. package/src/types/schema.ts +66 -0
  141. package/src/types/validate.ts +71 -0
  142. package/src/utils/SchemaHelper.ts +196 -0
  143. package/src/utils/SchemaUtils.ts +346 -0
  144. package/src/utils/TypeConverter.ts +215 -0
  145. package/src/utils/index.ts +10 -0
  146. package/src/validators/CustomKeywords.ts +477 -0
  147. package/.eslintignore +0 -11
  148. package/.eslintrc.json +0 -27
  149. package/CONTRIBUTING.md +0 -368
  150. package/STATUS.md +0 -491
  151. package/changelogs/v1.0.0.md +0 -328
  152. package/changelogs/v1.0.9.md +0 -367
  153. package/changelogs/v1.1.0.md +0 -389
  154. package/changelogs/v1.1.1.md +0 -308
  155. package/changelogs/v1.1.2.md +0 -183
  156. package/changelogs/v1.1.3.md +0 -161
  157. package/changelogs/v1.1.4.md +0 -432
  158. package/changelogs/v1.1.5.md +0 -493
  159. package/changelogs/v1.1.6.md +0 -211
  160. package/changelogs/v1.1.8.md +0 -376
  161. package/changelogs/v1.2.3.md +0 -124
  162. package/docs/INDEX.md +0 -252
  163. package/docs/issues-resolved-summary.md +0 -196
  164. package/docs/performance-benchmark-report.md +0 -179
  165. package/docs/performance-quick-reference.md +0 -123
  166. package/docs/user-questions-answered.md +0 -353
  167. package/docs/validation-rules-v1.0.2.md +0 -1608
  168. package/examples/README.md +0 -81
  169. package/examples/array-dsl-example.js +0 -227
  170. package/examples/conditional-example.js +0 -288
  171. package/examples/conditional-non-object.js +0 -129
  172. package/examples/conditional-validate-example.js +0 -321
  173. package/examples/custom-extension.js +0 -85
  174. package/examples/dsl-match-example.js +0 -74
  175. package/examples/dsl-style.js +0 -118
  176. package/examples/dynamic-locale-configuration.js +0 -348
  177. package/examples/dynamic-locale-example.js +0 -287
  178. package/examples/enum.examples.js +0 -324
  179. package/examples/export-demo.js +0 -130
  180. package/examples/express-integration.js +0 -376
  181. package/examples/i18n-error-handling-complete.js +0 -381
  182. package/examples/i18n-error-handling-quickstart.md +0 -0
  183. package/examples/i18n-error.examples.js +0 -181
  184. package/examples/i18n-full-demo.js +0 -301
  185. package/examples/i18n-memory-safety.examples.js +0 -268
  186. package/examples/markdown-export.js +0 -71
  187. package/examples/middleware-usage.js +0 -93
  188. package/examples/new-features-comparison.js +0 -315
  189. package/examples/password-reset/README.md +0 -153
  190. package/examples/password-reset/schema.js +0 -26
  191. package/examples/password-reset/test.js +0 -101
  192. package/examples/plugin-system.examples.js +0 -205
  193. package/examples/schema-utils-chaining.examples.js +0 -250
  194. package/examples/simple-example.js +0 -122
  195. package/examples/slug.examples.js +0 -179
  196. package/examples/string-extensions.js +0 -297
  197. package/examples/union-type-example.js +0 -127
  198. package/examples/union-types-example.js +0 -77
  199. package/examples/user-registration/README.md +0 -156
  200. package/examples/user-registration/routes.js +0 -92
  201. package/examples/user-registration/schema.js +0 -150
  202. package/examples/user-registration/server.js +0 -74
  203. package/index.d.ts +0 -3540
  204. package/index.js +0 -457
  205. package/index.mjs +0 -60
  206. package/lib/adapters/DslAdapter.js +0 -871
  207. package/lib/adapters/index.js +0 -20
  208. package/lib/config/constants.js +0 -286
  209. package/lib/config/patterns/common.js +0 -47
  210. package/lib/config/patterns/creditCard.js +0 -9
  211. package/lib/config/patterns/idCard.js +0 -9
  212. package/lib/config/patterns/index.js +0 -9
  213. package/lib/config/patterns/licensePlate.js +0 -4
  214. package/lib/config/patterns/passport.js +0 -4
  215. package/lib/config/patterns/phone.js +0 -9
  216. package/lib/config/patterns/postalCode.js +0 -5
  217. package/lib/core/CacheManager.js +0 -376
  218. package/lib/core/ConditionalBuilder.js +0 -503
  219. package/lib/core/DslBuilder.js +0 -1400
  220. package/lib/core/ErrorCodes.js +0 -233
  221. package/lib/core/ErrorFormatter.js +0 -445
  222. package/lib/core/JSONSchemaCore.js +0 -347
  223. package/lib/core/Locale.js +0 -130
  224. package/lib/core/MessageTemplate.js +0 -98
  225. package/lib/core/PluginManager.js +0 -448
  226. package/lib/core/StringExtensions.js +0 -240
  227. package/lib/core/Validator.js +0 -654
  228. package/lib/errors/I18nError.js +0 -328
  229. package/lib/errors/ValidationError.js +0 -191
  230. package/lib/exporters/MarkdownExporter.js +0 -420
  231. package/lib/exporters/MongoDBExporter.js +0 -162
  232. package/lib/exporters/MySQLExporter.js +0 -212
  233. package/lib/exporters/PostgreSQLExporter.js +0 -289
  234. package/lib/exporters/index.js +0 -24
  235. package/lib/locales/index.js +0 -8
  236. package/lib/utils/LRUCache.js +0 -174
  237. package/lib/utils/SchemaHelper.js +0 -240
  238. package/lib/utils/SchemaUtils.js +0 -445
  239. package/lib/utils/TypeConverter.js +0 -245
  240. package/lib/utils/index.js +0 -13
  241. package/lib/validators/CustomKeywords.js +0 -616
  242. package/lib/validators/index.js +0 -11
@@ -1,6 +1,6 @@
1
1
  # TypeConverter 类型转换工具
2
2
 
3
- > **模块**: `lib/utils/TypeConverter.js`
3
+ > **模块**: `src/utils/TypeConverter.ts`
4
4
 
5
5
  > **用途**: 提供 JSON Schema 与各种数据库类型之间的转换
6
6
 
@@ -34,7 +34,7 @@
34
34
  ## 快速开始
35
35
 
36
36
  ```javascript
37
- const { TypeConverter } = require('schema-dsl/lib/utils');
37
+ const { TypeConverter } = require('schema-dsl');
38
38
 
39
39
  // JSON Schema 类型转 MongoDB 类型
40
40
  const mongoType = TypeConverter.toMongoDBType('integer');
@@ -45,40 +45,29 @@ const mysqlType = TypeConverter.toMySQLType('string', { maxLength: 100 });
45
45
  console.log(mysqlType); // 'VARCHAR(100)'
46
46
 
47
47
  // JSON Schema 类型转 PostgreSQL 类型
48
- const pgType = TypeConverter.toPostgreSQLType('string', { format: 'uuid' });
49
- console.log(pgType); // 'UUID'
48
+ const pgType = TypeConverter.toPostgreSQLType('string', { format: 'date-time' });
49
+ console.log(pgType); // 'TIMESTAMP'
50
50
  ```
51
51
 
52
52
  ---
53
53
 
54
54
  ## API 参考
55
55
 
56
- ### `toJSONSchemaType(simpleType)`
56
+ ### `toJSONSchemaType(nativeType)`
57
57
 
58
- 将简单类型字符串转换为 JSON Schema 类型对象。
58
+ 将类型标识转换为 JSON Schema 的 `type` 字符串。
59
59
 
60
60
  ```javascript
61
61
  TypeConverter.toJSONSchemaType('string');
62
- // { type: 'string' }
62
+ // 'string'
63
63
 
64
- TypeConverter.toJSONSchemaType('int');
65
- // { type: 'integer' }
64
+ TypeConverter.toJSONSchemaType('integer');
65
+ // 'integer'
66
66
 
67
- TypeConverter.toJSONSchemaType('bool');
68
- // { type: 'boolean' }
67
+ TypeConverter.toJSONSchemaType('email');
68
+ // 'string'
69
69
  ```
70
70
 
71
- **支持的别名**:
72
-
73
- | 完整类型 | 别名 |
74
- |---------|------|
75
- | `string` | `str`, `s` |
76
- | `number` | `num`, `n` |
77
- | `integer` | `int`, `i` |
78
- | `boolean` | `bool`, `b` |
79
- | `object` | `obj`, `o` |
80
- | `array` | `arr`, `a` |
81
-
82
71
  ---
83
72
 
84
73
  ### `toMongoDBType(jsonSchemaType)`
@@ -94,7 +83,7 @@ TypeConverter.toMongoDBType('boolean'); // 'bool'
94
83
 
95
84
  ---
96
85
 
97
- ### `toMySQLType(jsonSchemaType, constraints)`
86
+ ### `toMySQLType(jsonSchemaType, schemaFragment)`
98
87
 
99
88
  JSON Schema 类型转 MySQL 数据类型。
100
89
 
@@ -115,21 +104,21 @@ TypeConverter.toMySQLType('string', { maxLength: 500 });
115
104
  TypeConverter.toMySQLType('string', { format: 'email' });
116
105
  // 'VARCHAR(255)'
117
106
 
118
- // 整数范围
119
- TypeConverter.toMySQLType('integer', { maximum: 100 });
107
+ // 整数范围(minimum + maximum 命中 TINYINT 分支)
108
+ TypeConverter.toMySQLType('integer', { minimum: 0, maximum: 100 });
120
109
  // 'TINYINT'
121
110
  ```
122
111
 
123
112
  ---
124
113
 
125
- ### `toPostgreSQLType(jsonSchemaType, constraints)`
114
+ ### `toPostgreSQLType(jsonSchemaType, schemaFragment)`
126
115
 
127
116
  JSON Schema 类型转 PostgreSQL 数据类型。
128
117
 
129
118
  ```javascript
130
119
  // UUID 格式
131
120
  TypeConverter.toPostgreSQLType('string', { format: 'uuid' });
132
- // 'UUID'
121
+ // 'VARCHAR(255)' // 当前实现不会因 format=uuid 自动切换到 UUID 列类型
133
122
 
134
123
  // 日期时间
135
124
  TypeConverter.toPostgreSQLType('string', { format: 'date-time' });
@@ -142,34 +131,35 @@ TypeConverter.toPostgreSQLType('object');
142
131
 
143
132
  ---
144
133
 
145
- ### `normalizePropertyName(name, style)`
134
+ ### `normalizePropertyName(name)`
146
135
 
147
- 规范化属性名,转换命名风格。
136
+ 规范化属性名:去除首尾空白、将非法字符替换为下划线,并压缩连续下划线。
148
137
 
149
138
  ```javascript
150
- // camelCase 转 snake_case
151
- TypeConverter.normalizePropertyName('userName', 'snake_case');
139
+ TypeConverter.normalizePropertyName('user name');
152
140
  // 'user_name'
153
141
 
154
- TypeConverter.normalizePropertyName('createdAt', 'snake_case');
155
- // 'created_at'
142
+ TypeConverter.normalizePropertyName('123created-at');
143
+ // '123created_at'
156
144
  ```
157
145
 
158
146
  ---
159
147
 
160
148
  ### `formatToRegex(format)`
161
149
 
162
- 获取格式对应的正则表达式。
150
+ 获取格式对应的 `RegExp` 实例;未知格式返回 `null`。
163
151
 
164
152
  ```javascript
165
- TypeConverter.formatToRegex('email');
166
- // '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$'
153
+ const emailRegex = TypeConverter.formatToRegex('email');
154
+ emailRegex?.test('user@example.com');
155
+ // true
167
156
 
168
- TypeConverter.formatToRegex('uuid');
169
- // '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$'
157
+ const uuidRegex = TypeConverter.formatToRegex('uuid');
158
+ uuidRegex?.test('123e4567-e89b-12d3-a456-426614174000');
159
+ // true
170
160
 
171
- TypeConverter.formatToRegex('ipv4');
172
- // IPv4 正则表达式
161
+ TypeConverter.formatToRegex('unknown');
162
+ // null
173
163
  ```
174
164
 
175
165
  ---
@@ -217,12 +207,8 @@ const constraints = TypeConverter.extractConstraints(schema);
217
207
  // {
218
208
  // minLength: 3,
219
209
  // maxLength: 32,
220
- // minimum: undefined,
221
- // maximum: undefined,
222
210
  // pattern: '^[a-z]+$',
223
- // format: 'email',
224
- // enum: undefined,
225
- // default: undefined
211
+ // format: 'email'
226
212
  // }
227
213
  ```
228
214
 
@@ -251,7 +237,7 @@ const constraints = TypeConverter.extractConstraints(schema);
251
237
  | `string` | `maxLength: 500` | `TEXT` |
252
238
  | `string` | `format: email` | `VARCHAR(255)` |
253
239
  | `string` | `format: date-time` | `DATETIME` |
254
- | `integer` | `maximum: 127` | `TINYINT` |
240
+ | `integer` | `minimum: 0, maximum: 100` | `TINYINT` |
255
241
  | `integer` | `maximum: 32767` | `SMALLINT` |
256
242
  | `integer` | `maximum: 2147483647` | `INT` |
257
243
  | `integer` | - | `BIGINT` |
@@ -267,11 +253,9 @@ const constraints = TypeConverter.extractConstraints(schema);
267
253
  | `string` | - | `VARCHAR(255)` |
268
254
  | `string` | `maxLength: 50` | `VARCHAR(50)` |
269
255
  | `string` | `maxLength: 500` | `TEXT` |
270
- | `string` | `format: uuid` | `UUID` |
256
+ | `string` | `format: uuid` | `VARCHAR(255)` |
271
257
  | `string` | `format: date` | `DATE` |
272
258
  | `string` | `format: date-time` | `TIMESTAMP` |
273
- | `integer` | `maximum: 32767` | `SMALLINT` |
274
- | `integer` | `maximum: 2147483647` | `INTEGER` |
275
259
  | `integer` | - | `BIGINT` |
276
260
  | `number` | - | `DOUBLE PRECISION` |
277
261
  | `boolean` | - | `BOOLEAN` |
@@ -285,7 +269,7 @@ const constraints = TypeConverter.extractConstraints(schema);
285
269
  ### 批量类型转换
286
270
 
287
271
  ```javascript
288
- const { TypeConverter } = require('schema-dsl/lib/utils');
272
+ const { TypeConverter } = require('schema-dsl');
289
273
 
290
274
  const fields = ['string', 'number', 'integer', 'boolean', 'object', 'array'];
291
275
 
@@ -317,3 +301,10 @@ console.log(regex.test('invalid-email')); // false
317
301
  - [MySQL 导出器](mysql-exporter.md)
318
302
  - [PostgreSQL 导出器](postgresql-exporter.md)
319
303
 
304
+ ---
305
+
306
+ ## 对应示例文件
307
+
308
+ **示例入口**: [type-converter.ts](https://github.com/vextjs/schema-dsl/blob/main/examples/docs/type-converter.ts)
309
+ **说明**: 覆盖类型映射、枚举到 MySQL `ENUM(...)`、PostgreSQL 实际 UUID 映射、属性名规范化、正则获取、Schema 合并和约束提取。
310
+
@@ -1,6 +1,6 @@
1
- # schema-dsl 完整类型列表
1
+ # schema-dsl 类型参考
2
2
 
3
- > **更新时间**: 2025-12-25
3
+ > **更新时间**: 2026-05-08
4
4
 
5
5
  ---
6
6
 
@@ -8,7 +8,7 @@
8
8
 
9
9
  ### 基本类型
10
10
 
11
- | 类型 | SchemaI-DSL | JSON Schema | 说明 |
11
+ | 类型 | schema-dsl DSL | JSON Schema | 说明 |
12
12
  |------|----------|-------------|------|
13
13
  | 字符串 | `string` | `{ type: 'string' }` | 文本类型 |
14
14
  | 数字 | `number` | `{ type: 'number' }` | 浮点数 |
@@ -23,14 +23,17 @@
23
23
 
24
24
  ### 格式类型(基于 string)
25
25
 
26
- | 类型 | SchemaI-DSL | JSON Schema format | 说明 |
26
+ | 类型 | schema-dsl DSL | JSON Schema format | 说明 |
27
27
  |------|----------|-------------------|------|
28
28
  | 邮箱 | `email` | `email` | 邮箱地址 |
29
29
  | URL | `url` | `uri` | 网址 |
30
+ | URI | `uri` | `uri` | URI 字符串 |
30
31
  | UUID | `uuid` | `uuid` | UUID格式 |
32
+ | IP(IPv4/IPv6) | `ip` | `anyOf(ipv4, ipv6)` | 双栈 IP |
31
33
  | 日期 | `date` | `date` | YYYY-MM-DD |
32
34
  | 日期时间 | `datetime` | `date-time` | ISO 8601 |
33
35
  | 时间 | `time` | `time` | HH:mm:ss |
36
+ | 主机名 | `hostname` | `hostname` | 主机名 |
34
37
  | IPv4 | `ipv4` | `ipv4` | IPv4地址 |
35
38
  | IPv6 | `ipv6` | `ipv6` | IPv6地址 |
36
39
 
@@ -38,13 +41,22 @@
38
41
 
39
42
  ### 特殊类型
40
43
 
41
- | 类型 | SchemaI-DSL | JSON Schema | 说明 |
44
+ | 类型 | schema-dsl DSL | JSON Schema | 说明 |
42
45
  |------|----------|-------------|------|
43
46
  | 二进制 | `binary` | `contentEncoding: base64` | Base64编码 |
44
47
  | ObjectId | `objectId` | `pattern: ^[0-9a-fA-F]{24}$` | MongoDB ObjectId |
45
48
  | HexColor | `hexColor` | `pattern: ^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$` | CSS 16进制颜色 |
46
49
  | MAC地址 | `macAddress` | `pattern: ^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$` | MAC地址 |
47
50
  | Cron | `cron` | `pattern: ...` | Cron表达式 |
51
+ | Slug | `slug` | `pattern: ^[a-z0-9]+(?:-[a-z0-9]+)*$` | URL Slug |
52
+ | 中文姓名 | `chineseName` | `pattern: ^[\u4e00-\u9fa5]{2,10}$` | 中文姓名 |
53
+ | 中文文本 | `chinese` | `pattern: ^[\u4e00-\u9fa5]+$` | 纯中文文本 |
54
+ | 邮箱域扩展 | `emailDomain` | `format: email` | 邮箱 + 域名扩展校验 |
55
+ | 只含字母数字 | `alphanum` | `alphanum: true` | 自定义 AJV keyword |
56
+ | 小写字符串 | `lower` | `lowercase: true` | 自定义 AJV keyword |
57
+ | 大写字符串 | `upper` | `uppercase: true` | 自定义 AJV keyword |
58
+ | JSON字符串 | `json` | `jsonString: true` | 自定义 AJV keyword |
59
+ | 端口号 | `port` | `port: true` | 整数端口号 |
48
60
 
49
61
  ---
50
62
 
@@ -87,14 +99,14 @@ const schema8 = dsl({ data: 'any' });
87
99
 
88
100
  ---
89
101
 
90
- ### 扩展验证类型
102
+ ### 参数化 DSL 类型
91
103
 
92
104
  ```javascript
93
- // 手机号
105
+ // 手机号(默认 cn)
94
106
  const schema1 = dsl({ mobile: 'phone:cn!' });
95
107
 
96
108
  // 身份证
97
- const schema2 = dsl({ id_card: 'idCard:cn!' });
109
+ const schema2 = dsl({ idCard: 'idCard:cn!' });
98
110
 
99
111
  // 信用卡
100
112
  const schema3 = dsl({ card: 'creditCard:visa!' });
@@ -106,7 +118,7 @@ const schema4 = dsl({ plate: 'licensePlate:cn!' });
106
118
  const schema5 = dsl({ zip: 'postalCode:cn!' });
107
119
 
108
120
  // 护照
109
- const schema6 = dsl({ passport: 'passport:cn!' });
121
+ const schema6 = dsl({ passportNo: 'passport:cn!' });
110
122
  ```
111
123
 
112
124
  ---
@@ -156,7 +168,7 @@ const schema = dsl({
156
168
 
157
169
  ### 完整对照表
158
170
 
159
- | joi | SchemaI-DSL | 说明 |
171
+ | joi | schema-dsl DSL | 说明 |
160
172
  |-----|--------------|------|
161
173
  | `Joi.string()` | `'string'` | 字符串 |
162
174
  | `Joi.string().email()` | `'email'` | 邮箱 |
@@ -190,23 +202,27 @@ const schema = dsl({
190
202
 
191
203
  ## ❓ 常见问题
192
204
 
193
- ### Q1: 为什么没有 `Joi.alternatives()` 对应?
205
+ ### Q1: 为什么没有直接叫 `Joi.alternatives()` 的 API?
194
206
 
195
- A: 使用条件验证 `dsl.match()` 实现:
207
+ A: schema-dsl 把这类需求拆成两类:
208
+
209
+ - 单字段跨类型联合: 使用 `types:` 语法
210
+ - 根据其他字段做条件分支: 使用 `dsl.match()`
196
211
 
197
212
  ```javascript
198
213
  const schema = dsl({
214
+ value: 'types:string|number',
199
215
  contactType: 'email|phone',
200
216
  contact: dsl.match('contactType', {
201
217
  email: 'email!',
202
- phone: 'string:11!'
218
+ phone: 'phone:cn!'
203
219
  })
204
220
  });
205
221
  ```
206
222
 
207
223
  ### Q2: 为什么 `integer` 不是 `number().integer()`?
208
224
 
209
- A: SchemaI-DSL 使用 JSON Schema 标准,`integer` 是独立类型。
225
+ A: schema-dsl 使用 JSON Schema 标准,`integer` 是独立类型。
210
226
 
211
227
  ### Q3: 不支持简写吗?
212
228
 
@@ -214,6 +230,13 @@ A: 不支持 `s`/`n`/`i`/`b` 等简写,统一使用完整类型名(`string`/
214
230
 
215
231
  ---
216
232
 
217
- **最后更新**: 2025-12-25
233
+ **最后更新**: 2026-05-08
234
+
235
+ ---
236
+
237
+ ## 对应示例文件
238
+
239
+ **示例入口**: [type-reference.ts](https://github.com/vextjs/schema-dsl/blob/main/examples/docs/type-reference.ts)
240
+ **说明**: 用一份 schema 串起常用内置类型、参数化 DSL 类型和运行时错误路径,方便快速核对实际支持范围。
218
241
 
219
242
 
@@ -1,7 +1,7 @@
1
1
  # TypeScript 使用指南
2
2
 
3
- > **版本**: schema-dsl v1.0.6+
4
- > **更新日期**: 2026-01-04
3
+ > **版本**: schema-dsl v2.0.0-beta.2
4
+ > **更新日期**: 2026-05-08
5
5
  > **重要**: v1.0.6 移除了全局 String 类型扩展以避免类型污染
6
6
 
7
7
  ---
@@ -106,7 +106,10 @@ const emailBuilder = dsl('email!');
106
106
  emailBuilder.label('邮箱')
107
107
  // ^? IDE 自动提示所有可用方法
108
108
  .pattern(/^[a-z]+@[a-z]+\.[a-z]+$/)
109
- .messages({ required: '邮箱必填' });
109
+ .error({ required: '邮箱必填' });
110
+
111
+ > ℹ️ 当前类型声明优先覆盖稳定链式 API,例如 `label()`、`pattern()`、`error()`、`default()`。
112
+ > 某些运行时扩展方法依然可用,但如果类型声明未暴露,建议在 TypeScript 代码里优先改写为上述稳定组合。
110
113
  ```
111
114
 
112
115
  ---
@@ -128,12 +131,13 @@ emailBuilder.label('邮箱')
128
131
  ```typescript
129
132
  const schema = dsl({
130
133
  username: dsl('string:3-32!')
131
- .pattern(/^[a-zA-Z0-9_]+$/, '只能包含字母、数字和下划线')
134
+ .pattern(/^[a-zA-Z0-9_]+$/)
132
135
  .label('用户名'),
136
+ .error({ pattern: '只能包含字母、数字和下划线' }),
133
137
 
134
138
  email: dsl('email!')
135
139
  .label('邮箱地址')
136
- .messages({ required: '邮箱必填' }),
140
+ .error({ required: '邮箱必填' }),
137
141
 
138
142
  age: dsl('number:18-100')
139
143
  .label('年龄')
@@ -151,17 +155,21 @@ const schema = dsl({
151
155
  // 定义可复用的字段
152
156
  const emailField = dsl('email!')
153
157
  .label('邮箱地址')
154
- .messages({ required: '邮箱必填' });
158
+ .error({ required: '邮箱必填' });
155
159
 
156
160
  const usernameField = dsl('string:3-32!')
157
161
  .pattern(/^[a-zA-Z0-9_]+$/)
158
- .label('用户名');
162
+ .label('用户名')
163
+ .error({ pattern: '用户名只能包含字母、数字和下划线' });
159
164
 
160
165
  // 组合使用
161
166
  const registrationSchema = dsl({
162
167
  email: emailField,
163
168
  username: usernameField,
164
- password: dsl('string:8-64!').password('strong')
169
+ password: dsl('string:8-64!')
170
+ .pattern(/^(?=.*[A-Za-z])(?=.*\d).{8,}$/)
171
+ .label('密码')
172
+ .error({ pattern: '密码至少 8 位且必须包含字母和数字' })
165
173
  });
166
174
 
167
175
  const loginSchema = dsl({
@@ -203,20 +211,18 @@ import { dsl, validateAsync, ValidationError } from 'schema-dsl';
203
211
  const registrationSchema = dsl({
204
212
  profile: dsl({
205
213
  username: dsl('string:3-32!')
206
- .pattern(/^[a-zA-Z0-9_]+$/, '只能包含字母、数字和下划线')
214
+ .pattern(/^[a-zA-Z0-9_]+$/)
207
215
  .label('用户名')
208
- .messages({
209
- min: '用户名至少3个字符',
210
- max: '用户名最多32个字符'
211
- }),
216
+ .error({ pattern: '只能包含字母、数字和下划线' }),
212
217
 
213
218
  email: dsl('email!')
214
219
  .label('邮箱地址')
215
- .messages({ required: '邮箱必填' }),
220
+ .error({ required: '邮箱必填' }),
216
221
 
217
- password: dsl('string!')
218
- .password('strong')
219
- .label('密码'),
222
+ password: dsl('string:8-64!')
223
+ .pattern(/^(?=.*[A-Za-z])(?=.*\d).{8,}$/)
224
+ .label('密码')
225
+ .error({ pattern: '密码至少 8 位且必须包含字母和数字' }),
220
226
 
221
227
  age: dsl('number:18-100')
222
228
  .label('年龄')
@@ -269,7 +275,7 @@ registerUser({
269
275
  ### 4.2 API 请求验证
270
276
 
271
277
  ```typescript
272
- import { dsl, validateAsync } from 'schema-dsl';
278
+ import { ValidationError, dsl, validateAsync } from 'schema-dsl';
273
279
  import express from 'express';
274
280
 
275
281
  const app = express();
@@ -322,15 +328,17 @@ import { dsl } from 'schema-dsl';
322
328
  const commonFields = {
323
329
  email: dsl('email!')
324
330
  .label('邮箱地址')
325
- .messages({ required: '邮箱必填' }),
331
+ .error({ required: '邮箱必填' }),
326
332
 
327
333
  username: dsl('string:3-32!')
328
334
  .pattern(/^[a-zA-Z0-9_]+$/)
329
- .label('用户名'),
335
+ .label('用户名')
336
+ .error({ pattern: '用户名只能包含字母、数字和下划线' }),
330
337
 
331
- password: dsl('string!')
332
- .password('strong')
338
+ password: dsl('string:8-64!')
339
+ .pattern(/^(?=.*[A-Za-z])(?=.*\d).{8,}$/)
333
340
  .label('密码')
341
+ .error({ pattern: '密码至少 8 位且必须包含字母和数字' })
334
342
  };
335
343
 
336
344
  // 注册表单
@@ -456,23 +464,21 @@ try {
456
464
 
457
465
  ## 6. 进阶技巧
458
466
 
459
- ### 6.1 自定义验证器
467
+ ### 6.1 额外业务规则
460
468
 
461
469
  ```typescript
462
470
  const schema = dsl({
463
- username: dsl('string:3-32!')
464
- .custom(async (value) => {
465
- // 异步验证(检查用户名是否已存在)
466
- const exists = await checkUsernameExists(value);
467
- if (exists) {
468
- return { error: 'USERNAME_EXISTS', message: '用户名已存在' };
469
- }
470
- return true;
471
- })
472
- .label('用户名')
471
+ username: dsl('string:3-32!').label('用户名')
473
472
  });
473
+
474
+ const result = await validateAsync(schema, data);
475
+ if (result.username === 'admin') {
476
+ throw new Error('用户名已存在');
477
+ }
474
478
  ```
475
479
 
480
+ 这种写法的好处是:结构校验仍由 schema-dsl 负责,业务唯一性、数据库查重等规则继续留在 TypeScript 业务层,避免把外部依赖塞进字段声明。
481
+
476
482
  ### 6.2 条件验证
477
483
 
478
484
  ```typescript
@@ -499,14 +505,14 @@ const baseUserSchema = dsl({
499
505
  });
500
506
 
501
507
  // 扩展为管理员 Schema
502
- const adminSchema = SchemaUtils.extend(baseUserSchema.toJsonSchema(), {
508
+ const adminSchema = SchemaUtils.extend(baseUserSchema, {
503
509
  role: dsl('string!').default('admin').label('角色'),
504
510
  permissions: dsl('array<string>').label('权限列表')
505
511
  });
506
512
 
507
513
  // 只选择部分字段
508
514
  const publicUserSchema = SchemaUtils.pick(
509
- baseUserSchema.toJsonSchema(),
515
+ baseUserSchema,
510
516
  ['username']
511
517
  );
512
518
  ```
@@ -515,16 +521,14 @@ const publicUserSchema = SchemaUtils.pick(
515
521
 
516
522
  ## 7. 性能优化
517
523
 
518
- ### 7.1 Schema 预编译
524
+ ### 7.1 复用 Schema 与默认缓存
519
525
 
520
526
  ```typescript
521
- // 预编译 Schema(只编译一次)
522
527
  const schema = dsl({
523
528
  email: dsl('email!').label('邮箱')
524
529
  });
525
- schema.compile(); // 预编译
526
530
 
527
- // 多次验证(使用缓存的编译结果)
531
+ // 多次验证会复用默认 Validator 的编译缓存
528
532
  await validateAsync(schema, data1);
529
533
  await validateAsync(schema, data2);
530
534
  await validateAsync(schema, data3);
@@ -554,7 +558,7 @@ dsl.config({
554
558
  4. ✅ **复用常用字段定义**
555
559
  5. ✅ **使用 `ValidationError` 类型守卫处理错误**
556
560
  6. ✅ **为用户提供友好的错误消息**
557
- 7. ✅ **预编译常用的 Schema**
561
+ 7. ✅ **复用常用 Schema 对象,让默认缓存命中**
558
562
 
559
563
  ---
560
564
 
@@ -568,6 +572,13 @@ dsl.config({
568
572
 
569
573
  ---
570
574
 
571
- **更新日期**: 2025-12-31
572
- **文档版本**: v1.0.4
575
+ ## 对应示例文件
576
+
577
+ **示例入口**: [typescript-guide.ts](https://github.com/vextjs/schema-dsl/blob/main/examples/docs/typescript-guide.ts)
578
+ **说明**: 展示 TypeScript 下推荐的 `dsl()` 包裹写法、`validate<T>()` / `validateAsync<T>()`、以及 `ValidationError` 的字段错误读取方式。
579
+
580
+ ---
581
+
582
+ **更新日期**: 2026-05-08
583
+ **文档版本**: v2.0.0-beta.2
573
584
 
@@ -2,6 +2,9 @@
2
2
 
3
3
  > 使用 `.pattern()` 方法匹配多种格式
4
4
 
5
+ > ⚠️ 这篇文档描述的是“同一字符串字段匹配多种格式”的做法。
6
+ > 如果你需要真正的跨基础类型联合语义,例如 `string | number | null`,请优先使用 [types: 语法](./union-types.md)。
7
+
5
8
  ---
6
9
 
7
10
  ## 基本用法
@@ -137,11 +140,18 @@ testData.forEach((data, index) => {
137
140
  ```
138
141
 
139
142
  **输出**:
140
- ```
143
+ ```text
141
144
  测试1: ✅
142
145
  测试2: ✅
143
146
  测试3: ❌
144
147
  错误: 必须是邮箱或手机号
145
148
  ```
146
149
 
150
+ ---
151
+
152
+ ## 对应示例文件
153
+
154
+ **示例入口**: [union-type-guide.ts](https://github.com/vextjs/schema-dsl/blob/main/examples/docs/union-type-guide.ts)
155
+ **说明**: 展示基于 `.pattern()` 的“单个字符串字段匹配多种格式”方案,以及对应的中英文错误消息。
156
+
147
157
 
@@ -55,7 +55,7 @@ validate(schema, { value: 101 }); // ❌ 超范围
55
55
 
56
56
  ### 基本格式
57
57
 
58
- ```
58
+ ```text
59
59
  types:type1|type2|type3[!]
60
60
  ```
61
61
 
@@ -65,7 +65,7 @@ types:type1|type2|type3[!]
65
65
 
66
66
  ### 带约束格式
67
67
 
68
- ```
68
+ ```text
69
69
  types:type1:constraint1|type2:constraint2
70
70
  ```
71
71
 
@@ -267,7 +267,7 @@ DslBuilder.registerType('phone_cn', { ... });
267
267
 
268
268
  - [插件系统](./plugin-system.md)
269
269
  - [自定义类型注册](./plugin-type-registration.md)
270
- - [代码规范](../specs/rules/代码规范.md)
270
+ - [贡献指南](https://github.com/vextjs/schema-dsl/blob/main/CONTRIBUTING.md)
271
271
 
272
272
  ---
273
273
 
@@ -275,3 +275,10 @@ DslBuilder.registerType('phone_cn', { ... });
275
275
 
276
276
  - **v1.1.0** - 首次发布跨类型联合验证功能
277
277
 
278
+ ---
279
+
280
+ ## 对应示例文件
281
+
282
+ **示例入口**: [union-types.ts](https://github.com/vextjs/schema-dsl/blob/main/examples/docs/union-types.ts)
283
+ **说明**: 覆盖 `types:` 语法的 `oneOf` 生成、字符串/数字联合,以及内置类型与自定义类型混用路径。
284
+