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.
- package/CHANGELOG.md +87 -210
- package/README.md +391 -2249
- package/dist/DslBuilder-DQDN0ZxZ.d.cts +341 -0
- package/dist/DslBuilder-DkLaOo9Q.d.ts +341 -0
- package/dist/Validator-C7GsVQOH.d.cts +192 -0
- package/dist/Validator-hFWKGxir.d.ts +192 -0
- package/dist/index.cjs +6594 -0
- package/dist/index.d.cts +1145 -0
- package/dist/index.d.ts +1145 -0
- package/dist/index.js +6528 -0
- package/dist/plugin-CIKtTMtS.d.cts +246 -0
- package/dist/plugin-CIKtTMtS.d.ts +246 -0
- package/dist/plugins/custom-format.cjs +3802 -0
- package/dist/plugins/custom-format.d.cts +12 -0
- package/dist/plugins/custom-format.d.ts +12 -0
- package/dist/plugins/custom-format.js +3772 -0
- package/dist/plugins/custom-type-example.cjs +3795 -0
- package/dist/plugins/custom-type-example.d.cts +8 -0
- package/dist/plugins/custom-type-example.d.ts +8 -0
- package/dist/plugins/custom-type-example.js +3765 -0
- package/dist/plugins/custom-validator.cjs +146 -0
- package/dist/plugins/custom-validator.d.cts +10 -0
- package/dist/plugins/custom-validator.d.ts +10 -0
- package/dist/plugins/custom-validator.js +121 -0
- package/docs/FEATURE-INDEX.md +102 -68
- package/docs/add-custom-locale.md +48 -35
- package/docs/add-keyword.md +24 -0
- package/docs/api-reference.md +396 -154
- package/docs/api.md +13 -0
- package/docs/best-practices-project-structure.md +19 -10
- package/docs/best-practices.md +93 -53
- package/docs/cache-manager.md +23 -15
- package/docs/compile.md +45 -0
- package/docs/conditional-api.md +40 -11
- package/docs/custom-extensions-guide.md +80 -152
- package/docs/design-philosophy.md +76 -71
- package/docs/doc-index.md +324 -0
- package/docs/dsl-syntax.md +69 -19
- package/docs/dynamic-locale.md +24 -14
- package/docs/enum.md +12 -5
- package/docs/error-handling.md +53 -44
- package/docs/export-guide.md +47 -8
- package/docs/export-limitations.md +27 -11
- package/docs/faq.md +86 -67
- package/docs/frontend-i18n-guide.md +26 -12
- package/docs/i18n-user-guide.md +60 -47
- package/docs/i18n.md +51 -32
- package/docs/index.md +48 -0
- package/docs/json-schema-basics.md +40 -0
- package/docs/label-vs-description.md +12 -3
- package/docs/markdown-exporter.md +15 -6
- package/docs/mongodb-exporter.md +11 -4
- package/docs/multi-language.md +26 -0
- package/docs/multi-type-support.md +26 -33
- package/docs/mysql-exporter.md +9 -2
- package/docs/number-operators.md +12 -5
- package/docs/optional-marker-guide.md +28 -23
- package/docs/performance-guide.md +49 -0
- package/docs/plugin-system.md +205 -366
- package/docs/plugin-type-registration.md +34 -0
- package/docs/postgresql-exporter.md +9 -2
- package/docs/public/favicon.svg +5 -0
- package/docs/quick-start.md +37 -363
- package/docs/runtime-locale-support.md +20 -9
- package/docs/schema-helper.md +10 -5
- package/docs/schema-utils-advanced-issues.md +23 -0
- package/docs/schema-utils-best-practices.md +20 -0
- package/docs/schema-utils-chaining.md +7 -0
- package/docs/schema-utils.md +76 -42
- package/docs/security-checklist.md +20 -0
- package/docs/string-extensions.md +17 -9
- package/docs/troubleshooting.md +36 -21
- package/docs/type-converter.md +41 -50
- package/docs/type-reference.md +38 -15
- package/docs/typescript-guide.md +53 -42
- package/docs/union-type-guide.md +11 -1
- package/docs/union-types.md +10 -3
- package/docs/validate-async.md +36 -25
- package/docs/validate-batch.md +49 -0
- package/docs/validate-dsl-object-support.md +33 -28
- package/docs/validate.md +36 -16
- package/docs/validation-guide.md +25 -7
- package/docs/validator.md +39 -0
- package/package.json +85 -27
- package/plugins/custom-format.cjs +8 -0
- package/plugins/custom-type-example.cjs +8 -0
- package/plugins/custom-validator.cjs +8 -0
- package/src/adapters/DslAdapter.ts +111 -0
- package/src/adapters/index.ts +1 -0
- package/src/config/constants.ts +83 -0
- package/src/config/index.ts +2 -0
- package/src/config/patterns.ts +77 -0
- package/src/core/CacheManager.ts +159 -0
- package/src/core/ConditionalBuilder.ts +382 -0
- package/src/core/ConditionalRuntime.ts +28 -0
- package/src/core/ConditionalValidator.ts +255 -0
- package/src/core/DslBuilder.ts +677 -0
- package/src/core/ErrorCodes.ts +38 -0
- package/src/core/ErrorFormatter.ts +271 -0
- package/src/core/JSONSchemaCore.ts +65 -0
- package/src/core/Locale.ts +187 -0
- package/src/core/MessageTemplate.ts +42 -0
- package/src/core/ObjectDslBuilder.ts +64 -0
- package/src/core/PluginManager.ts +326 -0
- package/src/core/StringExtensions.ts +140 -0
- package/src/core/TemplateEngine.ts +44 -0
- package/src/core/Validator.ts +448 -0
- package/src/errors/I18nError.ts +159 -0
- package/src/errors/ValidationError.ts +105 -0
- package/src/exporters/BaseExporter.ts +60 -0
- package/src/exporters/MarkdownExporter.ts +305 -0
- package/src/exporters/MongoDBExporter.ts +126 -0
- package/src/exporters/MySQLExporter.ts +155 -0
- package/src/exporters/PostgreSQLExporter.ts +222 -0
- package/src/exporters/index.ts +18 -0
- package/src/index.ts +633 -0
- package/{lib/locales/en-US.js → src/locales/en-US.ts} +21 -37
- package/{lib/locales/es-ES.js → src/locales/es-ES.ts} +63 -16
- package/{lib/locales/fr-FR.js → src/locales/fr-FR.ts} +74 -27
- package/src/locales/index.ts +103 -0
- package/{lib/locales/ja-JP.js → src/locales/ja-JP.ts} +59 -17
- package/src/locales/types.ts +156 -0
- package/{lib/locales/zh-CN.js → src/locales/zh-CN.ts} +21 -38
- package/src/parser/ConstraintParser.ts +101 -0
- package/src/parser/DslParser.ts +470 -0
- package/src/parser/SchemaCompiler.ts +66 -0
- package/src/parser/TypeRegistry.ts +250 -0
- package/src/parser/index.ts +6 -0
- package/src/plugins/custom-format.ts +126 -0
- package/src/plugins/custom-type-example.ts +108 -0
- package/src/plugins/custom-validator.ts +140 -0
- package/src/types/conditional.ts +28 -0
- package/src/types/config.ts +59 -0
- package/src/types/dsl.ts +131 -0
- package/src/types/error.ts +60 -0
- package/src/types/index.ts +17 -0
- package/src/types/infer.ts +128 -0
- package/src/types/plugin.ts +58 -0
- package/src/types/safe-regex.d.ts +9 -0
- package/src/types/schema.ts +66 -0
- package/src/types/validate.ts +71 -0
- package/src/utils/SchemaHelper.ts +196 -0
- package/src/utils/SchemaUtils.ts +346 -0
- package/src/utils/TypeConverter.ts +215 -0
- package/src/utils/index.ts +10 -0
- package/src/validators/CustomKeywords.ts +477 -0
- package/.eslintignore +0 -11
- package/.eslintrc.json +0 -27
- package/CONTRIBUTING.md +0 -368
- package/STATUS.md +0 -491
- package/changelogs/v1.0.0.md +0 -328
- package/changelogs/v1.0.9.md +0 -367
- package/changelogs/v1.1.0.md +0 -389
- package/changelogs/v1.1.1.md +0 -308
- package/changelogs/v1.1.2.md +0 -183
- package/changelogs/v1.1.3.md +0 -161
- package/changelogs/v1.1.4.md +0 -432
- package/changelogs/v1.1.5.md +0 -493
- package/changelogs/v1.1.6.md +0 -211
- package/changelogs/v1.1.8.md +0 -376
- package/changelogs/v1.2.3.md +0 -124
- package/docs/INDEX.md +0 -252
- package/docs/issues-resolved-summary.md +0 -196
- package/docs/performance-benchmark-report.md +0 -179
- package/docs/performance-quick-reference.md +0 -123
- package/docs/user-questions-answered.md +0 -353
- package/docs/validation-rules-v1.0.2.md +0 -1608
- package/examples/README.md +0 -81
- package/examples/array-dsl-example.js +0 -227
- package/examples/conditional-example.js +0 -288
- package/examples/conditional-non-object.js +0 -129
- package/examples/conditional-validate-example.js +0 -321
- package/examples/custom-extension.js +0 -85
- package/examples/dsl-match-example.js +0 -74
- package/examples/dsl-style.js +0 -118
- package/examples/dynamic-locale-configuration.js +0 -348
- package/examples/dynamic-locale-example.js +0 -287
- package/examples/enum.examples.js +0 -324
- package/examples/export-demo.js +0 -130
- package/examples/express-integration.js +0 -376
- package/examples/i18n-error-handling-complete.js +0 -381
- package/examples/i18n-error-handling-quickstart.md +0 -0
- package/examples/i18n-error.examples.js +0 -181
- package/examples/i18n-full-demo.js +0 -301
- package/examples/i18n-memory-safety.examples.js +0 -268
- package/examples/markdown-export.js +0 -71
- package/examples/middleware-usage.js +0 -93
- package/examples/new-features-comparison.js +0 -315
- package/examples/password-reset/README.md +0 -153
- package/examples/password-reset/schema.js +0 -26
- package/examples/password-reset/test.js +0 -101
- package/examples/plugin-system.examples.js +0 -205
- package/examples/schema-utils-chaining.examples.js +0 -250
- package/examples/simple-example.js +0 -122
- package/examples/slug.examples.js +0 -179
- package/examples/string-extensions.js +0 -297
- package/examples/union-type-example.js +0 -127
- package/examples/union-types-example.js +0 -77
- package/examples/user-registration/README.md +0 -156
- package/examples/user-registration/routes.js +0 -92
- package/examples/user-registration/schema.js +0 -150
- package/examples/user-registration/server.js +0 -74
- package/index.d.ts +0 -3540
- package/index.js +0 -457
- package/index.mjs +0 -60
- package/lib/adapters/DslAdapter.js +0 -871
- package/lib/adapters/index.js +0 -20
- package/lib/config/constants.js +0 -286
- package/lib/config/patterns/common.js +0 -47
- package/lib/config/patterns/creditCard.js +0 -9
- package/lib/config/patterns/idCard.js +0 -9
- package/lib/config/patterns/index.js +0 -9
- package/lib/config/patterns/licensePlate.js +0 -4
- package/lib/config/patterns/passport.js +0 -4
- package/lib/config/patterns/phone.js +0 -9
- package/lib/config/patterns/postalCode.js +0 -5
- package/lib/core/CacheManager.js +0 -376
- package/lib/core/ConditionalBuilder.js +0 -503
- package/lib/core/DslBuilder.js +0 -1400
- package/lib/core/ErrorCodes.js +0 -233
- package/lib/core/ErrorFormatter.js +0 -445
- package/lib/core/JSONSchemaCore.js +0 -347
- package/lib/core/Locale.js +0 -130
- package/lib/core/MessageTemplate.js +0 -98
- package/lib/core/PluginManager.js +0 -448
- package/lib/core/StringExtensions.js +0 -240
- package/lib/core/Validator.js +0 -654
- package/lib/errors/I18nError.js +0 -328
- package/lib/errors/ValidationError.js +0 -191
- package/lib/exporters/MarkdownExporter.js +0 -420
- package/lib/exporters/MongoDBExporter.js +0 -162
- package/lib/exporters/MySQLExporter.js +0 -212
- package/lib/exporters/PostgreSQLExporter.js +0 -289
- package/lib/exporters/index.js +0 -24
- package/lib/locales/index.js +0 -8
- package/lib/utils/LRUCache.js +0 -174
- package/lib/utils/SchemaHelper.js +0 -240
- package/lib/utils/SchemaUtils.js +0 -445
- package/lib/utils/TypeConverter.js +0 -245
- package/lib/utils/index.js +0 -13
- package/lib/validators/CustomKeywords.js +0 -616
- package/lib/validators/index.js +0 -11
package/docs/error-handling.md
CHANGED
|
@@ -280,13 +280,13 @@ dsl.config({
|
|
|
280
280
|
#### 方式3:从目录加载(大型项目)
|
|
281
281
|
|
|
282
282
|
**目录结构**:
|
|
283
|
-
```
|
|
283
|
+
```text
|
|
284
284
|
project/
|
|
285
|
-
├──
|
|
286
|
-
│ └──
|
|
287
|
-
│ ├── zh-CN.
|
|
288
|
-
│ ├── en-US.
|
|
289
|
-
│ └── ja-JP.
|
|
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, '
|
|
298
|
+
i18n: path.join(__dirname, 'i18n/errors')
|
|
299
299
|
});
|
|
300
300
|
```
|
|
301
301
|
|
|
302
|
-
|
|
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
|
-
|
|
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: [
|
|
1057
|
+
valid: false,
|
|
1058
|
+
errors: [
|
|
1059
1059
|
{
|
|
1060
|
-
|
|
1061
|
-
|
|
1060
|
+
path: 'username',
|
|
1061
|
+
field: 'username',
|
|
1062
1062
|
keyword: 'minLength',
|
|
1063
1063
|
params: { limit: 3 },
|
|
1064
|
-
message: '
|
|
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].
|
|
1093
|
-
console.log(result.errors[0].message);
|
|
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].
|
|
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
|
-
|
|
1186
|
+
schema-dsl 对 Ajv 的错误关键字进行了统一格式化,使其更易用:
|
|
1187
1187
|
|
|
1188
1188
|
#### 字符串错误码
|
|
1189
1189
|
|
|
@@ -1278,8 +1278,8 @@ const result = validate(schema, {
|
|
|
1278
1278
|
});
|
|
1279
1279
|
|
|
1280
1280
|
// 错误示例
|
|
1281
|
-
// result.errors[0].
|
|
1282
|
-
// result.errors[1].
|
|
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].
|
|
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.
|
|
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.
|
|
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.
|
|
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(
|
|
1656
|
-
if (
|
|
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(
|
|
1689
|
-
return
|
|
1690
|
-
field: err.
|
|
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
|
-
//
|
|
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.
|
|
1773
|
+
// zh-CN.cjs
|
|
1774
1774
|
'account.notFound': {
|
|
1775
1775
|
code: 40001, // ← 数字 code 一致
|
|
1776
1776
|
message: '账户不存在'
|
|
1777
1777
|
}
|
|
1778
1778
|
|
|
1779
|
-
// en-US.
|
|
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 完整变更日志](
|
|
1948
|
-
- [升级指南](
|
|
1949
|
-
- [最佳实践](
|
|
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 变更日志](
|
|
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-
|
|
1972
|
+
**最后更新**: 2026-05-08
|
|
1964
1973
|
**版本**: v1.1.5
|
|
1965
1974
|
|
|
1966
1975
|
|
package/docs/export-guide.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
#
|
|
1
|
+
# 导出完整指南
|
|
2
2
|
|
|
3
|
-
> **用途**: Schema
|
|
3
|
+
> **用途**: Schema 到多种输出格式的完整导出指南
|
|
4
4
|
> **阅读时间**: 10分钟
|
|
5
5
|
|
|
6
|
-
> ⚠️ **重要提示**: 并非所有
|
|
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
|
-
|
|
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
|
-
- 验证逻辑保留在应用层(使用
|
|
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
|
-
|
|
90
|
-
|
|
91
|
-
|
|
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
|
-
│ 应用层(
|
|
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
|
-
### 应用层验证(
|
|
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
|
+
|