schema-dsl 1.0.0 → 1.0.3

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 (44) hide show
  1. package/CHANGELOG.md +218 -542
  2. package/README.md +772 -903
  3. package/STATUS.md +97 -2
  4. package/docs/INDEX.md +1 -2
  5. package/docs/api-reference.md +1 -292
  6. package/docs/custom-extensions-guide.md +411 -0
  7. package/docs/enum.md +475 -0
  8. package/docs/i18n.md +394 -0
  9. package/docs/performance-benchmark-report.md +179 -0
  10. package/docs/plugin-system.md +8 -8
  11. package/docs/validate-async.md +1 -1
  12. package/docs/validation-rules-v1.0.2.md +1601 -0
  13. package/examples/README.md +81 -0
  14. package/examples/enum.examples.js +324 -0
  15. package/examples/express-integration.js +54 -54
  16. package/examples/i18n-full-demo.js +15 -24
  17. package/examples/schema-utils-chaining.examples.js +2 -2
  18. package/examples/slug.examples.js +179 -0
  19. package/index.d.ts +5 -5
  20. package/index.js +30 -34
  21. package/lib/config/constants.js +1 -1
  22. package/lib/config/patterns/common.js +47 -0
  23. package/lib/config/patterns/index.js +2 -1
  24. package/lib/core/DslBuilder.js +500 -8
  25. package/lib/core/StringExtensions.js +31 -0
  26. package/lib/core/Validator.js +42 -15
  27. package/lib/errors/ValidationError.js +3 -3
  28. package/lib/locales/en-US.js +79 -19
  29. package/lib/locales/es-ES.js +60 -19
  30. package/lib/locales/fr-FR.js +84 -43
  31. package/lib/locales/ja-JP.js +83 -42
  32. package/lib/locales/zh-CN.js +32 -0
  33. package/lib/validators/CustomKeywords.js +405 -0
  34. package/package.json +1 -1
  35. package/.github/CODE_OF_CONDUCT.md +0 -45
  36. package/.github/ISSUE_TEMPLATE/bug_report.md +0 -57
  37. package/.github/ISSUE_TEMPLATE/config.yml +0 -11
  38. package/.github/ISSUE_TEMPLATE/feature_request.md +0 -45
  39. package/.github/ISSUE_TEMPLATE/question.md +0 -31
  40. package/.github/PULL_REQUEST_TEMPLATE.md +0 -70
  41. package/.github/SECURITY.md +0 -184
  42. package/.github/workflows/ci.yml +0 -33
  43. package/plugins/custom-format.js +0 -101
  44. package/plugins/custom-validator.js +0 -200
@@ -0,0 +1,81 @@
1
+ # schema-dsl 示例代码
2
+
3
+ 本目录包含 schema-dsl 的各种功能示例。
4
+
5
+ ## 📂 示例列表
6
+
7
+ ### 基础示例
8
+ - [simple-example.js](simple-example.js) - 简单入门示例
9
+ - [dsl-style.js](dsl-style.js) - DSL 风格完整示例
10
+ - [enum.examples.js](enum.examples.js) - 枚举类型验证示例
11
+
12
+ ### 扩展功能
13
+ - [string-extensions.js](string-extensions.js) - String 扩展功能(username、password、phone)
14
+ - [custom-extension.js](custom-extension.js) - 自定义扩展示例
15
+ - [array-dsl-example.js](array-dsl-example.js) - 数组 DSL 语法示例
16
+
17
+ ### 数据库导出
18
+ - [export-demo.js](export-demo.js) - 导出为 MongoDB/MySQL/PostgreSQL Schema
19
+
20
+ ### 国际化 (i18n)
21
+ - [dynamic-locale-configuration.js](dynamic-locale-configuration.js) - 动态语言配置示例
22
+ - [dynamic-locale-example.js](dynamic-locale-example.js) - 动态语言切换示例
23
+ - [i18n-full-demo.js](i18n-full-demo.js) - 完整国际化示例
24
+ - [i18n-memory-safety.examples.js](i18n-memory-safety.examples.js) - i18n 内存安全示例
25
+
26
+ ### Schema 工具
27
+ - [schema-utils-chaining.examples.js](schema-utils-chaining.examples.js) - SchemaUtils 链式调用示例
28
+ - [dsl-match-example.js](dsl-match-example.js) - 条件验证 match 示例
29
+ - [new-features-comparison.js](new-features-comparison.js) - 新版本功能对比
30
+
31
+ ### 插件系统
32
+ - [plugin-system.examples.js](plugin-system.examples.js) - 插件系统完整示例
33
+
34
+ ### 实际应用
35
+ - [express-integration.js](express-integration.js) - Express 集成完整示例
36
+ - [middleware-usage.js](middleware-usage.js) - 中间件使用示例
37
+ - [user-registration/](user-registration/) - 用户注册流程完整示例
38
+ - [schema.js](user-registration/schema.js) - Schema 定义
39
+ - [routes.js](user-registration/routes.js) - 路由定义
40
+ - [server.js](user-registration/server.js) - 服务器入口
41
+ - [password-reset/](password-reset/) - 密码重置流程示例
42
+ - [schema.js](password-reset/schema.js) - Schema 定义
43
+ - [test.js](password-reset/test.js) - 测试用例
44
+
45
+ ## 🚀 快速开始
46
+
47
+ ### 1. 安装依赖
48
+
49
+ ```bash
50
+ cd schema-dsl
51
+ npm install
52
+ ```
53
+
54
+ ### 2. 运行示例
55
+
56
+ ```bash
57
+ # 运行简单示例
58
+ node examples/simple-example.js
59
+
60
+ # 运行 String 扩展示例
61
+ node examples/string-extensions.js
62
+
63
+ # 运行导出示例
64
+ node examples/export-demo.js
65
+ ```
66
+
67
+ ### 3. 查看完整文档
68
+
69
+ 访问 [docs/INDEX.md](../docs/INDEX.md) 查看完整文档索引。
70
+
71
+ ## 📖 相关文档
72
+
73
+ - [DSL 语法文档](../docs/dsl-syntax.md)
74
+ - [String 扩展文档](../docs/string-extensions.md)
75
+ - [插件系统文档](../docs/plugin-system.md)
76
+ - [API 参考](../docs/api-reference.md)
77
+ - [最佳实践](../docs/best-practices.md)
78
+
79
+ ## 🤝 贡献
80
+
81
+ 欢迎提交新的示例!请参考 [CONTRIBUTING.md](../CONTRIBUTING.md)。
@@ -0,0 +1,324 @@
1
+ /**
2
+ * 枚举功能完整示例
3
+ *
4
+ * 演示 schema-dsl 中枚举的各种用法
5
+ *
6
+ * @since v1.1.0
7
+ */
8
+
9
+ const { dsl, validate } = require('../index');
10
+
11
+ console.log('========== 枚举功能示例 ==========\n');
12
+
13
+ // ========================================
14
+ // 1. 基础字符串枚举
15
+ // ========================================
16
+ console.log('【示例 1】基础字符串枚举\n');
17
+
18
+ const userSchema = dsl({
19
+ username: 'string:3-32!',
20
+ role: 'admin|user|guest!', // 简写形式
21
+ status: 'enum:active|inactive|pending' // 完整形式
22
+ });
23
+
24
+ let result = validate(userSchema, {
25
+ username: 'john_doe',
26
+ role: 'admin',
27
+ status: 'active'
28
+ });
29
+
30
+ console.log('✅ 验证通过:', result.valid);
31
+ console.log('数据:', result.data);
32
+ console.log('');
33
+
34
+ // 测试无效值
35
+ result = validate(userSchema, {
36
+ username: 'jane',
37
+ role: 'superadmin', // 无效值
38
+ status: 'active'
39
+ });
40
+
41
+ console.log('❌ 验证失败:', !result.valid);
42
+ console.log('错误:', result.errors[0].message);
43
+ console.log('');
44
+
45
+ // ========================================
46
+ // 2. 布尔值枚举
47
+ // ========================================
48
+ console.log('【示例 2】布尔值枚举\n');
49
+
50
+ const featureSchema = dsl({
51
+ name: 'string!',
52
+ isEnabled: 'true|false!', // 自动识别为布尔值
53
+ isPublic: 'enum:boolean:true|false', // 显式指定布尔值
54
+ verified: 'true|false' // 可选的布尔值
55
+ });
56
+
57
+ result = validate(featureSchema, {
58
+ name: 'dark-mode',
59
+ isEnabled: true,
60
+ isPublic: false
61
+ });
62
+
63
+ console.log('✅ 验证通过:', result.valid);
64
+ console.log('数据:', result.data);
65
+ console.log('');
66
+
67
+ // 测试类型错误
68
+ result = validate(featureSchema, {
69
+ name: 'feature-x',
70
+ isEnabled: 'true', // 字符串 'true' 不是布尔值
71
+ isPublic: false
72
+ });
73
+
74
+ console.log('❌ 类型错误(字符串 vs 布尔值):', !result.valid);
75
+ console.log('');
76
+
77
+ // ========================================
78
+ // 3. 数字枚举
79
+ // ========================================
80
+ console.log('【示例 3】数字枚举\n');
81
+
82
+ const taskSchema = dsl({
83
+ title: 'string!',
84
+ priority: '1|2|3!', // 自动识别为数字
85
+ level: 'enum:number:1|2|3|4|5', // 显式指定数字
86
+ rating: '1.0|1.5|2.0|2.5|3.0' // 小数枚举
87
+ });
88
+
89
+ result = validate(taskSchema, {
90
+ title: 'Fix bug',
91
+ priority: 1,
92
+ level: 3,
93
+ rating: 2.5
94
+ });
95
+
96
+ console.log('✅ 验证通过:', result.valid);
97
+ console.log('数据:', result.data);
98
+ console.log('');
99
+
100
+ // 测试超出范围
101
+ result = validate(taskSchema, {
102
+ title: 'New task',
103
+ priority: 4, // 超出 1|2|3
104
+ level: 2
105
+ });
106
+
107
+ console.log('❌ 超出范围:', !result.valid);
108
+ console.log('');
109
+
110
+ // ========================================
111
+ // 4. 整数枚举
112
+ // ========================================
113
+ console.log('【示例 4】整数枚举(禁止小数)\n');
114
+
115
+ const gameSchema = dsl({
116
+ playerName: 'string!',
117
+ difficulty: 'enum:integer:1|2|3' // 必须是整数
118
+ });
119
+
120
+ result = validate(gameSchema, {
121
+ playerName: 'Alice',
122
+ difficulty: 2
123
+ });
124
+
125
+ console.log('✅ 整数验证通过:', result.valid);
126
+ console.log('');
127
+
128
+ // 小数应该失败
129
+ result = validate(gameSchema, {
130
+ playerName: 'Bob',
131
+ difficulty: 1.5 // 小数不符合 integer 类型
132
+ });
133
+
134
+ console.log('❌ 小数验证失败:', !result.valid);
135
+ console.log('');
136
+
137
+ // ========================================
138
+ // 5. 枚举与链式 API
139
+ // ========================================
140
+ console.log('【示例 5】枚举与链式 API\n');
141
+
142
+ const postSchema = dsl({
143
+ title: 'string:5-100!',
144
+ status: dsl('draft|published|archived')
145
+ .label('文章状态')
146
+ .messages({
147
+ 'enum': '状态必须是: 草稿、已发布或已归档'
148
+ }),
149
+ visibility: dsl('public|private|unlisted!')
150
+ .label('可见性')
151
+ .default('public')
152
+ });
153
+
154
+ result = validate(postSchema, {
155
+ title: 'My First Post',
156
+ status: 'invalid_status',
157
+ visibility: 'public'
158
+ });
159
+
160
+ console.log('❌ 自定义错误消息:', !result.valid);
161
+ console.log('错误:', result.errors[0].message);
162
+ console.log('');
163
+
164
+ // ========================================
165
+ // 6. 数组中的枚举
166
+ // ========================================
167
+ console.log('【示例 6】数组中的枚举\n');
168
+
169
+ const articleSchema = dsl({
170
+ title: 'string!',
171
+ tags: 'array<enum:tech|business|lifestyle>',
172
+ permissions: 'array<enum:read|write|delete>'
173
+ });
174
+
175
+ result = validate(articleSchema, {
176
+ title: 'Tech Article',
177
+ tags: ['tech', 'business'],
178
+ permissions: ['read', 'write']
179
+ });
180
+
181
+ console.log('✅ 数组枚举验证通过:', result.valid);
182
+ console.log('数据:', result.data);
183
+ console.log('');
184
+
185
+ // ========================================
186
+ // 7. 复杂对象中的枚举
187
+ // ========================================
188
+ console.log('【示例 7】复杂对象中的枚举\n');
189
+
190
+ const orderSchema = dsl({
191
+ orderId: 'string!',
192
+ status: 'pending|processing|completed|cancelled!',
193
+ priority: '1|2|3'.default(2),
194
+ payment: {
195
+ method: 'card|paypal|crypto!',
196
+ status: 'pending|success|failed!'
197
+ },
198
+ items: 'array',
199
+ metadata: {
200
+ isUrgent: 'true|false',
201
+ category: 'electronics|clothing|food'
202
+ }
203
+ });
204
+
205
+ result = validate(orderSchema, {
206
+ orderId: 'ORD-12345',
207
+ status: 'processing',
208
+ priority: 1,
209
+ payment: {
210
+ method: 'card',
211
+ status: 'success'
212
+ },
213
+ items: [],
214
+ metadata: {
215
+ isUrgent: true,
216
+ category: 'electronics'
217
+ }
218
+ });
219
+
220
+ console.log('✅ 复杂对象验证通过:', result.valid);
221
+ console.log('数据:', JSON.stringify(result.data, null, 2));
222
+ console.log('');
223
+
224
+ // ========================================
225
+ // 8. 错误处理
226
+ // ========================================
227
+ console.log('【示例 8】错误处理\n');
228
+
229
+ try {
230
+ // 无效的布尔值枚举
231
+ dsl({ flag: 'enum:boolean:true|false|maybe' });
232
+ } catch (error) {
233
+ console.log('❌ 捕获错误:', error.message);
234
+ }
235
+
236
+ try {
237
+ // 无效的数字枚举
238
+ dsl({ value: 'enum:number:1|2|abc' });
239
+ } catch (error) {
240
+ console.log('❌ 捕获错误:', error.message);
241
+ }
242
+
243
+ console.log('');
244
+
245
+ // ========================================
246
+ // 9. 实际应用场景
247
+ // ========================================
248
+ console.log('【示例 9】实际应用 - 用户管理系统\n');
249
+
250
+ const userManagementSchema = dsl({
251
+ // 基本信息
252
+ userId: 'string!',
253
+ username: 'string:3-32!',
254
+ email: 'email!',
255
+
256
+ // 枚举字段
257
+ role: 'admin|moderator|user|guest!',
258
+ status: 'active|inactive|suspended|banned',
259
+ emailVerified: 'true|false',
260
+
261
+ // 权限等级(数字枚举)
262
+ permissionLevel: '0|1|2|3|4|5'.default(0),
263
+
264
+ // 偏好设置
265
+ preferences: {
266
+ theme: 'light|dark|auto',
267
+ language: 'en|zh-CN|zh-TW|ja|ko',
268
+ notifications: 'all|mentions|none'
269
+ }
270
+ });
271
+
272
+ const newUser = {
273
+ userId: 'u_12345',
274
+ username: 'alice',
275
+ email: 'alice@example.com',
276
+ role: 'user',
277
+ status: 'active',
278
+ emailVerified: true,
279
+ permissionLevel: 1,
280
+ preferences: {
281
+ theme: 'dark',
282
+ language: 'zh-CN',
283
+ notifications: 'mentions'
284
+ }
285
+ };
286
+
287
+ result = validate(userManagementSchema, newUser);
288
+
289
+ console.log('✅ 用户数据验证通过:', result.valid);
290
+ console.log('用户数据:', JSON.stringify(result.data, null, 2));
291
+ console.log('');
292
+
293
+ // ========================================
294
+ // 10. 性能测试
295
+ // ========================================
296
+ console.log('【示例 10】性能测试\n');
297
+
298
+ const perfSchema = dsl({
299
+ status: 'active|inactive|pending',
300
+ priority: '1|2|3',
301
+ flag: 'true|false'
302
+ });
303
+
304
+ const iterations = 10000;
305
+ const startTime = Date.now();
306
+
307
+ for (let i = 0; i < iterations; i++) {
308
+ validate(perfSchema, {
309
+ status: 'active',
310
+ priority: 2,
311
+ flag: true
312
+ });
313
+ }
314
+
315
+ const endTime = Date.now();
316
+ const duration = endTime - startTime;
317
+ const perSecond = Math.round((iterations / duration) * 1000);
318
+
319
+ console.log(`验证 ${iterations} 次耗时: ${duration}ms`);
320
+ console.log(`平均每秒验证: ${perSecond.toLocaleString()} 次`);
321
+ console.log('');
322
+
323
+ console.log('========== 示例结束 ==========');
324
+
@@ -7,7 +7,7 @@
7
7
  * 3. SchemaUtils 链式调用
8
8
  * 4. 完整 CRUD 场景
9
9
  *
10
- * @version 2.1.0
10
+ * @version 1.0.3
11
11
  * @date 2025-12-29
12
12
  */
13
13
 
@@ -63,12 +63,12 @@ app.post('/users', async (req, res, next) => {
63
63
  try {
64
64
  console.log('\n[POST /users] 创建用户');
65
65
  console.log('请求体:', req.body);
66
-
66
+
67
67
  // 使用 validateAsync 验证
68
68
  const data = await validateAsync(createUserSchema, req.body);
69
-
69
+
70
70
  console.log('验证通过,数据:', data);
71
-
71
+
72
72
  // 保存到数据库
73
73
  const user = {
74
74
  id: String(db.nextId++),
@@ -76,20 +76,20 @@ app.post('/users', async (req, res, next) => {
76
76
  createdAt: new Date().toISOString(),
77
77
  updatedAt: new Date().toISOString()
78
78
  };
79
-
79
+
80
80
  db.users.push(user);
81
-
81
+
82
82
  // 返回公开信息
83
83
  const { validate } = require('../index');
84
84
  const result = validate(publicUserSchema, user);
85
-
85
+
86
86
  console.log('返回数据:', result.data);
87
-
87
+
88
88
  res.status(201).json({
89
89
  success: true,
90
90
  user: result.data
91
91
  });
92
-
92
+
93
93
  } catch (error) {
94
94
  next(error);
95
95
  }
@@ -102,17 +102,17 @@ app.post('/users', async (req, res, next) => {
102
102
  */
103
103
  app.get('/users', (req, res) => {
104
104
  console.log('\n[GET /users] 获取所有用户');
105
-
105
+
106
106
  const { validate } = require('../index');
107
-
107
+
108
108
  // 对每个用户应用 publicUserSchema
109
109
  const publicUsers = db.users.map(user => {
110
110
  const result = validate(publicUserSchema, user);
111
111
  return result.data;
112
112
  });
113
-
113
+
114
114
  console.log(`返回 ${publicUsers.length} 个用户`);
115
-
115
+
116
116
  res.json({
117
117
  success: true,
118
118
  count: publicUsers.length,
@@ -127,9 +127,9 @@ app.get('/users', (req, res) => {
127
127
  */
128
128
  app.get('/users/:id', (req, res) => {
129
129
  console.log(`\n[GET /users/${req.params.id}] 获取用户`);
130
-
130
+
131
131
  const user = db.users.find(u => u.id === req.params.id);
132
-
132
+
133
133
  if (!user) {
134
134
  console.log('用户不存在');
135
135
  return res.status(404).json({
@@ -137,13 +137,13 @@ app.get('/users/:id', (req, res) => {
137
137
  error: '用户不存在'
138
138
  });
139
139
  }
140
-
140
+
141
141
  // 使用 clean 模式自动移除敏感字段
142
142
  const { validate } = require('../index');
143
143
  const result = validate(publicUserSchema, user);
144
-
144
+
145
145
  console.log('返回数据:', result.data);
146
-
146
+
147
147
  res.json({
148
148
  success: true,
149
149
  user: result.data
@@ -162,9 +162,9 @@ app.patch('/users/:id', async (req, res, next) => {
162
162
  try {
163
163
  console.log(`\n[PATCH /users/${req.params.id}] 部分更新用户`);
164
164
  console.log('请求体:', req.body);
165
-
165
+
166
166
  const user = db.users.find(u => u.id === req.params.id);
167
-
167
+
168
168
  if (!user) {
169
169
  console.log('用户不存在');
170
170
  return res.status(404).json({
@@ -172,28 +172,28 @@ app.patch('/users/:id', async (req, res, next) => {
172
172
  error: '用户不存在'
173
173
  });
174
174
  }
175
-
175
+
176
176
  // 验证部分数据
177
177
  const data = await validateAsync(updateUserSchema, req.body);
178
-
178
+
179
179
  console.log('验证通过,更新字段:', data);
180
-
180
+
181
181
  // 更新用户
182
182
  Object.assign(user, data, {
183
183
  updatedAt: new Date().toISOString()
184
184
  });
185
-
185
+
186
186
  // 返回公开信息
187
187
  const { validate } = require('../index');
188
188
  const result = validate(publicUserSchema, user);
189
-
189
+
190
190
  console.log('返回数据:', result.data);
191
-
191
+
192
192
  res.json({
193
193
  success: true,
194
194
  user: result.data
195
195
  });
196
-
196
+
197
197
  } catch (error) {
198
198
  next(error);
199
199
  }
@@ -210,9 +210,9 @@ app.put('/users/:id', async (req, res, next) => {
210
210
  try {
211
211
  console.log(`\n[PUT /users/${req.params.id}] 替换用户`);
212
212
  console.log('请求体:', req.body);
213
-
213
+
214
214
  const userIndex = db.users.findIndex(u => u.id === req.params.id);
215
-
215
+
216
216
  if (userIndex === -1) {
217
217
  console.log('用户不存在');
218
218
  return res.status(404).json({
@@ -220,12 +220,12 @@ app.put('/users/:id', async (req, res, next) => {
220
220
  error: '用户不存在'
221
221
  });
222
222
  }
223
-
223
+
224
224
  // 验证完整数据
225
225
  const data = await validateAsync(replaceUserSchema, req.body);
226
-
226
+
227
227
  console.log('验证通过,替换用户:', data);
228
-
228
+
229
229
  // 替换用户(保留 id 和 createdAt)
230
230
  const oldUser = db.users[userIndex];
231
231
  db.users[userIndex] = {
@@ -234,18 +234,18 @@ app.put('/users/:id', async (req, res, next) => {
234
234
  createdAt: oldUser.createdAt,
235
235
  updatedAt: new Date().toISOString()
236
236
  };
237
-
237
+
238
238
  // 返回公开信息
239
239
  const { validate } = require('../index');
240
240
  const result = validate(publicUserSchema, db.users[userIndex]);
241
-
241
+
242
242
  console.log('返回数据:', result.data);
243
-
243
+
244
244
  res.json({
245
245
  success: true,
246
246
  user: result.data
247
247
  });
248
-
248
+
249
249
  } catch (error) {
250
250
  next(error);
251
251
  }
@@ -256,9 +256,9 @@ app.put('/users/:id', async (req, res, next) => {
256
256
  */
257
257
  app.delete('/users/:id', (req, res) => {
258
258
  console.log(`\n[DELETE /users/${req.params.id}] 删除用户`);
259
-
259
+
260
260
  const userIndex = db.users.findIndex(u => u.id === req.params.id);
261
-
261
+
262
262
  if (userIndex === -1) {
263
263
  console.log('用户不存在');
264
264
  return res.status(404).json({
@@ -266,11 +266,11 @@ app.delete('/users/:id', (req, res) => {
266
266
  error: '用户不存在'
267
267
  });
268
268
  }
269
-
269
+
270
270
  db.users.splice(userIndex, 1);
271
-
271
+
272
272
  console.log('删除成功');
273
-
273
+
274
274
  res.json({
275
275
  success: true,
276
276
  message: '用户已删除'
@@ -290,10 +290,10 @@ app.use((error, req, res, next) => {
290
290
  console.log('\n[错误] ValidationError 被捕获');
291
291
  console.log('错误数量:', error.getErrorCount());
292
292
  console.log('字段错误:', error.getFieldErrors());
293
-
293
+
294
294
  return res.status(error.statusCode).json(error.toJSON());
295
295
  }
296
-
296
+
297
297
  // 其他错误
298
298
  console.error('\n[错误] 服务器错误:', error);
299
299
  res.status(500).json({
@@ -319,7 +319,7 @@ app.listen(PORT, () => {
319
319
  console.log(` PUT http://localhost:${PORT}/users/:id - 替换用户`);
320
320
  console.log(` DELETE http://localhost:${PORT}/users/:id - 删除用户`);
321
321
  console.log(`\n========================================\n`);
322
-
322
+
323
323
  // 打印测试命令
324
324
  printTestCommands();
325
325
  });
@@ -328,46 +328,46 @@ app.listen(PORT, () => {
328
328
 
329
329
  function printTestCommands() {
330
330
  console.log(`测试命令(使用 curl):\n`);
331
-
331
+
332
332
  console.log(`# 1. 创建用户(成功)`);
333
333
  console.log(`curl -X POST http://localhost:${PORT}/users \\`);
334
334
  console.log(` -H "Content-Type: application/json" \\`);
335
335
  console.log(` -d '{"name":"John Doe","email":"john@example.com","password":"password123","age":30,"role":"user"}'\n`);
336
-
336
+
337
337
  console.log(`# 2. 创建用户(失败 - 缺少必填字段)`);
338
338
  console.log(`curl -X POST http://localhost:${PORT}/users \\`);
339
339
  console.log(` -H "Content-Type: application/json" \\`);
340
340
  console.log(` -d '{"name":"Jane"}'\n`);
341
-
341
+
342
342
  console.log(`# 3. 创建用户(失败 - 额外字段被拒绝)`);
343
343
  console.log(`curl -X POST http://localhost:${PORT}/users \\`);
344
344
  console.log(` -H "Content-Type: application/json" \\`);
345
345
  console.log(` -d '{"name":"Bob","email":"bob@example.com","password":"password123","extraField":"not allowed"}'\n`);
346
-
346
+
347
347
  console.log(`# 4. 获取所有用户`);
348
348
  console.log(`curl http://localhost:${PORT}/users\n`);
349
-
349
+
350
350
  console.log(`# 5. 获取单个用户(替换 ID)`);
351
351
  console.log(`curl http://localhost:${PORT}/users/1\n`);
352
-
352
+
353
353
  console.log(`# 6. 部分更新用户(成功 - 只更新 name)`);
354
354
  console.log(`curl -X PATCH http://localhost:${PORT}/users/1 \\`);
355
355
  console.log(` -H "Content-Type: application/json" \\`);
356
356
  console.log(` -d '{"name":"John Updated"}'\n`);
357
-
357
+
358
358
  console.log(`# 7. 部分更新用户(成功 - 允许额外字段)`);
359
359
  console.log(`curl -X PATCH http://localhost:${PORT}/users/1 \\`);
360
360
  console.log(` -H "Content-Type: application/json" \\`);
361
361
  console.log(` -d '{"age":31,"extraField":"allowed"}'\n`);
362
-
362
+
363
363
  console.log(`# 8. 替换用户(成功 - 必须提供所有必填字段)`);
364
364
  console.log(`curl -X PUT http://localhost:${PORT}/users/1 \\`);
365
365
  console.log(` -H "Content-Type: application/json" \\`);
366
366
  console.log(` -d '{"name":"John Replaced","email":"john.new@example.com","password":"newpassword123","age":32}'\n`);
367
-
367
+
368
368
  console.log(`# 9. 删除用户`);
369
369
  console.log(`curl -X DELETE http://localhost:${PORT}/users/1\n`);
370
-
370
+
371
371
  console.log(`========================================\n`);
372
372
  }
373
373