Skip to content

Annotations

Each annotation adds one modifier to the validator the generator derives from the field type. Most have a class form that takes arguments and a lowercase constant for the no-argument case: @IsEmail() and @isEmail are the same.

Annotation Effect
@luthor Marks the class as a model. The generator emits the five generated items for it.
Annotation Constant Applies to Adds
@HasMin(n) String .min(n), a minimum length; n must be integral
@HasMin(n) int, double, num .min(n), a minimum value; integral for int
@HasMax(n) String .max(n), a maximum length
@HasMax(n) int, double, num .max(n), a maximum value
@HasLength(n) String .length(n)
@Contains(s) String .contains(s)
@StartsWith(s) String .startsWith(s)
@EndsWith(s) String .endsWith(s)
@MatchRegex(p, caseSensitive:, multiLine:, unicode:, dotAll:) String .regex(RegExp(p, ...))
@IsEmail() @isEmail String .email()
@IsUri(allowedSchemes:) @isUri String .uri()
@IsUrl(allowedSchemes:) @isUrl String .url()
@IsIp(version:) @isIp String .ip()
@IsUuid() @isUuid String .uuid()
@IsCuid() @isCuid String .cuid()
@IsCuid2() @isCuid2 String .cuid2()
@IsDateTime() @isDateTime String .dateTime(); DateTime fields get it without annotation
@IsEmoji() @isEmoji String .emoji()
@IsFile(accept:) @isFile any, including package classes such as MultipartFile Replaces the type’s validator with l.file(); on a List<X> field, accept receives the whole list
@WithCustomValidator(fn) any except Null .custom(fn)
@WithSchemaCustomValidator(fn) any except Null .customWithSchema(fn)
@luthorForwardRef a model type Deprecated. It has no effect, because every nested reference is already a forward reference. Remove it.

Every annotation except @luthor and @luthorForwardRef accepts message and messageBuilder, which pass through to the modifier. A messageBuilder has to be a top-level function or a static method. Message builders covers both.

Annotations may sit on the constructor parameter or on the field, including fields reached through super. parameters. Before 1.0 only parameters were read.

An annotation on a field type it does not apply to fails generation with an error naming the field. @HasMin(2) on a bool, @IsEmail on an int, and @HasLength on a List are errors, not silently ignored. A fractional @HasMin or @HasMax on an int or String field is also an error.

Functions passed to @WithCustomValidator, @WithSchemaCustomValidator and messageBuilder have to be top-level functions or static methods, and take the field’s type: bool isEven(int value), bool matchesPassword(String value, SchemaData data).

Modifiers are generated in the order the annotations are written. @HasMin(2) @HasMax(50) generates .min(2).max(50).

bool matchesPassword(String value, SchemaData data) =>
value == data['password'];
enum AccountType { personal, business }
@luthor
@freezed
abstract class SignUp with _$SignUp {
const factory SignUp({
@HasMin(2) @HasMax(50) required String name,
@IsEmail() required String email,
@HasMin(8) required String password,
@WithSchemaCustomValidator(matchesPassword, message: 'Passwords must match')
required String confirm,
@HasMin(18) int? age,
@IsUrl(allowedSchemes: ['https']) String? website,
@Default(AccountType.personal) AccountType accountType,
}) = _SignUp;
factory SignUp.fromJson(Map<String, dynamic> json) => _$SignUpFromJson(json);
}
lib/sign_up.g.dart
final SchemaValidator $SignUpSchema = l
.schema({
SignUpSchemaKeys.name: l.string().min(2).max(50).required(),
SignUpSchemaKeys.email: l.string().email().required(),
SignUpSchemaKeys.password: l.string().min(8).required(),
SignUpSchemaKeys.confirm: l
.string()
.customWithSchema(matchesPassword, message: "Passwords must match")
.required(),
SignUpSchemaKeys.age: l.int().min(18),
SignUpSchemaKeys.website: l.string().url(allowedSchemes: ["https"]),
SignUpSchemaKeys.accountType: l.oneOf(["personal", "business"]),
})
.withName("SignUp");
$SignUpValidate(input)+1-1
  1. valid: {'name': 'Ada', 'email': '[email protected]', 'password': 'hunter2hunter2', 'confirm': 'hunter2hunter2', 'website': 'https://ada.dev'}
  2. invalid: {'name': 'Ada', 'email': '[email protected]', 'password': 'hunter2hunter2', 'confirm': 'nope', 'website': 'http://ada.dev', 'accountType': 'team'}confirm: Passwords must matchwebsite: website must be a valid URL. Allowed scheme is httpsaccountType: accountType must be one of: personal, business