schema-dsl 1.0.9 → 1.1.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 (44) hide show
  1. package/CHANGELOG.md +205 -2
  2. package/README.md +257 -0
  3. package/docs/FEATURE-INDEX.md +1 -1
  4. package/docs/best-practices.md +3 -3
  5. package/docs/cache-manager.md +1 -1
  6. package/docs/conditional-api.md +1032 -0
  7. package/docs/dsl-syntax.md +1 -1
  8. package/docs/dynamic-locale.md +2 -2
  9. package/docs/error-handling.md +2 -2
  10. package/docs/export-guide.md +2 -2
  11. package/docs/export-limitations.md +3 -3
  12. package/docs/faq.md +6 -6
  13. package/docs/frontend-i18n-guide.md +1 -1
  14. package/docs/mongodb-exporter.md +3 -3
  15. package/docs/multi-type-support.md +12 -2
  16. package/docs/mysql-exporter.md +1 -1
  17. package/docs/plugin-system.md +4 -4
  18. package/docs/postgresql-exporter.md +1 -1
  19. package/docs/quick-start.md +4 -4
  20. package/docs/troubleshooting.md +2 -2
  21. package/docs/type-reference.md +5 -5
  22. package/docs/typescript-guide.md +5 -6
  23. package/docs/union-type-guide.md +147 -0
  24. package/docs/union-types.md +277 -0
  25. package/docs/validate-async.md +1 -1
  26. package/examples/array-dsl-example.js +1 -1
  27. package/examples/conditional-example.js +288 -0
  28. package/examples/conditional-non-object.js +129 -0
  29. package/examples/conditional-validate-example.js +321 -0
  30. package/examples/union-type-example.js +127 -0
  31. package/examples/union-types-example.js +77 -0
  32. package/index.d.ts +332 -7
  33. package/index.js +19 -1
  34. package/lib/adapters/DslAdapter.js +14 -5
  35. package/lib/core/ConditionalBuilder.js +401 -0
  36. package/lib/core/DslBuilder.js +113 -0
  37. package/lib/core/Locale.js +13 -8
  38. package/lib/core/Validator.js +246 -2
  39. package/lib/locales/en-US.js +14 -0
  40. package/lib/locales/es-ES.js +4 -0
  41. package/lib/locales/fr-FR.js +4 -0
  42. package/lib/locales/ja-JP.js +9 -0
  43. package/lib/locales/zh-CN.js +14 -0
  44. package/package.json +3 -1
@@ -0,0 +1,129 @@
1
+ /**
2
+ * ConditionalBuilder 非对象类型示例
3
+ *
4
+ * 展示如何直接验证字符串、数组、布尔值等非对象类型
5
+ */
6
+
7
+ const { dsl, validate } = require('../index');
8
+
9
+ console.log('========================================');
10
+ console.log('ConditionalBuilder - 非对象类型示例');
11
+ console.log('========================================\n');
12
+
13
+ // ============================================
14
+ // 示例1:直接验证字符串
15
+ // ============================================
16
+ console.log('【示例1】直接验证字符串');
17
+ console.log('----------------------------');
18
+
19
+ const stringSchema = dsl.if((data) => typeof data === 'string' && data.includes('@'))
20
+ .then('email!')
21
+ .else('string:1-50');
22
+
23
+ const r1 = validate(stringSchema, 'test@example.com');
24
+ console.log('✅ 邮箱格式:', r1.valid ? '验证通过' : '验证失败');
25
+
26
+ const r2 = validate(stringSchema, 'just a text');
27
+ console.log('✅ 普通文本:', r2.valid ? '验证通过' : '验证失败');
28
+
29
+ // ============================================
30
+ // 示例2:直接验证数组
31
+ // ============================================
32
+ console.log('\n【示例2】直接验证数组');
33
+ console.log('----------------------------');
34
+
35
+ const arraySchema = dsl.if((data) => Array.isArray(data) && data.length > 5)
36
+ .message('数组最多5个元素');
37
+
38
+ const r3 = validate(arraySchema, [1, 2, 3]);
39
+ console.log('✅ 3个元素:', r3.valid ? '验证通过' : '验证失败');
40
+
41
+ const r4 = validate(arraySchema, [1, 2, 3, 4, 5, 6]);
42
+ console.log('❌ 6个元素:', r4.valid ? '验证通过' : '验证失败');
43
+ if (!r4.valid) {
44
+ console.log(' 错误:', r4.errors[0].message);
45
+ }
46
+
47
+ // ============================================
48
+ // 示例3:直接验证数字
49
+ // ============================================
50
+ console.log('\n【示例3】直接验证数字');
51
+ console.log('----------------------------');
52
+
53
+ const numberSchema = dsl.if((data) => typeof data === 'number' && data < 0)
54
+ .message('不允许负数')
55
+ .else(null); // 不需要额外验证
56
+
57
+ const r5 = validate(numberSchema, 10);
58
+ console.log('✅ 正数:', r5.valid ? '验证通过' : '验证失败');
59
+
60
+ const r6 = validate(numberSchema, -5);
61
+ console.log('❌ 负数:', r6.valid ? '验证通过' : '验证失败');
62
+ if (!r6.valid) {
63
+ console.log(' 错误:', r6.errors[0].message);
64
+ }
65
+
66
+ // ============================================
67
+ // 示例4:字符串类型判断(邮箱或手机号)
68
+ // ============================================
69
+ console.log('\n【示例4】自动识别邮箱或手机号');
70
+ console.log('----------------------------');
71
+
72
+ const contactSchema = dsl.if((data) => typeof data === 'string' && data.includes('@'))
73
+ .then('email!')
74
+ .else('string:11!');
75
+
76
+ const r7 = validate(contactSchema, 'user@example.com');
77
+ console.log('✅ 邮箱:', r7.valid ? '验证通过' : '验证失败');
78
+
79
+ const r8 = validate(contactSchema, '13800138000');
80
+ console.log('✅ 手机号:', r8.valid ? '验证通过' : '验证失败');
81
+
82
+ const r9 = validate(contactSchema, 'invalid');
83
+ console.log('❌ 无效输入:', r9.valid ? '验证通过' : '验证失败');
84
+ if (!r9.valid) {
85
+ console.log(' 错误:', r9.errors[0].message);
86
+ }
87
+
88
+ // ============================================
89
+ // 示例5:复杂条件组合
90
+ // ============================================
91
+ console.log('\n【示例5】字符串长度 + 内容组合判断');
92
+ console.log('----------------------------');
93
+
94
+ const complexSchema = dsl.if((data) => typeof data === 'string' && data.length > 20)
95
+ .and((data) => data.includes('@'))
96
+ .then('email!')
97
+ .else('string:1-50');
98
+
99
+ const r10 = validate(complexSchema, 'short');
100
+ console.log('✅ 短字符串:', r10.valid ? '验证通过' : '验证失败');
101
+
102
+ const r11 = validate(complexSchema, 'this-is-a-long-email@example.com');
103
+ console.log('✅ 长邮箱:', r11.valid ? '验证通过' : '验证失败');
104
+
105
+ const r12 = validate(complexSchema, 'this is a very long string without at symbol');
106
+ console.log('✅ 长文本(无@):', r12.valid ? '验证通过' : '验证失败');
107
+
108
+ // ============================================
109
+ // 示例6:边界值处理
110
+ // ============================================
111
+ console.log('\n【示例6】边界值处理');
112
+ console.log('----------------------------');
113
+
114
+ const boundarySchema = dsl.if((data) => data === null || data === undefined || data === '')
115
+ .message('值不能为空');
116
+
117
+ const r13 = validate(boundarySchema, 'valid value');
118
+ console.log('✅ 有效值:', r13.valid ? '验证通过' : '验证失败');
119
+
120
+ const r14 = validate(boundarySchema, '');
121
+ console.log('❌ 空字符串:', r14.valid ? '验证通过' : '验证失败');
122
+ if (!r14.valid) {
123
+ console.log(' 错误:', r14.errors[0].message);
124
+ }
125
+
126
+ console.log('\n========================================');
127
+ console.log('示例运行完成!');
128
+ console.log('========================================');
129
+
@@ -0,0 +1,321 @@
1
+ /**
2
+ * ConditionalBuilder 快捷验证方法示例
3
+ *
4
+ * 展示 .validate() 和 .check() 方法的使用
5
+ */
6
+
7
+ const { dsl } = require('../index');
8
+
9
+ console.log('========================================');
10
+ console.log('ConditionalBuilder - 快捷验证方法示例');
11
+ console.log('========================================\n');
12
+
13
+ // ============================================
14
+ // 示例1:一行代码验证
15
+ // ============================================
16
+ console.log('【示例1】一行代码验证');
17
+ console.log('----------------------------');
18
+
19
+ const result1 = dsl.if(d => d.age < 18)
20
+ .message('未成年用户不能注册')
21
+ .validate({ age: 16 });
22
+
23
+ console.log('验证未成年用户:', result1.valid ? '✅ 通过' : '❌ 失败');
24
+ if (!result1.valid) {
25
+ console.log('错误:', result1.errors[0].message);
26
+ }
27
+
28
+ const result2 = dsl.if(d => d.age < 18)
29
+ .message('未成年用户不能注册')
30
+ .validate({ age: 20 });
31
+
32
+ console.log('验证成年用户:', result2.valid ? '✅ 通过' : '❌ 失败');
33
+
34
+ // ============================================
35
+ // 示例2:复用验证器
36
+ // ============================================
37
+ console.log('\n【示例2】复用验证器');
38
+ console.log('----------------------------');
39
+
40
+ const ageValidator = dsl.if(d => d.age < 18).message('未成年用户不能注册');
41
+
42
+ const users = [
43
+ { name: '张三', age: 16 },
44
+ { name: '李四', age: 20 },
45
+ { name: '王五', age: 17 },
46
+ { name: '赵六', age: 25 }
47
+ ];
48
+
49
+ users.forEach(user => {
50
+ const result = ageValidator.validate(user);
51
+ console.log(`${user.name}(${user.age}岁):`, result.valid ? '✅ 可以注册' : '❌ 不能注册');
52
+ });
53
+
54
+ // ============================================
55
+ // 示例3:.check() 快速判断
56
+ // ============================================
57
+ console.log('\n【示例3】.check() 快速判断');
58
+ console.log('----------------------------');
59
+
60
+ const canRegister = dsl.if(d => d.age < 18)
61
+ .or(d => d.status === 'blocked')
62
+ .message('不允许注册');
63
+
64
+ const testUsers = [
65
+ { name: '用户A', age: 16, status: 'active' },
66
+ { name: '用户B', age: 20, status: 'blocked' },
67
+ { name: '用户C', age: 20, status: 'active' }
68
+ ];
69
+
70
+ testUsers.forEach(user => {
71
+ const isValid = canRegister.check(user);
72
+ console.log(`${user.name}:`, isValid ? '✅ 允许注册' : '❌ 禁止注册');
73
+ });
74
+
75
+ // ============================================
76
+ // 示例4:then/else 动态验证
77
+ // ============================================
78
+ console.log('\n【示例4】then/else 动态验证');
79
+ console.log('----------------------------');
80
+
81
+ const emailValidator = dsl.if(d => d.userType === 'admin')
82
+ .then('email!') // 管理员必填
83
+ .else('email'); // 普通用户可选
84
+
85
+ // 管理员有邮箱
86
+ const r1 = emailValidator.validate({
87
+ userType: 'admin',
88
+ email: 'admin@example.com'
89
+ });
90
+ console.log('管理员有邮箱:', r1.valid ? '✅ 通过' : '❌ 失败');
91
+
92
+ // 管理员无邮箱
93
+ const r2 = emailValidator.validate({
94
+ userType: 'admin',
95
+ email: ''
96
+ });
97
+ console.log('管理员无邮箱:', r2.valid ? '✅ 通过' : '❌ 失败');
98
+
99
+ // 普通用户无邮箱
100
+ const r3 = emailValidator.validate({
101
+ userType: 'user',
102
+ email: ''
103
+ });
104
+ console.log('普通用户无邮箱:', r3.valid ? '✅ 通过' : '❌ 失败');
105
+
106
+ // ============================================
107
+ // 示例5:非对象类型验证
108
+ // ============================================
109
+ console.log('\n【示例5】非对象类型验证');
110
+ console.log('----------------------------');
111
+
112
+ // 验证字符串
113
+ const stringValidator = dsl.if(d => typeof d === 'string' && d.includes('@'))
114
+ .then('email!')
115
+ .else('string:1-50');
116
+
117
+ const r4 = stringValidator.validate('test@example.com');
118
+ console.log('邮箱格式:', r4.valid ? '✅ 通过' : '❌ 失败');
119
+
120
+ const r5 = stringValidator.validate('just a text');
121
+ console.log('普通文本:', r5.valid ? '✅ 通过' : '❌ 失败');
122
+
123
+ // 验证数组
124
+ const arrayValidator = dsl.if(d => Array.isArray(d) && d.length > 5)
125
+ .message('数组最多5个元素');
126
+
127
+ const r6 = arrayValidator.validate([1, 2, 3]);
128
+ console.log('3个元素:', r6.valid ? '✅ 通过' : '❌ 失败');
129
+
130
+ const r7 = arrayValidator.validate([1, 2, 3, 4, 5, 6]);
131
+ console.log('6个元素:', r7.valid ? '✅ 通过' : '❌ 失败');
132
+ if (!r7.valid) {
133
+ console.log('错误:', r7.errors[0].message);
134
+ }
135
+
136
+ // ============================================
137
+ // 示例6:多语言支持
138
+ // ============================================
139
+ console.log('\n【示例6】多语言支持');
140
+ console.log('----------------------------');
141
+
142
+ const i18nValidator = dsl.if(d => d.age < 18)
143
+ .message('conditional.underAge');
144
+
145
+ // 中文
146
+ const r8 = i18nValidator.validate({ age: 16 }, { locale: 'zh-CN' });
147
+ console.log('中文:', r8.valid ? '✅ 通过' : '❌ 失败');
148
+ if (!r8.valid) {
149
+ console.log('错误:', r8.errors[0].message);
150
+ }
151
+
152
+ // 英文
153
+ const r9 = i18nValidator.validate({ age: 16 }, { locale: 'en-US' });
154
+ console.log('英文:', r9.valid ? '✅ 通过' : '❌ 失败');
155
+ if (!r9.valid) {
156
+ console.log('错误:', r9.errors[0].message);
157
+ }
158
+
159
+ // ============================================
160
+ // 示例7:实际业务场景
161
+ // ============================================
162
+ console.log('\n【示例7】实际业务场景 - 用户注册');
163
+ console.log('----------------------------');
164
+
165
+ // 创建多个验证器
166
+ const validators = {
167
+ age: dsl.if(d => d.age < 18)
168
+ .message('未成年用户不能注册'),
169
+
170
+ email: dsl.if(d => d.userType === 'admin')
171
+ .then('email!')
172
+ .else('email'),
173
+
174
+ phone: dsl.if(d => d.userType === 'vip')
175
+ .then('string:11!')
176
+ .else(null)
177
+ };
178
+
179
+ // 验证用户
180
+ function validateUser(userData) {
181
+ console.log(`\n验证用户: ${userData.username}`);
182
+
183
+ // 年龄检查
184
+ if (!validators.age.check(userData)) {
185
+ console.log('❌ 年龄验证失败');
186
+ return false;
187
+ }
188
+
189
+ // 邮箱检查
190
+ const emailResult = validators.email.validate(userData);
191
+ if (!emailResult.valid) {
192
+ console.log('❌ 邮箱验证失败:', emailResult.errors[0].message);
193
+ return false;
194
+ }
195
+
196
+ // 手机号检查
197
+ const phoneResult = validators.phone.validate(userData);
198
+ if (!phoneResult.valid) {
199
+ console.log('❌ 手机号验证失败:', phoneResult.errors[0].message);
200
+ return false;
201
+ }
202
+
203
+ console.log('✅ 所有验证通过');
204
+ return true;
205
+ }
206
+
207
+ // 测试数据
208
+ const userData1 = {
209
+ username: 'admin1',
210
+ age: 25,
211
+ userType: 'admin',
212
+ email: 'admin@example.com'
213
+ };
214
+
215
+ const userData2 = {
216
+ username: 'user1',
217
+ age: 16,
218
+ userType: 'user',
219
+ email: ''
220
+ };
221
+
222
+ validateUser(userData1);
223
+ validateUser(userData2);
224
+
225
+ // ============================================
226
+ // 示例8:异步验证 - .validateAsync()
227
+ // ============================================
228
+ console.log('\n【示例8】异步验证 - .validateAsync()');
229
+ console.log('----------------------------');
230
+
231
+ async function asyncRegister() {
232
+ const ageValidator = dsl.if(d => d.age < 18)
233
+ .message('未成年用户不能注册');
234
+
235
+ // 验证通过
236
+ try {
237
+ const data1 = await ageValidator.validateAsync({ age: 20, name: '张三' });
238
+ console.log('✅ 验证通过:', data1.name);
239
+ } catch (error) {
240
+ console.log('❌ 验证失败:', error.message);
241
+ }
242
+
243
+ // 验证失败
244
+ try {
245
+ await ageValidator.validateAsync({ age: 16, name: '李四' });
246
+ } catch (error) {
247
+ console.log('❌ 验证失败:', error.message);
248
+ }
249
+ }
250
+
251
+ asyncRegister();
252
+
253
+ // ============================================
254
+ // 示例9:断言验证 - .assert()
255
+ // ============================================
256
+ console.log('\n【示例9】断言验证 - .assert()');
257
+ console.log('----------------------------');
258
+
259
+ function createUser(userData) {
260
+ try {
261
+ // 断言验证,失败直接抛错
262
+ dsl.if(d => d.age < 18)
263
+ .message('未成年用户不能注册')
264
+ .assert(userData);
265
+
266
+ dsl.if(d => !d.email || d.email.length === 0)
267
+ .message('邮箱不能为空')
268
+ .assert(userData);
269
+
270
+ console.log(`✅ 用户 ${userData.name} 创建成功`);
271
+ return { success: true, user: userData };
272
+ } catch (error) {
273
+ console.log(`❌ 用户 ${userData.name} 创建失败: ${error.message}`);
274
+ return { success: false, error: error.message };
275
+ }
276
+ }
277
+
278
+ createUser({ name: '张三', age: 20, email: 'zhangsan@example.com' });
279
+ createUser({ name: '李四', age: 16, email: 'lisi@example.com' });
280
+ createUser({ name: '王五', age: 20, email: '' });
281
+
282
+ // ============================================
283
+ // 示例10:Express 中间件场景(模拟)
284
+ // ============================================
285
+ console.log('\n【示例10】Express 中间件场景(模拟)');
286
+ console.log('----------------------------');
287
+
288
+ // 模拟 Express 中间件
289
+ async function checkPermission(req, res, next) {
290
+ try {
291
+ await dsl.if(d => d.role !== 'admin' && d.role !== 'moderator')
292
+ .message('权限不足')
293
+ .validateAsync(req.user);
294
+
295
+ console.log('✅ 权限验证通过');
296
+ next();
297
+ } catch (error) {
298
+ console.log('❌ 权限不足:', error.message);
299
+ res.status = 403;
300
+ res.error = error.message;
301
+ }
302
+ }
303
+
304
+ // 模拟请求
305
+ const mockReq1 = { user: { name: 'admin', role: 'admin' } };
306
+ const mockReq2 = { user: { name: 'user', role: 'user' } };
307
+ const mockRes = { status: 200, error: null };
308
+ const mockNext = () => console.log(' 继续处理请求...');
309
+
310
+ (async () => {
311
+ console.log('请求1 - 管理员:');
312
+ await checkPermission(mockReq1, mockRes, mockNext);
313
+
314
+ console.log('请求2 - 普通用户:');
315
+ await checkPermission(mockReq2, mockRes, mockNext);
316
+ })();
317
+
318
+ console.log('\n========================================');
319
+ console.log('示例运行完成!');
320
+ console.log('========================================');
321
+
@@ -0,0 +1,127 @@
1
+ /**
2
+ * 联合类型验证示例
3
+ *
4
+ * 使用 .pattern() + .messages() 实现一个字段支持多种格式
5
+ */
6
+
7
+ const { dsl, validate } = require('../index');
8
+
9
+ console.log('========================================');
10
+ console.log('联合类型验证示例 - 使用 .pattern()');
11
+ console.log('========================================\n');
12
+
13
+ // ========================================
14
+ // 示例1:邮箱或手机号(使用多语言 key)
15
+ // ========================================
16
+ console.log('【示例1】邮箱或手机号 - 多语言支持');
17
+ console.log('----------------------------');
18
+
19
+ const schema1 = dsl({
20
+ name: 'string:1-50!',
21
+ contact: dsl('string!')
22
+ .pattern(/^([^\s@]+@[^\s@]+\.[^\s@]+|1[3-9]\d{9})$/)
23
+ .messages({ pattern: 'pattern.emailOrPhone' }) // 🌍 使用多语言 key
24
+ .label('联系方式')
25
+ });
26
+
27
+ const testData1 = [
28
+ { name: '张三', contact: 'zhangsan@example.com' },
29
+ { name: '李四', contact: '13800138000' },
30
+ { name: '王五', contact: 'invalid' }
31
+ ];
32
+
33
+ // 中文验证
34
+ console.log('🇨🇳 中文错误消息:');
35
+ testData1.forEach((data) => {
36
+ const result = validate(schema1, data, { locale: 'zh-CN' });
37
+ console.log(` ${data.name} (${data.contact}):`, result.valid ? '✅ 通过' : '❌ 失败');
38
+ if (!result.valid) {
39
+ console.log(` 错误: ${result.errors[0].message}`);
40
+ }
41
+ });
42
+
43
+ // 英文验证
44
+ console.log('\n🇺🇸 英文错误消息:');
45
+ testData1.forEach((data) => {
46
+ const result = validate(schema1, data, { locale: 'en-US' });
47
+ console.log(` ${data.name} (${data.contact}):`, result.valid ? '✅ Pass' : '❌ Fail');
48
+ if (!result.valid) {
49
+ console.log(` Error: ${result.errors[0].message}`);
50
+ }
51
+ });
52
+
53
+ console.log('');
54
+
55
+ // ========================================
56
+ // 示例2:用户登录(用户名或邮箱)- 多语言
57
+ // ========================================
58
+ console.log('【示例2】用户登录(用户名或邮箱)- 多语言');
59
+ console.log('----------------------------');
60
+
61
+ const loginSchema = dsl({
62
+ username: dsl('string:3-32!')
63
+ .pattern(/^([^\s@]+@[^\s@]+\.[^\s@]+|[a-zA-Z0-9_]+)$/)
64
+ .messages({ pattern: 'pattern.usernameOrEmail' }) // 🌍 多语言 key
65
+ .label('用户名'),
66
+ password: 'string:8-32!'
67
+ });
68
+
69
+ const loginTest = { username: 'invalid!@#', password: '12345678' };
70
+
71
+ console.log('🇨🇳 中文:');
72
+ const r1 = validate(loginSchema, loginTest, { locale: 'zh-CN' });
73
+ console.log(` ${loginTest.username}:`, r1.valid ? '✅' : `❌ ${r1.errors[0].message}`);
74
+
75
+ console.log('🇺🇸 英文:');
76
+ const r2 = validate(loginSchema, loginTest, { locale: 'en-US' });
77
+ console.log(` ${loginTest.username}:`, r2.valid ? '✅' : `❌ ${r2.errors[0].message}`);
78
+
79
+ console.log('');
80
+
81
+ // ========================================
82
+ // 示例3:URL(http 或 https)- 多语言
83
+ // ========================================
84
+ console.log('【示例3】URL(http 或 https)- 多语言');
85
+ console.log('----------------------------');
86
+
87
+ const urlSchema = dsl({
88
+ website: dsl('string!')
89
+ .pattern(/^https?:\/\/.+$/)
90
+ .messages({ pattern: 'pattern.httpOrHttps' }) // 🌍 多语言 key
91
+ .label('网站地址')
92
+ });
93
+
94
+ const urlTest = { website: 'ftp://example.com' };
95
+
96
+ console.log('🇨🇳 中文:');
97
+ const u1 = validate(urlSchema, urlTest, { locale: 'zh-CN' });
98
+ console.log(` ${urlTest.website}:`, u1.valid ? '✅' : `❌ ${u1.errors[0].message}`);
99
+
100
+ console.log('🇺🇸 英文:');
101
+ const u2 = validate(urlSchema, urlTest, { locale: 'en-US' });
102
+ console.log(` ${urlTest.website}:`, u2.valid ? '✅' : `❌ ${u2.errors[0].message}`);
103
+
104
+ console.log('');
105
+
106
+ // ========================================
107
+ // 示例4:直接写错误消息(不使用多语言)
108
+ // ========================================
109
+ console.log('【示例4】直接写错误消息(不使用多语言)');
110
+ console.log('----------------------------');
111
+
112
+ const simpleSchema = dsl({
113
+ contact: dsl('string!')
114
+ .pattern(/^([^\s@]+@[^\s@]+\.[^\s@]+|1[3-9]\d{9})$/)
115
+ .messages({ pattern: '必须是邮箱或手机号' }) // 直接写死
116
+ });
117
+
118
+ const result = validate(simpleSchema, { contact: 'invalid' });
119
+ console.log('invalid:', result.valid ? '✅' : `❌ ${result.errors[0].message}`);
120
+
121
+ console.log('');
122
+
123
+ console.log('========================================');
124
+ console.log('示例运行完成!');
125
+ console.log('多语言测试成功!🎉');
126
+ console.log('========================================');
127
+
@@ -0,0 +1,77 @@
1
+ /**
2
+ * 跨类型联合验证示例
3
+ *
4
+ * 演示如何使用 types: 语法实现跨类型联合验证
5
+ */
6
+
7
+ const { dsl, validate, DslBuilder, PluginManager } = require('../index');
8
+
9
+ console.log('='.repeat(60));
10
+ console.log('跨类型联合验证 - types: 语法示例');
11
+ console.log('='.repeat(60));
12
+
13
+ // ========== 示例1:基础联合类型 ==========
14
+ console.log('\n【示例1】基础联合类型:string|number');
15
+ const schema1 = dsl({
16
+ value: 'types:string|number'
17
+ });
18
+
19
+ console.log('✓ 字符串:', validate(schema1, { value: 'hello' }).valid);
20
+ console.log('✓ 数字:', validate(schema1, { value: 123 }).valid);
21
+ console.log('✗ 布尔:', validate(schema1, { value: true }).valid);
22
+
23
+ // ========== 示例2:带约束的联合类型 ==========
24
+ console.log('\n【示例2】带约束:string:3-10|number:0-100');
25
+ const schema2 = dsl({
26
+ value: 'types:string:3-10|number:0-100!'
27
+ });
28
+
29
+ console.log('✓ 字符串(abc):', validate(schema2, { value: 'abc' }).valid);
30
+ console.log('✓ 数字(50):', validate(schema2, { value: 50 }).valid);
31
+ console.log('✗ 字符串太短(ab):', validate(schema2, { value: 'ab' }).valid);
32
+ console.log('✗ 数字超范围(101):', validate(schema2, { value: 101 }).valid);
33
+
34
+ // ========== 示例3:使用插件自定义类型 ==========
35
+ console.log('\n【示例3】使用插件自定义类型');
36
+
37
+ // 加载custom-format插件
38
+ const customFormatPlugin = require('../plugins/custom-format');
39
+ const pluginManager = new PluginManager();
40
+ pluginManager.register(customFormatPlugin);
41
+ pluginManager.install(require('../index'));
42
+
43
+ const schema3 = dsl({
44
+ contact: 'types:email|phone-cn|qq!'
45
+ });
46
+
47
+ console.log('✓ 邮箱:', validate(schema3, { contact: 'user@example.com' }).valid);
48
+ console.log('✓ 手机号:', validate(schema3, { contact: '13800138000' }).valid);
49
+ console.log('✓ QQ号:', validate(schema3, { contact: '10000' }).valid);
50
+ console.log('✗ 无效格式:', validate(schema3, { contact: 'invalid' }).valid);
51
+
52
+ // ========== 示例4:复杂场景 - 用户注册表单 ==========
53
+ console.log('\n【示例4】实际场景:用户注册表单');
54
+
55
+ const registerSchema = dsl({
56
+ username: 'string:3-20!',
57
+ password: 'string:8-20!',
58
+ contact: 'types:email|phone-cn!', // 邮箱或手机号
59
+ age: 'types:integer:1-150|null', // 年龄或null
60
+ referralCode: 'types:string:6|null' // 推荐码(6位)或null
61
+ });
62
+
63
+ const testData = {
64
+ username: 'john_doe',
65
+ password: 'Pass1234',
66
+ contact: 'john@example.com',
67
+ age: 25,
68
+ referralCode: 'ABC123'
69
+ };
70
+
71
+ const result = validate(registerSchema, testData);
72
+ console.log('✓ 完整表单验证:', result.valid);
73
+
74
+ console.log('\n' + '='.repeat(60));
75
+ console.log('示例执行完成!');
76
+ console.log('='.repeat(60));
77
+