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
@@ -0,0 +1,39 @@
1
+ # Validator 类概述
2
+
3
+ `Validator` 是对 AJV 的封装,提供编译缓存、错误格式化、自定义关键字和批量验证能力。
4
+
5
+ ```javascript
6
+ const { Validator, dsl } = require('schema-dsl');
7
+ const validator = new Validator();
8
+ const schema = dsl({ email: 'email!' });
9
+ console.log(validator.validate(schema, { email: 'test@example.com' }));
10
+ ```
11
+
12
+ ## 缓存配置
13
+
14
+ `Validator` 构造器支持两种缓存写法:
15
+
16
+ ```javascript
17
+ new Validator({ cache: true }); // 使用默认缓存配置
18
+ new Validator({ cache: false }); // 关闭缓存
19
+
20
+ new Validator({
21
+ cache: {
22
+ enabled: true,
23
+ maxSize: 500,
24
+ ttl: 60 * 60 * 1000
25
+ }
26
+ });
27
+ ```
28
+
29
+ > 如果你希望直接传入 DSL 对象(例如 `validate({ email: 'email!' }, data)`),请使用顶层便捷函数 `validate()` / `validateAsync()`;`Validator` 实例方法仍建议接收标准 JSON Schema 或 `dsl({...})` 的转换结果。
30
+
31
+ 相关方法:`compile()`、`validate()`、`validateAsync()`、`validateBatch()`、`addKeyword()`、`addFormat()`。
32
+
33
+ ---
34
+
35
+ ## 对应示例文件
36
+
37
+ **示例入口**: [validator.ts](https://github.com/vextjs/schema-dsl/blob/main/examples/docs/validator.ts)
38
+ **说明**: 覆盖 `new Validator()` 的常见配置、单次验证、编译缓存命中和 `validateBatch()` 复用路径。
39
+
package/package.json CHANGED
@@ -1,73 +1,131 @@
1
- {
2
- "name": "schema-dsl",
3
- "version": "1.2.5",
4
- "description": "简洁强大的JSON Schema验证库 - DSL语法 + String扩展 + 便捷validate",
5
- "main": "index.js",
6
- "types": "index.d.ts",
7
- "exports": {
8
- ".": {
9
- "require": "./index.js",
10
- "import": "./index.mjs",
11
- "types": "./index.d.ts"
12
- }
13
- },
14
- "scripts": {
15
- "test": "mocha test/unit/**/*.test.js",
16
- "test:integration": "mocha test/integration/**/*.test.js",
17
- "test:all": "mocha test/**/*.test.js",
18
- "coverage": "nyc npm test",
19
- "lint": "eslint lib/**/*.js",
20
- "example": "node examples/dsl-style.js"
21
- },
22
- "keywords": [
23
- "schema",
24
- "validation",
25
- "validator",
26
- "dsl",
27
- "json-schema",
28
- "data-validation",
29
- "form-validation",
30
- "mongodb",
31
- "mysql",
32
- "postgresql",
33
- "database-schema",
34
- "i18n",
35
- "internationalization",
36
- "typescript",
37
- "express",
38
- "koa",
39
- "fastify",
40
- "rest-api",
41
- "input-validation"
42
- ],
43
- "author": "rocky <rockyshi1993@gmail.com>",
44
- "license": "MIT",
45
- "repository": {
46
- "type": "git",
47
- "url": "https://github.com/vextjs/schema-dsl.git"
48
- },
49
- "bugs": {
50
- "url": "https://github.com/vextjs/schema-dsl/issues"
51
- },
52
- "homepage": "https://github.com/vextjs/schema-dsl#readme",
53
- "engines": {
54
- "node": ">=12.0.0"
55
- },
56
- "dependencies": {
57
- "ajv": "^8.17.1",
58
- "ajv-formats": "^2.1.1"
59
- },
60
- "devDependencies": {
61
- "benchmark": "^2.1.4",
62
- "chai": "^4.5.0",
63
- "eslint": "^8.57.1",
64
- "express": "^5.2.1",
65
- "joi": "^18.0.2",
66
- "mocha": "^10.8.2",
67
- "monsqlize": "^1.0.1",
68
- "nyc": "^15.1.0",
69
- "sinon": "^17.0.1",
70
- "yup": "^1.7.1",
71
- "zod": "^4.2.1"
72
- }
73
- }
1
+ {
2
+ "name": "schema-dsl",
3
+ "version": "2.0.1",
4
+ "description": "A concise and powerful JSON Schema validation library - DSL syntax + String extensions + convenient validate API",
5
+ "main": "./dist/index.cjs",
6
+ "module": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": {
11
+ "types": "./dist/index.d.ts",
12
+ "default": "./dist/index.js"
13
+ },
14
+ "require": {
15
+ "types": "./dist/index.d.cts",
16
+ "default": "./dist/index.cjs"
17
+ }
18
+ },
19
+ "./plugins/custom-format": {
20
+ "import": {
21
+ "types": "./dist/plugins/custom-format.d.ts",
22
+ "default": "./dist/plugins/custom-format.js"
23
+ },
24
+ "require": {
25
+ "types": "./dist/plugins/custom-format.d.cts",
26
+ "default": "./dist/plugins/custom-format.cjs"
27
+ }
28
+ },
29
+ "./plugins/custom-validator": {
30
+ "import": {
31
+ "types": "./dist/plugins/custom-validator.d.ts",
32
+ "default": "./dist/plugins/custom-validator.js"
33
+ },
34
+ "require": {
35
+ "types": "./dist/plugins/custom-validator.d.cts",
36
+ "default": "./dist/plugins/custom-validator.cjs"
37
+ }
38
+ },
39
+ "./plugins/custom-type-example": {
40
+ "import": {
41
+ "types": "./dist/plugins/custom-type-example.d.ts",
42
+ "default": "./dist/plugins/custom-type-example.js"
43
+ },
44
+ "require": {
45
+ "types": "./dist/plugins/custom-type-example.d.cts",
46
+ "default": "./dist/plugins/custom-type-example.cjs"
47
+ }
48
+ }
49
+ },
50
+ "scripts": {
51
+ "build": "tsup",
52
+ "dev": "tsup --watch",
53
+ "test": "vitest run",
54
+ "test:watch": "vitest",
55
+ "test:coverage": "vitest run --coverage",
56
+ "typecheck": "tsc --noEmit",
57
+ "examples:typecheck": "tsc -p tsconfig.examples.json --noEmit",
58
+ "examples:build": "tsc -p tsconfig.examples.json",
59
+ "lint": "eslint src/**/*.ts",
60
+ "test:version": "node -e \"const p=require('./package.json');const {VERSION}=require('./dist/index.cjs');if(p.version!==VERSION)throw new Error('Version mismatch: '+p.version+' vs '+VERSION);console.log('Version OK:',p.version)\"",
61
+ "bench": "node test/benchmarks/library-comparison.js",
62
+ "prepublishOnly": "npm run build && npm run typecheck && npm test"
63
+ },
64
+ "keywords": [
65
+ "schema",
66
+ "validation",
67
+ "validator",
68
+ "dsl",
69
+ "json-schema",
70
+ "data-validation",
71
+ "form-validation",
72
+ "mongodb",
73
+ "mysql",
74
+ "postgresql",
75
+ "database-schema",
76
+ "i18n",
77
+ "internationalization",
78
+ "typescript",
79
+ "express",
80
+ "koa",
81
+ "fastify",
82
+ "rest-api",
83
+ "input-validation"
84
+ ],
85
+ "author": "rocky <rockyshi1993@gmail.com>",
86
+ "license": "MIT",
87
+ "repository": {
88
+ "type": "git",
89
+ "url": "https://github.com/vextjs/schema-dsl.git"
90
+ },
91
+ "bugs": {
92
+ "url": "https://github.com/vextjs/schema-dsl/issues"
93
+ },
94
+ "homepage": "https://github.com/vextjs/schema-dsl#readme",
95
+ "engines": {
96
+ "node": ">=18.0.0"
97
+ },
98
+ "dependencies": {
99
+ "ajv": "^8.18.0",
100
+ "ajv-formats": "^2.1.1",
101
+ "cache-hub": "^1.0.0",
102
+ "json5": "^2.2.3",
103
+ "safe-regex": "^2.1.1"
104
+ },
105
+ "devDependencies": {
106
+ "@types/node": "^25.6.0",
107
+ "@typescript-eslint/eslint-plugin": "^8.0.0",
108
+ "@typescript-eslint/parser": "^8.0.0",
109
+ "@vitest/coverage-v8": "^3.0.0",
110
+ "eslint": "^9.0.0",
111
+ "fastest-validator": "^1.19.1",
112
+ "joi": "^18.1.2",
113
+ "tsup": "^8.0.0",
114
+ "typescript": "^5.5.0",
115
+ "vitest": "^3.0.0",
116
+ "yup": "^1.7.1",
117
+ "zod": "^4.3.6"
118
+ },
119
+ "type": "module",
120
+ "files": [
121
+ "dist/**/*.js",
122
+ "dist/**/*.cjs",
123
+ "dist/**/*.d.ts",
124
+ "dist/**/*.d.cts",
125
+ "plugins",
126
+ "src",
127
+ "docs",
128
+ "README.md",
129
+ "CHANGELOG.md"
130
+ ]
131
+ }
@@ -0,0 +1,8 @@
1
+ 'use strict';
2
+
3
+ const mod = require('../dist/plugins/custom-format.cjs');
4
+ const plugin = mod.default ?? mod.customFormatPlugin ?? mod;
5
+
6
+ module.exports = plugin;
7
+ module.exports.default = plugin;
8
+
@@ -0,0 +1,8 @@
1
+ 'use strict';
2
+
3
+ const mod = require('../dist/plugins/custom-type-example.cjs');
4
+ const plugin = mod.default ?? mod.customTypeExamplePlugin ?? mod;
5
+
6
+ module.exports = plugin;
7
+ module.exports.default = plugin;
8
+
@@ -0,0 +1,8 @@
1
+ 'use strict';
2
+
3
+ const mod = require('../dist/plugins/custom-validator.cjs');
4
+ const plugin = mod.default ?? mod.customValidatorPlugin ?? mod;
5
+
6
+ module.exports = plugin;
7
+ module.exports.default = plugin;
8
+
@@ -0,0 +1,111 @@
1
+
2
+ /**
3
+ * DslAdapter — DSL parsing adapter (thin wrapper layer).
4
+ *
5
+ * v2 changes:
6
+ * - All parsing logic delegated to DslParser (replaces v1 DslAdapter._parseType duplication)
7
+ * - Fixes DA-01/DA-02/DA-03 (handled uniformly by the DslParser pipeline)
8
+ * - parseObject delegates to DslParser.parseObject (replaces JSONSchemaCore)
9
+ * - BC-2 fix: parseObject() returns ObjectDslBuilder (supports chain .strict()/.requireAll())
10
+ * - BC-4 fix: typeMap getter exposes all registered types; registerType() convenience entry point
11
+ */
12
+
13
+ import type { JSONSchema } from '../types/schema.js'
14
+ import type { DslDefinition } from '../types/dsl.js'
15
+ import { DslParser } from '../parser/DslParser.js'
16
+ import { TypeRegistry } from '../parser/TypeRegistry.js'
17
+ import { ObjectDslBuilder } from '../core/ObjectDslBuilder.js'
18
+
19
+ type DslMarker = Record<string, unknown>
20
+
21
+ export const DslAdapter = {
22
+ /**
23
+ * Parse a DSL string into a JSON Schema.
24
+ * Equivalent to v1 DslAdapter.parseString(), but delegates to the unified DslParser.
25
+ */
26
+ parseString(dslString: string): JSONSchema {
27
+ if (!dslString || typeof dslString !== 'string') {
28
+ throw new Error('[schema-dsl] DslAdapter.parseString: DSL must be a string')
29
+ }
30
+ return DslParser.parseString(dslString)
31
+ },
32
+
33
+ /**
34
+ * parse() — alias for parseString() (backwards compat with v1).
35
+ */
36
+ parse(dslString: string): JSONSchema {
37
+ if (!dslString || typeof dslString !== 'string') {
38
+ throw new Error('[schema-dsl] DslAdapter.parse: DSL must be a string')
39
+ }
40
+ const schema = DslParser.parseString(dslString)
41
+ // v1 compat: always set _required (false if not set)
42
+ if ((schema as Record<string, unknown>)['_required'] === undefined) {
43
+ (schema as Record<string, unknown>)['_required'] = false
44
+ }
45
+ return schema
46
+ },
47
+
48
+ /**
49
+ * Parse an object-form DSL definition → ObjectDslBuilder (BC-2 fix).
50
+ * v1: parseObject() returned a chainable builder (.strict()/.requireAll()).
51
+ * v2 fix: returns ObjectDslBuilder wrapping the compiled JSONSchema.
52
+ */
53
+ parseObject(dslObj: DslDefinition): ObjectDslBuilder {
54
+ const schema = DslParser.parseObject(dslObj)
55
+ return new ObjectDslBuilder(schema)
56
+ },
57
+
58
+ /**
59
+ * Create a Match marker (v1 compat). The actual JSON Schema is built per target field in parseObject.
60
+ */
61
+ match(field: string, map: Record<string, unknown>): DslMarker {
62
+ return { _isMatch: true, field, map }
63
+ },
64
+
65
+ /**
66
+ * Create an If marker (v1 compat). The actual JSON Schema is built per target field in parseObject.
67
+ */
68
+ if(condition: string, thenSchema: unknown, elseSchema?: unknown): DslMarker {
69
+ return { _isIf: true, condition, then: thenSchema, else: elseSchema }
70
+ },
71
+
72
+ /**
73
+ * toCore() — v1 compat: returns { schema } wrapper
74
+ */
75
+ toCore(dslInput: string | DslDefinition): { schema: JSONSchema } {
76
+ let schema: JSONSchema
77
+ if (typeof dslInput === 'string') {
78
+ schema = this.parse(dslInput)
79
+ } else {
80
+ schema = DslParser.parseObject(dslInput)
81
+ }
82
+ return { schema }
83
+ },
84
+
85
+ /**
86
+ * typeMap getter — v1 compat: DslAdapter.typeMap exposes all registered types (BC-4 fix).
87
+ * Assigning typeMap[name] = schema is equivalent to calling TypeRegistry.register(name, schema).
88
+ */
89
+ get typeMap(): Record<string, JSONSchema> {
90
+ const map: Record<string, JSONSchema> = {}
91
+ for (const [name, def] of TypeRegistry.entries()) {
92
+ map[name] = def.baseSchema as JSONSchema
93
+ }
94
+ return new Proxy(map, {
95
+ set(_target: Record<string, JSONSchema>, key: string, value: JSONSchema) {
96
+ TypeRegistry.register(key, { baseSchema: value })
97
+ return true
98
+ },
99
+ })
100
+ },
101
+
102
+ /**
103
+ * registerType() — v1 compat: register a custom type into TypeRegistry (BC-4 fix).
104
+ */
105
+ registerType(name: string, schema: JSONSchema): void {
106
+ TypeRegistry.register(name, { baseSchema: schema })
107
+ },
108
+ }
109
+
110
+ export type DslAdapterType = typeof DslAdapter
111
+
@@ -0,0 +1 @@
1
+ export * from './DslAdapter.js'
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Global constants.
3
+ * Fixes:
4
+ * CF-01 IPv4 regex too permissive → replaced with RFC-compliant standard regex
5
+ * CF-02 IPv6 regex did not support compressed notation → replaced with full RFC 5952 compatible regex
6
+ */
7
+
8
+ // ========== Validation config ==========
9
+ export const VALIDATION = {
10
+ MAX_RECURSION_DEPTH: 100,
11
+ MAX_ARRAY_SIZE: 100_000,
12
+ MAX_STRING_LENGTH: 1_000_000,
13
+ MAX_OBJECT_KEYS: 10_000,
14
+ DEFAULT_TIMEOUT: 5_000,
15
+ REGEX_TIMEOUT: 100,
16
+ CUSTOM_VALIDATOR_TIMEOUT: 1_000,
17
+ } as const
18
+
19
+ // ========== Cache config ==========
20
+ export const CACHE = {
21
+ ENABLED: true,
22
+ SCHEMA_CACHE: {
23
+ MAX_SIZE: 5_000,
24
+ TTL: 3_600_000, // 1 hour
25
+ STRATEGY: 'LRU',
26
+ },
27
+ STATS_ENABLED: true,
28
+ } as const
29
+
30
+ // ========== Format validation regex ==========
31
+
32
+ /**
33
+ * CF-01 fix: RFC-compliant IPv4 regex.
34
+ * Each octet 0-255, four groups, full-string match.
35
+ * Rejects invalid addresses such as 999.999.999.999.
36
+ */
37
+ const IPV4_OCTET = '(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d?)'
38
+ export const PATTERN_IPV4 = new RegExp(`^(?:${IPV4_OCTET}\\.){3}${IPV4_OCTET}$`)
39
+
40
+ /**
41
+ * CF-02 fix: Full IPv6 regex (RFC 5952 compatible).
42
+ * Covers:
43
+ * - Fully-expanded: 8 groups of hex
44
+ * - :: compressed: prefix / suffix / standalone :: variants
45
+ * No nested quantifiers (avoids ReDoS).
46
+ */
47
+ const HEX4 = '[0-9a-fA-F]{1,4}'
48
+ const IPV6_FULL = `(?:${HEX4}:){7}${HEX4}`
49
+ const IPV6_COMPRESS = [
50
+ `(?:${HEX4}:){1,7}:`, // n:...:
51
+ `(?:${HEX4}:){1,6}:${HEX4}`, // n:...:n
52
+ `(?:${HEX4}:){1,5}(?::${HEX4}){1,2}`,
53
+ `(?:${HEX4}:){1,4}(?::${HEX4}){1,3}`,
54
+ `(?:${HEX4}:){1,3}(?::${HEX4}){1,4}`,
55
+ `(?:${HEX4}:){1,2}(?::${HEX4}){1,5}`,
56
+ `${HEX4}:(?::${HEX4}){1,6}`,
57
+ `:(?::${HEX4}){1,7}`, // ::n...
58
+ `::`, // standalone :: (all-zeros)
59
+ ].join('|')
60
+ export const PATTERN_IPV6 = new RegExp(`^(?:${IPV6_FULL}|${IPV6_COMPRESS})$`)
61
+
62
+ export const FORMATS = {
63
+ BUILT_IN: [
64
+ 'email', 'url', 'uri', 'uuid', 'ipv4', 'ipv6',
65
+ 'hostname', 'date', 'date-time', 'time', 'regex', 'json',
66
+ ] as const,
67
+ PATTERNS: {
68
+ email: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
69
+ uuid: /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,
70
+ ipv4: PATTERN_IPV4,
71
+ ipv6: PATTERN_IPV6,
72
+ hostname: /^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)*$/i,
73
+ dateTime: /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{3})?Z?$/,
74
+ date: /^\d{4}-\d{2}-\d{2}$/,
75
+ time: /^\d{2}:\d{2}:\d{2}$/,
76
+ },
77
+ } as const
78
+
79
+ // ========== Plugin config ==========
80
+ export const PLUGINS = {
81
+ MAX_PLUGINS: 50,
82
+ NAMING_CONVENTION: /^schema-dsl-plugin-/,
83
+ } as const
@@ -0,0 +1,2 @@
1
+ export * from './constants.js'
2
+ export * from './patterns.js'
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Built-in regex validation patterns (migrated from v1 lib/config/patterns/ to a single TypeScript file)
3
+ */
4
+
5
+ export interface PatternConfig {
6
+ pattern: RegExp
7
+ min?: number
8
+ max?: number
9
+ key: string
10
+ }
11
+
12
+ const phone: Record<string, PatternConfig> = {
13
+ cn: { pattern: /^1[3-9]\d{9}$/, min: 11, max: 11, key: 'pattern.phone.cn' },
14
+ us: { pattern: /^\d{10}$/, min: 10, max: 10, key: 'pattern.phone.us' },
15
+ uk: { pattern: /^(\+44\s?)?0?\d{10}$/, min: 10, max: 15, key: 'pattern.phone.uk' },
16
+ hk: { pattern: /^[5-9]\d{7}$/, min: 8, max: 8, key: 'pattern.phone.hk' },
17
+ tw: { pattern: /^09\d{8}$/, min: 10, max: 10, key: 'pattern.phone.tw' },
18
+ international: { pattern: /^\+[1-9]\d{1,14}$/, min: 8, max: 15, key: 'pattern.phone.international' },
19
+ }
20
+
21
+ const idCard: Record<string, PatternConfig> = {
22
+ cn: {
23
+ pattern: /^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/,
24
+ min: 18, max: 18, key: 'pattern.idCard.cn',
25
+ },
26
+ }
27
+
28
+ const creditCard: Record<string, PatternConfig> = {
29
+ visa: { pattern: /^4[0-9]{12}(?:[0-9]{3})?$/, key: 'pattern.creditCard.visa' },
30
+ mastercard: { pattern: /^5[1-5][0-9]{14}$/, key: 'pattern.creditCard.mastercard' },
31
+ amex: { pattern: /^3[47][0-9]{13}$/, key: 'pattern.creditCard.amex' },
32
+ discover: { pattern: /^6(?:011|5[0-9]{2})[0-9]{12}$/, key: 'pattern.creditCard.discover' },
33
+ jcb: { pattern: /^(?:2131|1800|35\d{3})\d{11}$/, key: 'pattern.creditCard.jcb' },
34
+ unionpay: { pattern: /^62[0-9]{14,17}$/, key: 'pattern.creditCard.unionpay' },
35
+ }
36
+
37
+ const licensePlate: Record<string, PatternConfig> = {
38
+ cn: {
39
+ pattern: /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z][A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳]$/,
40
+ key: 'pattern.licensePlate.cn',
41
+ },
42
+ }
43
+
44
+ const postalCode: Record<string, PatternConfig> = {
45
+ cn: { pattern: /^[1-9]\d{5}$/, key: 'pattern.postalCode.cn' },
46
+ us: { pattern: /^\d{5}(-\d{4})?$/, key: 'pattern.postalCode.us' },
47
+ }
48
+
49
+ const passport: Record<string, PatternConfig> = {
50
+ cn: {
51
+ pattern: /(^[EeKkGgDdHhMQqSs][0-9]{8}$)|(^(([Ee][a-fA-F])|([DdSPp][Ee])|([Kk][Jj])|([Mm][Aa])|(1[45]))[0-9]{7}$)/,
52
+ key: 'pattern.passport.cn',
53
+ },
54
+ }
55
+
56
+ const common: Record<string, PatternConfig> = {
57
+ domain: {
58
+ pattern: /^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9][a-z0-9-]{0,61}[a-z0-9]$/i,
59
+ key: 'pattern.domain', min: 3, max: 253,
60
+ },
61
+ ip: {
62
+ // Composite IPv4 + IPv6 pattern (same as v1)
63
+ pattern:
64
+ /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$|^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/,
65
+ key: 'pattern.ip',
66
+ },
67
+ base64: {
68
+ pattern: /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/,
69
+ key: 'pattern.base64',
70
+ },
71
+ jwt: {
72
+ pattern: /^[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+\.[A-Za-z0-9-_]*$/,
73
+ key: 'pattern.jwt',
74
+ },
75
+ }
76
+
77
+ export const PATTERNS = { phone, idCard, creditCard, licensePlate, postalCode, passport, common }