Skip to content

Commit 080bdd8

Browse files
committed
feat: migrate handlers to dedicated classes
1 parent 72e4848 commit 080bdd8

28 files changed

+1199
-629
lines changed

lib/src/contracts/rule.dart

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1-
abstract interface class VineRuleValidator<T extends Object> {
2-
void handle(T value);
1+
import 'package:vine/src/contracts/vine.dart';
2+
3+
abstract interface class VineRule {
4+
void handle(VineValidationContext ctx, FieldContext field);
35
}

lib/src/contracts/schema.dart

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,16 @@ abstract interface class VineArray implements VineSchema, BasicSchema<VineArray>
450450
/// vine.array().fixedLength(5, message: 'The value must have exactly 5 items');
451451
/// ```
452452
VineArray fixedLength(int value, {String? message});
453+
454+
/// Check if values in the array are unique [message] the error message to display
455+
/// ```dart
456+
/// vine.array().unique();
457+
/// ```
458+
/// You can specify a custom error message
459+
/// ```dart
460+
/// vine.array().unique(message: 'The values must be unique');
461+
/// ```
462+
VineArray unique({String? message});
453463
}
454464

455465
abstract interface class VineUnion implements VineSchema, BasicSchema<VineUnion> {}

lib/src/field_pool.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import 'package:vine/vine.dart';
44

55
class FieldPool {
66
static final _pool = Queue<Field>();
7-
static final int _maxSize = 100;
7+
static final int _maxSize = 1000;
88

99
static Field acquire(String name, dynamic value) {
1010
if (_pool.isEmpty) return Field(name, value);

lib/src/rule_parser.dart

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,24 @@ import 'dart:collection';
22

33
import 'package:vine/src/contracts/vine.dart';
44
import 'package:vine/src/rules/basic_rule.dart';
5+
import 'package:vine/vine.dart';
56

67
abstract interface class RuleParserContract {
7-
Queue<ParseHandler> get rules;
8-
void addRule(ParseHandler rule, {bool positioned = false});
8+
Queue<VineRule> get rules;
9+
void addRule(VineRule rule, {bool positioned = false});
910
}
1011

1112
class RuleParser implements RuleParserContract {
1213
@override
13-
Queue<ParseHandler> rules;
14+
Queue<VineRule> rules;
1415

1516
bool isNullable = false;
1617
bool isOptional = false;
1718

1819
RuleParser(this.rules);
1920

2021
@override
21-
void addRule(ParseHandler rule, {bool positioned = false}) {
22+
void addRule(VineRule rule, {bool positioned = false}) {
2223
if (positioned) {
2324
rules.addFirst(rule);
2425
return;
@@ -29,16 +30,16 @@ class RuleParser implements RuleParserContract {
2930

3031
FieldContext parse(VineValidationContext ctx, FieldContext field) {
3132
if (isNullable) {
32-
addRule(nullableRuleHandler, positioned: true);
33+
addRule(VineNullableRule(), positioned: true);
3334
}
3435

3536
if (isOptional) {
36-
addRule(optionalRuleHandler, positioned: true);
37+
addRule(VineOptionalRule(), positioned: true);
3738
}
3839

3940
while(rules.isNotEmpty) {
4041
final rule = rules.removeFirst();
41-
rule(ctx, field);
42+
rule.handle(ctx, field);
4243

4344
if (!field.canBeContinue) break;
4445
if (ctx.errorReporter.hasErrorForField(field.name)) break;

lib/src/rules/any_rule.dart

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1+
import 'package:vine/src/contracts/rule.dart';
12
import 'package:vine/src/contracts/vine.dart';
23

3-
void anyRuleHandler(VineValidationContext ctx, FieldContext field) {
4-
4+
final class VineAnyRule implements VineRule {
5+
@override
6+
void handle(VineValidationContext ctx, FieldContext field) {}
57
}

lib/src/rules/array_rule.dart

Lines changed: 92 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,119 @@
1+
import 'package:vine/src/contracts/rule.dart';
12
import 'package:vine/src/contracts/schema.dart';
23
import 'package:vine/src/contracts/vine.dart';
34
import 'package:vine/src/field_pool.dart';
45
import 'package:vine/src/rule_parser.dart';
56

6-
void arrayRuleHandler(VineValidationContext ctx, FieldContext field, VineSchema schema) {
7-
final copy = field.customKeys;
7+
final class VineArrayRule implements VineRule {
8+
final VineSchema schema;
89

9-
if (field.value case List values) {
10-
final currentSchema = schema as RuleParser;
11-
final copyRules = currentSchema.rules.toList();
10+
const VineArrayRule(this.schema);
1211

13-
for (int i = 0; i < values.length; i++) {
14-
final currentField = FieldPool.acquire(field.name, values[i]);
12+
@override
13+
void handle(VineValidationContext ctx, FieldContext field) {
14+
final copy = field.customKeys;
1515

16-
currentSchema.rules.clear();
17-
currentSchema.rules.addAll(copyRules);
16+
if (field.value case List values) {
17+
final currentSchema = schema as RuleParser;
18+
final copyRules = currentSchema.rules.toList();
1819

19-
currentField.customKeys.add(i.toString());
20-
schema.parse(ctx, currentField);
20+
for (int i = 0; i < values.length; i++) {
21+
final currentField = FieldPool.acquire(field.name, values[i]);
2122

22-
currentField.customKeys
23-
..clear()
24-
..addAll(copy);
23+
currentSchema.rules.clear();
24+
currentSchema.rules.addAll(copyRules);
2525

26-
currentField.mutate([...field.value, currentField.value]);
27-
FieldPool.release(currentField);
26+
currentField.customKeys.add(i.toString());
27+
schema.parse(ctx, currentField);
28+
29+
currentField.customKeys
30+
..clear()
31+
..addAll(copy);
32+
33+
currentField.mutate([...field.value, currentField.value]);
34+
FieldPool.release(currentField);
35+
}
36+
37+
return;
2838
}
2939

30-
return;
40+
final error = ctx.errorReporter.format('array', field, null, {});
41+
ctx.errorReporter.report('array', [...field.customKeys, field.name], error);
3142
}
43+
}
44+
45+
final class VineArrayUniqueRule implements VineRule {
46+
final String? message;
3247

33-
final error = ctx.errorReporter.format('array', field, null, {});
34-
ctx.errorReporter.report('array', [...field.customKeys, field.name], error);
48+
const VineArrayUniqueRule(this.message);
49+
50+
@override
51+
void handle(VineValidationContext ctx, FieldContext field) {
52+
if (field.value is! List) {
53+
final error = ctx.errorReporter.format('array.unique', field, message, {});
54+
ctx.errorReporter.report('array.unique', [...field.customKeys, field.name], error);
55+
return;
56+
}
57+
58+
final values = field.value as List;
59+
final unique = values.toSet().toList();
60+
61+
if (values.length != unique.length) {
62+
final error = ctx.errorReporter.format('array.unique', field, message, {});
63+
ctx.errorReporter.report('array.unique', [...field.customKeys, field.name], error);
64+
}
65+
}
3566
}
3667

37-
void arrayMinLengthRuleHandler(VineValidationContext ctx, FieldContext field, int minValue, String? message) {
38-
if ((field.value as List).length < minValue) {
39-
final error = ctx.errorReporter.format('array.minLength', field, message, {
40-
'min': minValue,
41-
});
68+
final class VineArrayMinLengthRule implements VineRule {
69+
final int minValue;
70+
final String? message;
71+
72+
const VineArrayMinLengthRule(this.minValue, this.message);
73+
74+
@override
75+
void handle(VineValidationContext ctx, FieldContext field) {
76+
if ((field.value as List).length < minValue) {
77+
final error = ctx.errorReporter.format('array.minLength', field, message, {
78+
'min': minValue,
79+
});
4280

43-
ctx.errorReporter.report('array.minLength', [...field.customKeys, field.name], error);
81+
ctx.errorReporter.report('array.minLength', [...field.customKeys, field.name], error);
82+
}
4483
}
4584
}
4685

47-
void arrayMaxLengthRuleHandler(VineValidationContext ctx, FieldContext field, int maxValue, String? message) {
48-
if ((field.value as List).length > maxValue) {
49-
final error = ctx.errorReporter.format('array.maxLength', field, message, {
50-
'max': maxValue,
51-
});
86+
final class VineArrayMaxLengthRule implements VineRule {
87+
final int maxValue;
88+
final String? message;
89+
90+
const VineArrayMaxLengthRule(this.maxValue, this.message);
5291

53-
ctx.errorReporter.report('array.maxLength', [...field.customKeys, field.name], error);
92+
@override
93+
void handle(VineValidationContext ctx, FieldContext field) {
94+
if ((field.value as List).length > maxValue) {
95+
final error = ctx.errorReporter.format('array.maxLength', field, message, {
96+
'max': maxValue,
97+
});
98+
99+
ctx.errorReporter.report('array.maxLength', [...field.customKeys, field.name], error);
100+
}
54101
}
55102
}
56103

57-
void arrayFixedLengthRuleHandler(VineValidationContext ctx, FieldContext field, int count, String? message) {
58-
if ((field.value as List).length != count) {
59-
final error = ctx.errorReporter.format('array.fixedLength', field, message, {
60-
'length': count,
61-
});
62-
ctx.errorReporter.report('array.fixedLength', [...field.customKeys, field.name], error);
104+
final class VineArrayFixedLengthRule implements VineRule {
105+
final int count;
106+
final String? message;
107+
108+
const VineArrayFixedLengthRule(this.count, this.message);
109+
110+
@override
111+
void handle(VineValidationContext ctx, FieldContext field) {
112+
if ((field.value as List).length != count) {
113+
final error = ctx.errorReporter.format('array.fixedLength', field, message, {
114+
'length': count,
115+
});
116+
ctx.errorReporter.report('array.fixedLength', [...field.customKeys, field.name], error);
117+
}
63118
}
64119
}

0 commit comments

Comments
 (0)