schema-dsl 1.2.4 → 2.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 (242) hide show
  1. package/CHANGELOG.md +87 -210
  2. package/README.md +391 -2249
  3. package/dist/DslBuilder-DQDN0ZxZ.d.cts +341 -0
  4. package/dist/DslBuilder-DkLaOo9Q.d.ts +341 -0
  5. package/dist/Validator-C7GsVQOH.d.cts +192 -0
  6. package/dist/Validator-hFWKGxir.d.ts +192 -0
  7. package/dist/index.cjs +6594 -0
  8. package/dist/index.d.cts +1145 -0
  9. package/dist/index.d.ts +1145 -0
  10. package/dist/index.js +6528 -0
  11. package/dist/plugin-CIKtTMtS.d.cts +246 -0
  12. package/dist/plugin-CIKtTMtS.d.ts +246 -0
  13. package/dist/plugins/custom-format.cjs +3802 -0
  14. package/dist/plugins/custom-format.d.cts +12 -0
  15. package/dist/plugins/custom-format.d.ts +12 -0
  16. package/dist/plugins/custom-format.js +3772 -0
  17. package/dist/plugins/custom-type-example.cjs +3795 -0
  18. package/dist/plugins/custom-type-example.d.cts +8 -0
  19. package/dist/plugins/custom-type-example.d.ts +8 -0
  20. package/dist/plugins/custom-type-example.js +3765 -0
  21. package/dist/plugins/custom-validator.cjs +146 -0
  22. package/dist/plugins/custom-validator.d.cts +10 -0
  23. package/dist/plugins/custom-validator.d.ts +10 -0
  24. package/dist/plugins/custom-validator.js +121 -0
  25. package/docs/FEATURE-INDEX.md +102 -68
  26. package/docs/add-custom-locale.md +48 -35
  27. package/docs/add-keyword.md +24 -0
  28. package/docs/api-reference.md +396 -154
  29. package/docs/api.md +13 -0
  30. package/docs/best-practices-project-structure.md +19 -10
  31. package/docs/best-practices.md +93 -53
  32. package/docs/cache-manager.md +23 -15
  33. package/docs/compile.md +45 -0
  34. package/docs/conditional-api.md +40 -11
  35. package/docs/custom-extensions-guide.md +80 -152
  36. package/docs/design-philosophy.md +76 -71
  37. package/docs/doc-index.md +324 -0
  38. package/docs/dsl-syntax.md +69 -19
  39. package/docs/dynamic-locale.md +24 -14
  40. package/docs/enum.md +12 -5
  41. package/docs/error-handling.md +53 -44
  42. package/docs/export-guide.md +47 -8
  43. package/docs/export-limitations.md +27 -11
  44. package/docs/faq.md +86 -67
  45. package/docs/frontend-i18n-guide.md +26 -12
  46. package/docs/i18n-user-guide.md +60 -47
  47. package/docs/i18n.md +51 -32
  48. package/docs/index.md +48 -0
  49. package/docs/json-schema-basics.md +40 -0
  50. package/docs/label-vs-description.md +12 -3
  51. package/docs/markdown-exporter.md +15 -6
  52. package/docs/mongodb-exporter.md +11 -4
  53. package/docs/multi-language.md +26 -0
  54. package/docs/multi-type-support.md +26 -33
  55. package/docs/mysql-exporter.md +9 -2
  56. package/docs/number-operators.md +12 -5
  57. package/docs/optional-marker-guide.md +28 -23
  58. package/docs/performance-guide.md +49 -0
  59. package/docs/plugin-system.md +205 -366
  60. package/docs/plugin-type-registration.md +34 -0
  61. package/docs/postgresql-exporter.md +9 -2
  62. package/docs/public/favicon.svg +5 -0
  63. package/docs/quick-start.md +37 -363
  64. package/docs/runtime-locale-support.md +20 -9
  65. package/docs/schema-helper.md +10 -5
  66. package/docs/schema-utils-advanced-issues.md +23 -0
  67. package/docs/schema-utils-best-practices.md +20 -0
  68. package/docs/schema-utils-chaining.md +7 -0
  69. package/docs/schema-utils.md +76 -42
  70. package/docs/security-checklist.md +20 -0
  71. package/docs/string-extensions.md +17 -9
  72. package/docs/troubleshooting.md +36 -21
  73. package/docs/type-converter.md +41 -50
  74. package/docs/type-reference.md +38 -15
  75. package/docs/typescript-guide.md +53 -42
  76. package/docs/union-type-guide.md +11 -1
  77. package/docs/union-types.md +10 -3
  78. package/docs/validate-async.md +36 -25
  79. package/docs/validate-batch.md +49 -0
  80. package/docs/validate-dsl-object-support.md +33 -28
  81. package/docs/validate.md +36 -16
  82. package/docs/validation-guide.md +25 -7
  83. package/docs/validator.md +39 -0
  84. package/package.json +85 -27
  85. package/plugins/custom-format.cjs +8 -0
  86. package/plugins/custom-type-example.cjs +8 -0
  87. package/plugins/custom-validator.cjs +8 -0
  88. package/src/adapters/DslAdapter.ts +111 -0
  89. package/src/adapters/index.ts +1 -0
  90. package/src/config/constants.ts +83 -0
  91. package/src/config/index.ts +2 -0
  92. package/src/config/patterns.ts +77 -0
  93. package/src/core/CacheManager.ts +159 -0
  94. package/src/core/ConditionalBuilder.ts +382 -0
  95. package/src/core/ConditionalRuntime.ts +28 -0
  96. package/src/core/ConditionalValidator.ts +255 -0
  97. package/src/core/DslBuilder.ts +677 -0
  98. package/src/core/ErrorCodes.ts +38 -0
  99. package/src/core/ErrorFormatter.ts +271 -0
  100. package/src/core/JSONSchemaCore.ts +65 -0
  101. package/src/core/Locale.ts +187 -0
  102. package/src/core/MessageTemplate.ts +42 -0
  103. package/src/core/ObjectDslBuilder.ts +64 -0
  104. package/src/core/PluginManager.ts +326 -0
  105. package/src/core/StringExtensions.ts +140 -0
  106. package/src/core/TemplateEngine.ts +44 -0
  107. package/src/core/Validator.ts +448 -0
  108. package/src/errors/I18nError.ts +159 -0
  109. package/src/errors/ValidationError.ts +105 -0
  110. package/src/exporters/BaseExporter.ts +60 -0
  111. package/src/exporters/MarkdownExporter.ts +305 -0
  112. package/src/exporters/MongoDBExporter.ts +126 -0
  113. package/src/exporters/MySQLExporter.ts +155 -0
  114. package/src/exporters/PostgreSQLExporter.ts +222 -0
  115. package/src/exporters/index.ts +18 -0
  116. package/src/index.ts +633 -0
  117. package/{lib/locales/en-US.js → src/locales/en-US.ts} +21 -37
  118. package/{lib/locales/es-ES.js → src/locales/es-ES.ts} +63 -16
  119. package/{lib/locales/fr-FR.js → src/locales/fr-FR.ts} +74 -27
  120. package/src/locales/index.ts +103 -0
  121. package/{lib/locales/ja-JP.js → src/locales/ja-JP.ts} +59 -17
  122. package/src/locales/types.ts +156 -0
  123. package/{lib/locales/zh-CN.js → src/locales/zh-CN.ts} +21 -38
  124. package/src/parser/ConstraintParser.ts +101 -0
  125. package/src/parser/DslParser.ts +470 -0
  126. package/src/parser/SchemaCompiler.ts +66 -0
  127. package/src/parser/TypeRegistry.ts +250 -0
  128. package/src/parser/index.ts +6 -0
  129. package/src/plugins/custom-format.ts +126 -0
  130. package/src/plugins/custom-type-example.ts +108 -0
  131. package/src/plugins/custom-validator.ts +140 -0
  132. package/src/types/conditional.ts +28 -0
  133. package/src/types/config.ts +59 -0
  134. package/src/types/dsl.ts +131 -0
  135. package/src/types/error.ts +60 -0
  136. package/src/types/index.ts +17 -0
  137. package/src/types/infer.ts +128 -0
  138. package/src/types/plugin.ts +58 -0
  139. package/src/types/safe-regex.d.ts +9 -0
  140. package/src/types/schema.ts +66 -0
  141. package/src/types/validate.ts +71 -0
  142. package/src/utils/SchemaHelper.ts +196 -0
  143. package/src/utils/SchemaUtils.ts +346 -0
  144. package/src/utils/TypeConverter.ts +215 -0
  145. package/src/utils/index.ts +10 -0
  146. package/src/validators/CustomKeywords.ts +477 -0
  147. package/.eslintignore +0 -11
  148. package/.eslintrc.json +0 -27
  149. package/CONTRIBUTING.md +0 -368
  150. package/STATUS.md +0 -491
  151. package/changelogs/v1.0.0.md +0 -328
  152. package/changelogs/v1.0.9.md +0 -367
  153. package/changelogs/v1.1.0.md +0 -389
  154. package/changelogs/v1.1.1.md +0 -308
  155. package/changelogs/v1.1.2.md +0 -183
  156. package/changelogs/v1.1.3.md +0 -161
  157. package/changelogs/v1.1.4.md +0 -432
  158. package/changelogs/v1.1.5.md +0 -493
  159. package/changelogs/v1.1.6.md +0 -211
  160. package/changelogs/v1.1.8.md +0 -376
  161. package/changelogs/v1.2.3.md +0 -124
  162. package/docs/INDEX.md +0 -252
  163. package/docs/issues-resolved-summary.md +0 -196
  164. package/docs/performance-benchmark-report.md +0 -179
  165. package/docs/performance-quick-reference.md +0 -123
  166. package/docs/user-questions-answered.md +0 -353
  167. package/docs/validation-rules-v1.0.2.md +0 -1608
  168. package/examples/README.md +0 -81
  169. package/examples/array-dsl-example.js +0 -227
  170. package/examples/conditional-example.js +0 -288
  171. package/examples/conditional-non-object.js +0 -129
  172. package/examples/conditional-validate-example.js +0 -321
  173. package/examples/custom-extension.js +0 -85
  174. package/examples/dsl-match-example.js +0 -74
  175. package/examples/dsl-style.js +0 -118
  176. package/examples/dynamic-locale-configuration.js +0 -348
  177. package/examples/dynamic-locale-example.js +0 -287
  178. package/examples/enum.examples.js +0 -324
  179. package/examples/export-demo.js +0 -130
  180. package/examples/express-integration.js +0 -376
  181. package/examples/i18n-error-handling-complete.js +0 -381
  182. package/examples/i18n-error-handling-quickstart.md +0 -0
  183. package/examples/i18n-error.examples.js +0 -181
  184. package/examples/i18n-full-demo.js +0 -301
  185. package/examples/i18n-memory-safety.examples.js +0 -268
  186. package/examples/markdown-export.js +0 -71
  187. package/examples/middleware-usage.js +0 -93
  188. package/examples/new-features-comparison.js +0 -315
  189. package/examples/password-reset/README.md +0 -153
  190. package/examples/password-reset/schema.js +0 -26
  191. package/examples/password-reset/test.js +0 -101
  192. package/examples/plugin-system.examples.js +0 -205
  193. package/examples/schema-utils-chaining.examples.js +0 -250
  194. package/examples/simple-example.js +0 -122
  195. package/examples/slug.examples.js +0 -179
  196. package/examples/string-extensions.js +0 -297
  197. package/examples/union-type-example.js +0 -127
  198. package/examples/union-types-example.js +0 -77
  199. package/examples/user-registration/README.md +0 -156
  200. package/examples/user-registration/routes.js +0 -92
  201. package/examples/user-registration/schema.js +0 -150
  202. package/examples/user-registration/server.js +0 -74
  203. package/index.d.ts +0 -3540
  204. package/index.js +0 -457
  205. package/index.mjs +0 -60
  206. package/lib/adapters/DslAdapter.js +0 -871
  207. package/lib/adapters/index.js +0 -20
  208. package/lib/config/constants.js +0 -286
  209. package/lib/config/patterns/common.js +0 -47
  210. package/lib/config/patterns/creditCard.js +0 -9
  211. package/lib/config/patterns/idCard.js +0 -9
  212. package/lib/config/patterns/index.js +0 -9
  213. package/lib/config/patterns/licensePlate.js +0 -4
  214. package/lib/config/patterns/passport.js +0 -4
  215. package/lib/config/patterns/phone.js +0 -9
  216. package/lib/config/patterns/postalCode.js +0 -5
  217. package/lib/core/CacheManager.js +0 -376
  218. package/lib/core/ConditionalBuilder.js +0 -503
  219. package/lib/core/DslBuilder.js +0 -1400
  220. package/lib/core/ErrorCodes.js +0 -233
  221. package/lib/core/ErrorFormatter.js +0 -445
  222. package/lib/core/JSONSchemaCore.js +0 -347
  223. package/lib/core/Locale.js +0 -130
  224. package/lib/core/MessageTemplate.js +0 -98
  225. package/lib/core/PluginManager.js +0 -448
  226. package/lib/core/StringExtensions.js +0 -240
  227. package/lib/core/Validator.js +0 -654
  228. package/lib/errors/I18nError.js +0 -328
  229. package/lib/errors/ValidationError.js +0 -191
  230. package/lib/exporters/MarkdownExporter.js +0 -420
  231. package/lib/exporters/MongoDBExporter.js +0 -162
  232. package/lib/exporters/MySQLExporter.js +0 -212
  233. package/lib/exporters/PostgreSQLExporter.js +0 -289
  234. package/lib/exporters/index.js +0 -24
  235. package/lib/locales/index.js +0 -8
  236. package/lib/utils/LRUCache.js +0 -174
  237. package/lib/utils/SchemaHelper.js +0 -240
  238. package/lib/utils/SchemaUtils.js +0 -445
  239. package/lib/utils/TypeConverter.js +0 -245
  240. package/lib/utils/index.js +0 -13
  241. package/lib/validators/CustomKeywords.js +0 -616
  242. package/lib/validators/index.js +0 -11
@@ -1,494 +1,316 @@
1
1
  # 插件系统
2
2
 
3
-
4
- > **更新**: 2025-12-26
3
+ > **更新**: 2026-05-01
5
4
  > **状态**: ✅ 稳定
6
5
 
7
6
  ---
8
7
 
9
- ## 📑 目录
10
-
11
- - [概述](#概述)
12
- - [快速开始](#快速开始)
13
- - [插件开发](#插件开发)
14
- - [钩子系统](#钩子系统)
15
- - [官方插件](#官方插件)
16
- - [最佳实践](#最佳实践)
17
- - [API 参考](#api-参考)
18
-
19
- ---
20
-
21
8
  ## 概述
22
9
 
23
- SchemaI-DSL 插件系统允许你扩展核心功能,添加自定义验证器、格式化器、导出器等。
24
-
25
- ### 特性
10
+ `PluginManager` 是一个独立的插件管理器,负责:
26
11
 
27
- **动态加载** - 运行时注册/卸载插件
28
- ✅ **生命周期钩子** - 在关键时刻执行自定义逻辑
29
- ✅ **事件驱动** - 基于 EventEmitter 的事件系统
30
- **依赖管理** - 插件间通信和依赖注入
31
- ✅ **TypeScript 支持** - 完整的类型定义
12
+ - 注册 / 安装 / 卸载插件
13
+ - 管理插件钩子
14
+ - 提供 `EventEmitter` 兼容事件系统
15
+ - 通过 `context` 暴露插件注册表和钩子表
32
16
 
33
- ### 架构
34
-
35
- ```
36
- PluginManager
37
- ├── 插件注册表 (Map)
38
- ├── 钩子系统 (Hooks)
39
- ├── 事件系统 (EventEmitter)
40
- └── 上下文 (Context)
41
- ```
17
+ > **重要说明**
18
+ > `PluginManager` 本身不会自动接入 `dsl()`、`Validator`、各类 Exporter 的执行流程。
19
+ > 如果你希望在验证、编译或导出阶段运行某些 hook,需要由你的集成代码显式调用 `pluginManager.runHook(...)`。
42
20
 
43
21
  ---
44
22
 
45
23
  ## 快速开始
46
24
 
47
- ### 1. 创建插件管理器
48
-
49
25
  ```javascript
50
26
  const { PluginManager } = require('schema-dsl');
27
+ const schemaDsl = require('schema-dsl');
51
28
 
52
29
  const pluginManager = new PluginManager();
53
- ```
54
-
55
- ### 2. 注册插件
56
30
 
57
- ```javascript
58
31
  const myPlugin = {
59
32
  name: 'my-plugin',
60
33
  version: '1.0.0',
61
34
  description: '我的自定义插件',
62
35
 
63
- install(schemaDsl, options, context) {
64
- console.log('插件安装成功!');
36
+ install(core, options, context) {
37
+ console.log('installed:', !!core, options);
38
+ console.log('registered plugins:', context.plugins.size);
39
+ },
40
+
41
+ uninstall(core, context) {
42
+ console.log('cleanup:', !!core, context.hooks.size);
65
43
  }
66
44
  };
67
45
 
68
46
  pluginManager.register(myPlugin);
47
+ pluginManager.install(schemaDsl, 'my-plugin', { enabled: true });
48
+ pluginManager.uninstall('my-plugin', schemaDsl);
69
49
  ```
70
50
 
71
- ### 3. 安装插件
72
-
73
- ```javascript
74
- const schemaDsl = require('schema-dsl');
75
-
76
- pluginManager.install(schemaDsl, 'my-plugin');
77
- ```
78
-
79
- ### 4. 使用插件
80
-
81
- 插件安装后,自动生效,无需额外配置。
82
-
83
51
  ---
84
52
 
85
- ## 插件开发
86
-
87
- ### 插件结构
88
-
89
- 一个标准的插件对象包含以下字段:
53
+ ## 插件对象结构
90
54
 
91
55
  ```javascript
92
56
  module.exports = {
93
- // ========== 必填 ==========
94
- name: 'plugin-name', // 插件名称(唯一)
95
- install: function(schemaDsl, options, context) {
57
+ // 必填
58
+ name: 'plugin-name',
59
+ install(core, options, context) {
96
60
  // 安装逻辑
97
61
  },
98
62
 
99
- // ========== 可选 ==========
100
- version: '1.0.0', // 插件版本
101
- description: '插件描述', // 插件描述
102
- uninstall: function(schemaDsl, context) {
63
+ // 可选
64
+ version: '1.0.0',
65
+ description: '插件描述',
66
+ uninstall(core, context) {
103
67
  // 卸载逻辑
104
68
  },
105
- hooks: { // 生命周期钩子
106
- onBeforeValidate: function() {},
107
- onAfterValidate: function() {}
69
+ hooks: {
70
+ onBeforeValidate(schema, data) {},
71
+ onAfterValidate(result) {}
108
72
  },
109
- options: { // 默认选项
73
+ options: {
110
74
  enabled: true
111
75
  }
112
76
  };
113
77
  ```
114
78
 
115
- ### 示例:自定义验证器插件
79
+ ### 参数说明
116
80
 
117
- ```javascript
118
- module.exports = {
119
- name: 'custom-validator',
120
- version: '1.0.0',
81
+ | 参数 | 说明 |
82
+ |---|---|
83
+ | `core` | 传给 `install()` / `uninstall()` 的核心对象,通常是 `require('schema-dsl')` 的结果或你自己的集成对象 |
84
+ | `options` | 安装时的合并配置:`{ ...plugin.options, ...installOptions }` |
85
+ | `context.plugins` | 当前已注册插件的 `Map<string, Plugin>` |
86
+ | `context.hooks` | 当前 hook 注册表的 `Map<string, Function[]>` |
121
87
 
122
- install(schemaDsl, options, context) {
123
- const { Validator } = schemaDsl;
124
-
125
- // 添加自定义关键字
126
- Validator.prototype.addKeyword('unique', {
127
- async: true,
128
- validate: async function(schema, data) {
129
- // 验证逻辑
130
- const exists = await checkDatabase(data);
131
- return !exists;
132
- }
133
- });
134
- }
135
- };
136
- ```
88
+ ---
137
89
 
138
- ### 示例:自定义格式插件
90
+ ## 钩子系统
139
91
 
140
- ```javascript
141
- module.exports = {
142
- name: 'custom-format',
143
- version: '1.0.0',
92
+ ### 1. 自动触发的内置生命周期
144
93
 
145
- install(schemaDsl, options, context) {
146
- const validator = schemaDsl.getDefaultValidator();
147
- const ajv = validator.getAjv();
148
-
149
- // 添加自定义格式
150
- ajv.addFormat('phone-cn', {
151
- validate: /^1[3-9]\d{9}$/
152
- });
153
- }
154
- };
155
- ```
94
+ 这些 hook `PluginManager` 自动触发:
156
95
 
157
- ---
96
+ | 名称 | 触发时机 | 参数 |
97
+ |---|---|---|
98
+ | `onBeforeRegister` | `register(plugin)` 写入注册表前 | `(plugin)` |
99
+ | `onAfterRegister` | `register(plugin)` 完成后 | `(plugin)` |
100
+ | `onError` | 某个 hook 执行抛错后 | `(error, meta)` |
158
101
 
159
- ## 钩子系统
102
+ ### 2. 约定式 hook 名称
103
+
104
+ 以下名称是常用约定,`PluginManager` 支持注册它们,但**是否执行取决于你的代码是否调用 `runHook()`**:
160
105
 
161
- ### 可用钩子
106
+ | 名称 | 常见用途 |
107
+ |---|---|
108
+ | `onBeforeValidate` / `onAfterValidate` | 验证前后 |
109
+ | `onBeforeCompile` / `onAfterCompile` | 编译前后 |
110
+ | `onBeforeExport` / `onAfterExport` | 导出前后 |
111
+ | `beforeParse` / `afterParse` | 解析阶段 |
112
+ | `beforeValidate` / `afterValidate` | v2 风格命名 |
113
+ | `beforeCompile` / `afterCompile` | v2 风格命名 |
162
114
 
163
- | 钩子名称 | 触发时机 | 参数 |
164
- |---------|---------|------|
165
- | `onBeforeRegister` | 插件注册前 | `(plugin)` |
166
- | `onAfterRegister` | 插件注册后 | `(plugin)` |
167
- | `onBeforeValidate` | 验证前 | `(schema, data)` |
168
- | `onAfterValidate` | 验证后 | `(result)` |
169
- | `onBeforeExport` | 导出前 | `(schema, options)` |
170
- | `onAfterExport` | 导出后 | `(result)` |
171
- | `onError` | 错误发生时 | `(error, context)` |
115
+ > `hook()` / `runHook()` 支持任意字符串名称,不限于上表。
172
116
 
173
- ### 注册钩子
117
+ ### 3. 注册与运行 hook
174
118
 
175
119
  ```javascript
176
120
  pluginManager.hook('onBeforeValidate', (schema, data) => {
177
121
  console.log('验证前:', schema, data);
178
122
  });
179
- ```
180
-
181
- ### 运行钩子
182
123
 
183
- ```javascript
184
124
  const results = await pluginManager.runHook('onBeforeValidate', schema, data);
185
125
  ```
186
126
 
187
- ### 插件中定义钩子
127
+ ### 4. 在插件中声明 hook
188
128
 
189
129
  ```javascript
190
- module.exports = {
191
- name: 'my-plugin',
192
-
130
+ const loggingPlugin = {
131
+ name: 'logging',
132
+ install() {},
193
133
  hooks: {
194
134
  onBeforeValidate(schema, data) {
195
- // 在这里修改 schema data
135
+ console.log('before validate', schema, data);
196
136
  },
197
-
198
137
  onAfterValidate(result) {
199
- // 在这里修改验证结果
138
+ console.log('after validate', result);
200
139
  }
201
140
  }
202
141
  };
203
- ```
204
-
205
- ---
206
142
 
207
- ## 官方插件
208
-
209
- ### 1. custom-validator
210
-
211
- 添加业务特定的验证规则。
212
-
213
- ```javascript
214
- const customValidator = require('schema-dsl/plugins/custom-validator');
215
-
216
- pluginManager.register(customValidator);
217
- pluginManager.install(schema-dsl);
143
+ pluginManager.register(loggingPlugin);
144
+ await pluginManager.runHook('onBeforeValidate', schema, data);
218
145
  ```
219
146
 
220
- **功能**:
221
- - `unique` - 唯一性验证(异步)
222
- - `passwordStrength` - 密码强度验证
223
- - `idCard` - 身份证号验证
224
-
225
- ### 2. custom-format
226
-
227
- 添加常用的格式验证。
228
-
229
- ```javascript
230
- const customFormat = require('schema-dsl/plugins/custom-format');
231
-
232
- pluginManager.register(customFormat);
233
- pluginManager.install(schema-dsl);
234
- ```
235
-
236
- **格式**:
237
- - `phone-cn` - 中国手机号
238
- - `postal-code-cn` - 邮政编码
239
- - `wechat` - 微信号
240
- - `qq` - QQ号
241
- - `bank-card` - 银行卡号
242
- - `license-plate` - 车牌号
243
-
244
147
  ---
245
148
 
246
- ## 最佳实践
247
-
248
- ### 1. 插件命名
249
-
250
- 使用 `kebab-case` 命名:
251
-
252
- ```javascript
253
- // ✅ 推荐
254
- name: 'custom-validator'
255
- name: 'mongodb-plugin'
256
-
257
- // ❌ 不推荐
258
- name: 'CustomValidator'
259
- name: 'mongodb_plugin'
260
- ```
261
-
262
- ### 2. 版本管理
263
-
264
- 使用语义化版本:
265
-
266
- ```javascript
267
- version: '1.0.0' // 主版本.次版本.修订版本
268
- ```
149
+ ## 事件系统
269
150
 
270
- ### 3. 错误处理
151
+ `PluginManager` 继承自 `EventEmitter`,因此可以使用:
271
152
 
272
- 插件应该优雅地处理错误:
153
+ - `on()`
154
+ - `once()`
155
+ - `off()`
156
+ - `emit()`
157
+ - `removeListener()`
158
+ - `removeAllListeners()`
273
159
 
274
- ```javascript
275
- install(schema-dsl, options, context) {
276
- try {
277
- // 安装逻辑
278
- } catch (error) {
279
- console.error(`[${this.name}] 安装失败:`, error.message);
280
- throw error; // 重新抛出,让调用者知道
281
- }
282
- }
283
- ```
160
+ ### 可用事件
284
161
 
285
- ### 4. 清理资源
162
+ | 事件名 | 触发时机 | 参数 |
163
+ |---|---|---|
164
+ | `plugin:registered` | 插件注册成功 | `(plugin)` |
165
+ | `plugin:installed` | 插件安装成功 | `(plugin)` |
166
+ | `plugin:uninstalled` | 插件卸载成功 | `(plugin)` |
167
+ | `plugin:error` | 插件安装 / 卸载失败 | `({ plugin, error })` |
168
+ | `hook:error` | hook 执行失败 | `({ hookName, handler, error })` |
169
+ | `plugins:cleared` | `clear()` 完成后 | `()` |
286
170
 
287
- 提供 `uninstall` 方法:
171
+ ### 示例
288
172
 
289
173
  ```javascript
290
- uninstall(schema-dsl, context) {
291
- // 清理注册的验证器、格式、钩子等
292
- delete schemaDsl.myCustomMethod;
293
- }
294
- ```
174
+ pluginManager.on('plugin:registered', (plugin) => {
175
+ console.log('插件已注册:', plugin.name);
176
+ });
295
177
 
296
- ### 5. 文档
178
+ pluginManager.on('plugin:installed', (plugin) => {
179
+ console.log('插件已安装:', plugin.name);
180
+ });
297
181
 
298
- 为你的插件编写清晰的文档:
182
+ pluginManager.on('plugin:error', ({ plugin, error }) => {
183
+ console.error('插件错误:', plugin.name, error.message);
184
+ });
299
185
 
300
- ```javascript
301
- /**
302
- * 我的自定义插件
303
- *
304
- * @description 添加业务特定的验证规则
305
- *
306
- * @example
307
- * ```javascript
308
- * pluginManager.register(myPlugin);
309
- * pluginManager.install(schema-dsl);
310
- * ```
311
- */
312
- module.exports = { /* ... */ };
186
+ pluginManager.on('hook:error', ({ hookName, error }) => {
187
+ console.error('Hook 错误:', hookName, error.message);
188
+ });
313
189
  ```
314
190
 
315
191
  ---
316
192
 
317
193
  ## API 参考
318
194
 
319
- ### PluginManager
320
-
321
- #### `register(plugin)`
195
+ ### `register(plugin)`
322
196
 
323
- 注册插件。
197
+ 注册插件,并自动触发:
324
198
 
325
- **参数**:
326
- - `plugin` (Object) - 插件配置
199
+ 1. `onBeforeRegister`
200
+ 2. 写入注册表 / 注册插件自带 hooks
201
+ 3. `onAfterRegister`
202
+ 4. `plugin:registered`
327
203
 
328
- **返回**: `this`
329
-
330
- **示例**:
331
- ```javascript
332
- pluginManager.register({
333
- name: 'my-plugin',
334
- install(schema-dsl) {
335
- // ...
336
- }
337
- });
338
- ```
339
-
340
- #### `install(schema-dsl, [pluginName], [options])`
204
+ ### `install(core, [pluginName], [options])`
341
205
 
342
206
  安装插件。
343
207
 
344
- **参数**:
345
- - `schema-dsl` (Object) - SchemaI-DSL 实例
346
- - `pluginName` (String, optional) - 插件名称
347
- - `options` (Object, optional) - 安装选项
348
-
349
- **返回**: `this`
208
+ - `install(core)`:安装所有已注册插件
209
+ - `install(core, 'name', options)`:安装指定插件
210
+ - `install()` 时会把第三个参数 `context` 传给插件
211
+ - 安装成功后触发 `plugin:installed`
212
+ - 安装失败时触发 `plugin:error`,然后抛错
350
213
 
351
- #### `uninstall(pluginName, schema-dsl)`
214
+ ### `unregister(name, [core])`
352
215
 
353
- 卸载插件。
216
+ 卸载插件并移除该插件注册的 hooks。
354
217
 
355
- **参数**:
356
- - `pluginName` (String) - 插件名称
357
- - `schema-dsl` (Object) - SchemaI-DSL 实例
218
+ - `plugin.uninstall(core, context)` 成功后才会真正移除插件
219
+ - 卸载成功后触发 `plugin:uninstalled`
220
+ - 卸载失败时触发 `plugin:error`,然后抛错
358
221
 
359
- **返回**: `this`
222
+ ### `uninstall(name, [core])`
360
223
 
361
- #### `hook(hookName, handler)`
224
+ `unregister()` 的别名,兼容 v1。
362
225
 
363
- 注册钩子。
226
+ ### `hook(name, handler)`
364
227
 
365
- **参数**:
366
- - `hookName` (String) - 钩子名称
367
- - `handler` (Function) - 钩子处理函数
228
+ 注册一个 hook 处理器。
368
229
 
369
- **返回**: `this`
230
+ ### `unhook(name, handler)`
370
231
 
371
- #### `runHook(hookName, ...args)`
232
+ 移除指定 hook 处理器。
372
233
 
373
- 运行钩子。
234
+ ### `runHook(name, ...args)`
374
235
 
375
- **参数**:
376
- - `hookName` (String) - 钩子名称
377
- - `...args` (any) - 钩子参数
236
+ 异步运行某个 hook 下的全部处理器,返回结果数组。
378
237
 
379
- **返回**: `Promise<any[]>`
238
+ - 单个 handler 抛错不会中断后续 handler
239
+ - 抛错时会触发 `hook:error`
240
+ - 同时会执行 `onError`
380
241
 
381
- #### `list()`
242
+ ### `has(name)`
382
243
 
383
- 获取插件列表。
244
+ 检查插件是否已注册。
384
245
 
385
- **返回**: `Array<{name, version, description}>`
246
+ ### `get([name])`
386
247
 
387
- #### `has(pluginName)`
248
+ - `get(name)`:获取单个插件
249
+ - `get()`:获取全部插件 `Map`
388
250
 
389
- 检查插件是否存在。
251
+ ### `list()`
390
252
 
391
- **参数**:
392
- - `pluginName` (String) - 插件名称
253
+ 返回插件元数据数组:
393
254
 
394
- **返回**: `Boolean`
255
+ ```javascript
256
+ [{ name, version, description }]
257
+ ```
395
258
 
396
- #### `clear(schema-dsl)`
259
+ ### `clear([core])`
397
260
 
398
- 清空所有插件。
261
+ 逐个卸载所有插件,清空注册表和 hooks,最后触发 `plugins:cleared`。
399
262
 
400
- **参数**:
401
- - `schema-dsl` (Object) - SchemaI-DSL 实例
263
+ ### 属性
402
264
 
403
- **返回**: `this`
265
+ | 属性 | 说明 |
266
+ |---|---|
267
+ | `pluginManager.plugins` | 插件注册表 `Map<string, Plugin>` |
268
+ | `pluginManager.hooks` | hook 注册表 `Map<string, Function[]>` |
269
+ | `pluginManager.context` | `{ plugins, hooks }` |
270
+ | `pluginManager.size` | 已注册插件数量 |
271
+ | `pluginManager.pluginCount` | 已注册插件数量(别名) |
404
272
 
405
273
  ---
406
274
 
407
- ## 事件系统
275
+ ## 最佳实践
408
276
 
409
- PluginManager 继承自 EventEmitter,支持事件监听:
277
+ ### 1. 命名
410
278
 
411
- ```javascript
412
- pluginManager.on('plugin:registered', (plugin) => {
413
- console.log('插件已注册:', plugin.name);
414
- });
415
-
416
- pluginManager.on('plugin:installed', (plugin) => {
417
- console.log('插件已安装:', plugin.name);
418
- });
279
+ 使用 `kebab-case`:
419
280
 
420
- pluginManager.on('plugin:error', ({ plugin, error }) => {
421
- console.error('插件错误:', plugin.name, error.message);
422
- });
281
+ ```javascript
282
+ name: 'custom-validator'
283
+ name: 'mongodb-plugin'
423
284
  ```
424
285
 
425
- **可用事件**:
426
- - `plugin:registered` - 插件注册成功
427
- - `plugin:installed` - 插件安装成功
428
- - `plugin:uninstalled` - 插件卸载成功
429
- - `plugin:error` - 插件错误
430
- - `hook:error` - 钩子执行错误
431
- - `plugins:cleared` - 所有插件已清空
432
-
433
- ---
434
-
435
- ## 进阶话题
436
-
437
- ### 1. 插件间通信
438
-
439
- 通过 `context` 参数访问其他插件:
286
+ ### 2. 错误处理
440
287
 
441
288
  ```javascript
442
- install(schema-dsl, options, context) {
443
- // 检查依赖插件
444
- if (!context.plugins.has('dependency-plugin')) {
445
- throw new Error('需要先安装 dependency-plugin');
289
+ install(core, options, context) {
290
+ try {
291
+ // 安装逻辑
292
+ } catch (error) {
293
+ throw error;
446
294
  }
447
-
448
- // 获取其他插件实例
449
- const depPlugin = context.plugins.get('dependency-plugin');
450
295
  }
451
296
  ```
452
297
 
453
- ### 2. 插件配置
454
-
455
- 通过 `options` 参数传递配置:
298
+ ### 3. 资源清理
456
299
 
457
300
  ```javascript
458
- // 注册时设置默认配置
459
- module.exports = {
460
- name: 'my-plugin',
461
- options: {
462
- strict: false,
463
- maxRetries: 3
464
- },
465
-
466
- install(schema-dsl, options) {
467
- const config = { ...this.options, ...options };
468
- console.log('配置:', config);
469
- }
470
- };
471
-
472
- // 安装时覆盖配置
473
- pluginManager.install(schema-dsl, 'my-plugin', {
474
- strict: true
475
- });
301
+ uninstall(core, context) {
302
+ // 清理注册的资源
303
+ }
476
304
  ```
477
305
 
478
- ### 3. 异步安装
479
-
480
- 插件安装函数可以是异步的:
306
+ ### 4. 插件间通信
481
307
 
482
308
  ```javascript
483
- module.exports = {
484
- name: 'async-plugin',
485
-
486
- async install(schema-dsl, options) {
487
- // 异步初始化
488
- await this.loadConfig();
489
- await this.connectDatabase();
309
+ install(core, options, context) {
310
+ if (!context.plugins.has('dependency-plugin')) {
311
+ throw new Error('需要先安装 dependency-plugin');
490
312
  }
491
- };
313
+ }
492
314
  ```
493
315
 
494
316
  ---
@@ -497,46 +319,63 @@ module.exports = {
497
319
 
498
320
  ### 插件未生效
499
321
 
500
- 1. 检查插件是否已注册:
501
322
  ```javascript
502
- console.log(pluginManager.has('my-plugin')); // true?
323
+ pluginManager.has('my-plugin');
324
+ pluginManager.list();
503
325
  ```
504
326
 
505
- 2. 检查插件是否已安装:
506
- ```javascript
507
- pluginManager.list(); // 是否在列表中?
508
- ```
327
+ 确认插件已注册、已安装,并且 `install()` 确实执行到了你的逻辑。
509
328
 
510
- 3. 检查 `install` 函数是否正确执行。
329
+ ### hook 未触发
511
330
 
512
- ### 钩子未触发
331
+ 检查两件事:
513
332
 
514
- 1. 确认钩子名称拼写正确。
515
- 2. 使用 `pluginManager.hooks.get('hookName')` 查看已注册的钩子。
333
+ 1. hook 名称是否一致
334
+ 2. 你的代码是否真的调用了 `pluginManager.runHook('hookName', ...)`
516
335
 
517
- ### 插件冲突
336
+ ### 当前仓库的发布方式
518
337
 
519
- 如果两个插件修改同一个方法,后安装的会覆盖前一个。解决方案:
520
- - 使用不同的方法名
521
- - 在插件中保存原始方法的引用
338
+ 当前仓库已恢复 v1 风格的官方插件子路径入口,可直接使用:
522
339
 
523
- ---
340
+ - `schema-dsl/plugins/custom-format`
341
+ - `schema-dsl/plugins/custom-validator`
342
+ - `schema-dsl/plugins/custom-type-example`
524
343
 
525
- ## 完整示例
344
+ ```javascript
345
+ const { PluginManager } = require('schema-dsl');
346
+ const schemaDsl = require('schema-dsl');
347
+ const customFormat = require('schema-dsl/plugins/custom-format');
348
+
349
+ const pluginManager = new PluginManager();
350
+ pluginManager.register(customFormat);
351
+ pluginManager.install(schemaDsl, 'custom-format');
352
+ ```
353
+
354
+ ```typescript
355
+ import { PluginManager } from 'schema-dsl';
356
+ import * as schemaDsl from 'schema-dsl';
357
+ import customTypeExample from 'schema-dsl/plugins/custom-type-example';
358
+
359
+ const pluginManager = new PluginManager();
360
+ pluginManager.register(customTypeExample);
361
+ pluginManager.install(schemaDsl, 'custom-type-example');
362
+ ```
526
363
 
527
- [examples/plugin-system.examples.js](../examples/plugin-system.examples.js)
364
+ > ⚠️ 注意:官方插件子路径只补齐了 v1 已存在的三个示例插件入口;
365
+ > `PluginManager` 仍然不会自动接入 `validate()` / `compile()` / exporter 流程,hook 是否执行仍取决于你的集成代码是否显式调用 `runHook()`。
528
366
 
529
367
  ---
530
368
 
531
369
  ## 相关文档
532
370
 
533
371
  - [API 参考](api-reference.md)
534
- - [最佳实践](best-practices.md)
535
- - [故障排查](troubleshooting.md)
372
+ - [验证指南](validate.md)
373
+ - [DSL 语法](dsl-syntax.md)
536
374
 
537
375
  ---
538
376
 
539
- **贡献**
377
+ ## 对应示例文件
540
378
 
541
- 欢迎提交你的插件到官方插件库!请提交 PR 到 `plugins/` 目录。
379
+ **示例入口**: [plugin-system.ts](https://github.com/vextjs/schema-dsl/blob/main/examples/docs/plugin-system.ts)
380
+ **说明**: 覆盖自定义插件的注册 / 安装 / 卸载、`runHook()` 执行结果,以及官方 `custom-format` 子路径插件的安装效果。
542
381