schema-dsl 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (116) hide show
  1. package/.eslintignore +10 -0
  2. package/.eslintrc.json +27 -0
  3. package/.github/CODE_OF_CONDUCT.md +45 -0
  4. package/.github/ISSUE_TEMPLATE/bug_report.md +57 -0
  5. package/.github/ISSUE_TEMPLATE/config.yml +11 -0
  6. package/.github/ISSUE_TEMPLATE/feature_request.md +45 -0
  7. package/.github/ISSUE_TEMPLATE/question.md +31 -0
  8. package/.github/PULL_REQUEST_TEMPLATE.md +70 -0
  9. package/.github/SECURITY.md +184 -0
  10. package/.github/workflows/ci.yml +33 -0
  11. package/CHANGELOG.md +633 -0
  12. package/CONTRIBUTING.md +368 -0
  13. package/LICENSE +21 -0
  14. package/README.md +1184 -0
  15. package/STATUS.md +101 -0
  16. package/docs/FEATURE-INDEX.md +519 -0
  17. package/docs/INDEX.md +253 -0
  18. package/docs/api-reference.md +1096 -0
  19. package/docs/best-practices.md +672 -0
  20. package/docs/cache-manager.md +336 -0
  21. package/docs/design-philosophy.md +601 -0
  22. package/docs/dsl-syntax.md +653 -0
  23. package/docs/dynamic-locale.md +552 -0
  24. package/docs/error-handling.md +703 -0
  25. package/docs/export-guide.md +462 -0
  26. package/docs/export-limitations.md +551 -0
  27. package/docs/faq.md +577 -0
  28. package/docs/frontend-i18n-guide.md +290 -0
  29. package/docs/i18n-user-guide.md +476 -0
  30. package/docs/label-vs-description.md +262 -0
  31. package/docs/markdown-exporter.md +397 -0
  32. package/docs/mongodb-exporter.md +295 -0
  33. package/docs/multi-type-support.md +319 -0
  34. package/docs/mysql-exporter.md +273 -0
  35. package/docs/plugin-system.md +542 -0
  36. package/docs/postgresql-exporter.md +304 -0
  37. package/docs/quick-start.md +761 -0
  38. package/docs/schema-helper.md +340 -0
  39. package/docs/schema-utils-chaining.md +143 -0
  40. package/docs/schema-utils.md +490 -0
  41. package/docs/string-extensions.md +480 -0
  42. package/docs/troubleshooting.md +471 -0
  43. package/docs/type-converter.md +319 -0
  44. package/docs/type-reference.md +219 -0
  45. package/docs/validate-async.md +480 -0
  46. package/docs/validate.md +486 -0
  47. package/docs/validation-guide.md +484 -0
  48. package/examples/array-dsl-example.js +227 -0
  49. package/examples/custom-extension.js +85 -0
  50. package/examples/dsl-match-example.js +74 -0
  51. package/examples/dsl-style.js +118 -0
  52. package/examples/dynamic-locale-configuration.js +348 -0
  53. package/examples/dynamic-locale-example.js +287 -0
  54. package/examples/export-demo.js +130 -0
  55. package/examples/express-integration.js +376 -0
  56. package/examples/i18n-full-demo.js +310 -0
  57. package/examples/i18n-memory-safety.examples.js +268 -0
  58. package/examples/markdown-export.js +71 -0
  59. package/examples/middleware-usage.js +93 -0
  60. package/examples/new-features-comparison.js +315 -0
  61. package/examples/password-reset/README.md +153 -0
  62. package/examples/password-reset/schema.js +26 -0
  63. package/examples/password-reset/test.js +101 -0
  64. package/examples/plugin-system.examples.js +205 -0
  65. package/examples/schema-utils-chaining.examples.js +250 -0
  66. package/examples/simple-example.js +122 -0
  67. package/examples/string-extensions.js +297 -0
  68. package/examples/user-registration/README.md +156 -0
  69. package/examples/user-registration/routes.js +92 -0
  70. package/examples/user-registration/schema.js +150 -0
  71. package/examples/user-registration/server.js +74 -0
  72. package/index.d.ts +1999 -0
  73. package/index.js +282 -0
  74. package/index.mjs +30 -0
  75. package/lib/adapters/DslAdapter.js +699 -0
  76. package/lib/adapters/index.js +20 -0
  77. package/lib/config/constants.js +286 -0
  78. package/lib/config/patterns/creditCard.js +9 -0
  79. package/lib/config/patterns/idCard.js +9 -0
  80. package/lib/config/patterns/index.js +8 -0
  81. package/lib/config/patterns/licensePlate.js +4 -0
  82. package/lib/config/patterns/passport.js +4 -0
  83. package/lib/config/patterns/phone.js +9 -0
  84. package/lib/config/patterns/postalCode.js +5 -0
  85. package/lib/core/CacheManager.js +376 -0
  86. package/lib/core/DslBuilder.js +740 -0
  87. package/lib/core/ErrorCodes.js +233 -0
  88. package/lib/core/ErrorFormatter.js +342 -0
  89. package/lib/core/JSONSchemaCore.js +347 -0
  90. package/lib/core/Locale.js +119 -0
  91. package/lib/core/MessageTemplate.js +89 -0
  92. package/lib/core/PluginManager.js +448 -0
  93. package/lib/core/StringExtensions.js +209 -0
  94. package/lib/core/Validator.js +376 -0
  95. package/lib/errors/ValidationError.js +191 -0
  96. package/lib/exporters/MarkdownExporter.js +420 -0
  97. package/lib/exporters/MongoDBExporter.js +162 -0
  98. package/lib/exporters/MySQLExporter.js +212 -0
  99. package/lib/exporters/PostgreSQLExporter.js +289 -0
  100. package/lib/exporters/index.js +24 -0
  101. package/lib/locales/en-US.js +65 -0
  102. package/lib/locales/es-ES.js +66 -0
  103. package/lib/locales/fr-FR.js +66 -0
  104. package/lib/locales/index.js +8 -0
  105. package/lib/locales/ja-JP.js +66 -0
  106. package/lib/locales/zh-CN.js +93 -0
  107. package/lib/utils/LRUCache.js +174 -0
  108. package/lib/utils/SchemaHelper.js +240 -0
  109. package/lib/utils/SchemaUtils.js +445 -0
  110. package/lib/utils/TypeConverter.js +245 -0
  111. package/lib/utils/index.js +13 -0
  112. package/lib/validators/CustomKeywords.js +203 -0
  113. package/lib/validators/index.js +11 -0
  114. package/package.json +70 -0
  115. package/plugins/custom-format.js +101 -0
  116. package/plugins/custom-validator.js +200 -0
@@ -0,0 +1,490 @@
1
+ # Schema 工具函数文档
2
+
3
+ > **更新时间**: 2025-12-25
4
+
5
+ ---
6
+
7
+ ## 📑 目录
8
+
9
+ - [Schema 复用](#schema-复用)
10
+ - [Schema 合并](#schema-合并)
11
+ - [Schema 筛选](#schema-筛选)
12
+ - [Schema 导出](#schema-导出)
13
+ - [性能监控](#性能监控)
14
+ - [完整示例](#完整示例)
15
+
16
+ ---
17
+
18
+ ## Schema 复用
19
+
20
+ ### 直接复用(最简单)✅
21
+
22
+ ```javascript
23
+ const { dsl } = require('schema-dsl');
24
+
25
+ // 定义可复用字段(就是普通对象)
26
+ const commonFields = {
27
+ email: 'email!'.label('邮箱地址'),
28
+ phone: 'string:11!'.phone('cn').label('手机号'),
29
+ username: 'string:3-32!'.username().label('用户名')
30
+ };
31
+
32
+ // 直接使用
33
+ const registerSchema = dsl({
34
+ ...commonFields, // ✅ 直接展开
35
+ password: 'string:8-64!'.password('strong')
36
+ });
37
+
38
+ const profileSchema = dsl({
39
+ ...commonFields, // ✅ 重复使用
40
+ bio: 'string:500',
41
+ avatar: 'url'
42
+ });
43
+ ```
44
+
45
+ **优点**: 最简单,直接使用 JavaScript 对象展开
46
+
47
+ ---
48
+
49
+ ### 函数复用(需要参数时)
50
+
51
+ ```javascript
52
+ // 定义可复用字段函数
53
+ const createEmailField = (label = '邮箱地址') =>
54
+ 'email!'.label(label);
55
+
56
+ const createRangeField = (min, max) =>
57
+ `number:${min}-${max}`.label('数值范围');
58
+
59
+ // 使用
60
+ const schema = dsl({
61
+ email: createEmailField('联系邮箱'),
62
+ workEmail: createEmailField('工作邮箱'),
63
+ age: createRangeField(18, 120),
64
+ score: createRangeField(0, 100)
65
+ });
66
+ ```
67
+
68
+ **优点**: 支持参数化,灵活性强
69
+
70
+ ---
71
+
72
+ ### 字段库复用(大型项目)
73
+
74
+ ```javascript
75
+ // fields/common.js - 定义字段库
76
+ module.exports = {
77
+ email: () => 'email!'.label('邮箱地址'),
78
+ phone: (country = 'cn') => `string:11!`.phone(country).label('手机号'),
79
+ username: (range = '3-32') => `string:${range}!`.username(range).label('用户名'),
80
+ password: (strength = 'medium') => 'string:8-64!'.password(strength).label('密码'),
81
+
82
+ // 组合字段
83
+ userAuth: () => ({
84
+ username: 'string:3-32!'.username().label('用户名'),
85
+ password: 'string:8-64!'.password('strong').label('密码')
86
+ }),
87
+
88
+ userProfile: () => ({
89
+ nickname: 'string:2-20!'.label('昵称'),
90
+ bio: 'string:500',
91
+ avatar: 'url'
92
+ })
93
+ };
94
+
95
+ // 使用
96
+ const fields = require('./fields/common');
97
+
98
+ const loginSchema = dsl({
99
+ email: fields.email(),
100
+ password: fields.password('strong')
101
+ });
102
+
103
+ const registerSchema = dsl({
104
+ ...fields.userAuth(), // ✅ 展开组合字段
105
+ email: fields.email(),
106
+ phone: fields.phone('cn')
107
+ });
108
+ ```
109
+
110
+ **优点**: 统一管理,易于维护
111
+
112
+ ---
113
+
114
+ ## Schema 合并
115
+
116
+ ### merge() - 合并多个Schema
117
+
118
+ ```javascript
119
+ const { SchemaUtils, dsl } = require('schema-dsl');
120
+
121
+ // 基础Schema
122
+ const baseUser = dsl({
123
+ name: 'string:1-50!',
124
+ email: 'email!'
125
+ });
126
+
127
+ // 扩展Schema
128
+ const withAge = dsl({
129
+ age: 'number:18-120',
130
+ gender: 'male|female|other'
131
+ });
132
+
133
+ // 扩展
134
+ const fullUser = SchemaUtils.extend(baseUser, {
135
+ age: 'number:18-120',
136
+ bio: 'string:500',
137
+ avatar: 'url'
138
+ });
139
+ ```
140
+
141
+ **说明**: 扩展字段,合并 properties 和 required 数组
142
+
143
+ ---
144
+
145
+ ### extend() - 扩展Schema(继承)
146
+
147
+ ```javascript
148
+ const baseUser = dsl({
149
+ name: 'string!',
150
+ email: 'email!'
151
+ });
152
+
153
+ // 扩展基础Schema
154
+ const admin = SchemaUtils.extend(baseUser, {
155
+ role: 'admin|superadmin',
156
+ permissions: 'array<string>'
157
+ });
158
+
159
+ // admin包含所有baseUser字段 + role + permissions
160
+ ```
161
+
162
+ **说明**: 类似继承,保留基础Schema的所有字段
163
+
164
+ ---
165
+
166
+ ## Schema 筛选
167
+
168
+ ### pick() - 选择字段
169
+
170
+ ```javascript
171
+ const fullUser = dsl({
172
+ name: 'string!',
173
+ email: 'email!',
174
+ password: 'string:8-64!',
175
+ phone: 'string:11!',
176
+ age: 'number:18-120'
177
+ });
178
+
179
+ // 只选择特定字段
180
+ const publicUser = SchemaUtils.pick(fullUser, ['name', 'email']);
181
+
182
+ // publicUser 只包含 name 和 email
183
+ ```
184
+
185
+ **用途**: 从完整Schema中提取部分字段(如公开信息)
186
+
187
+ ---
188
+
189
+ ### omit() - 排除字段
190
+
191
+ ```javascript
192
+ const fullUser = dsl({
193
+ name: 'string!',
194
+ email: 'email!',
195
+ password: 'string:8-64!',
196
+ phone: 'string:11!'
197
+ });
198
+
199
+ // 排除敏感字段
200
+ const safeUser = SchemaUtils.omit(fullUser, ['password']);
201
+
202
+ // safeUser 包含除 password 外的所有字段
203
+ ```
204
+
205
+ **用途**: 移除敏感字段(如密码)
206
+
207
+ ---
208
+
209
+ ## Schema 导出
210
+
211
+ ### toMarkdown() - 导出为Markdown文档
212
+
213
+ ```javascript
214
+ const schema = dsl({
215
+ username: 'string:3-32!'.label('用户名'),
216
+ email: 'email!'.label('邮箱地址'),
217
+ age: 'number:18-120'
218
+ });
219
+
220
+ const markdown = SchemaUtils.toMarkdown(schema, {
221
+ title: '用户注册Schema',
222
+ showRequired: true,
223
+ showType: true,
224
+ showConstraints: true
225
+ });
226
+
227
+ console.log(markdown);
228
+ ```
229
+
230
+ **输出**:
231
+ ```markdown
232
+ # 用户注册Schema
233
+
234
+ | 字段 | 类型 | 必填 | 约束 | 说明 |
235
+ |------|------|------|------|------|
236
+ | username | string | ✅ | 3-32字符 | 用户名 |
237
+ | email | email | ✅ | - | 邮箱地址 |
238
+ | age | number | ❌ | 18-120 | - |
239
+ ```
240
+
241
+ **用途**: 生成API文档
242
+
243
+ ---
244
+
245
+ ### toHTML() - 导出为HTML表格
246
+
247
+ ```javascript
248
+ const html = SchemaUtils.toHTML(schema, {
249
+ title: '用户注册Schema',
250
+ theme: 'bootstrap' // 或 'default'
251
+ });
252
+
253
+ // 生成HTML表格,可以嵌入文档
254
+ ```
255
+
256
+ **用途**: 集成到Web文档
257
+
258
+ ---
259
+
260
+ ## 性能监控
261
+
262
+ ### validateBatch() - 批量验证
263
+
264
+ ```javascript
265
+ const { Validator } = require('schema-dsl');
266
+
267
+ const schema = dsl({
268
+ email: 'email!',
269
+ age: 'number:18-120'
270
+ });
271
+
272
+ const validator = new Validator();
273
+
274
+ const items = [
275
+ { email: 'user1@example.com', age: 25 },
276
+ { email: 'invalid', age: 15 },
277
+ { email: 'user2@example.com', age: 30 }
278
+ ];
279
+
280
+ const results = validator.validateBatch(schema, items);
281
+
282
+ console.log(results);
283
+ // {
284
+ // results: [
285
+ // { valid: true, ... },
286
+ // { valid: false, errors: [...] },
287
+ // { valid: true, ... }
288
+ // ],
289
+ // stats: {
290
+ // total: 3,
291
+ // valid: 2,
292
+ // invalid: 1,
293
+ // duration: '5.2ms'
294
+ // }
295
+ // }
296
+ ```
297
+
298
+ **用途**: 批量验证数据,获取性能统计
299
+
300
+ ---
301
+
302
+ ### 性能监控(自动)
303
+
304
+ ```javascript
305
+ const validator = new Validator({ performance: true });
306
+
307
+ const result = validator.validate(schema, data);
308
+
309
+ console.log(result.performance);
310
+ // {
311
+ // duration: '2.1ms',
312
+ // compileDuration: '1.5ms',
313
+ // validateDuration: '0.6ms'
314
+ // }
315
+ ```
316
+
317
+ **用途**: 监控验证性能
318
+
319
+ ---
320
+
321
+ ## 其他工具
322
+
323
+ ### clone() - 深度克隆Schema
324
+
325
+ ```javascript
326
+ const original = dsl({
327
+ user: {
328
+ name: 'string!',
329
+ profile: {
330
+ bio: 'string:500'
331
+ }
332
+ }
333
+ });
334
+
335
+ const cloned = SchemaUtils.clone(original);
336
+
337
+ // cloned 是完全独立的副本
338
+ cloned.properties.user.properties.name.maxLength = 100;
339
+ // original 不会被修改
340
+ ```
341
+
342
+ ---
343
+
344
+ ### validateNestingDepth() - 检查嵌套深度
345
+
346
+ ```javascript
347
+ const schema = dsl({
348
+ level1: {
349
+ level2: {
350
+ level3: {
351
+ level4: 'string'
352
+ }
353
+ }
354
+ }
355
+ });
356
+
357
+ const depth = schema.validateNestingDepth(10);
358
+ // 返回: 4
359
+
360
+ if (depth > 5) {
361
+ console.warn('嵌套层级过深,建议扁平化');
362
+ }
363
+ ```
364
+
365
+ **用途**: 防止过深嵌套
366
+
367
+ ---
368
+
369
+ ## 完整示例
370
+
371
+ ### 企业级字段库
372
+
373
+ ```javascript
374
+ // libs/fields/index.js
375
+ module.exports = {
376
+ // 基础字段
377
+ id: () => 'string!'.pattern(/^[a-zA-Z0-9_-]+$/).label('ID'),
378
+ email: () => 'email!'.label('邮箱地址'),
379
+ phone: (country = 'cn') => 'string:11!'.phone(country).label('手机号'),
380
+
381
+ // 认证字段
382
+ auth: {
383
+ username: () => 'string:3-32!'.username().label('用户名'),
384
+ password: (strength = 'strong') =>
385
+ 'string:8-64!'.password(strength).label('密码')
386
+ },
387
+
388
+ // 个人信息
389
+ profile: {
390
+ nickname: () => 'string:2-20!'.label('昵称'),
391
+ realName: () => 'string:2-50'.label('真实姓名'),
392
+ bio: () => 'string:500',
393
+ avatar: () => 'url'.label('头像'),
394
+ birthday: () => 'date'
395
+ },
396
+
397
+ // 地址信息
398
+ address: () => ({
399
+ country: 'string:2-50!',
400
+ province: 'string:2-50!',
401
+ city: 'string:2-50!',
402
+ detail: 'string:10-200!'
403
+ }),
404
+
405
+ // 时间戳
406
+ timestamps: () => ({
407
+ created_at: 'datetime!',
408
+ updated_at: 'datetime!'
409
+ })
410
+ };
411
+
412
+ // 使用
413
+ const fields = require('./libs/fields');
414
+
415
+ // 用户注册
416
+ const registerSchema = dsl({
417
+ ...fields.auth,
418
+ email: fields.email(),
419
+ phone: fields.phone('cn'),
420
+ agree: 'boolean!'
421
+ });
422
+
423
+ // 用户资料
424
+ const profileSchema = dsl({
425
+ ...fields.profile,
426
+ ...fields.timestamps()
427
+ });
428
+
429
+ // 完整用户
430
+ const userSchema = SchemaUtils.extend(
431
+ SchemaUtils.extend(registerSchema, profileSchema),
432
+ fields.address()
433
+ );
434
+ ```
435
+
436
+ ---
437
+
438
+ ## 最佳实践
439
+
440
+ ### 1. 小项目:直接复用
441
+
442
+ ```javascript
443
+ const commonFields = {
444
+ email: 'email!'.label('邮箱'),
445
+ phone: 'string:11!'.phone('cn')
446
+ };
447
+
448
+ const schema1 = dsl({ ...commonFields, ... });
449
+ const schema2 = dsl({ ...commonFields, ... });
450
+ ```
451
+
452
+ ### 2. 中型项目:函数复用
453
+
454
+ ```javascript
455
+ const createUserFields = (options = {}) => ({
456
+ email: 'email!'.label(options.emailLabel || '邮箱'),
457
+ phone: 'string:11!'.phone(options.country || 'cn')
458
+ });
459
+
460
+ const schema = dsl({
461
+ ...createUserFields({ emailLabel: '联系邮箱' }),
462
+ ...otherFields
463
+ });
464
+ ```
465
+
466
+ ### 3. 大型项目:字段库
467
+
468
+ ```javascript
469
+ // 统一管理在 fields/ 目录
470
+ const fields = require('./fields');
471
+
472
+ const schema = dsl({
473
+ ...fields.auth,
474
+ ...fields.profile
475
+ });
476
+ ```
477
+
478
+ ---
479
+
480
+ ## 相关文档
481
+
482
+ - [DSL 语法](./dsl-syntax.md)
483
+ - [String 扩展](./string-extensions.md)
484
+ - [API 参考](./api-reference.md)
485
+
486
+ ---
487
+
488
+ **最后更新**: 2025-12-25
489
+
490
+