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,462 +1,501 @@
1
- # 数据库导出完整指南
2
-
3
- > **用途**: Schema 到数据库 DDL 的完整导出指南
4
- > **阅读时间**: 10分钟
5
-
6
- > ⚠️ **重要提示**: 并非所有 SchemaI-DSL 特性都能导出到数据库。请先阅读 [导出限制说明](export-limitations.md) 了解哪些特性不支持导出。
7
-
8
- ---
9
-
10
- ## 📑 目录
11
-
12
- - [概述](#概述)
13
- - [快速开始](#快速开始)
14
- - [MongoDB 导出](#mongodb-导出)
15
- - [MySQL 导出](#mysql-导出)
16
- - [PostgreSQL 导出](#postgresql-导出)
17
- - [导出对比](#导出对比)
18
- - [最佳实践](#最佳实践)
19
-
20
- ---
21
-
22
- ## 概述
23
-
24
- SchemaI-DSL 支持将 JSON Schema 导出为多种数据库的 DDL 语句,实现"一次定义,多处使用"。
25
-
26
- ### 支持的数据库
27
-
28
- | 数据库 | 导出器 | 输出格式 |
29
- |--------|--------|----------|
30
- | MongoDB | `MongoDBExporter` | `$jsonSchema` 验证文档 |
31
- | MySQL | `MySQLExporter` | `CREATE TABLE` DDL |
32
- | PostgreSQL | `PostgreSQLExporter` | `CREATE TABLE` DDL + COMMENT |
33
-
34
- ---
35
-
36
- ## 快速开始
37
-
38
- ```javascript
39
- const { dsl, exporters } = require('schema-dsl');
40
-
41
- // 定义统一的 Schema
42
- const userSchema = dsl({
43
- id: 'uuid!',
44
- username: 'string:3-32!'
45
- .pattern(/^[a-zA-Z0-9_]+$/)
46
- .description('用户登录名'),
47
- email: 'email!'
48
- .description('用户邮箱'),
49
- age: 'number:18-120',
50
- status: 'active|inactive|banned',
51
- createdAt: 'datetime!'
52
- });
53
-
54
- // 导出到不同数据库
55
- const mongoSchema = new exporters.MongoDBExporter().export(userSchema);
56
- const mysqlDdl = new exporters.MySQLExporter().export('users', userSchema);
57
- const pgDdl = new exporters.PostgreSQLExporter().export('users', userSchema);
58
- ```
59
-
60
- ---
61
-
62
- ## MongoDB 导出
63
-
64
- ### 基本用法
65
-
66
- ```javascript
67
- const { dsl, exporters } = require('schema-dsl');
68
-
69
- const schema = dsl({
70
- username: 'string:3-32!',
71
- email: 'email!',
72
- age: 'number:18-120'
73
- });
74
-
75
- const exporter = new exporters.MongoDBExporter();
76
- const mongoSchema = exporter.export(schema);
77
-
78
- console.log(JSON.stringify(mongoSchema, null, 2));
79
- ```
80
-
81
- **输出**:
82
-
83
- ```json
84
- {
85
- "$jsonSchema": {
86
- "bsonType": "object",
87
- "required": ["username", "email"],
88
- "properties": {
89
- "username": {
90
- "bsonType": "string",
91
- "minLength": 3,
92
- "maxLength": 32
93
- },
94
- "email": {
95
- "bsonType": "string"
96
- },
97
- "age": {
98
- "bsonType": "double",
99
- "minimum": 18,
100
- "maximum": 120
101
- }
102
- }
103
- }
104
- }
105
- ```
106
-
107
- ### 生成创建命令
108
-
109
- ```javascript
110
- const command = exporter.generateCommand('users', schema);
111
- console.log(command);
112
- ```
113
-
114
- **输出**:
115
-
116
- ```javascript
117
- db.createCollection("users", {
118
- "validator": {
119
- "$jsonSchema": { ... }
120
- },
121
- "validationLevel": "moderate",
122
- "validationAction": "error"
123
- })
124
- ```
125
-
126
- ### 在 MongoDB 中使用
127
-
128
- ```javascript
129
- const { MongoClient } = require('mongodb');
130
-
131
- async function setupCollection() {
132
- const client = new MongoClient('mongodb://localhost:27017');
133
- await client.connect();
134
-
135
- const db = client.db('myapp');
136
- const exporter = new exporters.MongoDBExporter({ strict: true });
137
- const { options } = exporter.generateCreateCommand('users', schema);
138
-
139
- await db.createCollection('users', options);
140
- console.log('创建带验证的集合成功');
141
- }
142
- ```
143
-
144
- ---
145
-
146
- ## MySQL 导出
147
-
148
- ### 基本用法
149
-
150
- ```javascript
151
- const { dsl, exporters } = require('schema-dsl');
152
-
153
- const schema = dsl({
154
- id: 'string!',
155
- username: 'string:3-32!',
156
- email: 'email!',
157
- age: 'number:0-150',
158
- status: 'active|inactive'
159
- });
160
-
161
- const exporter = new exporters.MySQLExporter();
162
- const ddl = exporter.export('users', schema);
163
-
164
- console.log(ddl);
165
- ```
166
-
167
- **输出**:
168
-
169
- ```sql
170
- CREATE TABLE `users` (
171
- `id` VARCHAR(255) NOT NULL,
172
- `username` VARCHAR(32) NOT NULL,
173
- `email` VARCHAR(255) NOT NULL,
174
- `age` DOUBLE NULL,
175
- `status` VARCHAR(255) NULL,
176
- PRIMARY KEY (`id`)
177
- ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
178
- ```
179
-
180
- ### 配置选项
181
-
182
- ```javascript
183
- const exporter = new exporters.MySQLExporter({
184
- engine: 'InnoDB', // 存储引擎
185
- charset: 'utf8mb4', // 字符集
186
- collate: 'utf8mb4_unicode_ci' // 排序规则
187
- });
188
- ```
189
-
190
- ### 生成索引
191
-
192
- ```javascript
193
- // 唯一索引
194
- console.log(exporter.generateIndex('users', 'email', { unique: true }));
195
- // CREATE UNIQUE INDEX `idx_users_email` ON `users` (`email`);
196
-
197
- // 普通索引
198
- console.log(exporter.generateIndex('users', 'status'));
199
- // CREATE INDEX `idx_users_status` ON `users` (`status`);
200
- ```
201
-
202
- ---
203
-
204
- ## PostgreSQL 导出
205
-
206
- ### 基本用法
207
-
208
- ```javascript
209
- const { dsl, exporters } = require('schema-dsl');
210
-
211
- const schema = dsl({
212
- id: 'uuid!',
213
- username: 'string:3-32!'
214
- .description('用户登录名'),
215
- email: 'email!'
216
- .description('用户邮箱'),
217
- age: 'number:18-120',
218
- status: 'active|inactive|banned',
219
- metadata: {
220
- lastLogin: 'datetime',
221
- preferences: 'object'
222
- }
223
- });
224
-
225
- const exporter = new exporters.PostgreSQLExporter();
226
- const ddl = exporter.export('users', schema);
227
-
228
- console.log(ddl);
229
- ```
230
-
231
- **输出**:
232
-
233
- ```sql
234
- CREATE TABLE public.users (
235
- id UUID NOT NULL,
236
- username VARCHAR(32) NOT NULL CHECK (LENGTH(username) BETWEEN 3 AND 32),
237
- email VARCHAR(255) NOT NULL,
238
- age DOUBLE PRECISION CHECK (age BETWEEN 18 AND 120),
239
- status VARCHAR(255) CHECK (status IN ('active', 'inactive', 'banned')),
240
- metadata JSONB,
241
- PRIMARY KEY (id)
242
- );
243
-
244
- COMMENT ON COLUMN public.users.username IS '用户登录名';
245
- COMMENT ON COLUMN public.users.email IS '用户邮箱';
246
- ```
247
-
248
- ### 配置选项
249
-
250
- ```javascript
251
- const exporter = new exporters.PostgreSQLExporter({
252
- schema: 'myapp' // PostgreSQL schema 名称
253
- });
254
- ```
255
-
256
- ### 生成索引
257
-
258
- ```javascript
259
- // B-tree 索引(默认)
260
- console.log(exporter.generateIndex('users', 'email', { unique: true }));
261
- // CREATE UNIQUE INDEX idx_users_email ON public.users USING btree (email);
262
-
263
- // GIN 索引(用于 JSONB)
264
- console.log(exporter.generateIndex('users', 'metadata', { method: 'gin' }));
265
- // CREATE INDEX idx_users_metadata ON public.users USING gin (metadata);
266
- ```
267
-
268
- ---
269
-
270
- ## 导出对比
271
-
272
- ### 同一 Schema 的三种导出
273
-
274
- ```javascript
275
- const schema = dsl({
276
- id: 'uuid!',
277
- name: 'string:3-100!',
278
- score: 'number:0-100',
279
- tags: 'array<string>',
280
- active: 'boolean'
281
- });
282
- ```
283
-
284
- | 字段 | MongoDB | MySQL | PostgreSQL |
285
- |------|---------|-------|------------|
286
- | `id` | `bsonType: 'string'` | `VARCHAR(255) NOT NULL` | `UUID NOT NULL` |
287
- | `name` | `bsonType: 'string', minLength: 3, maxLength: 100` | `VARCHAR(100) NOT NULL` | `VARCHAR(100) NOT NULL CHECK (...)` |
288
- | `score` | `bsonType: 'double', minimum: 0, maximum: 100` | `DOUBLE NULL` | `DOUBLE PRECISION CHECK (...)` |
289
- | `tags` | `bsonType: 'array', items: {...}` | `JSON NULL` | `JSONB` |
290
- | `active` | `bsonType: 'bool'` | `BOOLEAN NULL` | `BOOLEAN` |
291
-
292
- ### 约束支持对比
293
-
294
- | 约束类型 | MongoDB | MySQL | PostgreSQL |
295
- |---------|---------|-------|------------|
296
- | NOT NULL | `required` | ✅ `NOT NULL` | ✅ `NOT NULL` |
297
- | 长度范围 | `minLength/maxLength` | | ✅ `CHECK` |
298
- | 数值范围 | ✅ `minimum/maximum` | ❌ | ✅ `CHECK` |
299
- | 枚举 | ✅ `enum` | ❌ | ✅ `CHECK` |
300
- | 正则 | ✅ `pattern` | ❌ | ❌ |
301
- | 默认值 | ❌ | ✅ `DEFAULT` | ✅ `DEFAULT` |
302
- | 注释 | ❌ | ✅ `COMMENT` | ✅ `COMMENT ON` |
303
-
304
- ---
305
-
306
- ## 最佳实践
307
-
308
- ### 1. 使用 description 添加注释
309
-
310
- ```javascript
311
- const schema = dsl({
312
- username: 'string:3-32!'
313
- .description('用户登录名,只能包含字母数字下划线'),
314
- email: 'email!'
315
- .description('用户邮箱,用于登录和接收通知')
316
- });
317
-
318
- // MySQL PostgreSQL 会生成带注释的 DDL
319
- ```
320
-
321
- ### 2. 统一定义,多处导出
322
-
323
- ```javascript
324
- // schemas/user.js
325
- const { dsl } = require('schema-dsl');
326
-
327
- module.exports = dsl({
328
- id: 'uuid!',
329
- username: 'string:3-32!',
330
- email: 'email!',
331
- createdAt: 'datetime!'
332
- });
333
-
334
- // 导出脚本
335
- const { exporters } = require('schema-dsl');
336
- const userSchema = require('./schemas/user');
337
-
338
- // 生成所有数据库的 DDL
339
- const outputs = {
340
- mongo: new exporters.MongoDBExporter().generateCommand('users', userSchema),
341
- mysql: new exporters.MySQLExporter().export('users', userSchema),
342
- postgres: new exporters.PostgreSQLExporter().export('users', userSchema)
343
- };
344
- ```
345
-
346
- ### 3. 自动化迁移脚本
347
-
348
- ```javascript
349
- const fs = require('fs');
350
- const { dsl, exporters } = require('schema-dsl');
351
-
352
- function generateMigration(schemaName, schema) {
353
- const mysql = new exporters.MySQLExporter();
354
- const pg = new exporters.PostgreSQLExporter();
355
-
356
- const timestamp = Date.now();
357
-
358
- // 生成 MySQL 迁移
359
- fs.writeFileSync(
360
- `migrations/${timestamp}_create_${schemaName}.mysql.sql`,
361
- mysql.export(schemaName, schema)
362
- );
363
-
364
- // 生成 PostgreSQL 迁移
365
- fs.writeFileSync(
366
- `migrations/${timestamp}_create_${schemaName}.pg.sql`,
367
- pg.export(schemaName, schema)
368
- );
369
-
370
- console.log(`生成迁移文件: ${schemaName}`);
371
- }
372
-
373
- generateMigration('users', userSchema);
374
- generateMigration('orders', orderSchema);
375
- ```
376
-
377
- ### 4. 版本管理
378
-
379
- ```javascript
380
- // 在 Schema 中添加版本信息
381
- const userSchemaV1 = dsl({ username: 'string!' });
382
- const userSchemaV2 = dsl({ username: 'string:3-32!', email: 'email!' });
383
-
384
- // 导出时标注版本
385
- function exportWithVersion(name, schema, version) {
386
- const ddl = new exporters.MySQLExporter().export(name, schema);
387
- return `-- Schema Version: ${version}\n-- Generated: ${new Date().toISOString()}\n\n${ddl}`;
388
- }
389
- ```
390
-
391
- ---
392
-
393
- ## 完整示例
394
-
395
- ### 电商系统 Schema 导出
396
-
397
- ```javascript
398
- const { dsl, exporters } = require('schema-dsl');
399
- const fs = require('fs');
400
-
401
- // 用户 Schema
402
- const userSchema = dsl({
403
- id: 'uuid!',
404
- username: 'string:3-32!'.description('用户名'),
405
- email: 'email!'.description('邮箱'),
406
- phone: 'string:11'.phone('cn').description('手机号'),
407
- status: 'active|inactive|banned',
408
- createdAt: 'datetime!'
409
- });
410
-
411
- // 商品 Schema
412
- const productSchema = dsl({
413
- id: 'uuid!',
414
- name: 'string:3-200!'.description('商品名称'),
415
- price: 'number:0-'.description('价格'),
416
- stock: 'integer:0-'.description('库存'),
417
- category: 'string:2-50!',
418
- tags: 'array<string>',
419
- active: 'boolean'
420
- });
421
-
422
- // 订单 Schema
423
- const orderSchema = dsl({
424
- id: 'uuid!',
425
- userId: 'uuid!',
426
- items: 'array!1-100',
427
- totalAmount: 'number:0-!',
428
- status: 'pending|paid|shipped|delivered|cancelled',
429
- createdAt: 'datetime!',
430
- updatedAt: 'datetime'
431
- });
432
-
433
- // 导出所有 Schema
434
- const schemas = { users: userSchema, products: productSchema, orders: orderSchema };
435
- const mysqlExporter = new exporters.MySQLExporter();
436
- const pgExporter = new exporters.PostgreSQLExporter({ schema: 'ecommerce' });
437
-
438
- let mysqlDdl = '';
439
- let pgDdl = '';
440
-
441
- for (const [name, schema] of Object.entries(schemas)) {
442
- mysqlDdl += mysqlExporter.export(name, schema) + '\n\n';
443
- pgDdl += pgExporter.export(name, schema) + '\n\n';
444
- }
445
-
446
- fs.writeFileSync('schema.mysql.sql', mysqlDdl);
447
- fs.writeFileSync('schema.pg.sql', pgDdl);
448
-
449
- console.log('导出完成!');
450
- ```
451
-
452
- ---
453
-
454
- ## 相关文档
455
-
456
- - [**导出限制说明**](export-limitations.md) ⚠️ **必读**
457
- - [MongoDB 导出器](mongodb-exporter.md)
458
- - [MySQL 导出器](mysql-exporter.md)
459
- - [PostgreSQL 导出器](postgresql-exporter.md)
460
- - [TypeConverter](type-converter.md)
461
- - [DSL 语法](dsl-syntax.md)
462
-
1
+ # 导出完整指南
2
+
3
+ > **用途**: Schema 到多种输出格式的完整导出指南
4
+ > **阅读时间**: 10分钟
5
+
6
+ > ⚠️ **重要提示**: 并非所有 schema-dsl 特性都能导出到数据库。请先阅读 [导出限制说明](export-limitations.md) 了解哪些特性不支持导出。
7
+
8
+ ---
9
+
10
+ ## 📑 目录
11
+
12
+ - [概述](#概述)
13
+ - [快速开始](#快速开始)
14
+ - [MongoDB 导出](#mongodb-导出)
15
+ - [MySQL 导出](#mysql-导出)
16
+ - [PostgreSQL 导出](#postgresql-导出)
17
+ - [Markdown 导出](#markdown-导出)
18
+ - [导出对比](#导出对比)
19
+ - [最佳实践](#最佳实践)
20
+
21
+ ---
22
+
23
+ ## 概述
24
+
25
+ schema-dsl 支持将 JSON Schema 导出为多种数据库结构或文档格式,实现“一次定义,多处使用”。
26
+
27
+ ### 支持的导出格式
28
+
29
+ | 类型 | 导出器 | 输出格式 |
30
+ |------|--------|----------|
31
+ | MongoDB | `MongoDBExporter` | `$jsonSchema` 验证文档 |
32
+ | MySQL | `MySQLExporter` | `CREATE TABLE` DDL |
33
+ | PostgreSQL | `PostgreSQLExporter` | `CREATE TABLE` DDL + COMMENT |
34
+ | Markdown | `MarkdownExporter` | 面向人类阅读的 Markdown 文档 |
35
+
36
+ 其中 `MarkdownExporter` 更适合生成接口字段说明、表单文档或内部规范文档,完整用法见 [Markdown 导出器](./markdown-exporter.md)。
37
+
38
+ ---
39
+
40
+ ## 快速开始
41
+
42
+ ```javascript
43
+ const { dsl, exporters } = require('schema-dsl');
44
+
45
+ // 定义统一的 Schema
46
+ const userSchema = dsl({
47
+ id: 'uuid!',
48
+ username: 'string:3-32!'
49
+ .pattern(/^[a-zA-Z0-9_]+$/)
50
+ .description('用户登录名'),
51
+ email: 'email!'
52
+ .description('用户邮箱'),
53
+ age: 'number:18-120',
54
+ status: 'active|inactive|banned',
55
+ createdAt: 'datetime!'
56
+ });
57
+
58
+ // 导出到不同目标
59
+ const mongoSchema = new exporters.MongoDBExporter().export(userSchema);
60
+ const mysqlDdl = new exporters.MySQLExporter().export('users', userSchema);
61
+ const pgDdl = new exporters.PostgreSQLExporter().export('users', userSchema);
62
+ const markdownDoc = exporters.MarkdownExporter.export(userSchema, {
63
+ title: '用户 Schema 文档'
64
+ });
65
+ ```
66
+
67
+ ---
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
+
94
+ ## MongoDB 导出
95
+
96
+ ### 基本用法
97
+
98
+ ```javascript
99
+ const { dsl, exporters } = require('schema-dsl');
100
+
101
+ const schema = dsl({
102
+ username: 'string:3-32!',
103
+ email: 'email!',
104
+ age: 'number:18-120'
105
+ });
106
+
107
+ const exporter = new exporters.MongoDBExporter();
108
+ const mongoSchema = exporter.export(schema);
109
+
110
+ console.log(JSON.stringify(mongoSchema, null, 2));
111
+ ```
112
+
113
+ **输出**:
114
+
115
+ ```json
116
+ {
117
+ "$jsonSchema": {
118
+ "bsonType": "object",
119
+ "required": ["username", "email"],
120
+ "properties": {
121
+ "username": {
122
+ "bsonType": "string",
123
+ "minLength": 3,
124
+ "maxLength": 32
125
+ },
126
+ "email": {
127
+ "bsonType": "string"
128
+ },
129
+ "age": {
130
+ "bsonType": "double",
131
+ "minimum": 18,
132
+ "maximum": 120
133
+ }
134
+ }
135
+ }
136
+ }
137
+ ```
138
+
139
+ ### 生成创建命令
140
+
141
+ ```javascript
142
+ const command = exporter.generateCommand('users', schema);
143
+ console.log(command);
144
+ ```
145
+
146
+ **输出**:
147
+
148
+ ```javascript
149
+ db.createCollection("users", {
150
+ "validator": {
151
+ "$jsonSchema": { ... }
152
+ },
153
+ "validationLevel": "moderate",
154
+ "validationAction": "error"
155
+ })
156
+ ```
157
+
158
+ ### 在 MongoDB 中使用
159
+
160
+ ```javascript
161
+ const { MongoClient } = require('mongodb');
162
+
163
+ async function setupCollection() {
164
+ const client = new MongoClient('mongodb://localhost:27017');
165
+ await client.connect();
166
+
167
+ const db = client.db('myapp');
168
+ const exporter = new exporters.MongoDBExporter({ strict: true });
169
+ const { options } = exporter.generateCreateCommand('users', schema);
170
+
171
+ await db.createCollection('users', options);
172
+ console.log('创建带验证的集合成功');
173
+ }
174
+ ```
175
+
176
+ ---
177
+
178
+ ## MySQL 导出
179
+
180
+ ### 基本用法
181
+
182
+ ```javascript
183
+ const { dsl, exporters } = require('schema-dsl');
184
+
185
+ const schema = dsl({
186
+ id: 'string!',
187
+ username: 'string:3-32!',
188
+ email: 'email!',
189
+ age: 'number:0-150',
190
+ status: 'active|inactive'
191
+ });
192
+
193
+ const exporter = new exporters.MySQLExporter();
194
+ const ddl = exporter.export('users', schema);
195
+
196
+ console.log(ddl);
197
+ ```
198
+
199
+ **输出**:
200
+
201
+ ```sql
202
+ CREATE TABLE `users` (
203
+ `id` VARCHAR(255) NOT NULL,
204
+ `username` VARCHAR(32) NOT NULL,
205
+ `email` VARCHAR(255) NOT NULL,
206
+ `age` DOUBLE NULL,
207
+ `status` VARCHAR(255) NULL,
208
+ PRIMARY KEY (`id`)
209
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
210
+ ```
211
+
212
+ ### 配置选项
213
+
214
+ ```javascript
215
+ const exporter = new exporters.MySQLExporter({
216
+ engine: 'InnoDB', // 存储引擎
217
+ charset: 'utf8mb4', // 字符集
218
+ collate: 'utf8mb4_unicode_ci' // 排序规则
219
+ });
220
+ ```
221
+
222
+ ### 生成索引
223
+
224
+ ```javascript
225
+ // 唯一索引
226
+ console.log(exporter.generateIndex('users', 'email', { unique: true }));
227
+ // CREATE UNIQUE INDEX `idx_users_email` ON `users` (`email`);
228
+
229
+ // 普通索引
230
+ console.log(exporter.generateIndex('users', 'status'));
231
+ // CREATE INDEX `idx_users_status` ON `users` (`status`);
232
+ ```
233
+
234
+ ---
235
+
236
+ ## PostgreSQL 导出
237
+
238
+ ### 基本用法
239
+
240
+ ```javascript
241
+ const { dsl, exporters } = require('schema-dsl');
242
+
243
+ const schema = dsl({
244
+ id: 'uuid!',
245
+ username: 'string:3-32!'
246
+ .description('用户登录名'),
247
+ email: 'email!'
248
+ .description('用户邮箱'),
249
+ age: 'number:18-120',
250
+ status: 'active|inactive|banned',
251
+ metadata: {
252
+ lastLogin: 'datetime',
253
+ preferences: 'object'
254
+ }
255
+ });
256
+
257
+ const exporter = new exporters.PostgreSQLExporter();
258
+ const ddl = exporter.export('users', schema);
259
+
260
+ console.log(ddl);
261
+ ```
262
+
263
+ **输出**:
264
+
265
+ ```sql
266
+ CREATE TABLE public.users (
267
+ id UUID NOT NULL,
268
+ username VARCHAR(32) NOT NULL CHECK (LENGTH(username) BETWEEN 3 AND 32),
269
+ email VARCHAR(255) NOT NULL,
270
+ age DOUBLE PRECISION CHECK (age BETWEEN 18 AND 120),
271
+ status VARCHAR(255) CHECK (status IN ('active', 'inactive', 'banned')),
272
+ metadata JSONB,
273
+ PRIMARY KEY (id)
274
+ );
275
+
276
+ COMMENT ON COLUMN public.users.username IS '用户登录名';
277
+ COMMENT ON COLUMN public.users.email IS '用户邮箱';
278
+ ```
279
+
280
+ ### 配置选项
281
+
282
+ ```javascript
283
+ const exporter = new exporters.PostgreSQLExporter({
284
+ schema: 'myapp' // PostgreSQL schema 名称
285
+ });
286
+ ```
287
+
288
+ ### 生成索引
289
+
290
+ ```javascript
291
+ // B-tree 索引(默认)
292
+ console.log(exporter.generateIndex('users', 'email', { unique: true }));
293
+ // CREATE UNIQUE INDEX idx_users_email ON public.users USING btree (email);
294
+
295
+ // GIN 索引(用于 JSONB)
296
+ console.log(exporter.generateIndex('users', 'metadata', { method: 'gin' }));
297
+ // CREATE INDEX idx_users_metadata ON public.users USING gin (metadata);
298
+ ```
299
+
300
+ ---
301
+
302
+ ## 导出对比
303
+
304
+ ### 同一 Schema 的三种导出
305
+
306
+ ```javascript
307
+ const schema = dsl({
308
+ id: 'uuid!',
309
+ name: 'string:3-100!',
310
+ score: 'number:0-100',
311
+ tags: 'array<string>',
312
+ active: 'boolean'
313
+ });
314
+ ```
315
+
316
+ | 字段 | MongoDB | MySQL | PostgreSQL |
317
+ |------|---------|-------|------------|
318
+ | `id` | `bsonType: 'string'` | `VARCHAR(255) NOT NULL` | `UUID NOT NULL` |
319
+ | `name` | `bsonType: 'string', minLength: 3, maxLength: 100` | `VARCHAR(100) NOT NULL` | `VARCHAR(100) NOT NULL CHECK (...)` |
320
+ | `score` | `bsonType: 'double', minimum: 0, maximum: 100` | `DOUBLE NULL` | `DOUBLE PRECISION CHECK (...)` |
321
+ | `tags` | `bsonType: 'array', items: {...}` | `JSON NULL` | `JSONB` |
322
+ | `active` | `bsonType: 'bool'` | `BOOLEAN NULL` | `BOOLEAN` |
323
+
324
+ ### 约束支持对比
325
+
326
+ | 约束类型 | MongoDB | MySQL | PostgreSQL |
327
+ |---------|---------|-------|------------|
328
+ | NOT NULL | ✅ `required` | ✅ `NOT NULL` | ✅ `NOT NULL` |
329
+ | 长度范围 | ✅ `minLength/maxLength` | ❌ | ✅ `CHECK` |
330
+ | 数值范围 | ✅ `minimum/maximum` | ❌ | ✅ `CHECK` |
331
+ | 枚举 | ✅ `enum` | ❌ | ✅ `CHECK` |
332
+ | 正则 | ✅ `pattern` | ❌ | ❌ |
333
+ | 默认值 | ❌ | ✅ `DEFAULT` | ✅ `DEFAULT` |
334
+ | 注释 | ❌ | ✅ `COMMENT` | ✅ `COMMENT ON` |
335
+
336
+ ---
337
+
338
+ ## 最佳实践
339
+
340
+ ### 1. 使用 description 添加注释
341
+
342
+ ```javascript
343
+ const schema = dsl({
344
+ username: 'string:3-32!'
345
+ .description('用户登录名,只能包含字母数字下划线'),
346
+ email: 'email!'
347
+ .description('用户邮箱,用于登录和接收通知')
348
+ });
349
+
350
+ // MySQL PostgreSQL 会生成带注释的 DDL
351
+ ```
352
+
353
+ ### 2. 统一定义,多处导出
354
+
355
+ ```javascript
356
+ // schemas/user.js
357
+ const { dsl } = require('schema-dsl');
358
+
359
+ module.exports = dsl({
360
+ id: 'uuid!',
361
+ username: 'string:3-32!',
362
+ email: 'email!',
363
+ createdAt: 'datetime!'
364
+ });
365
+
366
+ // 导出脚本
367
+ const { exporters } = require('schema-dsl');
368
+ const userSchema = require('./schemas/user');
369
+
370
+ // 生成所有数据库的 DDL
371
+ const outputs = {
372
+ mongo: new exporters.MongoDBExporter().generateCommand('users', userSchema),
373
+ mysql: new exporters.MySQLExporter().export('users', userSchema),
374
+ postgres: new exporters.PostgreSQLExporter().export('users', userSchema)
375
+ };
376
+ ```
377
+
378
+ ### 3. 自动化迁移脚本
379
+
380
+ ```javascript
381
+ const fs = require('fs');
382
+ const { dsl, exporters } = require('schema-dsl');
383
+
384
+ function generateMigration(schemaName, schema) {
385
+ const mysql = new exporters.MySQLExporter();
386
+ const pg = new exporters.PostgreSQLExporter();
387
+
388
+ const timestamp = Date.now();
389
+
390
+ // 生成 MySQL 迁移
391
+ fs.writeFileSync(
392
+ `migrations/${timestamp}_create_${schemaName}.mysql.sql`,
393
+ mysql.export(schemaName, schema)
394
+ );
395
+
396
+ // 生成 PostgreSQL 迁移
397
+ fs.writeFileSync(
398
+ `migrations/${timestamp}_create_${schemaName}.pg.sql`,
399
+ pg.export(schemaName, schema)
400
+ );
401
+
402
+ console.log(`生成迁移文件: ${schemaName}`);
403
+ }
404
+
405
+ generateMigration('users', userSchema);
406
+ generateMigration('orders', orderSchema);
407
+ ```
408
+
409
+ ### 4. 版本管理
410
+
411
+ ```javascript
412
+ // Schema 中添加版本信息
413
+ const userSchemaV1 = dsl({ username: 'string!' });
414
+ const userSchemaV2 = dsl({ username: 'string:3-32!', email: 'email!' });
415
+
416
+ // 导出时标注版本
417
+ function exportWithVersion(name, schema, version) {
418
+ const ddl = new exporters.MySQLExporter().export(name, schema);
419
+ return `-- Schema Version: ${version}\n-- Generated: ${new Date().toISOString()}\n\n${ddl}`;
420
+ }
421
+ ```
422
+
423
+ ---
424
+
425
+ ## 完整示例
426
+
427
+ ### 电商系统 Schema 导出
428
+
429
+ ```javascript
430
+ const { dsl, exporters } = require('schema-dsl');
431
+ const fs = require('fs');
432
+
433
+ // 用户 Schema
434
+ const userSchema = dsl({
435
+ id: 'uuid!',
436
+ username: 'string:3-32!'.description('用户名'),
437
+ email: 'email!'.description('邮箱'),
438
+ phone: 'string:11'.phone('cn').description('手机号'),
439
+ status: 'active|inactive|banned',
440
+ createdAt: 'datetime!'
441
+ });
442
+
443
+ // 商品 Schema
444
+ const productSchema = dsl({
445
+ id: 'uuid!',
446
+ name: 'string:3-200!'.description('商品名称'),
447
+ price: 'number:0-'.description('价格'),
448
+ stock: 'integer:0-'.description('库存'),
449
+ category: 'string:2-50!',
450
+ tags: 'array<string>',
451
+ active: 'boolean'
452
+ });
453
+
454
+ // 订单 Schema
455
+ const orderSchema = dsl({
456
+ id: 'uuid!',
457
+ userId: 'uuid!',
458
+ items: 'array!1-100',
459
+ totalAmount: 'number:0-!',
460
+ status: 'pending|paid|shipped|delivered|cancelled',
461
+ createdAt: 'datetime!',
462
+ updatedAt: 'datetime'
463
+ });
464
+
465
+ // 导出所有 Schema
466
+ const schemas = { users: userSchema, products: productSchema, orders: orderSchema };
467
+ const mysqlExporter = new exporters.MySQLExporter();
468
+ const pgExporter = new exporters.PostgreSQLExporter({ schema: 'ecommerce' });
469
+
470
+ let mysqlDdl = '';
471
+ let pgDdl = '';
472
+
473
+ for (const [name, schema] of Object.entries(schemas)) {
474
+ mysqlDdl += mysqlExporter.export(name, schema) + '\n\n';
475
+ pgDdl += pgExporter.export(name, schema) + '\n\n';
476
+ }
477
+
478
+ fs.writeFileSync('schema.mysql.sql', mysqlDdl);
479
+ fs.writeFileSync('schema.pg.sql', pgDdl);
480
+
481
+ console.log('导出完成!');
482
+ ```
483
+
484
+ ---
485
+
486
+ ## 相关文档
487
+
488
+ - [**导出限制说明**](export-limitations.md) ⚠️ **必读**
489
+ - [MongoDB 导出器](mongodb-exporter.md)
490
+ - [MySQL 导出器](mysql-exporter.md)
491
+ - [PostgreSQL 导出器](postgresql-exporter.md)
492
+ - [TypeConverter](type-converter.md)
493
+ - [DSL 语法](dsl-syntax.md)
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
+