dox_validation 3.1.2
dox_validation: ^3.1.2 copied to clipboard
Typed input for Dart. DTO classes with generated checks, fluent schemas like Zod, JSON Schema export and the Standard Schema interface.
3.1.2 #
- Docs: the dartdoc of
@OrDefaultsays that errors from@Unique,@Existsandvalidate()are not dropped. - New:
@Describe('...')on a DTO field. It setsdescriptionin the JSON Schema of the field. It does not change the checks. Needs a dox_builder that knows it.
3.1.1 #
- New:
@Dto(emptyStringsToNull: true)reads""asnull, like Laravel'sConvertEmptyStringsToNull. So{"note": ""}clears aMaybe<String?>field instead of counting as missing. Needs a dox_builder that knows it. - New:
@OrDefault()on a DTO field: a bad value (a type error or a failed rule) gives the default of the field, ornull, not an error. For query strings like?page=abc. Needs a dox_builder that knows it. - New:
hexColor()/@HexColor():#and 6 hex digits, like#1a2b3c.short: truealso takes#abc. - New:
DtoState.read(..., emptyToNull: true)andDtoState.dropIssuesAfter(count), used by the generated code.
3.1.0 #
-
Break:
IpRuleis no longer aRegexRule, soIpRule().patternis gone. -
v.string().ip()now accepts IPv6, like@Ip. Its JSON Schema is nowanyOfipv4andipv6(wasformat: ipv4). -
email()now accepts+and'before the@(likeann+tag@x.com), the same symbols as HTML5. -
alphaDash()now allows digits (post-123), like Laravelalpha_dash. The message text changed too. -
New Laravel-style rules. Each works in fluent schemas and as a DTO annotation, unless noted:
same('other')/@Same('other'): the value must equal another key in the same object.confirmed()/@Confirmed():<field>_confirmationmust have the same value.sameandconfirmedcompare the raw input of both keys, like Laravel. Text matches a number or a bool by text, both ways..optional().requiredIf('type', 'company')/@RequiredIf('type', 'company'): required when another key has a value. An enum value matches its name. Missing means: not there,null, blank text or an empty list..optional().requiredWith(['phone'])/@RequiredWith(['phone']): required when another key is present..nullable()afterrequiredIforrequiredWithkeeps the check. Before,nullpassed even when the rule applied. It looks through every wrapper, so.transform(...).nullable(),.defaultTo(...).nullable()and.nullable().nullable()keep the check too.requiredIfandrequiredWithread the other key after its own conversion, liketrim()andtoLowerCase(). This is the value the app gets. Before, they read the raw input, sotype: ' Company 'did not makevatrequired, but the app gottype == 'company'. When the other key fails its own check, the raw input is still used. In a fluent object, the keys with these rules are checked last, so the order of the keys does not matter. The output and the issues still come in the order of the shape. An object without these rules does no extra work. In a DTO, the other field must come before the field with the rule, because the generated code checks the fields in order.json()/@Json(): the text must be valid JSON.digits(6)/@Digits(6)anddigitsBetween(4, 6)/@DigitsBetween(4, 6): only digits, with this length.between(1, 10)onv.int()andv.num(). DTOs already have@Range(1, 10).dateFormat('Y-m-d')/@DateFormatted('Y-m-d'): a real date in this format. It knows the PHPdate()letters, likeM,D,AandU. Another letter throws anArgumentError; put\before it to use it as text. Like Laravel,j,n,g,G,zandUtake no leading zero.password(min: 8, letters: true, mixedCase: true, numbers: true, symbols: true)/@Password(...): a strong password. It does not check leaked passwords.exists('teams')andunique('users', column: 'email')onv.string(),v.int()andv.num(). They needparseAsync.uniqueneedscolumn:; it never uses the input key. The database decides what matches, also for a list, so on MySQLTAKEN@dox.devis taken whentaken@dox.devis there. A DTOListfield (andfailedItemsof the rules) is one query for the whole list: anexistsitem passes only when its exact text is found, and auniqueitem fails when a found row has its exact text. When a found row matches no item by its text (MySQL ignores case and trailing spaces), one query can not tell which item it was, so every item fails (the safe side).v.list(v.string().exists(...))still checks each item alone, so the database decides for each one. Limit long lists with.max(n)/@MaxItems. They ask aPresenceVerifier, whichdox_ormsets when the database starts. Table and column names are checked when the schema is built: the same plain names the dox_orm query builder takes, like2fa_codesorpublic.users. DTOs keep@Existsand@Uniquefromdox_orm.
-
@RequiredIfand@RequiredWithneed adox_builderthat knows them. -
RuleContext.sibling('key')reads another key of the same object. -
@Dto(messages:)matches the full dotted path first, like Laravel:tags.*.requiredfor list items, andaddress.city.requiredin the outer DTO for a field of a nested DTO. Then the last key (city.required), then the code (required), as before. -
New file rules, like Laravel:
v.file().maxSize(bytes)andminSize(bytes), and@MinSize('10KB'). Laravel counts KB; the fluent rules count bytes. The message shows a short size, like2MB.v.file().mimes([...]), the same check as@Mimes.v.file().mimeTypes(['image/png', 'image/*'])and@MimeTypes. The MIME type is checked against the real file bytes, not the content type the client sent. SVG is never part ofimage/*.v.file().dimensions(minWidth:, maxWidth:, minHeight:, maxHeight:, width:, height:, ratio:)and@Dimensions. It reads only the image header of PNG, GIF, WebP and JPEG files. Other files, and broken or cut short headers, fail.
-
ImageSize.read(head)gives the width and height from the first bytes of an image.FileTypes.matchesMimeTypesandFileTypes.extensionsOfturn MIME types into checked file types. -
FileInput.headmay hold more thanFileTypes.headSizebytes. A JPEG keeps its size after the photo metadata, sodimensionsneeds more bytes for it (seeImageSize.jpegHeadSize). -
@MinSize,@MimeTypesand@Dimensionsneed dox_builder 3.1.0 or newer. An older dox_builder skips them without an error, so they check nothing. -
dimensionson a JPEG needs dox_core 3.1.0 or newer. With an older dox_core,RequestFile.headhas only 32 bytes, so every JPEG failsdimensions. -
ip()and@Ipnow reject IPv4 addresses with leading zeros, like01.1.1.1. Laravel does the same. Some tools read010as octal (8), so these addresses are not what they look like.
3.0.0 #
- The first stable release.
- The package now lives in its own repo: dartondox/dox-validation. Nothing changes for users: same package name, same API.
3.0.0-rc.1 #
- Version bump only, to match the other packages.
3.0.0-alpha.17 #
- Version bump only, to match the other packages.
3.0.0-alpha.16 #
- Version bump only, to match the other packages.
3.0.0-alpha.15 #
- Version bump only, to match the other packages.
3.0.0-alpha.14 #
- Version bump only, to match the other packages.
3.0.0-alpha.13 #
- Version bump only, to match the other packages.
3.0.0-alpha.12 #
- Version bump only, to match the other packages.
3.0.0-alpha.11 #
- Version bump only, to match the other packages.
3.0.0-alpha.10 #
- Version bump only, to match the other packages.
3.0.0-alpha.9 #
- Version bump only, to match the other packages.
3.0.0-alpha.8 #
- Fix:
FileTypes.sniffread any data that starts withBMasbmp, like the text "BMW...". Now it also checks the BMP header size at byte 14 (12, 40, 52, 56, 64, 108 or 124).
3.0.0-alpha.7 #
- Perf: object, list, map and union schemas work out
isAsynconce and keep the answer. Before, the whole schema tree was walked on everyvalidateSchemacall. url()now allows onlyhttpandhttpslinks. Passschemesto allow others.- File type checks now also need the file name extension to fit the bytes. A
.htmlfile with GIF bytes no longer passes@Image. Only another known type (like.pngwith GIF bytes) or a type the browser runs (html,htm,xhtml,svg,xml,js,mjs) is refused. A file with no or an unknown extension (like a canvas upload namedblob) passes when the bytes match.
3.0.0-alpha.6 #
- Version bump only, to match the other packages.
3.0.0-alpha.5 #
- Version bump only, to match the other packages.
3.0.0-alpha.4 #
- Version bump only, to match the other packages.
3.0.0-alpha.3 #
- Version bump only, to match the other packages.
3.0.0-alpha.2 #
- A JSON body that is not an object now says
The request body must be a JSON object.(key_root). Change it with the message key_root.object. - Needs Dart 3.13 or newer.
- All dependencies updated to their latest versions.
- New: DTOs. A class with
@Dto()and rule annotations (@Length,@Email,@Min,@Regex,@MaxSize, ...).dox_builderwrites aconst DtoSchema<T>with the checks, a converter and the JSON Schema. See the Validation guide. - New:
DtoSchema<T>withvalidateMap,safeValidateMap,fromMap,toMapandtoJsonSchema. It is also aSchema<T>. - New:
Maybe<T>knows a missing key fromnull.DtoErrorsfor checks across fields invalidate(). - New:
FileTypesfinds the real type of a file from its first bytes.@Image()andv.file().image()do not allowsvg. - New:
MessageRequest.locale,ParseState.params. A message set on a rule is used as it is; the resolver only fills its placeholders. Rulehas aconstconstructor and afinalmessage, so a rule class works as an annotation.AsyncRule.failedItems()checks a list in one call.FileInputhaslengthandhead(the first bytes).Schemahas aconstconstructor. The fluent schemas extendBaseSchema.- Text length messages say "characters".
- Breaking: removed
v.fromRules(),v.registerRule(),RuleRegistry,RuleDefinition,CallbackRuleand all rule strings. Use a DTO, or aRule<T>class.
3.0.0-alpha.1 #
- First release of
dox_validation. - Fluent schema builder: string, int, num, bool, date, enum, literal, list, object, map, union, any, file.
optional,nullable,nullish,defaultTo,transform,refine,superRefine, async refinements.- Coercion with
v.coercefor query strings and form data. parse,safeParse,parseAsync,safeParseAsyncwith issue paths.- Standard Schema interface (
StandardSchema). - JSON Schema (draft 2020-12 / OpenAPI 3.1) export with
toJsonSchema(). - Custom
Ruleclasses and a globalMessageResolver. - Laravel style string rules with
v.fromRules().