schema-dsl 2.3.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 (109) 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 +35 -0
  11. package/CHANGELOG.md +633 -0
  12. package/CONTRIBUTING.md +368 -0
  13. package/LICENSE +21 -0
  14. package/README.md +1122 -0
  15. package/STATUS.md +273 -0
  16. package/docs/FEATURE-INDEX.md +521 -0
  17. package/docs/INDEX.md +224 -0
  18. package/docs/api-reference.md +1098 -0
  19. package/docs/best-practices.md +672 -0
  20. package/docs/cache-manager.md +336 -0
  21. package/docs/design-philosophy.md +602 -0
  22. package/docs/dsl-syntax.md +654 -0
  23. package/docs/dynamic-locale.md +552 -0
  24. package/docs/error-handling.md +703 -0
  25. package/docs/export-guide.md +459 -0
  26. package/docs/faq.md +576 -0
  27. package/docs/frontend-i18n-guide.md +290 -0
  28. package/docs/i18n-user-guide.md +488 -0
  29. package/docs/label-vs-description.md +262 -0
  30. package/docs/markdown-exporter.md +398 -0
  31. package/docs/mongodb-exporter.md +279 -0
  32. package/docs/multi-type-support.md +319 -0
  33. package/docs/mysql-exporter.md +257 -0
  34. package/docs/plugin-system.md +542 -0
  35. package/docs/postgresql-exporter.md +290 -0
  36. package/docs/quick-start.md +761 -0
  37. package/docs/schema-helper.md +340 -0
  38. package/docs/schema-utils.md +492 -0
  39. package/docs/string-extensions.md +480 -0
  40. package/docs/troubleshooting.md +471 -0
  41. package/docs/type-converter.md +319 -0
  42. package/docs/type-reference.md +219 -0
  43. package/docs/validate.md +486 -0
  44. package/docs/validation-guide.md +484 -0
  45. package/examples/array-dsl-example.js +227 -0
  46. package/examples/custom-extension.js +85 -0
  47. package/examples/dsl-match-example.js +74 -0
  48. package/examples/dsl-style.js +118 -0
  49. package/examples/dynamic-locale-configuration.js +348 -0
  50. package/examples/dynamic-locale-example.js +287 -0
  51. package/examples/export-demo.js +130 -0
  52. package/examples/i18n-full-demo.js +310 -0
  53. package/examples/i18n-memory-safety.examples.js +268 -0
  54. package/examples/markdown-export.js +71 -0
  55. package/examples/middleware-usage.js +93 -0
  56. package/examples/password-reset/README.md +153 -0
  57. package/examples/password-reset/schema.js +26 -0
  58. package/examples/password-reset/test.js +101 -0
  59. package/examples/plugin-system.examples.js +205 -0
  60. package/examples/simple-example.js +122 -0
  61. package/examples/string-extensions.js +297 -0
  62. package/examples/user-registration/README.md +156 -0
  63. package/examples/user-registration/routes.js +92 -0
  64. package/examples/user-registration/schema.js +150 -0
  65. package/examples/user-registration/server.js +74 -0
  66. package/index.d.ts +1999 -0
  67. package/index.js +270 -0
  68. package/index.mjs +30 -0
  69. package/lib/adapters/DslAdapter.js +653 -0
  70. package/lib/adapters/index.js +20 -0
  71. package/lib/config/constants.js +286 -0
  72. package/lib/config/patterns/creditCard.js +9 -0
  73. package/lib/config/patterns/idCard.js +9 -0
  74. package/lib/config/patterns/index.js +8 -0
  75. package/lib/config/patterns/licensePlate.js +4 -0
  76. package/lib/config/patterns/passport.js +4 -0
  77. package/lib/config/patterns/phone.js +9 -0
  78. package/lib/config/patterns/postalCode.js +5 -0
  79. package/lib/core/CacheManager.js +376 -0
  80. package/lib/core/DslBuilder.js +740 -0
  81. package/lib/core/ErrorCodes.js +233 -0
  82. package/lib/core/ErrorFormatter.js +342 -0
  83. package/lib/core/JSONSchemaCore.js +347 -0
  84. package/lib/core/Locale.js +119 -0
  85. package/lib/core/MessageTemplate.js +89 -0
  86. package/lib/core/PluginManager.js +448 -0
  87. package/lib/core/StringExtensions.js +209 -0
  88. package/lib/core/Validator.js +316 -0
  89. package/lib/exporters/MarkdownExporter.js +420 -0
  90. package/lib/exporters/MongoDBExporter.js +162 -0
  91. package/lib/exporters/MySQLExporter.js +212 -0
  92. package/lib/exporters/PostgreSQLExporter.js +289 -0
  93. package/lib/exporters/index.js +24 -0
  94. package/lib/locales/en-US.js +65 -0
  95. package/lib/locales/es-ES.js +66 -0
  96. package/lib/locales/fr-FR.js +66 -0
  97. package/lib/locales/index.js +8 -0
  98. package/lib/locales/ja-JP.js +66 -0
  99. package/lib/locales/zh-CN.js +93 -0
  100. package/lib/utils/LRUCache.js +174 -0
  101. package/lib/utils/SchemaHelper.js +240 -0
  102. package/lib/utils/SchemaUtils.js +313 -0
  103. package/lib/utils/TypeConverter.js +245 -0
  104. package/lib/utils/index.js +13 -0
  105. package/lib/validators/CustomKeywords.js +203 -0
  106. package/lib/validators/index.js +11 -0
  107. package/package.json +70 -0
  108. package/plugins/custom-format.js +101 -0
  109. package/plugins/custom-validator.js +200 -0
@@ -0,0 +1,420 @@
1
+ /**
2
+ * Markdown 文档导出器
3
+ *
4
+ * @description 将 JSON Schema 导出为人类可读的 Markdown 文档
5
+ * @module lib/exporters/MarkdownExporter
6
+ * @version 2.2.0
7
+ */
8
+
9
+ class MarkdownExporter {
10
+ /**
11
+ * 导出为 Markdown
12
+ * @param {Object} schema - JSON Schema
13
+ * @param {Object} options - 导出选项
14
+ * @param {string} [options.title='Schema 文档'] - 文档标题
15
+ * @param {string} [options.locale='zh-CN'] - 语言 (zh-CN/en-US/ja-JP)
16
+ * @param {boolean} [options.includeExample=true] - 是否包含示例
17
+ * @param {boolean} [options.includeDescription=true] - 是否包含描述
18
+ * @returns {string} Markdown 文本
19
+ *
20
+ * @example
21
+ * const markdown = MarkdownExporter.export(schema, {
22
+ * title: '用户注册 API',
23
+ * locale: 'zh-CN',
24
+ * includeExample: true
25
+ * });
26
+ */
27
+ static export(schema, options = {}) {
28
+ const {
29
+ title = 'Schema 文档',
30
+ locale = 'zh-CN',
31
+ includeExample = true,
32
+ includeDescription = true
33
+ } = options;
34
+
35
+ let markdown = `# ${title}\n\n`;
36
+
37
+ // 添加描述
38
+ if (includeDescription && schema.description) {
39
+ markdown += `${schema.description}\n\n`;
40
+ }
41
+
42
+ // 生成字段列表
43
+ markdown += this._generateFieldsTable(schema, locale);
44
+
45
+ // 生成示例
46
+ if (includeExample) {
47
+ markdown += '\n' + this._generateExample(schema, locale);
48
+ }
49
+
50
+ // 生成约束规则
51
+ markdown += '\n' + this._generateConstraintsSection(schema, locale);
52
+
53
+ return markdown;
54
+ }
55
+
56
+ /**
57
+ * 生成字段列表表格
58
+ * @private
59
+ */
60
+ static _generateFieldsTable(schema, locale) {
61
+ const i18n = {
62
+ 'zh-CN': {
63
+ fields: '字段列表',
64
+ name: '字段名',
65
+ type: '类型',
66
+ required: '必填',
67
+ constraints: '约束',
68
+ description: '说明'
69
+ },
70
+ 'en-US': {
71
+ fields: 'Fields',
72
+ name: 'Field',
73
+ type: 'Type',
74
+ required: 'Required',
75
+ constraints: 'Constraints',
76
+ description: 'Description'
77
+ },
78
+ 'ja-JP': {
79
+ fields: 'フィールド一覧',
80
+ name: 'フィールド名',
81
+ type: 'タイプ',
82
+ required: '必須',
83
+ constraints: '制約',
84
+ description: '説明'
85
+ }
86
+ };
87
+
88
+ const t = i18n[locale] || i18n['en-US'];
89
+
90
+ let table = `## ${t.fields}\n\n`;
91
+ table += `| ${t.name} | ${t.type} | ${t.required} | ${t.constraints} | ${t.description} |\n`;
92
+ table += `|--------|------|------|------|------|\n`;
93
+
94
+ // 遍历 properties
95
+ if (schema.properties) {
96
+ Object.entries(schema.properties).forEach(([key, prop]) => {
97
+ const type = this._formatType(prop, locale);
98
+ const required = prop._required || schema.required?.includes(key) ? '✅' : '❌';
99
+ const constraints = this._formatConstraints(prop, locale);
100
+ const description = this._getDescription(prop, locale);
101
+
102
+ table += `| ${key} | ${type} | ${required} | ${constraints} | ${description} |\n`;
103
+ });
104
+ }
105
+
106
+ return table;
107
+ }
108
+
109
+ /**
110
+ * 格式化类型
111
+ * @private
112
+ */
113
+ static _formatType(prop, locale) {
114
+ const typeMap = {
115
+ 'zh-CN': {
116
+ string: '字符串',
117
+ number: '数字',
118
+ integer: '整数',
119
+ boolean: '布尔值',
120
+ array: '数组',
121
+ object: '对象',
122
+ email: '邮箱',
123
+ url: '网址',
124
+ date: '日期',
125
+ uuid: 'UUID'
126
+ },
127
+ 'en-US': {
128
+ string: 'String',
129
+ number: 'Number',
130
+ integer: 'Integer',
131
+ boolean: 'Boolean',
132
+ array: 'Array',
133
+ object: 'Object',
134
+ email: 'Email',
135
+ url: 'URL',
136
+ date: 'Date',
137
+ uuid: 'UUID'
138
+ },
139
+ 'ja-JP': {
140
+ string: '文字列',
141
+ number: '数値',
142
+ integer: '整数',
143
+ boolean: 'ブール値',
144
+ array: '配列',
145
+ object: 'オブジェクト',
146
+ email: 'メールアドレス',
147
+ url: 'URL',
148
+ date: '日付',
149
+ uuid: 'UUID'
150
+ }
151
+ };
152
+
153
+ const t = typeMap[locale] || typeMap['en-US'];
154
+
155
+ // 优先使用 format
156
+ if (prop.format) {
157
+ return t[prop.format] || prop.format;
158
+ }
159
+
160
+ // 数组类型
161
+ if (prop.type === 'array' && prop.items) {
162
+ const itemType = this._formatType(prop.items, locale);
163
+ return `${t.array}<${itemType}>`;
164
+ }
165
+
166
+ return t[prop.type] || prop.type;
167
+ }
168
+
169
+ /**
170
+ * 格式化约束
171
+ * @private
172
+ */
173
+ static _formatConstraints(prop, locale) {
174
+ const constraints = [];
175
+
176
+ const i18n = {
177
+ 'zh-CN': {
178
+ length: '长度',
179
+ range: '范围',
180
+ pattern: '正则',
181
+ enum: '枚举',
182
+ items: '元素数'
183
+ },
184
+ 'en-US': {
185
+ length: 'Length',
186
+ range: 'Range',
187
+ pattern: 'Pattern',
188
+ enum: 'Enum',
189
+ items: 'Items'
190
+ },
191
+ 'ja-JP': {
192
+ length: '長さ',
193
+ range: '範囲',
194
+ pattern: '正規表現',
195
+ enum: '列挙',
196
+ items: '要素数'
197
+ }
198
+ };
199
+
200
+ const t = i18n[locale] || i18n['en-US'];
201
+
202
+ // 字符串长度
203
+ if (prop.minLength !== undefined || prop.maxLength !== undefined) {
204
+ const min = prop.minLength !== undefined ? prop.minLength : '';
205
+ const max = prop.maxLength !== undefined ? prop.maxLength : '';
206
+ if (min && max) {
207
+ constraints.push(`${t.length}: ${min}-${max}`);
208
+ } else if (min) {
209
+ constraints.push(`${t.length}: ≥${min}`);
210
+ } else if (max) {
211
+ constraints.push(`${t.length}: ≤${max}`);
212
+ }
213
+ }
214
+
215
+ // 数字范围
216
+ if (prop.minimum !== undefined || prop.maximum !== undefined) {
217
+ const min = prop.minimum !== undefined ? prop.minimum : '';
218
+ const max = prop.maximum !== undefined ? prop.maximum : '';
219
+ if (min !== '' && max !== '') {
220
+ constraints.push(`${t.range}: ${min}-${max}`);
221
+ } else if (min !== '') {
222
+ constraints.push(`${t.range}: ≥${min}`);
223
+ } else if (max !== '') {
224
+ constraints.push(`${t.range}: ≤${max}`);
225
+ }
226
+ }
227
+
228
+ // 数组元素数
229
+ if (prop.minItems !== undefined || prop.maxItems !== undefined) {
230
+ const min = prop.minItems !== undefined ? prop.minItems : '';
231
+ const max = prop.maxItems !== undefined ? prop.maxItems : '';
232
+ if (min !== '' && max !== '') {
233
+ constraints.push(`${t.items}: ${min}-${max}`);
234
+ } else if (min !== '') {
235
+ constraints.push(`${t.items}: ≥${min}`);
236
+ } else if (max !== '') {
237
+ constraints.push(`${t.items}: ≤${max}`);
238
+ }
239
+ }
240
+
241
+ // 正则表达式
242
+ if (prop.pattern) {
243
+ constraints.push(`${t.pattern}: \`${prop.pattern}\``);
244
+ }
245
+
246
+ // 枚举值
247
+ if (prop.enum) {
248
+ const enumStr = prop.enum.map(v => `\`${v}\``).join(', ');
249
+ constraints.push(`${t.enum}: ${enumStr}`);
250
+ }
251
+
252
+ return constraints.length > 0 ? constraints.join('<br>') : '-';
253
+ }
254
+
255
+ /**
256
+ * 获取描述
257
+ * @private
258
+ */
259
+ static _getDescription(prop, locale) {
260
+ // 优先使用多语言 label
261
+ if (prop._labelI18n && prop._labelI18n[locale]) {
262
+ return prop._labelI18n[locale];
263
+ }
264
+
265
+ // 其次使用单语言 label
266
+ if (prop._label) {
267
+ return prop._label;
268
+ }
269
+
270
+ // 最后使用 description
271
+ if (prop.description) {
272
+ return prop.description;
273
+ }
274
+
275
+ return '-';
276
+ }
277
+
278
+ /**
279
+ * 生成示例数据
280
+ * @private
281
+ */
282
+ static _generateExample(schema, locale) {
283
+ const i18n = {
284
+ 'zh-CN': { example: '示例数据' },
285
+ 'en-US': { example: 'Example Data' },
286
+ 'ja-JP': { example: 'サンプルデータ' }
287
+ };
288
+
289
+ const t = i18n[locale] || i18n['en-US'];
290
+
291
+ let example = `## ${t.example}\n\n\`\`\`json\n`;
292
+ example += JSON.stringify(this._buildExample(schema), null, 2);
293
+ example += '\n\`\`\`\n';
294
+ return example;
295
+ }
296
+
297
+ /**
298
+ * 构建示例对象
299
+ * @private
300
+ */
301
+ static _buildExample(schema) {
302
+ if (schema.properties) {
303
+ const obj = {};
304
+ Object.entries(schema.properties).forEach(([key, prop]) => {
305
+ // 只生成必填字段的示例
306
+ if (prop._required || schema.required?.includes(key)) {
307
+ obj[key] = this._getExampleValue(prop);
308
+ }
309
+ });
310
+ return obj;
311
+ }
312
+ return null;
313
+ }
314
+
315
+ /**
316
+ * 获取示例值
317
+ * @private
318
+ */
319
+ static _getExampleValue(prop) {
320
+ // 使用默认值
321
+ if (prop.default !== undefined) {
322
+ return prop.default;
323
+ }
324
+
325
+ // 使用枚举第一项
326
+ if (prop.enum) {
327
+ return prop.enum[0];
328
+ }
329
+
330
+ // 根据类型和格式生成
331
+ switch (prop.type) {
332
+ case 'string':
333
+ if (prop.format === 'email') return 'user@example.com';
334
+ if (prop.format === 'url') return 'https://example.com';
335
+ if (prop.format === 'date') return '2025-12-29';
336
+ if (prop.format === 'uuid') return '550e8400-e29b-41d4-a716-446655440000';
337
+ return 'example';
338
+
339
+ case 'number':
340
+ case 'integer':
341
+ if (prop.minimum !== undefined) return prop.minimum;
342
+ if (prop.maximum !== undefined) return Math.floor(prop.maximum / 2);
343
+ return 0;
344
+
345
+ case 'boolean':
346
+ return true;
347
+
348
+ case 'array':
349
+ if (prop.items) {
350
+ return [this._getExampleValue(prop.items)];
351
+ }
352
+ return [];
353
+
354
+ case 'object':
355
+ if (prop.properties) {
356
+ return this._buildExample(prop);
357
+ }
358
+ return {};
359
+
360
+ default:
361
+ return null;
362
+ }
363
+ }
364
+
365
+ /**
366
+ * 生成约束规则章节
367
+ * @private
368
+ */
369
+ static _generateConstraintsSection(schema, locale) {
370
+ const i18n = {
371
+ 'zh-CN': {
372
+ rules: '约束规则',
373
+ required: '必填字段',
374
+ optional: '可选字段'
375
+ },
376
+ 'en-US': {
377
+ rules: 'Validation Rules',
378
+ required: 'Required Fields',
379
+ optional: 'Optional Fields'
380
+ },
381
+ 'ja-JP': {
382
+ rules: '検証ルール',
383
+ required: '必須フィールド',
384
+ optional: 'オプションフィールド'
385
+ }
386
+ };
387
+
388
+ const t = i18n[locale] || i18n['en-US'];
389
+
390
+ if (!schema.properties) {
391
+ return '';
392
+ }
393
+
394
+ const requiredFields = [];
395
+ const optionalFields = [];
396
+
397
+ Object.entries(schema.properties).forEach(([key, prop]) => {
398
+ if (prop._required || schema.required?.includes(key)) {
399
+ requiredFields.push(key);
400
+ } else {
401
+ optionalFields.push(key);
402
+ }
403
+ });
404
+
405
+ let section = `## ${t.rules}\n\n`;
406
+
407
+ if (requiredFields.length > 0) {
408
+ section += `**${t.required}**: ${requiredFields.map(f => `\`${f}\``).join(', ')}\n\n`;
409
+ }
410
+
411
+ if (optionalFields.length > 0) {
412
+ section += `**${t.optional}**: ${optionalFields.map(f => `\`${f}\``).join(', ')}\n`;
413
+ }
414
+
415
+ return section;
416
+ }
417
+ }
418
+
419
+ module.exports = MarkdownExporter;
420
+
@@ -0,0 +1,162 @@
1
+ /**
2
+ * MongoDB Schema导出器
3
+ *
4
+ * 将JSON Schema转换为MongoDB验证Schema
5
+ *
6
+ * @module lib/exporters/MongoDBExporter
7
+ * @version 1.0.0
8
+ */
9
+
10
+ const TypeConverter = require('../utils/TypeConverter');
11
+
12
+ /**
13
+ * MongoDB导出器类
14
+ * @class MongoDBExporter
15
+ */
16
+ class MongoDBExporter {
17
+ /**
18
+ * 构造函数
19
+ * @param {Object} options - 配置选项
20
+ * @param {boolean} options.strict - 是否严格模式(默认false)
21
+ */
22
+ constructor(options = {}) {
23
+ this.options = {
24
+ strict: options.strict || false,
25
+ ...options
26
+ };
27
+ }
28
+
29
+ /**
30
+ * 导出为MongoDB验证Schema
31
+ * @param {Object} jsonSchema - JSON Schema对象
32
+ * @returns {Object} MongoDB验证Schema
33
+ */
34
+ export(jsonSchema) {
35
+ if (!jsonSchema || typeof jsonSchema !== 'object') {
36
+ throw new Error('Invalid JSON Schema');
37
+ }
38
+
39
+ const mongoSchema = this._convertSchema(jsonSchema);
40
+
41
+ return {
42
+ $jsonSchema: mongoSchema
43
+ };
44
+ }
45
+
46
+ /**
47
+ * 转换Schema
48
+ * @private
49
+ * @param {Object} schema - JSON Schema
50
+ * @returns {Object} MongoDB Schema
51
+ */
52
+ _convertSchema(schema) {
53
+ const result = {};
54
+
55
+ // 转换type
56
+ if (schema.type) {
57
+ result.bsonType = TypeConverter.toMongoDBType(schema.type);
58
+ }
59
+
60
+ // 转换properties
61
+ if (schema.properties) {
62
+ result.properties = {};
63
+ for (const [key, value] of Object.entries(schema.properties)) {
64
+ result.properties[key] = this._convertSchema(value);
65
+ }
66
+ }
67
+
68
+ // 转换required
69
+ if (schema.required && Array.isArray(schema.required)) {
70
+ result.required = schema.required;
71
+ }
72
+
73
+ // 转换items(数组)
74
+ if (schema.items) {
75
+ result.items = this._convertSchema(schema.items);
76
+ }
77
+
78
+ // 字符串约束
79
+ if (schema.minLength !== undefined) {
80
+ result.minLength = schema.minLength;
81
+ }
82
+ if (schema.maxLength !== undefined) {
83
+ result.maxLength = schema.maxLength;
84
+ }
85
+ if (schema.pattern) {
86
+ result.pattern = schema.pattern;
87
+ }
88
+
89
+ // 数值约束
90
+ if (schema.minimum !== undefined) {
91
+ result.minimum = schema.minimum;
92
+ }
93
+ if (schema.maximum !== undefined) {
94
+ result.maximum = schema.maximum;
95
+ }
96
+
97
+ // 数组约束
98
+ if (schema.minItems !== undefined) {
99
+ result.minItems = schema.minItems;
100
+ }
101
+ if (schema.maxItems !== undefined) {
102
+ result.maxItems = schema.maxItems;
103
+ }
104
+
105
+ // 枚举
106
+ if (schema.enum) {
107
+ result.enum = schema.enum;
108
+ }
109
+
110
+ // 描述
111
+ if (schema.description) {
112
+ result.description = schema.description;
113
+ }
114
+
115
+ return result;
116
+ }
117
+
118
+ /**
119
+ * 生成createCollection命令
120
+ * @param {string} collectionName - 集合名称
121
+ * @param {Object} jsonSchema - JSON Schema对象
122
+ * @returns {Object} createCollection命令对象
123
+ */
124
+ generateCreateCommand(collectionName, jsonSchema) {
125
+ const validationSchema = this.export(jsonSchema);
126
+
127
+ return {
128
+ collectionName,
129
+ options: {
130
+ validator: validationSchema,
131
+ validationLevel: this.options.strict ? 'strict' : 'moderate',
132
+ validationAction: 'error'
133
+ }
134
+ };
135
+ }
136
+
137
+ /**
138
+ * 生成可执行的MongoDB命令字符串
139
+ * @param {string} collectionName - 集合名称
140
+ * @param {Object} jsonSchema - JSON Schema对象
141
+ * @returns {string} MongoDB命令字符串
142
+ */
143
+ generateCommand(collectionName, jsonSchema) {
144
+ const command = this.generateCreateCommand(collectionName, jsonSchema);
145
+
146
+ return `db.createCollection("${command.collectionName}", ${JSON.stringify(command.options, null, 2)})`;
147
+ }
148
+
149
+ /**
150
+ * 静态方法:快速导出
151
+ * @static
152
+ * @param {Object} jsonSchema - JSON Schema对象
153
+ * @returns {Object} MongoDB验证Schema
154
+ */
155
+ static export(jsonSchema) {
156
+ const exporter = new MongoDBExporter();
157
+ return exporter.export(jsonSchema);
158
+ }
159
+ }
160
+
161
+ module.exports = MongoDBExporter;
162
+