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
@@ -280,13 +280,13 @@ dsl.config({
280
280
  #### 方式3:从目录加载(大型项目)
281
281
 
282
282
  **目录结构**:
283
- ```
283
+ ```text
284
284
  project/
285
- ├── lib/
286
- │ └── locales/
287
- │ ├── zh-CN.js
288
- │ ├── en-US.js
289
- │ └── ja-JP.js
285
+ ├── i18n/
286
+ │ └── errors/
287
+ │ ├── zh-CN.cjs
288
+ │ ├── en-US.jsonc
289
+ │ └── ja-JP.json5
290
290
  └── app.js
291
291
  ```
292
292
 
@@ -295,11 +295,11 @@ project/
295
295
  const path = require('path');
296
296
 
297
297
  dsl.config({
298
- i18n: path.join(__dirname, 'lib/locales')
298
+ i18n: path.join(__dirname, 'i18n/errors')
299
299
  });
300
300
  ```
301
301
 
302
- **语言包文件** (`lib/locales/zh-CN.js`):
302
+ **语言包文件**(例如 `i18n/errors/zh-CN.cjs`):
303
303
  ```javascript
304
304
  module.exports = {
305
305
  'account.notFound': {
@@ -329,7 +329,7 @@ module.exports = {
329
329
  ```javascript
330
330
  const { Locale } = require('schema-dsl');
331
331
 
332
- // 设置默认语言为中文
332
+ // 按应用需要切换默认语言
333
333
  Locale.setLocale('zh-CN');
334
334
 
335
335
  // 获取当前语言
@@ -374,7 +374,7 @@ const app = express();
374
374
 
375
375
  // 中间件:提取客户端语言
376
376
  app.use((req, res, next) => {
377
- req.locale = req.headers['accept-language']?.split(',')[0] || 'zh-CN';
377
+ req.locale = req.headers['accept-language']?.split(',')[0]?.trim() || 'zh-CN';
378
378
  next();
379
379
  });
380
380
 
@@ -478,7 +478,7 @@ dsl.error.throw('account.notFound');
478
478
  app.get('/api/account/:id', async (req, res) => {
479
479
  try {
480
480
  const account = await findAccount(req.params.id);
481
- const locale = req.headers['accept-language'] || 'zh-CN';
481
+ const locale = req.headers['accept-language']?.split(',')[0]?.trim() || 'zh-CN';
482
482
 
483
483
  // 🎯 简化语法:只需2个参数
484
484
  dsl.error.assert(account, 'account.notFound', locale);
@@ -528,7 +528,7 @@ Locale.addLocale('en-US', {
528
528
 
529
529
  // ========== 中间件:提取语言 ==========
530
530
  app.use((req, res, next) => {
531
- req.locale = req.headers['accept-language']?.split(',')[0] || 'zh-CN';
531
+ req.locale = req.headers['accept-language']?.split(',')[0]?.trim() || 'zh-CN';
532
532
  next();
533
533
  });
534
534
 
@@ -604,7 +604,7 @@ Locale.addLocale('zh-CN', {
604
604
 
605
605
  // ========== 中间件:提取语言 ==========
606
606
  app.use(async (ctx, next) => {
607
- ctx.locale = ctx.headers['accept-language']?.split(',')[0] || 'zh-CN';
607
+ ctx.locale = ctx.headers['accept-language']?.split(',')[0]?.trim() || 'zh-CN';
608
608
  await next();
609
609
  });
610
610
 
@@ -657,7 +657,7 @@ Locale.addLocale('zh-CN', {
657
657
  const server = http.createServer((req, res) => {
658
658
  try {
659
659
  // 提取语言
660
- const locale = req.headers['accept-language']?.split(',')[0] || 'zh-CN';
660
+ const locale = req.headers['accept-language']?.split(',')[0]?.trim() || 'zh-CN';
661
661
 
662
662
  // 业务逻辑
663
663
  const order = getOrder(req.url);
@@ -962,7 +962,7 @@ async function apiCall() {
962
962
  ```javascript
963
963
  const { Locale } = require('schema-dsl');
964
964
 
965
- // 启动时设置默认语言
965
+ // 启动时按应用需要设置默认语言
966
966
  Locale.setLocale('zh-CN');
967
967
 
968
968
  // 获取当前默认语言
@@ -1041,7 +1041,7 @@ app.use((error, req, res, next) => {
1041
1041
 
1042
1042
  ### 基础结构
1043
1043
 
1044
- SchemaI-DSL 验证返回的错误对象结构:
1044
+ schema-dsl 验证返回的错误对象结构:
1045
1045
 
1046
1046
  ```javascript
1047
1047
  const { dsl, validate } = require('schema-dsl');
@@ -1054,14 +1054,14 @@ const result = validate(schema, { username: 'ab' });
1054
1054
 
1055
1055
  // 返回结构
1056
1056
  {
1057
- valid: false, // 验证是否通过
1058
- errors: [ // 错误数组(基于 ajv)
1057
+ valid: false,
1058
+ errors: [
1059
1059
  {
1060
- instancePath: '/username',
1061
- schemaPath: '#/properties/username/minLength',
1060
+ path: 'username',
1061
+ field: 'username',
1062
1062
  keyword: 'minLength',
1063
1063
  params: { limit: 3 },
1064
- message: 'must NOT have fewer than 3 characters'
1064
+ message: '用户名长度不能少于3个字符'
1065
1065
  }
1066
1066
  ]
1067
1067
  }
@@ -1089,8 +1089,8 @@ const result = validate(schema, {
1089
1089
  });
1090
1090
 
1091
1091
  // 错误路径
1092
- console.log(result.errors[0].instancePath); // '/user/profile/email'
1093
- console.log(result.errors[0].message); // 'must match format "email"'
1092
+ console.log(result.errors[0].path); // 'user/profile/email'
1093
+ console.log(result.errors[0].message); // '邮箱必须是有效的邮箱地址'
1094
1094
  ```
1095
1095
 
1096
1096
  ### 数组项错误
@@ -1107,7 +1107,7 @@ const result = validate(schema, {
1107
1107
  });
1108
1108
 
1109
1109
  // 错误路径
1110
- console.log(result.errors[0].instancePath); // '/items/0'
1110
+ console.log(result.errors[0].path); // 'items/0'
1111
1111
  ```
1112
1112
 
1113
1113
  ---
@@ -1183,7 +1183,7 @@ Locale.setMessages({
1183
1183
 
1184
1184
  ### 内置错误码(简化版)
1185
1185
 
1186
- SchemaI-DSLajv 的错误关键字进行了简化映射,使其更易用:
1186
+ schema-dslAjv 的错误关键字进行了统一格式化,使其更易用:
1187
1187
 
1188
1188
  #### 字符串错误码
1189
1189
 
@@ -1278,8 +1278,8 @@ const result = validate(schema, {
1278
1278
  });
1279
1279
 
1280
1280
  // 错误示例
1281
- // result.errors[0].instancePath: '/user/address/city'
1282
- // result.errors[1].instancePath: '/user/address/street'
1281
+ // result.errors[0].path: 'user/address/city'
1282
+ // result.errors[1].path: 'user/address/street'
1283
1283
  ```
1284
1284
 
1285
1285
  ### 数组验证
@@ -1297,7 +1297,7 @@ const result = validate(schema, {
1297
1297
  });
1298
1298
 
1299
1299
  // 错误路径
1300
- console.log(result.errors[0].instancePath); // '/items/0'
1300
+ console.log(result.errors[0].path); // 'items/0'
1301
1301
  ```
1302
1302
 
1303
1303
  ---
@@ -1355,7 +1355,7 @@ function validateBody(schema) {
1355
1355
  code: 'VALIDATION_ERROR',
1356
1356
  message: '请检查输入信息',
1357
1357
  errors: result.errors.map(err => ({
1358
- field: err.instancePath.replace(/^\//, '').replace(/\//g, '.'),
1358
+ field: err.path.replace(/\//g, '.'),
1359
1359
  message: err.message,
1360
1360
  keyword: err.keyword,
1361
1361
  params: err.params
@@ -1402,7 +1402,7 @@ function validateBody(schema) {
1402
1402
  code: 'VALIDATION_ERROR',
1403
1403
  message: '数据验证失败',
1404
1404
  errors: result.errors.map(err => ({
1405
- field: err.instancePath.replace(/^\//, '').replace(/\//g, '.'),
1405
+ field: err.path.replace(/\//g, '.'),
1406
1406
  message: err.message,
1407
1407
  keyword: err.keyword
1408
1408
  }))
@@ -1591,7 +1591,7 @@ function logValidationError(req, result) {
1591
1591
  url: req.url,
1592
1592
  method: req.method,
1593
1593
  errors: result.errors.map(err => ({
1594
- path: err.path.join('.'),
1594
+ path: err.path.replace(/\//g, '.'),
1595
1595
  type: err.type,
1596
1596
  message: err.message
1597
1597
  })),
@@ -1652,8 +1652,8 @@ const { dsl } = require('schema-dsl');
1652
1652
  // ✅ 推荐:返回错误消息字符串
1653
1653
  const schema = dsl({
1654
1654
  username: 'string:3-32!'
1655
- .custom(async (value) => {
1656
- if (await userExists(value)) {
1655
+ .custom((value) => {
1656
+ if (value === 'admin') {
1657
1657
  return '用户名已被占用';
1658
1658
  }
1659
1659
  // 验证通过时无需返回
@@ -1685,9 +1685,9 @@ logger.warn('验证失败', {
1685
1685
 
1686
1686
  ```javascript
1687
1687
  // 统一的错误格式化函数
1688
- function formatValidationErrors(ajvErrors) {
1689
- return ajvErrors.map(err => ({
1690
- field: err.instancePath.replace(/^\//, '').replace(/\//g, '.'),
1688
+ function formatValidationErrors(errors) {
1689
+ return errors.map(err => ({
1690
+ field: err.path.replace(/\//g, '.'),
1691
1691
  message: err.message,
1692
1692
  keyword: err.keyword,
1693
1693
  params: err.params
@@ -1716,7 +1716,7 @@ if (!result.valid) {
1716
1716
 
1717
1717
  **语言包配置**:
1718
1718
  ```javascript
1719
- // lib/locales/zh-CN.js (或自定义语言包)
1719
+ // i18n/errors/zh-CN.cjs(或任意 .json/.jsonc/.json5 自定义语言包文件)
1720
1720
  module.exports = {
1721
1721
  // 字符串格式(向后兼容)
1722
1722
  'user.notFound': '用户不存在',
@@ -1770,13 +1770,13 @@ try {
1770
1770
  不同语言使用相同的数字 `code`,便于前端统一处理:
1771
1771
 
1772
1772
  ```javascript
1773
- // zh-CN.js
1773
+ // zh-CN.cjs
1774
1774
  'account.notFound': {
1775
1775
  code: 40001, // ← 数字 code 一致
1776
1776
  message: '账户不存在'
1777
1777
  }
1778
1778
 
1779
- // en-US.js
1779
+ // en-US.cjs
1780
1780
  'account.notFound': {
1781
1781
  code: 40001, // ← 数字 code 一致
1782
1782
  message: 'Account not found'
@@ -1794,6 +1794,8 @@ switch (error.code) {
1794
1794
  showPaymentDialog();
1795
1795
  break;
1796
1796
  }
1797
+ ```
1798
+
1797
1799
  #### 3. 增强的 error.is() 方法
1798
1800
 
1799
1801
  同时支持 `originalKey` 和数字 `code` 判断:
@@ -1944,9 +1946,9 @@ function handleError(error) {
1944
1946
 
1945
1947
  ### 更多信息
1946
1948
 
1947
- - [v1.1.5 完整变更日志](../changelogs/v1.1.5.md)
1948
- - [升级指南](../changelogs/v1.1.5.md#升级指南)
1949
- - [最佳实践](../changelogs/v1.1.5.md#最佳实践)
1949
+ - [v1.1.5 完整变更日志](https://github.com/vextjs/schema-dsl/blob/main/changelogs/v1.1.5.md)
1950
+ - [升级指南](https://github.com/vextjs/schema-dsl/blob/main/changelogs/v1.1.5.md#升级指南)
1951
+ - [最佳实践](https://github.com/vextjs/schema-dsl/blob/main/changelogs/v1.1.5.md#最佳实践)
1950
1952
 
1951
1953
  ---
1952
1954
 
@@ -1956,11 +1958,18 @@ function handleError(error) {
1956
1958
  - [DSL 语法指南](./dsl-syntax.md)
1957
1959
  - [String 扩展文档](./string-extensions.md)
1958
1960
  - [多语言配置](./dynamic-locale.md)
1959
- - [v1.1.5 变更日志](../changelogs/v1.1.5.md)
1961
+ - [v1.1.5 变更日志](https://github.com/vextjs/schema-dsl/blob/main/changelogs/v1.1.5.md)
1962
+
1963
+ ---
1964
+
1965
+ ## 对应示例文件
1966
+
1967
+ **示例入口**: [error-handling.ts](https://github.com/vextjs/schema-dsl/blob/main/examples/docs/error-handling.ts)
1968
+ **说明**: 覆盖 `validate()` 产生的字段错误、`I18nError` 业务错误对象、`toJSON()` 输出与错误码判断。
1960
1969
 
1961
1970
  ---
1962
1971
 
1963
- **最后更新**: 2026-01-17
1972
+ **最后更新**: 2026-05-08
1964
1973
  **版本**: v1.1.5
1965
1974
 
1966
1975
 
@@ -1,9 +1,9 @@
1
- # 数据库导出完整指南
1
+ # 导出完整指南
2
2
 
3
- > **用途**: Schema 到数据库 DDL 的完整导出指南
3
+ > **用途**: Schema 到多种输出格式的完整导出指南
4
4
  > **阅读时间**: 10分钟
5
5
 
6
- > ⚠️ **重要提示**: 并非所有 SchemaI-DSL 特性都能导出到数据库。请先阅读 [导出限制说明](export-limitations.md) 了解哪些特性不支持导出。
6
+ > ⚠️ **重要提示**: 并非所有 schema-dsl 特性都能导出到数据库。请先阅读 [导出限制说明](export-limitations.md) 了解哪些特性不支持导出。
7
7
 
8
8
  ---
9
9
 
@@ -14,6 +14,7 @@
14
14
  - [MongoDB 导出](#mongodb-导出)
15
15
  - [MySQL 导出](#mysql-导出)
16
16
  - [PostgreSQL 导出](#postgresql-导出)
17
+ - [Markdown 导出](#markdown-导出)
17
18
  - [导出对比](#导出对比)
18
19
  - [最佳实践](#最佳实践)
19
20
 
@@ -21,15 +22,18 @@
21
22
 
22
23
  ## 概述
23
24
 
24
- SchemaI-DSL 支持将 JSON Schema 导出为多种数据库的 DDL 语句,实现"一次定义,多处使用"。
25
+ schema-dsl 支持将 JSON Schema 导出为多种数据库结构或文档格式,实现“一次定义,多处使用”。
25
26
 
26
- ### 支持的数据库
27
+ ### 支持的导出格式
27
28
 
28
- | 数据库 | 导出器 | 输出格式 |
29
- |--------|--------|----------|
29
+ | 类型 | 导出器 | 输出格式 |
30
+ |------|--------|----------|
30
31
  | MongoDB | `MongoDBExporter` | `$jsonSchema` 验证文档 |
31
32
  | MySQL | `MySQLExporter` | `CREATE TABLE` DDL |
32
33
  | PostgreSQL | `PostgreSQLExporter` | `CREATE TABLE` DDL + COMMENT |
34
+ | Markdown | `MarkdownExporter` | 面向人类阅读的 Markdown 文档 |
35
+
36
+ 其中 `MarkdownExporter` 更适合生成接口字段说明、表单文档或内部规范文档,完整用法见 [Markdown 导出器](./markdown-exporter.md)。
33
37
 
34
38
  ---
35
39
 
@@ -51,14 +55,42 @@ const userSchema = dsl({
51
55
  createdAt: 'datetime!'
52
56
  });
53
57
 
54
- // 导出到不同数据库
58
+ // 导出到不同目标
55
59
  const mongoSchema = new exporters.MongoDBExporter().export(userSchema);
56
60
  const mysqlDdl = new exporters.MySQLExporter().export('users', userSchema);
57
61
  const pgDdl = new exporters.PostgreSQLExporter().export('users', userSchema);
62
+ const markdownDoc = exporters.MarkdownExporter.export(userSchema, {
63
+ title: '用户 Schema 文档'
64
+ });
58
65
  ```
59
66
 
60
67
  ---
61
68
 
69
+ ## Markdown 导出
70
+
71
+ 如果你的目标不是数据库,而是给研发、测试、产品或接口使用方生成一份可直接阅读的字段说明文档,可以使用 `MarkdownExporter`:
72
+
73
+ ```javascript
74
+ const { dsl, exporters } = require('schema-dsl');
75
+
76
+ const schema = dsl({
77
+ username: 'string:3-32!'.description('登录账号'),
78
+ email: 'email!'.description('联系邮箱'),
79
+ age: 'number:18-120'.description('年龄')
80
+ });
81
+
82
+ const markdown = exporters.MarkdownExporter.export(schema, {
83
+ title: '用户注册字段说明',
84
+ locale: 'zh-CN'
85
+ });
86
+
87
+ console.log(markdown);
88
+ ```
89
+
90
+ 更完整的选项、示例和多语言输出说明见 [Markdown 导出器](./markdown-exporter.md)。
91
+
92
+ ---
93
+
62
94
  ## MongoDB 导出
63
95
 
64
96
  ### 基本用法
@@ -460,3 +492,10 @@ console.log('导出完成!');
460
492
  - [TypeConverter](type-converter.md)
461
493
  - [DSL 语法](dsl-syntax.md)
462
494
 
495
+ ---
496
+
497
+ ## 对应示例文件
498
+
499
+ **示例入口**: [export-guide.ts](https://github.com/vextjs/schema-dsl/blob/main/examples/docs/export-guide.ts)
500
+ **说明**: 覆盖同一组 schema 同时导出到 MongoDB、MySQL 和 PostgreSQL 的最小工作流,便于对照多导出器结果。
501
+
@@ -49,7 +49,7 @@ const schema = dsl({
49
49
 
50
50
  **替代方案**:
51
51
  - 导出为最宽松的类型(`VARCHAR(255)`)
52
- - 验证逻辑保留在应用层(使用 SchemaI-DSL 验证器)
52
+ - 验证逻辑保留在应用层(使用 schema-dsl 验证器)
53
53
 
54
54
  ---
55
55
 
@@ -74,8 +74,8 @@ const schema = dsl({
74
74
  | 关键字 | 说明 | 导出行为 |
75
75
  |--------|------|----------|
76
76
  | `allOf` | 所有 Schema 都满足 | ❌ 忽略 |
77
- | `anyOf` | 满足任一 Schema | 忽略 |
78
- | `oneOf` | 仅满足一个 Schema | 忽略 |
77
+ | `anyOf` | 满足任一 Schema | ⚠️ 仅当所有分支映射到同一 SQL 类型时可导出;否则抛错 |
78
+ | `oneOf` | 仅满足一个 Schema | ⚠️ 仅当所有分支映射到同一 SQL 类型时可导出;否则抛错 |
79
79
  | `not` | 不满足某 Schema | ❌ 忽略 |
80
80
  | `if/then/else` | 条件 Schema | ❌ 忽略 |
81
81
  | `dependencies` | 字段依赖关系 | ❌ 忽略 |
@@ -83,16 +83,25 @@ const schema = dsl({
83
83
  **示例**:
84
84
 
85
85
  ```javascript
86
- // 这些结构无法导出
86
+ // ⚠️ 这些结构无法直接稳定导出到单一 SQL 列类型
87
87
  const schema = {
88
88
  type: 'object',
89
- allOf: [
90
- { properties: { name: { type: 'string' } } },
91
- { properties: { age: { type: 'number' } } }
92
- ]
89
+ properties: {
90
+ value: {
91
+ anyOf: [
92
+ { type: 'string' },
93
+ { type: 'number' }
94
+ ]
95
+ }
96
+ }
93
97
  };
94
98
  ```
95
99
 
100
+ **当前行为**:
101
+
102
+ - `ipv4 | ipv6` 这类所有分支最终都映射为同一 SQL 列类型的联合,仍可导出
103
+ - `string | number` 这类会落到不同 SQL 列类型的联合,MySQL / PostgreSQL 导出器会**显式抛错**,而不是静默取第一项
104
+
96
105
  ---
97
106
 
98
107
  ### 3. 自定义验证器 ❌
@@ -329,9 +338,9 @@ const schema = dsl('string!')
329
338
 
330
339
  ### 1. 分层验证策略 🎯
331
340
 
332
- ```
341
+ ```text
333
342
  ┌─────────────────────────────────────────┐
334
- │ 应用层(SchemaI-DSL 完整验证)
343
+ │ 应用层(schema-dsl 完整验证)
335
344
  │ - 条件逻辑(match/if) │
336
345
  │ - 自定义验证器 │
337
346
  │ - 复杂约束(正则、范围等) │
@@ -449,7 +458,7 @@ module.exports = {
449
458
  ```markdown
450
459
  ## 数据验证说明
451
460
 
452
- ### 应用层验证(SchemaI-DSL
461
+ ### 应用层验证(schema-dsl
453
462
  - ✅ `contact` 字段根据 `contactType` 动态验证
454
463
  - ✅ 用户名正则验证(`^[a-zA-Z0-9_]+$`)
455
464
  - ✅ 自定义业务规则验证
@@ -549,3 +558,10 @@ dsl('active|inactive|banned')
549
558
  - [PostgreSQL 导出器](postgresql-exporter.md)
550
559
  - [最佳实践](best-practices.md)
551
560
 
561
+ ---
562
+
563
+ ## 对应示例文件
564
+
565
+ **示例入口**: [export-limitations.ts](https://github.com/vextjs/schema-dsl/blob/main/examples/docs/export-limitations.ts)
566
+ **说明**: 展示“完整应用层 schema”与“数据库导出专用简化 schema”的分工,以及三类导出器对静态 schema 的落地结果。
567
+