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,381 +0,0 @@
1
- /**
2
- * schema-dsl 多语言错误处理完整示例
3
- *
4
- * 展示如何动态配置多语言来使用 dsl.error.throw('account.notFound')
5
- *
6
- * @version 1.1.5+
7
- * @author schema-dsl Team
8
- */
9
-
10
- const { dsl, Locale } = require('schema-dsl');
11
-
12
- // ============================================================
13
- // 第一步:配置语言包
14
- // ============================================================
15
-
16
- console.log('📚 步骤1:配置多语言包\n');
17
-
18
- // 方式1:使用 Locale.addLocale() 添加单个语言
19
- Locale.addLocale('zh-CN', {
20
- // 字符串格式(向后兼容)
21
- 'user.notFound': '用户不存在',
22
-
23
- // 对象格式(v1.1.5+ 推荐)- 统一数字错误码
24
- 'account.notFound': {
25
- code: 40001,
26
- message: '账户不存在'
27
- },
28
- 'account.insufficientBalance': {
29
- code: 40002,
30
- message: '余额不足,当前余额{{#balance}}元,需要{{#required}}元'
31
- },
32
- 'order.notPaid': {
33
- code: 50001,
34
- message: '订单未支付'
35
- },
36
- 'permission.denied': {
37
- code: 40003,
38
- message: '您没有权限执行此操作'
39
- }
40
- });
41
-
42
- Locale.addLocale('en-US', {
43
- 'user.notFound': 'User not found',
44
-
45
- 'account.notFound': {
46
- code: 40001, // 相同的数字码
47
- message: 'Account not found'
48
- },
49
- 'account.insufficientBalance': {
50
- code: 40002,
51
- message: 'Insufficient balance: current {{#balance}}, required {{#required}}'
52
- },
53
- 'order.notPaid': {
54
- code: 50001,
55
- message: 'Order not paid'
56
- },
57
- 'permission.denied': {
58
- code: 40003,
59
- message: 'Permission denied'
60
- }
61
- });
62
-
63
- Locale.addLocale('ja-JP', {
64
- 'user.notFound': 'ユーザーが見つかりません',
65
-
66
- 'account.notFound': {
67
- code: 40001,
68
- message: 'アカウントが見つかりません'
69
- },
70
- 'account.insufficientBalance': {
71
- code: 40002,
72
- message: '残高不足: 現在{{#balance}}、必要{{#required}}'
73
- },
74
- 'order.notPaid': {
75
- code: 50001,
76
- message: '注文が未払いです'
77
- },
78
- 'permission.denied': {
79
- code: 40003,
80
- message: 'アクセス権限がありません'
81
- }
82
- });
83
-
84
- // 方式2:批量配置(使用 dsl.config)
85
- dsl.config({
86
- i18n: {
87
- 'zh-CN': {
88
- 'payment.failed': {
89
- code: 50002,
90
- message: '支付失败:{{#reason}}'
91
- }
92
- },
93
- 'en-US': {
94
- 'payment.failed': {
95
- code: 50002,
96
- message: 'Payment failed: {{#reason}}'
97
- }
98
- }
99
- }
100
- });
101
-
102
- console.log('✅ 语言包配置完成\n');
103
-
104
- // ============================================================
105
- // 第二步:设置默认语言
106
- // ============================================================
107
-
108
- console.log('📚 步骤2:设置默认语言\n');
109
-
110
- Locale.setLocale('zh-CN');
111
- console.log(`✅ 默认语言设置为: ${Locale.getLocale()}\n`);
112
-
113
- // ============================================================
114
- // 第三步:使用 dsl.error 抛出多语言错误
115
- // ============================================================
116
-
117
- console.log('📚 步骤3:使用 dsl.error 抛出多语言错误\n');
118
-
119
- // 3.1 使用默认语言(全局语言)
120
- console.log('--- 3.1 使用默认语言(全局语言)---');
121
- try {
122
- dsl.error.throw('account.notFound');
123
- } catch (error) {
124
- console.log('错误码:', error.code); // 40001
125
- console.log('原始Key:', error.originalKey); // 'account.notFound'
126
- console.log('错误消息:', error.message); // '账户不存在'
127
- console.log('语言:', error.locale); // 'zh-CN'
128
- console.log('状态码:', error.statusCode); // 400
129
- console.log();
130
- }
131
-
132
- // 3.2 运行时指定语言(推荐用于API)⭐
133
- console.log('--- 3.2 运行时指定语言(英文)---');
134
- try {
135
- dsl.error.throw('account.notFound', {}, 404, 'en-US');
136
- } catch (error) {
137
- console.log('错误码:', error.code); // 40001
138
- console.log('原始Key:', error.originalKey); // 'account.notFound'
139
- console.log('错误消息:', error.message); // 'Account not found'
140
- console.log('语言:', error.locale); // 'en-US'
141
- console.log();
142
- }
143
-
144
- // 3.3 带参数的错误消息
145
- console.log('--- 3.3 带参数的错误消息(中文)---');
146
- try {
147
- dsl.error.throw('account.insufficientBalance', {
148
- balance: 50,
149
- required: 100
150
- }, 400, 'zh-CN');
151
- } catch (error) {
152
- console.log('错误消息:', error.message);
153
- // '余额不足,当前余额50元,需要100元'
154
- console.log('参数:', error.params);
155
- console.log();
156
- }
157
-
158
- console.log('--- 3.4 带参数的错误消息(英文)---');
159
- try {
160
- dsl.error.throw('account.insufficientBalance', {
161
- balance: 50,
162
- required: 100
163
- }, 400, 'en-US');
164
- } catch (error) {
165
- console.log('错误消息:', error.message);
166
- // 'Insufficient balance: current 50, required 100'
167
- console.log();
168
- }
169
-
170
- // ============================================================
171
- // 第四步:使用 dsl.error.create(创建但不抛出)
172
- // ============================================================
173
-
174
- console.log('📚 步骤4:使用 dsl.error.create(创建但不抛出)\n');
175
-
176
- const error1 = dsl.error.create('account.notFound', {}, 404, 'zh-CN');
177
- console.log('中文错误:', error1.message);
178
-
179
- const error2 = dsl.error.create('account.notFound', {}, 404, 'en-US');
180
- console.log('英文错误:', error2.message);
181
-
182
- const error3 = dsl.error.create('account.notFound', {}, 404, 'ja-JP');
183
- console.log('日文错误:', error3.message);
184
- console.log();
185
-
186
- // ============================================================
187
- // 第五步:使用 dsl.error.assert(断言方式)
188
- // ============================================================
189
-
190
- console.log('📚 步骤5:使用 dsl.error.assert(断言方式)\n');
191
-
192
- // 模拟数据
193
- const account = null;
194
- const user = { role: 'user' };
195
-
196
- // 5.1 断言账户存在
197
- console.log('--- 5.1 断言账户存在(中文)---');
198
- try {
199
- dsl.error.assert(account, 'account.notFound', {}, 404, 'zh-CN');
200
- console.log('账户存在');
201
- } catch (error) {
202
- console.log('断言失败:', error.message);
203
- console.log();
204
- }
205
-
206
- // 5.2 断言权限
207
- console.log('--- 5.2 断言权限(英文)---');
208
- try {
209
- dsl.error.assert(
210
- user.role === 'admin',
211
- 'permission.denied',
212
- {},
213
- 403,
214
- 'en-US'
215
- );
216
- console.log('权限通过');
217
- } catch (error) {
218
- console.log('断言失败:', error.message);
219
- console.log();
220
- }
221
-
222
- // ============================================================
223
- // 第六步:错误判断(error.is())
224
- // ============================================================
225
-
226
- console.log('📚 步骤6:错误判断(error.is())\n');
227
-
228
- try {
229
- dsl.error.throw('account.notFound');
230
- } catch (error) {
231
- // 方式1:使用 originalKey 判断
232
- if (error.is('account.notFound')) {
233
- console.log('✅ 使用 originalKey 判断成功');
234
- }
235
-
236
- // 方式2:使用数字 code 判断(v1.1.5+)
237
- if (error.is(40001)) {
238
- console.log('✅ 使用数字 code 判断成功');
239
- }
240
- console.log();
241
- }
242
-
243
- // ============================================================
244
- // 第七步:Express/Koa 中的实际应用
245
- // ============================================================
246
-
247
- console.log('📚 步骤7:Express/Koa 中的实际应用\n');
248
-
249
- // 模拟 Express 请求处理
250
- function expressHandler(req, res) {
251
- try {
252
- // 从请求头获取语言
253
- const locale = req.headers['accept-language'] || 'zh-CN';
254
-
255
- // 模拟业务逻辑
256
- const account = findAccount(req.params.id);
257
-
258
- // 使用运行时语言抛出错误
259
- dsl.error.assert(account, 'account.notFound', {}, 404, locale);
260
-
261
- // 检查余额
262
- dsl.error.assert(
263
- account.balance >= req.body.amount,
264
- 'account.insufficientBalance',
265
- {
266
- balance: account.balance,
267
- required: req.body.amount
268
- },
269
- 400,
270
- locale
271
- );
272
-
273
- res.json({ success: true, account });
274
- } catch (error) {
275
- // 返回多语言错误
276
- res.status(error.statusCode).json(error.toJSON());
277
- }
278
- }
279
-
280
- // 模拟中文请求
281
- console.log('--- 模拟中文请求 ---');
282
- const req1 = {
283
- headers: { 'accept-language': 'zh-CN' },
284
- params: { id: '123' },
285
- body: { amount: 100 }
286
- };
287
- const res1 = {
288
- json: (data) => console.log('响应:', JSON.stringify(data, null, 2)),
289
- status: (code) => ({ json: (data) => {
290
- console.log(`状态码: ${code}`);
291
- console.log('响应:', JSON.stringify(data, null, 2));
292
- }})
293
- };
294
- expressHandler(req1, res1);
295
- console.log();
296
-
297
- // 模拟英文请求
298
- console.log('--- 模拟英文请求 ---');
299
- const req2 = {
300
- headers: { 'accept-language': 'en-US' },
301
- params: { id: '123' },
302
- body: { amount: 100 }
303
- };
304
- const res2 = {
305
- json: (data) => console.log('响应:', JSON.stringify(data, null, 2)),
306
- status: (code) => ({ json: (data) => {
307
- console.log(`状态码: ${code}`);
308
- console.log('响应:', JSON.stringify(data, null, 2));
309
- }})
310
- };
311
- expressHandler(req2, res2);
312
- console.log();
313
-
314
- // ============================================================
315
- // 第八步:前端统一错误处理
316
- // ============================================================
317
-
318
- console.log('📚 步骤8:前端统一错误处理示例\n');
319
-
320
- // 前端错误处理示例(JavaScript)
321
- const frontendErrorHandler = `
322
- // 前端统一错误处理(使用数字 code)
323
- async function handleRequest() {
324
- try {
325
- const response = await fetch('/api/account/123');
326
- const data = await response.json();
327
-
328
- if (!response.ok) {
329
- throw data; // 服务端返回的错误对象
330
- }
331
-
332
- return data;
333
- } catch (error) {
334
- // 根据数字 code 统一处理,不受语言影响
335
- switch (error.code) {
336
- case 40001: // ACCOUNT_NOT_FOUND
337
- showNotFoundPage();
338
- break;
339
- case 40002: // INSUFFICIENT_BALANCE
340
- showTopUpDialog(error.params);
341
- break;
342
- case 50001: // ORDER_NOT_PAID
343
- showPaymentDialog();
344
- break;
345
- default:
346
- showGenericError(error.message);
347
- }
348
- }
349
- }
350
- `;
351
-
352
- console.log(frontendErrorHandler);
353
-
354
- // ============================================================
355
- // 工具函数
356
- // ============================================================
357
-
358
- function findAccount(id) {
359
- // 模拟查询失败
360
- return null;
361
- }
362
-
363
- // ============================================================
364
- // 总结
365
- // ============================================================
366
-
367
- console.log('\n📝 总结\n');
368
- console.log('✅ 1. 使用 Locale.addLocale() 或 dsl.config() 配置语言包');
369
- console.log('✅ 2. 使用 Locale.setLocale() 设置默认语言');
370
- console.log('✅ 3. 使用 dsl.error.throw() 抛出多语言错误');
371
- console.log('✅ 4. 使用 dsl.error.create() 创建错误(不抛出)');
372
- console.log('✅ 5. 使用 dsl.error.assert() 断言式错误处理');
373
- console.log('✅ 6. 使用 error.is() 判断错误类型(支持 key 和 code)');
374
- console.log('✅ 7. API 开发中使用运行时语言(推荐)');
375
- console.log('✅ 8. 前端使用统一的数字 code 处理错误');
376
- console.log('\n🎯 关键点:');
377
- console.log(' - 对象格式支持统一数字错误码(v1.1.5+)');
378
- console.log(' - 运行时语言不改变全局状态(并发安全)');
379
- console.log(' - 完全向后兼容字符串格式');
380
- console.log(' - 多语言共享相同的数字 code');
381
- console.log('\n📖 完整文档:docs/error-handling.md 和 docs/runtime-locale-support.md');
File without changes
@@ -1,181 +0,0 @@
1
- /**
2
- * I18nError 使用示例
3
- *
4
- * 统一的多语言错误抛出机制
5
- *
6
- * @version 1.1.1
7
- */
8
-
9
- const { I18nError, dsl, Locale } = require('../index');
10
-
11
- console.log('=== I18nError 使用示例 ===\n');
12
-
13
- // ========== 1. 基础用法 ==========
14
- console.log('1. 基础用法:');
15
- try {
16
- throw I18nError.create('account.notFound');
17
- } catch (error) {
18
- console.log('错误:', error.message); // "账户不存在"
19
- console.log('代码:', error.code); // "account.notFound"
20
- }
21
-
22
- // ========== 2. 带参数的错误 ==========
23
- console.log('\n2. 带参数的错误:');
24
- try {
25
- throw I18nError.create('account.insufficientBalance', {
26
- balance: 50,
27
- required: 100
28
- });
29
- } catch (error) {
30
- console.log('错误:', error.message); // "余额不足,当前余额50,需要100"
31
- }
32
-
33
- // ========== 3. 使用 throw 方法 ==========
34
- console.log('\n3. 使用 throw 方法(直接抛错):');
35
- try {
36
- I18nError.throw('user.noPermission');
37
- } catch (error) {
38
- console.log('错误:', error.message); // "没有管理员权限"
39
- }
40
-
41
- // ========== 4. 使用 assert 断言 ==========
42
- console.log('\n4. 使用 assert 断言:');
43
- const account = { balance: 50 };
44
-
45
- try {
46
- I18nError.assert(account.balance >= 100, 'account.insufficientBalance', {
47
- balance: account.balance,
48
- required: 100
49
- });
50
- } catch (error) {
51
- console.log('错误:', error.message);
52
- }
53
-
54
- // ========== 5. dsl.error 快捷方法 ==========
55
- console.log('\n5. dsl.error 快捷方法:');
56
- try {
57
- dsl.error.throw('order.notPaid');
58
- } catch (error) {
59
- console.log('错误:', error.message); // "订单未支付"
60
- }
61
-
62
- // ========== 6. 多语言支持 ==========
63
- console.log('\n6. 多语言支持:');
64
- try {
65
- // 中文
66
- Locale.setLocale('zh-CN');
67
- throw I18nError.create('account.notFound');
68
- } catch (error) {
69
- console.log('中文:', error.message); // "账户不存在"
70
- }
71
-
72
- try {
73
- // 英文
74
- Locale.setLocale('en-US');
75
- throw I18nError.create('account.notFound');
76
- } catch (error) {
77
- console.log('英文:', error.message); // "Account not found"
78
- }
79
-
80
- // 恢复中文
81
- Locale.setLocale('zh-CN');
82
-
83
- // ========== 7. 实际业务场景 =========
84
- console.log('\n7. 实际业务场景:');
85
-
86
- // 场景1:账户验证函数
87
- function getAccount(id) {
88
- const account = id === '123' ? { id: '123', balance: 50, status: 'active' } : null;
89
-
90
- // 断言账户存在
91
- I18nError.assert(account, 'account.notFound');
92
-
93
- // 断言账户状态
94
- I18nError.assert(account.status === 'active', 'account.inactive');
95
-
96
- // 断言余额充足
97
- I18nError.assert(
98
- account.balance >= 100,
99
- 'account.insufficientBalance',
100
- { balance: account.balance, required: 100 }
101
- );
102
-
103
- return account;
104
- }
105
-
106
- try {
107
- getAccount('123');
108
- } catch (error) {
109
- console.log('业务错误:', error.message);
110
- console.log('错误代码:', error.code);
111
- }
112
-
113
- // 场景2:与 dsl.if 结合
114
- console.log('\n8. 与 dsl.if 结合使用:');
115
- function validateUser(user) {
116
- // 使用 dsl.if 进行数据验证
117
- dsl.if(d => !d)
118
- .message('user.notFound')
119
- .and(d => !d.isVerified)
120
- .message('user.notVerified')
121
- .assert(user);
122
-
123
- // 使用 I18nError 进行业务逻辑验证
124
- I18nError.assert(user.role === 'admin', 'user.noPermission');
125
- }
126
-
127
- try {
128
- validateUser({ isVerified: true, role: 'user' });
129
- } catch (error) {
130
- console.log('验证错误:', error.message);
131
- }
132
-
133
- // ========== 9. Express/Koa 中间件 ==========
134
- console.log('\n9. Express/Koa 错误处理:');
135
-
136
- // Express 错误处理中间件
137
- function expressErrorHandler(error, req, res, next) {
138
- if (error instanceof I18nError) {
139
- return res.status(error.statusCode).json(error.toJSON());
140
- }
141
- next(error);
142
- }
143
-
144
- // 模拟使用
145
- const mockError = I18nError.create('account.notFound', {}, 404);
146
- const mockRes = {
147
- status: (code) => {
148
- console.log('HTTP Status:', code);
149
- return mockRes;
150
- },
151
- json: (data) => {
152
- console.log('Response:', JSON.stringify(data, null, 2));
153
- return mockRes;
154
- }
155
- };
156
-
157
- expressErrorHandler(mockError, {}, mockRes, () => {});
158
-
159
- // ========== 10. 自定义状态码 ==========
160
- console.log('\n10. 自定义状态码:');
161
- try {
162
- throw I18nError.create('user.notFound', {}, 404);
163
- } catch (error) {
164
- console.log('状态码:', error.statusCode); // 404
165
- console.log('错误:', error.message);
166
- }
167
-
168
- // ========== 11. 错误检查 ==========
169
- console.log('\n11. 错误类型检查:');
170
- try {
171
- throw I18nError.create('account.notFound');
172
- } catch (error) {
173
- if (error instanceof I18nError) {
174
- console.log('是 I18nError:', true);
175
- console.log('是账户不存在:', error.is('account.notFound'));
176
- console.log('是用户不存在:', error.is('user.notFound'));
177
- }
178
- }
179
-
180
- console.log('\n=== 示例完成 ===');
181
-