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
package/index.js DELETED
@@ -1,475 +0,0 @@
1
- /**
2
- * schema-dsl - 主入口文件
3
- *
4
- * 统一的DSL Builder Pattern
5
- * 简洁 + 强大 = 完美平衡
6
- *
7
- * @module schema-dsl
8
- * @version 1.0.4
9
- */
10
-
11
- // ========== 核心层 ==========
12
- const JSONSchemaCore = require("./lib/core/JSONSchemaCore");
13
- const Validator = require("./lib/core/Validator");
14
- const ErrorFormatter = require("./lib/core/ErrorFormatter");
15
- const CacheManager = require("./lib/core/CacheManager");
16
- const DslBuilder = require("./lib/core/DslBuilder");
17
- const PluginManager = require("./lib/core/PluginManager");
18
- const ConditionalBuilder = require("./lib/core/ConditionalBuilder");
19
-
20
- // ========== 错误消息系统 ==========
21
- const ErrorCodes = require("./lib/core/ErrorCodes");
22
- const MessageTemplate = require("./lib/core/MessageTemplate");
23
- const Locale = require("./lib/core/Locale");
24
-
25
- // ========== 错误类 ==========
26
- const ValidationError = require("./lib/errors/ValidationError");
27
- const I18nError = require("./lib/errors/I18nError");
28
-
29
- // ========== String 扩展 ==========
30
- const {
31
- installStringExtensions,
32
- uninstallStringExtensions,
33
- } = require("./lib/core/StringExtensions");
34
-
35
- // ========== 适配器层 ==========
36
- const dsl = require("./lib/adapters/DslAdapter");
37
-
38
- // 挂载静态方法 (v2.1.0)
39
- dsl.match = dsl.DslAdapter.match;
40
-
41
- // ✅ 智能 dsl.if:根据参数类型选择实现
42
- dsl.if = function (...args) {
43
- // 如果第一个参数是函数 → 使用新的 ConditionalBuilder(链式API)
44
- if (typeof args[0] === "function") {
45
- return ConditionalBuilder.start(args[0]);
46
- }
47
-
48
- // 如果第一个参数是字符串且有3个参数 → 使用原有的字段条件实现
49
- // dsl.if('fieldName', thenSchema, elseSchema)
50
- if (typeof args[0] === "string" && args.length >= 2) {
51
- return dsl.DslAdapter.if(args[0], args[1], args[2]);
52
- }
53
-
54
- // 其他情况 → 调用 ConditionalBuilder 让它抛出正确的错误
55
- return ConditionalBuilder.start(args[0]);
56
- };
57
-
58
- // ✅ dsl.error:统一的多语言错误抛出(v1.1.1+)
59
- // v1.1.8: 支持简化语法,智能参数识别
60
- dsl.error = {
61
- /**
62
- * 创建多语言错误(不抛出)
63
- * @param {string} code - 错误代码(多语言 key)
64
- * @param {Object|string} paramsOrLocale - 错误参数对象 或 语言代码(智能识别)
65
- * @param {number} statusCode - HTTP 状态码
66
- * @param {string} locale - 语言环境(仅当第2个参数是对象时有效)
67
- * @returns {I18nError} 错误实例
68
- *
69
- * @example
70
- * // 简化语法
71
- * dsl.error.create('account.notFound', 'zh-CN');
72
- *
73
- * @example
74
- * // 标准语法
75
- * dsl.error.create('account.notFound', { id: '123' }, 404, 'zh-CN');
76
- */
77
- create: (code, paramsOrLocale, statusCode, locale) =>
78
- I18nError.create(code, paramsOrLocale, statusCode, locale),
79
-
80
- /**
81
- * 抛出多语言错误
82
- * @param {string} code - 错误代码(多语言 key)
83
- * @param {Object|string} paramsOrLocale - 错误参数对象 或 语言代码(智能识别)
84
- * @param {number} statusCode - HTTP 状态码
85
- * @param {string} locale - 语言环境(仅当第2个参数是对象时有效)
86
- * @throws {I18nError} 直接抛出错误
87
- *
88
- * @example
89
- * // 简化语法
90
- * dsl.error.throw('account.notFound', 'zh-CN');
91
- *
92
- * @example
93
- * // 标准语法
94
- * dsl.error.throw('account.notFound', { id: '123' }, 404, 'zh-CN');
95
- */
96
- throw: (code, paramsOrLocale, statusCode, locale) =>
97
- I18nError.throw(code, paramsOrLocale, statusCode, locale),
98
-
99
- /**
100
- * 断言方法 - 条件不满足时抛错
101
- * @param {boolean} condition - 条件表达式
102
- * @param {string} code - 错误代码(多语言 key)
103
- * @param {Object|string} paramsOrLocale - 错误参数对象 或 语言代码(智能识别)
104
- * @param {number} statusCode - HTTP 状态码
105
- * @param {string} locale - 语言环境(仅当第3个参数是对象时有效)
106
- *
107
- * @example
108
- * // 简化语法
109
- * dsl.error.assert(account, 'account.notFound', 'zh-CN');
110
- *
111
- * @example
112
- * // 标准语法
113
- * dsl.error.assert(account, 'account.notFound', { id: '123' }, 404, 'zh-CN');
114
- */
115
- assert: (condition, code, paramsOrLocale, statusCode, locale) =>
116
- I18nError.assert(condition, code, paramsOrLocale, statusCode, locale),
117
- };
118
-
119
- /**
120
- * 从目录递归加载语言包(内部函数)
121
- *
122
- * 支持子目录递归扫描,子目录名作为模块组织层(不影响语言 key)。
123
- * 同名 key 冲突时:strict 模式抛错,默认模式打 WARN 日志。
124
- *
125
- * @param {string} dirPath - 目录绝对路径
126
- * @param {Object} options - 配置选项
127
- * @param {boolean} [options.strict=false] - 严格模式:同名 key 冲突时抛出 Error
128
- * @private
129
- */
130
- function loadLocalesFromDir(dirPath, options = {}) {
131
- const fs = require("fs");
132
- const path = require("path");
133
-
134
- if (!fs.existsSync(dirPath) || !fs.statSync(dirPath).isDirectory()) {
135
- console.warn(
136
- "[schema-dsl] i18n path does not exist or is not a directory:",
137
- dirPath,
138
- );
139
- return;
140
- }
141
-
142
- // 语言代码格式校验:zh-CN / en-US / zh / en 等
143
- const LOCALE_NAME_RE = /^[a-z]{2,3}(-[A-Z]{2,4})?$/;
144
-
145
- const entries = fs.readdirSync(dirPath, { withFileTypes: true });
146
-
147
- entries.forEach((entry) => {
148
- const fullPath = path.join(dirPath, entry.name);
149
-
150
- if (entry.isDirectory()) {
151
- // 递归进入子目录(子目录名仅作模块组织层,不影响语言 key)
152
- loadLocalesFromDir(fullPath, options);
153
- } else if (entry.isFile()) {
154
- const ext = path.extname(entry.name);
155
- if (ext !== ".js" && ext !== ".cjs" && ext !== ".json") return;
156
-
157
- const localeName = path.basename(entry.name, ext);
158
-
159
- // 文件名格式校验:只加载符合语言代码格式的文件
160
- if (!LOCALE_NAME_RE.test(localeName)) {
161
- // 仅 debug 级别,不影响正常运行
162
- return;
163
- }
164
-
165
- let messages;
166
- try {
167
- messages = require(path.resolve(fullPath));
168
- } catch (e) {
169
- console.warn(
170
- "[schema-dsl] Failed to load locale file:",
171
- fullPath,
172
- e.message,
173
- );
174
- return;
175
- }
176
-
177
- // 冲突检测:检查 messages 的每个 key 是否已存在于当前语言包
178
- const existing = Locale.locales[localeName] || {};
179
- const conflictKeys = Object.keys(messages).filter((k) =>
180
- Object.prototype.hasOwnProperty.call(existing, k),
181
- );
182
-
183
- if (conflictKeys.length > 0) {
184
- const keyList = conflictKeys.join(", ");
185
- const msg = `[schema-dsl] i18n key 冲突 in locale '${localeName}'\n 冲突 key: ${keyList}\n 来源文件: ${fullPath}`;
186
- if (options.strict) {
187
- throw new Error(msg);
188
- } else {
189
- console.warn(msg);
190
- }
191
- }
192
-
193
- Locale.addLocale(localeName, messages);
194
- }
195
- });
196
- }
197
-
198
- /**
199
- * 全局配置
200
- * @param {Object} options - 配置选项
201
- * @param {Object} options.patterns - 验证规则扩展 (phone, idCard, creditCard)
202
- * @param {string|Object} options.i18n - 多语言配置(目录路径、对象语言包、或含 localesPath 的对象)
203
- * @param {Object} options.cache - 缓存配置
204
- * @param {boolean} [options.strict=false] - 严格模式:i18n 目录扫描时 key 冲突直接抛错(默认 false)
205
- */
206
- dsl.config = function (options = {}) {
207
- const patterns = require("./lib/config/patterns");
208
-
209
- // patterns 配置
210
- if (options.patterns) {
211
- if (options.patterns.phone)
212
- Object.assign(patterns.phone, options.patterns.phone);
213
- if (options.patterns.idCard)
214
- Object.assign(patterns.idCard, options.patterns.idCard);
215
- if (options.patterns.creditCard)
216
- Object.assign(patterns.creditCard, options.patterns.creditCard);
217
- }
218
-
219
- // 多语言支持 (v1.0.1 优化;v1.2.3 增强:递归子目录 + 冲突检测)
220
- if (options.i18n) {
221
- // 方式 1: 传入目录路径(字符串)→ 递归扫描
222
- if (typeof options.i18n === "string") {
223
- loadLocalesFromDir(options.i18n, options);
224
- }
225
- // 方式 2: 传入对象
226
- else if (typeof options.i18n === "object") {
227
- // 方式 2a: 含 localesPath 字段 → 走目录扫描(兼容文档记载用法)
228
- if (options.i18n.localesPath) {
229
- loadLocalesFromDir(options.i18n.localesPath, options);
230
- }
231
- // 方式 2b: 直接传语言包对象 { 'zh-CN': {...}, 'en-US': {...} }(原有逻辑,不变)
232
- else {
233
- Object.keys(options.i18n).forEach((locale) => {
234
- Locale.addLocale(locale, options.i18n[locale]);
235
- });
236
- }
237
- }
238
- }
239
-
240
- // 缓存配置 (v1.0.4+)
241
- if (options.cache) {
242
- // 如果 Validator 还未创建,保存配置供后续创建时使用
243
- if (!_defaultValidator) {
244
- _validatorOptions.cache = options.cache;
245
- } else {
246
- // 如果已创建,动态修改现有实例的配置(向后兼容)
247
- const cacheOpts = _defaultValidator.cache.options;
248
- if (options.cache.maxSize !== undefined) {
249
- cacheOpts.maxSize = options.cache.maxSize;
250
- }
251
- if (options.cache.ttl !== undefined) {
252
- cacheOpts.ttl = options.cache.ttl;
253
- }
254
- if (options.cache.enabled !== undefined) {
255
- cacheOpts.enabled = options.cache.enabled;
256
- }
257
- if (options.cache.statsEnabled !== undefined) {
258
- cacheOpts.statsEnabled = options.cache.statsEnabled;
259
- }
260
- }
261
- }
262
- };
263
-
264
- // ========== 导出器层 ==========
265
- const exporters = require("./lib/exporters");
266
-
267
- // ========== 初始化默认语言包 ==========
268
- const defaultLocales = require("./lib/locales");
269
- Object.entries(defaultLocales).forEach(([locale, messages]) => {
270
- Locale.addLocale(locale, messages);
271
- });
272
-
273
- // ========== 单例Validator ==========
274
- let _defaultValidator = null;
275
- let _validatorOptions = {}; // 存储 Validator 配置选项
276
-
277
- /**
278
- * 获取默认Validator实例(单例)
279
- * @returns {Validator}
280
- */
281
- function getDefaultValidator() {
282
- if (!_defaultValidator) {
283
- _defaultValidator = new Validator(_validatorOptions);
284
- }
285
- return _defaultValidator;
286
- }
287
-
288
- /**
289
- * 智能类型转换:只转换字符串→数字(当schema要求number且能转换时)
290
- * @private
291
- * @param {*} data - 原始数据
292
- * @param {Object} schema - JSON Schema对象
293
- * @returns {*} 转换后的数据
294
- */
295
- function smartCoerceTypes(data, schema) {
296
- if (!data || typeof data !== "object") return data;
297
-
298
- // 获取 schema 对象
299
- const schemaObj = schema.toSchema ? schema.toSchema() : schema;
300
- const properties = schemaObj.properties || {};
301
-
302
- // 处理数组
303
- if (Array.isArray(data)) {
304
- return data.map((item) => smartCoerceTypes(item, schema));
305
- }
306
-
307
- // 处理对象
308
- const result = { ...data };
309
-
310
- Object.keys(result).forEach((key) => {
311
- const value = result[key];
312
- const fieldSchema = properties[key];
313
-
314
- if (!fieldSchema) return;
315
-
316
- // ⚠️ 关键修复:如果字段有 enum 约束,不进行类型转换
317
- // 原因:枚举验证需要严格匹配类型
318
- // 例如:数字枚举 [1,2,3] 不应该接受字符串 "1"
319
- if (fieldSchema.enum) {
320
- return; // 跳过枚举字段的转换
321
- }
322
-
323
- // 核心规则:只有同时满足以下三个条件才转换
324
- // 1. 值是字符串
325
- // 2. Schema 要求 number 类型
326
- // 3. 能正常转换为有效数字
327
- // 4. 不是枚举字段(已在上面检查)
328
- if (fieldSchema.type === "number" && typeof value === "string") {
329
- const trimmed = value.trim();
330
- if (trimmed !== "") {
331
- const num = Number(trimmed);
332
- if (!isNaN(num)) {
333
- result[key] = num;
334
- }
335
- }
336
- }
337
- // 处理嵌套对象
338
- else if (
339
- fieldSchema.type === "object" &&
340
- typeof value === "object" &&
341
- value !== null
342
- ) {
343
- result[key] = smartCoerceTypes(value, fieldSchema);
344
- }
345
- // 处理数组元素
346
- else if (fieldSchema.type === "array" && Array.isArray(value)) {
347
- if (fieldSchema.items && fieldSchema.items.type === "number") {
348
- result[key] = value.map((item) => {
349
- if (typeof item === "string") {
350
- const trimmed = item.trim();
351
- if (trimmed !== "") {
352
- const num = Number(trimmed);
353
- return !isNaN(num) ? num : item;
354
- }
355
- }
356
- return item;
357
- });
358
- }
359
- }
360
- });
361
-
362
- return result;
363
- }
364
-
365
- /**
366
- * 便捷验证方法(使用默认Validator)
367
- * @param {Object} schema - JSON Schema对象
368
- * @param {*} data - 待验证数据
369
- * @param {Object} [options] - 验证选项
370
- * @param {boolean} [options.format=true] - 是否格式化错误
371
- * @param {string} [options.locale] - 动态指定语言(如 'zh-CN', 'en-US')
372
- * @param {Object} [options.messages] - 自定义错误消息
373
- * @param {boolean} [options.coerce=true] - 是否启用智能类型转换(字符串→数字)
374
- * @returns {Object} 验证结果
375
- *
376
- * @example
377
- * const { validate, dsl } = require('schema-dsl');
378
- *
379
- * const schema = dsl({ email: 'email!' });
380
- *
381
- * // 基本验证(默认启用智能转换)
382
- * const result1 = validate(schema, { userId: '123', age: '25' });
383
- * // userId 和 age 自动转为数字
384
- *
385
- * // 禁用智能转换
386
- * const result2 = validate(schema, data, { coerce: false });
387
- *
388
- * // 指定语言
389
- * const result3 = validate(schema, { email: 'invalid' }, { locale: 'zh-CN' });
390
- */
391
- function validate(schema, data, options = {}) {
392
- // 默认启用智能转换(只转换字符串→数字)
393
- const shouldCoerce = options.coerce !== false;
394
-
395
- if (shouldCoerce) {
396
- data = smartCoerceTypes(data, schema);
397
- }
398
-
399
- return getDefaultValidator().validate(schema, data, options);
400
- }
401
-
402
- // ========== 工具函数 ==========
403
- const { TypeConverter, SchemaHelper } = require("./lib/utils");
404
- const SchemaUtils = require("./lib/utils/SchemaUtils");
405
-
406
- // ========== 验证器扩展 ==========
407
- const { CustomKeywords } = require("./lib/validators");
408
-
409
- // ========== 常量 ==========
410
- const CONSTANTS = require("./lib/config/constants");
411
-
412
- // ========== 自动安装 String 扩展 ==========
413
- installStringExtensions(dsl);
414
-
415
- // ========== 导出 ==========
416
-
417
- // 导入 validateAsync
418
- const { validateAsync } = require("./lib/adapters/DslAdapter");
419
-
420
- module.exports = {
421
- // 统一DSL API
422
- dsl,
423
- DslBuilder,
424
-
425
- // 配置函数 (v1.0.4+)
426
- config: dsl.config,
427
-
428
- // String 扩展控制
429
- installStringExtensions: () => installStringExtensions(dsl),
430
- uninstallStringExtensions,
431
-
432
- // 核心类
433
- JSONSchemaCore,
434
- Validator,
435
-
436
- // 便捷方法(推荐)
437
- validate, // 便捷验证(单例)
438
- validateAsync, // v2.1.0 新增:异步验证
439
- getDefaultValidator, // 获取单例Validator
440
- ErrorFormatter,
441
- CacheManager,
442
-
443
- // 错误类 (v2.1.0 新增)
444
- ValidationError,
445
- I18nError, // v1.1.1 新增:多语言错误类
446
-
447
- // 错误消息系统
448
- ErrorCodes,
449
- MessageTemplate,
450
- Locale,
451
-
452
- // 插件系统 (v2.2.0 新增)
453
- PluginManager,
454
-
455
- // 导出器
456
- exporters,
457
- MongoDBExporter: exporters.MongoDBExporter,
458
- MySQLExporter: exporters.MySQLExporter,
459
- PostgreSQLExporter: exporters.PostgreSQLExporter,
460
- MarkdownExporter: exporters.MarkdownExporter,
461
-
462
- // 工具函数
463
- TypeConverter,
464
- SchemaHelper,
465
- SchemaUtils, // v2.0.1新增:Schema工具类
466
-
467
- // 验证器扩展
468
- CustomKeywords,
469
-
470
- // 常量
471
- CONSTANTS,
472
-
473
- // 版本信息
474
- VERSION: "1.2.3",
475
- };
package/index.mjs DELETED
@@ -1,60 +0,0 @@
1
- import schemaDsl from './index.js';
2
-
3
- export const {
4
- // 统一DSL API
5
- dsl,
6
- DslBuilder,
7
-
8
- // 配置函数 (v1.0.4+)
9
- config,
10
-
11
- // String 扩展控制
12
- installStringExtensions,
13
- uninstallStringExtensions,
14
-
15
- // 核心类
16
- JSONSchemaCore,
17
- Validator,
18
-
19
- // 便捷方法(推荐)
20
- validate,
21
- validateAsync,
22
- getDefaultValidator,
23
- ErrorFormatter,
24
- CacheManager,
25
-
26
- // 错误类 (v2.1.0 新增)
27
- ValidationError,
28
- I18nError,
29
-
30
- // 错误消息系统
31
- ErrorCodes,
32
- MessageTemplate,
33
- Locale,
34
-
35
- // 插件系统 (v2.2.0 新增)
36
- PluginManager,
37
-
38
- // 导出器
39
- exporters,
40
- MongoDBExporter,
41
- MySQLExporter,
42
- PostgreSQLExporter,
43
- MarkdownExporter,
44
-
45
- // 工具函数
46
- TypeConverter,
47
- SchemaHelper,
48
- SchemaUtils,
49
-
50
- // 验证器扩展
51
- CustomKeywords,
52
-
53
- // 常量
54
- CONSTANTS,
55
-
56
- // 版本信息
57
- VERSION
58
- } = schemaDsl;
59
-
60
- export default dsl;