schema-dsl 1.2.5 → 2.0.1

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 (243) hide show
  1. package/CHANGELOG.md +130 -238
  2. package/LICENSE +21 -21
  3. package/README.md +628 -2486
  4. package/dist/DslBuilder-BIgQOAXp.d.ts +343 -0
  5. package/dist/DslBuilder-CjHTucNQ.d.cts +343 -0
  6. package/dist/Validator-CllRdrY0.d.ts +192 -0
  7. package/dist/Validator-D6okG9tr.d.cts +192 -0
  8. package/dist/index.cjs +6640 -0
  9. package/dist/index.d.cts +1151 -0
  10. package/dist/index.d.ts +1151 -0
  11. package/dist/index.js +6574 -0
  12. package/dist/plugin-CIKtTMtS.d.cts +246 -0
  13. package/dist/plugin-CIKtTMtS.d.ts +246 -0
  14. package/dist/plugins/custom-format.cjs +3818 -0
  15. package/dist/plugins/custom-format.d.cts +12 -0
  16. package/dist/plugins/custom-format.d.ts +12 -0
  17. package/dist/plugins/custom-format.js +3788 -0
  18. package/dist/plugins/custom-type-example.cjs +3811 -0
  19. package/dist/plugins/custom-type-example.d.cts +8 -0
  20. package/dist/plugins/custom-type-example.d.ts +8 -0
  21. package/dist/plugins/custom-type-example.js +3781 -0
  22. package/dist/plugins/custom-validator.cjs +144 -0
  23. package/dist/plugins/custom-validator.d.cts +10 -0
  24. package/dist/plugins/custom-validator.d.ts +10 -0
  25. package/dist/plugins/custom-validator.js +119 -0
  26. package/docs/FEATURE-INDEX.md +553 -519
  27. package/docs/add-custom-locale.md +496 -483
  28. package/docs/add-keyword.md +24 -0
  29. package/docs/api-reference.md +1047 -805
  30. package/docs/api.md +13 -0
  31. package/docs/best-practices-project-structure.md +417 -408
  32. package/docs/best-practices.md +712 -672
  33. package/docs/cache-manager.md +344 -336
  34. package/docs/compile.md +45 -0
  35. package/docs/conditional-api.md +1307 -1278
  36. package/docs/custom-extensions-guide.md +339 -411
  37. package/docs/design-philosophy.md +606 -601
  38. package/docs/doc-index.md +324 -0
  39. package/docs/dsl-syntax.md +714 -664
  40. package/docs/dynamic-locale.md +608 -598
  41. package/docs/enum.md +482 -475
  42. package/docs/error-handling.md +1975 -1966
  43. package/docs/export-guide.md +501 -462
  44. package/docs/export-limitations.md +567 -551
  45. package/docs/faq.md +596 -577
  46. package/docs/frontend-i18n-guide.md +307 -293
  47. package/docs/i18n-user-guide.md +487 -474
  48. package/docs/i18n.md +476 -457
  49. package/docs/index.md +48 -0
  50. package/docs/json-schema-basics.md +40 -0
  51. package/docs/label-vs-description.md +271 -262
  52. package/docs/markdown-exporter.md +406 -397
  53. package/docs/mongodb-exporter.md +302 -295
  54. package/docs/multi-language.md +26 -0
  55. package/docs/multi-type-support.md +322 -329
  56. package/docs/mysql-exporter.md +280 -273
  57. package/docs/number-operators.md +449 -442
  58. package/docs/optional-marker-guide.md +326 -321
  59. package/docs/performance-guide.md +49 -0
  60. package/docs/plugin-system.md +381 -542
  61. package/docs/plugin-type-registration.md +34 -0
  62. package/docs/postgresql-exporter.md +311 -304
  63. package/docs/public/favicon.svg +5 -0
  64. package/docs/quick-start.md +435 -761
  65. package/docs/runtime-locale-support.md +532 -521
  66. package/docs/schema-helper.md +345 -340
  67. package/docs/schema-utils-advanced-issues.md +23 -0
  68. package/docs/schema-utils-best-practices.md +20 -0
  69. package/docs/schema-utils-chaining.md +150 -143
  70. package/docs/schema-utils.md +524 -490
  71. package/docs/security-checklist.md +20 -0
  72. package/docs/string-extensions.md +488 -480
  73. package/docs/troubleshooting.md +486 -471
  74. package/docs/type-converter.md +310 -319
  75. package/docs/type-reference.md +242 -219
  76. package/docs/typescript-guide.md +584 -573
  77. package/docs/union-type-guide.md +157 -147
  78. package/docs/union-types.md +284 -277
  79. package/docs/validate-async.md +491 -480
  80. package/docs/validate-batch.md +49 -0
  81. package/docs/validate-dsl-object-support.md +578 -573
  82. package/docs/validate.md +506 -486
  83. package/docs/validation-guide.md +502 -484
  84. package/docs/validator.md +39 -0
  85. package/package.json +131 -73
  86. package/plugins/custom-format.cjs +8 -0
  87. package/plugins/custom-type-example.cjs +8 -0
  88. package/plugins/custom-validator.cjs +8 -0
  89. package/src/adapters/DslAdapter.ts +111 -0
  90. package/src/adapters/index.ts +1 -0
  91. package/src/config/constants.ts +83 -0
  92. package/src/config/index.ts +2 -0
  93. package/src/config/patterns.ts +77 -0
  94. package/src/core/CacheManager.ts +169 -0
  95. package/src/core/ConditionalBuilder.ts +382 -0
  96. package/src/core/ConditionalRuntime.ts +28 -0
  97. package/src/core/ConditionalValidator.ts +255 -0
  98. package/src/core/DslBuilder.ts +687 -0
  99. package/src/core/ErrorCodes.ts +38 -0
  100. package/src/core/ErrorFormatter.ts +271 -0
  101. package/src/core/JSONSchemaCore.ts +65 -0
  102. package/src/core/Locale.ts +187 -0
  103. package/src/core/MessageTemplate.ts +42 -0
  104. package/src/core/ObjectDslBuilder.ts +64 -0
  105. package/src/core/PluginManager.ts +326 -0
  106. package/src/core/StringExtensions.ts +140 -0
  107. package/src/core/TemplateEngine.ts +44 -0
  108. package/src/core/Validator.ts +448 -0
  109. package/src/errors/I18nError.ts +159 -0
  110. package/src/errors/ValidationError.ts +105 -0
  111. package/src/exporters/BaseExporter.ts +60 -0
  112. package/src/exporters/MarkdownExporter.ts +305 -0
  113. package/src/exporters/MongoDBExporter.ts +126 -0
  114. package/src/exporters/MySQLExporter.ts +156 -0
  115. package/src/exporters/PostgreSQLExporter.ts +222 -0
  116. package/src/exporters/index.ts +18 -0
  117. package/src/index.ts +651 -0
  118. package/{lib/locales/en-US.js → src/locales/en-US.ts} +160 -176
  119. package/{lib/locales/es-ES.js → src/locales/es-ES.ts} +160 -113
  120. package/{lib/locales/fr-FR.js → src/locales/fr-FR.ts} +160 -113
  121. package/src/locales/index.ts +103 -0
  122. package/{lib/locales/ja-JP.js → src/locales/ja-JP.ts} +160 -118
  123. package/src/locales/types.ts +156 -0
  124. package/{lib/locales/zh-CN.js → src/locales/zh-CN.ts} +160 -177
  125. package/src/parser/ConstraintParser.ts +101 -0
  126. package/src/parser/DslParser.ts +470 -0
  127. package/src/parser/SchemaCompiler.ts +66 -0
  128. package/src/parser/TypeRegistry.ts +250 -0
  129. package/src/parser/index.ts +6 -0
  130. package/src/plugins/custom-format.ts +124 -0
  131. package/src/plugins/custom-type-example.ts +106 -0
  132. package/src/plugins/custom-validator.ts +138 -0
  133. package/src/types/conditional.ts +28 -0
  134. package/src/types/config.ts +59 -0
  135. package/src/types/dsl.ts +131 -0
  136. package/src/types/error.ts +60 -0
  137. package/src/types/index.ts +17 -0
  138. package/src/types/infer.ts +128 -0
  139. package/src/types/plugin.ts +58 -0
  140. package/src/types/safe-regex.d.ts +9 -0
  141. package/src/types/schema.ts +66 -0
  142. package/src/types/validate.ts +71 -0
  143. package/src/utils/SchemaHelper.ts +196 -0
  144. package/src/utils/SchemaUtils.ts +365 -0
  145. package/src/utils/TypeConverter.ts +215 -0
  146. package/src/utils/index.ts +10 -0
  147. package/src/validators/CustomKeywords.ts +477 -0
  148. package/.eslintignore +0 -11
  149. package/.eslintrc.json +0 -27
  150. package/CONTRIBUTING.md +0 -368
  151. package/STATUS.md +0 -491
  152. package/changelogs/v1.0.0.md +0 -328
  153. package/changelogs/v1.0.9.md +0 -367
  154. package/changelogs/v1.1.0.md +0 -389
  155. package/changelogs/v1.1.1.md +0 -308
  156. package/changelogs/v1.1.2.md +0 -183
  157. package/changelogs/v1.1.3.md +0 -161
  158. package/changelogs/v1.1.4.md +0 -432
  159. package/changelogs/v1.1.5.md +0 -493
  160. package/changelogs/v1.1.6.md +0 -211
  161. package/changelogs/v1.1.8.md +0 -376
  162. package/changelogs/v1.2.3.md +0 -124
  163. package/docs/INDEX.md +0 -252
  164. package/docs/issues-resolved-summary.md +0 -196
  165. package/docs/performance-benchmark-report.md +0 -179
  166. package/docs/performance-quick-reference.md +0 -123
  167. package/docs/user-questions-answered.md +0 -353
  168. package/docs/validation-rules-v1.0.2.md +0 -1608
  169. package/examples/README.md +0 -81
  170. package/examples/array-dsl-example.js +0 -227
  171. package/examples/conditional-example.js +0 -288
  172. package/examples/conditional-non-object.js +0 -129
  173. package/examples/conditional-validate-example.js +0 -321
  174. package/examples/custom-extension.js +0 -85
  175. package/examples/dsl-match-example.js +0 -74
  176. package/examples/dsl-style.js +0 -118
  177. package/examples/dynamic-locale-configuration.js +0 -348
  178. package/examples/dynamic-locale-example.js +0 -287
  179. package/examples/enum.examples.js +0 -324
  180. package/examples/export-demo.js +0 -130
  181. package/examples/express-integration.js +0 -376
  182. package/examples/i18n-error-handling-complete.js +0 -381
  183. package/examples/i18n-error-handling-quickstart.md +0 -0
  184. package/examples/i18n-error.examples.js +0 -181
  185. package/examples/i18n-full-demo.js +0 -301
  186. package/examples/i18n-memory-safety.examples.js +0 -268
  187. package/examples/markdown-export.js +0 -71
  188. package/examples/middleware-usage.js +0 -93
  189. package/examples/new-features-comparison.js +0 -315
  190. package/examples/password-reset/README.md +0 -153
  191. package/examples/password-reset/schema.js +0 -26
  192. package/examples/password-reset/test.js +0 -101
  193. package/examples/plugin-system.examples.js +0 -205
  194. package/examples/schema-utils-chaining.examples.js +0 -250
  195. package/examples/simple-example.js +0 -122
  196. package/examples/slug.examples.js +0 -179
  197. package/examples/string-extensions.js +0 -297
  198. package/examples/union-type-example.js +0 -127
  199. package/examples/union-types-example.js +0 -77
  200. package/examples/user-registration/README.md +0 -156
  201. package/examples/user-registration/routes.js +0 -92
  202. package/examples/user-registration/schema.js +0 -150
  203. package/examples/user-registration/server.js +0 -74
  204. package/index.d.ts +0 -3658
  205. package/index.js +0 -475
  206. package/index.mjs +0 -60
  207. package/lib/adapters/DslAdapter.js +0 -995
  208. package/lib/adapters/index.js +0 -20
  209. package/lib/config/constants.js +0 -286
  210. package/lib/config/patterns/common.js +0 -47
  211. package/lib/config/patterns/creditCard.js +0 -9
  212. package/lib/config/patterns/idCard.js +0 -9
  213. package/lib/config/patterns/index.js +0 -9
  214. package/lib/config/patterns/licensePlate.js +0 -4
  215. package/lib/config/patterns/passport.js +0 -4
  216. package/lib/config/patterns/phone.js +0 -9
  217. package/lib/config/patterns/postalCode.js +0 -5
  218. package/lib/core/CacheManager.js +0 -376
  219. package/lib/core/ConditionalBuilder.js +0 -503
  220. package/lib/core/DslBuilder.js +0 -1589
  221. package/lib/core/ErrorCodes.js +0 -233
  222. package/lib/core/ErrorFormatter.js +0 -445
  223. package/lib/core/JSONSchemaCore.js +0 -347
  224. package/lib/core/Locale.js +0 -130
  225. package/lib/core/MessageTemplate.js +0 -98
  226. package/lib/core/PluginManager.js +0 -448
  227. package/lib/core/StringExtensions.js +0 -240
  228. package/lib/core/Validator.js +0 -654
  229. package/lib/errors/I18nError.js +0 -328
  230. package/lib/errors/ValidationError.js +0 -191
  231. package/lib/exporters/MarkdownExporter.js +0 -420
  232. package/lib/exporters/MongoDBExporter.js +0 -162
  233. package/lib/exporters/MySQLExporter.js +0 -212
  234. package/lib/exporters/PostgreSQLExporter.js +0 -289
  235. package/lib/exporters/index.js +0 -24
  236. package/lib/locales/index.js +0 -8
  237. package/lib/utils/LRUCache.js +0 -174
  238. package/lib/utils/SchemaHelper.js +0 -240
  239. package/lib/utils/SchemaUtils.js +0 -445
  240. package/lib/utils/TypeConverter.js +0 -245
  241. package/lib/utils/index.js +0 -13
  242. package/lib/validators/CustomKeywords.js +0 -616
  243. package/lib/validators/index.js +0 -11
@@ -1,551 +1,567 @@
1
- # 数据库导出限制说明
2
-
3
- > **重要提示**: 在使用 schema-dsl 导出数据库 Schema 功能时,请仔细阅读本文档,了解哪些特性可以导出,哪些不支持。
4
-
5
- ---
6
-
7
- ## 📑 目录
8
-
9
- - [核心原则](#核心原则)
10
- - [不支持导出的特性](#不支持导出的特性)
11
- - [部分支持的特性](#部分支持的特性)
12
- - [完全支持的特性](#完全支持的特性)
13
- - [数据库特定限制](#数据库特定限制)
14
- - [最佳实践建议](#最佳实践建议)
15
-
16
- ---
17
-
18
- ## 核心原则
19
-
20
- **schema-dsl 的数据库导出功能遵循以下原则**:
21
-
22
- 1. ✅ **静态结构优先**: 只导出固定的、静态的 Schema 定义
23
- 2. ❌ **动态逻辑不导出**: 运行时条件逻辑、动态计算等无法转换为数据库约束
24
- 3. ⚠️ **约束映射有限**: 数据库原生约束能力有限,部分高级约束会被忽略或简化
25
- 4. 🎯 **类型映射为主**: 主要关注类型定义和基础约束(长度、范围、必填等)
26
-
27
- ---
28
-
29
- ## 不支持导出的特性
30
-
31
- 以下 schema-dsl 特性**无法导出到数据库 Schema**(会被忽略):
32
-
33
- ### 1. 条件验证逻辑 ❌
34
-
35
- #### `dsl.match()` - 条件字段映射
36
-
37
- ```javascript
38
- // ❌ 无法导出
39
- const schema = dsl({
40
- contactType: 'email|phone',
41
- contact: dsl.match('contactType', {
42
- email: 'email!',
43
- phone: 'phone:cn!'
44
- })
45
- });
46
- ```
47
-
48
- **原因**: 数据库不支持"根据 A 字段值决定 B 字段类型"的动态约束。
49
-
50
- **替代方案**:
51
- - 导出为最宽松的类型(`VARCHAR(255)`)
52
- - 验证逻辑保留在应用层(使用 SchemaI-DSL 验证器)
53
-
54
- ---
55
-
56
- #### `dsl.if()` - 条件验证
57
-
58
- ```javascript
59
- // ❌ 无法导出
60
- const schema = dsl({
61
- isVip: 'boolean',
62
- discount: dsl.if('isVip', 'number:10-100!', 'number:0-10')
63
- });
64
- ```
65
-
66
- **原因**: 同上,数据库不支持条件约束。
67
-
68
- ---
69
-
70
- ### 2. 复杂的 JSON Schema 关键字 ❌
71
-
72
- 以下 JSON Schema 高级特性无法导出:
73
-
74
- | 关键字 | 说明 | 导出行为 |
75
- |--------|------|----------|
76
- | `allOf` | 所有 Schema 都满足 | ❌ 忽略 |
77
- | `anyOf` | 满足任一 Schema | 忽略 |
78
- | `oneOf` | 仅满足一个 Schema | 忽略 |
79
- | `not` | 不满足某 Schema | ❌ 忽略 |
80
- | `if/then/else` | 条件 Schema | ❌ 忽略 |
81
- | `dependencies` | 字段依赖关系 | ❌ 忽略 |
82
-
83
- **示例**:
84
-
85
- ```javascript
86
- // 这些结构无法导出
87
- const schema = {
88
- type: 'object',
89
- allOf: [
90
- { properties: { name: { type: 'string' } } },
91
- { properties: { age: { type: 'number' } } }
92
- ]
93
- };
94
- ```
95
-
96
- ---
97
-
98
- ### 3. 自定义验证器 ❌
99
-
100
- ```javascript
101
- // ❌ 自定义验证器无法导出
102
- const schema = dsl('string:3-32!')
103
- .custom((value) => value.startsWith('USER_'))
104
- .messages({ 'string.custom': '必须以 USER_ 开头' });
105
- ```
106
-
107
- **原因**: 数据库无法执行 JavaScript 函数。
108
-
109
- **替代方案**:
110
- - 使用 `pattern` 正则表达式(如果可表达)
111
- - 验证逻辑保留在应用层
112
-
113
- ---
114
-
115
- ### 4. 自定义错误消息 ❌
116
-
117
- ```javascript
118
- // ❌ 错误消息无法导出
119
- const schema = dsl('email!')
120
- .messages({
121
- 'string.format': '请输入有效的邮箱地址'
122
- })
123
- .label('用户邮箱');
124
- ```
125
-
126
- **导出行为**:
127
- - `label()` 会导出为 `COMMENT`(MySQL/PostgreSQL)
128
- - `messages()` 会被忽略(数据库不存储错误消息)
129
-
130
- ---
131
-
132
- ### 5. 嵌套对象的深度约束 ⚠️
133
-
134
- ```javascript
135
- // ⚠️ 嵌套对象会简化为 JSON/JSONB 类型
136
- const schema = dsl({
137
- profile: {
138
- bio: 'string:500',
139
- avatar: 'url',
140
- social: {
141
- twitter: 'url',
142
- github: 'url'
143
- }
144
- }
145
- });
146
- ```
147
-
148
- **导出行为**:
149
- - MongoDB: ✅ 完整支持嵌套验证
150
- - MySQL: ❌ 导出为 `JSON` 类型,内部约束丢失
151
- - PostgreSQL: ❌ 导出为 `JSONB` 类型,内部约束丢失
152
-
153
- ---
154
-
155
- ## 部分支持的特性
156
-
157
- 以下特性在不同数据库中支持程度不同:
158
-
159
- ### 1. 正则表达式约束 ⚠️
160
-
161
- ```javascript
162
- const schema = dsl('string!')
163
- .pattern(/^[A-Z][a-z]+$/);
164
- ```
165
-
166
- | 数据库 | 支持程度 | 导出结果 |
167
- |--------|----------|----------|
168
- | MongoDB | ✅ 完全支持 | `pattern: "^[A-Z][a-z]+$"` |
169
- | MySQL | ❌ 不支持 | 忽略 |
170
- | PostgreSQL | ❌ 不支持 | 忽略 |
171
-
172
- **注意**: MySQL 和 PostgreSQL 没有原生的正则约束,需在应用层验证。
173
-
174
- ---
175
-
176
- ### 2. 数值范围约束 ⚠️
177
-
178
- ```javascript
179
- const schema = dsl('number:18-120');
180
- ```
181
-
182
- | 数据库 | 支持程度 | 导出结果 |
183
- |--------|----------|----------|
184
- | MongoDB | ✅ 完全支持 | `minimum: 18, maximum: 120` |
185
- | MySQL | ❌ 不支持 | 忽略 |
186
- | PostgreSQL | ✅ 支持 | `CHECK (age BETWEEN 18 AND 120)` |
187
-
188
- ---
189
-
190
- ### 3. 字符串长度约束 ⚠️
191
-
192
- ```javascript
193
- const schema = dsl('string:3-32');
194
- ```
195
-
196
- | 数据库 | 支持程度 | 导出结果 |
197
- |--------|----------|----------|
198
- | MongoDB | ✅ 完全支持 | `minLength: 3, maxLength: 32` |
199
- | MySQL | ⚠️ 仅 maxLength | `VARCHAR(32)` |
200
- | PostgreSQL | ✅ 完全支持 | `VARCHAR(32) CHECK (LENGTH(...) >= 3)` |
201
-
202
- ---
203
-
204
- ### 4. 枚举约束 ⚠️
205
-
206
- ```javascript
207
- const schema = dsl('active|inactive|banned');
208
- ```
209
-
210
- | 数据库 | 支持程度 | 导出结果 |
211
- |--------|----------|----------|
212
- | MongoDB | ✅ 完全支持 | `enum: ['active', 'inactive', 'banned']` |
213
- | MySQL | ❌ 不支持 | `VARCHAR(255)` |
214
- | PostgreSQL | ✅ 支持 | `CHECK (status IN (...))` |
215
-
216
- ---
217
-
218
- ### 5. 数组约束 ⚠️
219
-
220
- ```javascript
221
- const schema = dsl('array!1-10<string:3-32>');
222
- ```
223
-
224
- | 数据库 | 支持程度 | 导出结果 |
225
- |--------|----------|----------|
226
- | MongoDB | ✅ 完全支持 | `type: array, minItems: 1, maxItems: 10, items: {...}` |
227
- | MySQL | ❌ 简化 | `JSON` |
228
- | PostgreSQL | ❌ 简化 | `JSONB` |
229
-
230
- ---
231
-
232
- ## 完全支持的特性
233
-
234
- 以下特性在所有数据库中都能良好导出:
235
-
236
- ### 基础类型
237
-
238
- ```javascript
239
- dsl({
240
- name: 'string!',
241
- age: 'number',
242
- active: 'boolean',
243
- createdAt: 'datetime!'
244
- })
245
- ```
246
-
247
- **所有数据库都支持类型映射**。
248
-
249
- ---
250
-
251
- ### ✅ 必填约束
252
-
253
- ```javascript
254
- dsl({
255
- email: 'email!', // 必填
256
- phone: 'phone:cn' // 可选
257
- })
258
- ```
259
-
260
- **导出为**:
261
- - MongoDB: `required: ['email']`
262
- - MySQL/PostgreSQL: `NOT NULL` / `NULL`
263
-
264
- ---
265
-
266
- ### ✅ 默认值(仅 MySQL/PostgreSQL)
267
-
268
- ```javascript
269
- const schema = dsl('boolean')
270
- .default(false);
271
- ```
272
-
273
- **导出为**:
274
- - MongoDB: ❌ 不支持 `default`
275
- - MySQL/PostgreSQL: ✅ `DEFAULT false`
276
-
277
- ---
278
-
279
- ### ✅ 字段描述
280
-
281
- ```javascript
282
- const schema = dsl('string!')
283
- .description('用户登录名');
284
- ```
285
-
286
- **导出为**:
287
- - MongoDB: `description: "用户登录名"`
288
- - MySQL: `COMMENT '用户登录名'`
289
- - PostgreSQL: `COMMENT ON COLUMN ... IS '用户登录名'`
290
-
291
- ---
292
-
293
- ## 数据库特定限制
294
-
295
- ### MongoDB
296
-
297
- | 限制 | 说明 |
298
- |------|------|
299
- | ❌ 不支持 `default` | MongoDB JSON Schema 不支持默认值 |
300
- | ❌ 不支持外键 | 需在应用层实现引用完整性 |
301
- | ✅ 最完整的约束支持 | 正则、范围、枚举、数组约束都支持 |
302
-
303
- ---
304
-
305
- ### MySQL
306
-
307
- | 限制 | 说明 |
308
- |------|------|
309
- | ❌ 不支持正则 | 无法导出 `pattern` 约束 |
310
- | 不支持数值范围 | 无法导出 `minimum/maximum` |
311
- | ❌ 不支持枚举 CHECK | 枚举导出为普通 `VARCHAR` |
312
- | ⚠️ 字符串长度仅 maxLength | `minLength` 会被忽略 |
313
- | ❌ 对象/数组简化为 JSON | 内部结构约束丢失 |
314
-
315
- ---
316
-
317
- ### PostgreSQL
318
-
319
- | 限制 | 说明 |
320
- |------|------|
321
- | 不支持正则 | 无法导出 `pattern` 约束 |
322
- | 支持 CHECK 约束 | 可导出范围、枚举、长度约束 |
323
- | ❌ 对象/数组简化为 JSONB | 内部结构约束丢失 |
324
- | ✅ 完整的注释支持 | `COMMENT ON COLUMN` |
325
-
326
- ---
327
-
328
- ## 最佳实践建议
329
-
330
- ### 1. 分层验证策略 🎯
331
-
332
- ```
333
- ┌─────────────────────────────────────────┐
334
- │ 应用层(SchemaI-DSL 完整验证) │
335
- │ - 条件逻辑(match/if) │
336
- │ - 自定义验证器 │
337
- │ - 复杂约束(正则、范围等) │
338
- │ - 友好的错误消息 │
339
- └─────────────────────────────────────────┘
340
-
341
- ┌─────────────────────────────────────────┐
342
- │ 数据库层(基础约束) │
343
- │ - 类型定义(string/number/boolean)
344
- │ - NOT NULL 约束
345
- │ - 主键/外键
346
- │ - 简单长度限制(maxLength)
347
- └─────────────────────────────────────────┘
348
- ```
349
-
350
- **原则**:
351
- - 数据库:防止数据损坏的最后一道防线
352
- - 应用层:完整的业务逻辑验证
353
-
354
- ---
355
-
356
- ### 2. 明确导出前的预期 📋
357
-
358
- 在使用导出功能前,请先检查 Schema 是否包含不支持的特性:
359
-
360
- ```javascript
361
- const { dsl, exporters } = require('schema-dsl');
362
-
363
- // ❌ 不适合导出的 Schema(包含条件逻辑)
364
- const conditionalSchema = dsl({
365
- type: 'email|phone',
366
- value: dsl.match('type', {
367
- email: 'email!',
368
- phone: 'phone:cn!'
369
- })
370
- });
371
-
372
- // 适合导出的 Schema(静态定义)
373
- const staticSchema = dsl({
374
- id: 'uuid!',
375
- email: 'email!',
376
- phone: 'string:11',
377
- status: 'active|inactive',
378
- createdAt: 'datetime!'
379
- });
380
-
381
- // 导出前先了解限制
382
- const exporter = new exporters.MySQLExporter();
383
- const ddl = exporter.export('users', staticSchema);
384
- ```
385
-
386
- ---
387
-
388
- ### 3. 使用描述说明约束 📝
389
-
390
- 对于无法导出的约束,使用 `description()` 在数据库中留下说明:
391
-
392
- ```javascript
393
- const schema = dsl('string!')
394
- .pattern(/^[A-Z][a-z]+$/)
395
- .description('首字母大写,其余小写(正则:^[A-Z][a-z]+$)');
396
- ```
397
-
398
- **导出为**:
399
-
400
- ```sql
401
- -- MySQL
402
- `name` VARCHAR(255) NOT NULL COMMENT '首字母大写,其余小写(正则:^[A-Z][a-z]+$)'
403
-
404
- -- PostgreSQL
405
- COMMENT ON COLUMN users.name IS '首字母大写,其余小写(正则:^[A-Z][a-z]+$)';
406
- ```
407
-
408
- ---
409
-
410
- ### 4. 保留完整 Schema 定义 💾
411
-
412
- ```javascript
413
- // schemas/user.js
414
- const { dsl } = require('schema-dsl');
415
-
416
- // 完整定义(包含所有验证逻辑)
417
- const userSchema = dsl({
418
- username: 'string:3-32!'
419
- .pattern(/^[a-zA-Z0-9_]+$/)
420
- .messages({ 'string.pattern': '只能包含字母数字下划线' })
421
- .description('用户登录名'),
422
-
423
- contactType: 'email|phone',
424
- contact: dsl.match('contactType', {
425
- email: 'email!',
426
- phone: 'phone:cn!'
427
- })
428
- });
429
-
430
- module.exports = {
431
- // 应用层使用完整 Schema
432
- full: userSchema,
433
-
434
- // 数据库导出使用简化 Schema
435
- db: dsl({
436
- username: 'string:3-32!'.description('用户登录名'),
437
- contactType: 'email|phone',
438
- contact: 'string!'.description('邮箱或手机号(根据 contactType)')
439
- })
440
- };
441
- ```
442
-
443
- ---
444
-
445
- ### 5. 文档化不兼容特性 📖
446
-
447
- 在项目文档中明确说明哪些验证逻辑在数据库层不生效:
448
-
449
- ```markdown
450
- ## 数据验证说明
451
-
452
- ### 应用层验证(SchemaI-DSL)
453
- - ✅ `contact` 字段根据 `contactType` 动态验证
454
- - 用户名正则验证(`^[a-zA-Z0-9_]+$`)
455
- - ✅ 自定义业务规则验证
456
-
457
- ### 数据库层约束
458
- - ✅ `username` 长度限制(3-32 字符)
459
- - ✅ 必填字段约束
460
- - ❌ 动态类型验证(依赖应用层)
461
- - ❌ 正则表达式验证(依赖应用层)
462
- ```
463
-
464
- ---
465
-
466
- ## 常见问题
467
-
468
- ### Q1: 为什么 `dsl.match()` 不能导出?
469
-
470
- **A**: 数据库不支持"根据字段 A 的值决定字段 B 的类型"这种动态约束。数据库 Schema 在创建时就固定了,无法运行时改变。
471
-
472
- **解决方案**:
473
- - 导出为最宽松的类型(如 `VARCHAR(255)`)
474
- - 应用层使用完整 Schema 验证
475
-
476
- ---
477
-
478
- ### Q2: MySQL 不支持正则,怎么办?
479
-
480
- **A**: MySQL 的 `CHECK` 约束不支持正则表达式。
481
-
482
- **解决方案**:
483
- 1. 应用层验证(推荐)
484
- 2. 使用触发器(不推荐,复杂且难维护)
485
- 3. 在 `COMMENT` 中说明约束规则
486
-
487
- ---
488
-
489
- ### Q3: 嵌套对象导出后丢失约束?
490
-
491
- **A**: MySQL/PostgreSQL 将嵌套对象导出为 `JSON`/`JSONB` 类型,内部约束无法表达。
492
-
493
- **解决方案**:
494
- - MongoDB: 完整支持嵌套验证
495
- - MySQL/PostgreSQL: 应用层验证
496
-
497
- ---
498
-
499
- ### Q4: 如何检查 Schema 是否适合导出?
500
-
501
- **A**: 以下特性**不适合**导出:
502
-
503
- ```javascript
504
- // 包含条件逻辑
505
- dsl.match(...)
506
- dsl.if(...)
507
-
508
- // 包含自定义验证器
509
- .custom(...)
510
-
511
- // ❌ 复杂的 allOf/anyOf/oneOf
512
- { allOf: [...] }
513
- ```
514
-
515
- **适合导出**的特性:
516
-
517
- ```javascript
518
- // ✅ 基础类型 + 简单约束
519
- dsl('string:3-32!')
520
- dsl('number:0-100')
521
- dsl('email!')
522
- dsl('active|inactive|banned')
523
- ```
524
-
525
- ---
526
-
527
- ## 总结
528
-
529
- | 特性 | MongoDB | MySQL | PostgreSQL |
530
- |------|---------|-------|------------|
531
- | 基础类型 | ✅ | ✅ | ✅ |
532
- | 必填约束 | ✅ | ✅ | ✅ |
533
- | 长度约束 | ✅ | ⚠️ 仅 max | ✅ |
534
- | 数值范围 | ✅ | ❌ | ✅ |
535
- | 正则表达式 | ✅ | ❌ | ❌ |
536
- | 枚举 | ✅ | ❌ | ✅ |
537
- | 条件逻辑 | ❌ | ❌ | ❌ |
538
- | 自定义验证器 | | | |
539
- | 嵌套对象 | ✅ | ⚠️ JSON | ⚠️ JSONB |
540
- | 字段描述 | ✅ | ✅ | ✅ |
541
-
542
- ---
543
-
544
- ## 相关文档
545
-
546
- - [数据库导出指南](export-guide.md)
547
- - [MongoDB 导出器](mongodb-exporter.md)
548
- - [MySQL 导出器](mysql-exporter.md)
549
- - [PostgreSQL 导出器](postgresql-exporter.md)
550
- - [最佳实践](best-practices.md)
551
-
1
+ # 数据库导出限制说明
2
+
3
+ > **重要提示**: 在使用 schema-dsl 导出数据库 Schema 功能时,请仔细阅读本文档,了解哪些特性可以导出,哪些不支持。
4
+
5
+ ---
6
+
7
+ ## 📑 目录
8
+
9
+ - [核心原则](#核心原则)
10
+ - [不支持导出的特性](#不支持导出的特性)
11
+ - [部分支持的特性](#部分支持的特性)
12
+ - [完全支持的特性](#完全支持的特性)
13
+ - [数据库特定限制](#数据库特定限制)
14
+ - [最佳实践建议](#最佳实践建议)
15
+
16
+ ---
17
+
18
+ ## 核心原则
19
+
20
+ **schema-dsl 的数据库导出功能遵循以下原则**:
21
+
22
+ 1. ✅ **静态结构优先**: 只导出固定的、静态的 Schema 定义
23
+ 2. ❌ **动态逻辑不导出**: 运行时条件逻辑、动态计算等无法转换为数据库约束
24
+ 3. ⚠️ **约束映射有限**: 数据库原生约束能力有限,部分高级约束会被忽略或简化
25
+ 4. 🎯 **类型映射为主**: 主要关注类型定义和基础约束(长度、范围、必填等)
26
+
27
+ ---
28
+
29
+ ## 不支持导出的特性
30
+
31
+ 以下 schema-dsl 特性**无法导出到数据库 Schema**(会被忽略):
32
+
33
+ ### 1. 条件验证逻辑 ❌
34
+
35
+ #### `dsl.match()` - 条件字段映射
36
+
37
+ ```javascript
38
+ // ❌ 无法导出
39
+ const schema = dsl({
40
+ contactType: 'email|phone',
41
+ contact: dsl.match('contactType', {
42
+ email: 'email!',
43
+ phone: 'phone:cn!'
44
+ })
45
+ });
46
+ ```
47
+
48
+ **原因**: 数据库不支持"根据 A 字段值决定 B 字段类型"的动态约束。
49
+
50
+ **替代方案**:
51
+ - 导出为最宽松的类型(`VARCHAR(255)`)
52
+ - 验证逻辑保留在应用层(使用 schema-dsl 验证器)
53
+
54
+ ---
55
+
56
+ #### `dsl.if()` - 条件验证
57
+
58
+ ```javascript
59
+ // ❌ 无法导出
60
+ const schema = dsl({
61
+ isVip: 'boolean',
62
+ discount: dsl.if('isVip', 'number:10-100!', 'number:0-10')
63
+ });
64
+ ```
65
+
66
+ **原因**: 同上,数据库不支持条件约束。
67
+
68
+ ---
69
+
70
+ ### 2. 复杂的 JSON Schema 关键字 ❌
71
+
72
+ 以下 JSON Schema 高级特性无法导出:
73
+
74
+ | 关键字 | 说明 | 导出行为 |
75
+ |--------|------|----------|
76
+ | `allOf` | 所有 Schema 都满足 | ❌ 忽略 |
77
+ | `anyOf` | 满足任一 Schema | ⚠️ 仅当所有分支映射到同一 SQL 类型时可导出;否则抛错 |
78
+ | `oneOf` | 仅满足一个 Schema | ⚠️ 仅当所有分支映射到同一 SQL 类型时可导出;否则抛错 |
79
+ | `not` | 不满足某 Schema | ❌ 忽略 |
80
+ | `if/then/else` | 条件 Schema | ❌ 忽略 |
81
+ | `dependencies` | 字段依赖关系 | ❌ 忽略 |
82
+
83
+ **示例**:
84
+
85
+ ```javascript
86
+ // ⚠️ 这些结构无法直接稳定导出到单一 SQL 列类型
87
+ const schema = {
88
+ type: 'object',
89
+ properties: {
90
+ value: {
91
+ anyOf: [
92
+ { type: 'string' },
93
+ { type: 'number' }
94
+ ]
95
+ }
96
+ }
97
+ };
98
+ ```
99
+
100
+ **当前行为**:
101
+
102
+ - `ipv4 | ipv6` 这类所有分支最终都映射为同一 SQL 列类型的联合,仍可导出
103
+ - `string | number` 这类会落到不同 SQL 列类型的联合,MySQL / PostgreSQL 导出器会**显式抛错**,而不是静默取第一项
104
+
105
+ ---
106
+
107
+ ### 3. 自定义验证器
108
+
109
+ ```javascript
110
+ // 自定义验证器无法导出
111
+ const schema = dsl('string:3-32!')
112
+ .custom((value) => value.startsWith('USER_'))
113
+ .messages({ 'string.custom': '必须以 USER_ 开头' });
114
+ ```
115
+
116
+ **原因**: 数据库无法执行 JavaScript 函数。
117
+
118
+ **替代方案**:
119
+ - 使用 `pattern` 正则表达式(如果可表达)
120
+ - 验证逻辑保留在应用层
121
+
122
+ ---
123
+
124
+ ### 4. 自定义错误消息 ❌
125
+
126
+ ```javascript
127
+ // 错误消息无法导出
128
+ const schema = dsl('email!')
129
+ .messages({
130
+ 'string.format': '请输入有效的邮箱地址'
131
+ })
132
+ .label('用户邮箱');
133
+ ```
134
+
135
+ **导出行为**:
136
+ - `label()` 会导出为 `COMMENT`(MySQL/PostgreSQL)
137
+ - ❌ `messages()` 会被忽略(数据库不存储错误消息)
138
+
139
+ ---
140
+
141
+ ### 5. 嵌套对象的深度约束 ⚠️
142
+
143
+ ```javascript
144
+ // ⚠️ 嵌套对象会简化为 JSON/JSONB 类型
145
+ const schema = dsl({
146
+ profile: {
147
+ bio: 'string:500',
148
+ avatar: 'url',
149
+ social: {
150
+ twitter: 'url',
151
+ github: 'url'
152
+ }
153
+ }
154
+ });
155
+ ```
156
+
157
+ **导出行为**:
158
+ - MongoDB: ✅ 完整支持嵌套验证
159
+ - MySQL: 导出为 `JSON` 类型,内部约束丢失
160
+ - PostgreSQL: ❌ 导出为 `JSONB` 类型,内部约束丢失
161
+
162
+ ---
163
+
164
+ ## 部分支持的特性
165
+
166
+ 以下特性在不同数据库中支持程度不同:
167
+
168
+ ### 1. 正则表达式约束 ⚠️
169
+
170
+ ```javascript
171
+ const schema = dsl('string!')
172
+ .pattern(/^[A-Z][a-z]+$/);
173
+ ```
174
+
175
+ | 数据库 | 支持程度 | 导出结果 |
176
+ |--------|----------|----------|
177
+ | MongoDB | ✅ 完全支持 | `pattern: "^[A-Z][a-z]+$"` |
178
+ | MySQL | ❌ 不支持 | 忽略 |
179
+ | PostgreSQL | ❌ 不支持 | 忽略 |
180
+
181
+ **注意**: MySQL 和 PostgreSQL 没有原生的正则约束,需在应用层验证。
182
+
183
+ ---
184
+
185
+ ### 2. 数值范围约束 ⚠️
186
+
187
+ ```javascript
188
+ const schema = dsl('number:18-120');
189
+ ```
190
+
191
+ | 数据库 | 支持程度 | 导出结果 |
192
+ |--------|----------|----------|
193
+ | MongoDB | ✅ 完全支持 | `minimum: 18, maximum: 120` |
194
+ | MySQL | ❌ 不支持 | 忽略 |
195
+ | PostgreSQL | ✅ 支持 | `CHECK (age BETWEEN 18 AND 120)` |
196
+
197
+ ---
198
+
199
+ ### 3. 字符串长度约束 ⚠️
200
+
201
+ ```javascript
202
+ const schema = dsl('string:3-32');
203
+ ```
204
+
205
+ | 数据库 | 支持程度 | 导出结果 |
206
+ |--------|----------|----------|
207
+ | MongoDB | ✅ 完全支持 | `minLength: 3, maxLength: 32` |
208
+ | MySQL | ⚠️ 仅 maxLength | `VARCHAR(32)` |
209
+ | PostgreSQL | ✅ 完全支持 | `VARCHAR(32) CHECK (LENGTH(...) >= 3)` |
210
+
211
+ ---
212
+
213
+ ### 4. 枚举约束 ⚠️
214
+
215
+ ```javascript
216
+ const schema = dsl('active|inactive|banned');
217
+ ```
218
+
219
+ | 数据库 | 支持程度 | 导出结果 |
220
+ |--------|----------|----------|
221
+ | MongoDB | ✅ 完全支持 | `enum: ['active', 'inactive', 'banned']` |
222
+ | MySQL | ❌ 不支持 | `VARCHAR(255)` |
223
+ | PostgreSQL | ✅ 支持 | `CHECK (status IN (...))` |
224
+
225
+ ---
226
+
227
+ ### 5. 数组约束 ⚠️
228
+
229
+ ```javascript
230
+ const schema = dsl('array!1-10<string:3-32>');
231
+ ```
232
+
233
+ | 数据库 | 支持程度 | 导出结果 |
234
+ |--------|----------|----------|
235
+ | MongoDB | ✅ 完全支持 | `type: array, minItems: 1, maxItems: 10, items: {...}` |
236
+ | MySQL | ❌ 简化 | `JSON` |
237
+ | PostgreSQL | ❌ 简化 | `JSONB` |
238
+
239
+ ---
240
+
241
+ ## 完全支持的特性
242
+
243
+ 以下特性在所有数据库中都能良好导出:
244
+
245
+ ### ✅ 基础类型
246
+
247
+ ```javascript
248
+ dsl({
249
+ name: 'string!',
250
+ age: 'number',
251
+ active: 'boolean',
252
+ createdAt: 'datetime!'
253
+ })
254
+ ```
255
+
256
+ **所有数据库都支持类型映射**。
257
+
258
+ ---
259
+
260
+ ### ✅ 必填约束
261
+
262
+ ```javascript
263
+ dsl({
264
+ email: 'email!', // 必填
265
+ phone: 'phone:cn' // 可选
266
+ })
267
+ ```
268
+
269
+ **导出为**:
270
+ - MongoDB: `required: ['email']`
271
+ - MySQL/PostgreSQL: `NOT NULL` / `NULL`
272
+
273
+ ---
274
+
275
+ ### ✅ 默认值(仅 MySQL/PostgreSQL
276
+
277
+ ```javascript
278
+ const schema = dsl('boolean')
279
+ .default(false);
280
+ ```
281
+
282
+ **导出为**:
283
+ - MongoDB: ❌ 不支持 `default`
284
+ - MySQL/PostgreSQL: ✅ `DEFAULT false`
285
+
286
+ ---
287
+
288
+ ### 字段描述
289
+
290
+ ```javascript
291
+ const schema = dsl('string!')
292
+ .description('用户登录名');
293
+ ```
294
+
295
+ **导出为**:
296
+ - MongoDB: `description: "用户登录名"`
297
+ - MySQL: `COMMENT '用户登录名'`
298
+ - PostgreSQL: `COMMENT ON COLUMN ... IS '用户登录名'`
299
+
300
+ ---
301
+
302
+ ## 数据库特定限制
303
+
304
+ ### MongoDB
305
+
306
+ | 限制 | 说明 |
307
+ |------|------|
308
+ | ❌ 不支持 `default` | MongoDB JSON Schema 不支持默认值 |
309
+ | ❌ 不支持外键 | 需在应用层实现引用完整性 |
310
+ | 最完整的约束支持 | 正则、范围、枚举、数组约束都支持 |
311
+
312
+ ---
313
+
314
+ ### MySQL
315
+
316
+ | 限制 | 说明 |
317
+ |------|------|
318
+ | ❌ 不支持正则 | 无法导出 `pattern` 约束 |
319
+ | 不支持数值范围 | 无法导出 `minimum/maximum` |
320
+ | ❌ 不支持枚举 CHECK | 枚举导出为普通 `VARCHAR` |
321
+ | ⚠️ 字符串长度仅 maxLength | `minLength` 会被忽略 |
322
+ | 对象/数组简化为 JSON | 内部结构约束丢失 |
323
+
324
+ ---
325
+
326
+ ### PostgreSQL
327
+
328
+ | 限制 | 说明 |
329
+ |------|------|
330
+ | 不支持正则 | 无法导出 `pattern` 约束 |
331
+ | ✅ 支持 CHECK 约束 | 可导出范围、枚举、长度约束 |
332
+ | ❌ 对象/数组简化为 JSONB | 内部结构约束丢失 |
333
+ | ✅ 完整的注释支持 | `COMMENT ON COLUMN` |
334
+
335
+ ---
336
+
337
+ ## 最佳实践建议
338
+
339
+ ### 1. 分层验证策略 🎯
340
+
341
+ ```text
342
+ ┌─────────────────────────────────────────┐
343
+ 应用层(schema-dsl 完整验证)
344
+ │ - 条件逻辑(match/if)
345
+ │ - 自定义验证器
346
+ │ - 复杂约束(正则、范围等)
347
+ │ - 友好的错误消息 │
348
+ └─────────────────────────────────────────┘
349
+
350
+ ┌─────────────────────────────────────────┐
351
+ │ 数据库层(基础约束) │
352
+ - 类型定义(string/number/boolean) │
353
+ │ - NOT NULL 约束 │
354
+ │ - 主键/外键 │
355
+ │ - 简单长度限制(maxLength) │
356
+ └─────────────────────────────────────────┘
357
+ ```
358
+
359
+ **原则**:
360
+ - 数据库:防止数据损坏的最后一道防线
361
+ - 应用层:完整的业务逻辑验证
362
+
363
+ ---
364
+
365
+ ### 2. 明确导出前的预期 📋
366
+
367
+ 在使用导出功能前,请先检查 Schema 是否包含不支持的特性:
368
+
369
+ ```javascript
370
+ const { dsl, exporters } = require('schema-dsl');
371
+
372
+ // 不适合导出的 Schema(包含条件逻辑)
373
+ const conditionalSchema = dsl({
374
+ type: 'email|phone',
375
+ value: dsl.match('type', {
376
+ email: 'email!',
377
+ phone: 'phone:cn!'
378
+ })
379
+ });
380
+
381
+ // ✅ 适合导出的 Schema(静态定义)
382
+ const staticSchema = dsl({
383
+ id: 'uuid!',
384
+ email: 'email!',
385
+ phone: 'string:11',
386
+ status: 'active|inactive',
387
+ createdAt: 'datetime!'
388
+ });
389
+
390
+ // 导出前先了解限制
391
+ const exporter = new exporters.MySQLExporter();
392
+ const ddl = exporter.export('users', staticSchema);
393
+ ```
394
+
395
+ ---
396
+
397
+ ### 3. 使用描述说明约束 📝
398
+
399
+ 对于无法导出的约束,使用 `description()` 在数据库中留下说明:
400
+
401
+ ```javascript
402
+ const schema = dsl('string!')
403
+ .pattern(/^[A-Z][a-z]+$/)
404
+ .description('首字母大写,其余小写(正则:^[A-Z][a-z]+$)');
405
+ ```
406
+
407
+ **导出为**:
408
+
409
+ ```sql
410
+ -- MySQL
411
+ `name` VARCHAR(255) NOT NULL COMMENT '首字母大写,其余小写(正则:^[A-Z][a-z]+$)'
412
+
413
+ -- PostgreSQL
414
+ COMMENT ON COLUMN users.name IS '首字母大写,其余小写(正则:^[A-Z][a-z]+$)';
415
+ ```
416
+
417
+ ---
418
+
419
+ ### 4. 保留完整 Schema 定义 💾
420
+
421
+ ```javascript
422
+ // schemas/user.js
423
+ const { dsl } = require('schema-dsl');
424
+
425
+ // 完整定义(包含所有验证逻辑)
426
+ const userSchema = dsl({
427
+ username: 'string:3-32!'
428
+ .pattern(/^[a-zA-Z0-9_]+$/)
429
+ .messages({ 'string.pattern': '只能包含字母数字下划线' })
430
+ .description('用户登录名'),
431
+
432
+ contactType: 'email|phone',
433
+ contact: dsl.match('contactType', {
434
+ email: 'email!',
435
+ phone: 'phone:cn!'
436
+ })
437
+ });
438
+
439
+ module.exports = {
440
+ // 应用层使用完整 Schema
441
+ full: userSchema,
442
+
443
+ // 数据库导出使用简化 Schema
444
+ db: dsl({
445
+ username: 'string:3-32!'.description('用户登录名'),
446
+ contactType: 'email|phone',
447
+ contact: 'string!'.description('邮箱或手机号(根据 contactType)')
448
+ })
449
+ };
450
+ ```
451
+
452
+ ---
453
+
454
+ ### 5. 文档化不兼容特性 📖
455
+
456
+ 在项目文档中明确说明哪些验证逻辑在数据库层不生效:
457
+
458
+ ```markdown
459
+ ## 数据验证说明
460
+
461
+ ### 应用层验证(schema-dsl)
462
+ - ✅ `contact` 字段根据 `contactType` 动态验证
463
+ - ✅ 用户名正则验证(`^[a-zA-Z0-9_]+$`)
464
+ - ✅ 自定义业务规则验证
465
+
466
+ ### 数据库层约束
467
+ - ✅ `username` 长度限制(3-32 字符)
468
+ - 必填字段约束
469
+ - ❌ 动态类型验证(依赖应用层)
470
+ - 正则表达式验证(依赖应用层)
471
+ ```
472
+
473
+ ---
474
+
475
+ ## 常见问题
476
+
477
+ ### Q1: 为什么 `dsl.match()` 不能导出?
478
+
479
+ **A**: 数据库不支持"根据字段 A 的值决定字段 B 的类型"这种动态约束。数据库 Schema 在创建时就固定了,无法运行时改变。
480
+
481
+ **解决方案**:
482
+ - 导出为最宽松的类型(如 `VARCHAR(255)`)
483
+ - 应用层使用完整 Schema 验证
484
+
485
+ ---
486
+
487
+ ### Q2: MySQL 不支持正则,怎么办?
488
+
489
+ **A**: MySQL 的 `CHECK` 约束不支持正则表达式。
490
+
491
+ **解决方案**:
492
+ 1. 应用层验证(推荐)
493
+ 2. 使用触发器(不推荐,复杂且难维护)
494
+ 3. `COMMENT` 中说明约束规则
495
+
496
+ ---
497
+
498
+ ### Q3: 嵌套对象导出后丢失约束?
499
+
500
+ **A**: MySQL/PostgreSQL 将嵌套对象导出为 `JSON`/`JSONB` 类型,内部约束无法表达。
501
+
502
+ **解决方案**:
503
+ - MongoDB: 完整支持嵌套验证
504
+ - MySQL/PostgreSQL: 应用层验证
505
+
506
+ ---
507
+
508
+ ### Q4: 如何检查 Schema 是否适合导出?
509
+
510
+ **A**: 以下特性**不适合**导出:
511
+
512
+ ```javascript
513
+ // ❌ 包含条件逻辑
514
+ dsl.match(...)
515
+ dsl.if(...)
516
+
517
+ // ❌ 包含自定义验证器
518
+ .custom(...)
519
+
520
+ // ❌ 复杂的 allOf/anyOf/oneOf
521
+ { allOf: [...] }
522
+ ```
523
+
524
+ **适合导出**的特性:
525
+
526
+ ```javascript
527
+ // ✅ 基础类型 + 简单约束
528
+ dsl('string:3-32!')
529
+ dsl('number:0-100')
530
+ dsl('email!')
531
+ dsl('active|inactive|banned')
532
+ ```
533
+
534
+ ---
535
+
536
+ ## 总结
537
+
538
+ | 特性 | MongoDB | MySQL | PostgreSQL |
539
+ |------|---------|-------|------------|
540
+ | 基础类型 | ✅ | ✅ | ✅ |
541
+ | 必填约束 | ✅ | ✅ | ✅ |
542
+ | 长度约束 | ✅ | ⚠️ 仅 max | ✅ |
543
+ | 数值范围 | ✅ | ❌ | ✅ |
544
+ | 正则表达式 | ✅ | ❌ | ❌ |
545
+ | 枚举 | ✅ | ❌ | ✅ |
546
+ | 条件逻辑 | ❌ | ❌ | ❌ |
547
+ | 自定义验证器 | ❌ | ❌ | ❌ |
548
+ | 嵌套对象 | ✅ | ⚠️ JSON | ⚠️ JSONB |
549
+ | 字段描述 | ✅ | ✅ | ✅ |
550
+
551
+ ---
552
+
553
+ ## 相关文档
554
+
555
+ - [数据库导出指南](export-guide.md)
556
+ - [MongoDB 导出器](mongodb-exporter.md)
557
+ - [MySQL 导出器](mysql-exporter.md)
558
+ - [PostgreSQL 导出器](postgresql-exporter.md)
559
+ - [最佳实践](best-practices.md)
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
+