ack 2.0.0-beta.3
ack: ^2.0.0-beta.3 copied to clipboard
Schema validation and bidirectional codecs for Dart and Flutter
2.0.0-beta.3 #
Breaking #
- Breaking: Require Dart
>=3.13.0(Flutter>=3.47.0, which bundles Dart 3.13.0). Dart 3.13 adds the primary constructors that the class-first examples use. Apps on Flutter 3.41 to 3.46 cannot use Ack 2.0.
Added #
- Add top-level rule annotations:
Is…says what a value is andHas…says a bound or property it has.@IsOptional,@IsRequired,@IsNotNull,@HasMin,@HasMax,@IsMultipleOf,@IsPositive,@IsNegative,@HasMinLength,@HasMaxLength,@HasMatch,@IsNotEmpty,@IsEmail,@IsUrl,@IsUri,@IsUuid,@IsDate,@IsDateTime,@IsIp,@HasMinItems,@HasMaxItems, and@HasUniqueItemskeep the semantics of the matchingValidateconstructors.ipv4()andipv6()become@IsIp(version: 4)and@IsIp(version: 6).
Deprecated #
- Deprecate
Validate, including the class. Each constructor redirects to its rule annotation and names that replacement.kindandvaluestay visible on those rules untilValidateis removed before Ack 2.0.0.
2.0.0-beta.2 #
Breaking #
- Breaking: Object property defaults now fill omitted keys. A present JSON
nullis rejected unless the property accepts null; use.nullable().withDefault(value)to parse a present null as the default. Direct parsing with a defaulted schema still resolvesparse(null). - Breaking: Object encoding substitutes the validated, encoded default for missing or null defaulted fields. Nullable fields without defaults retain their existing null behavior.
- Breaking:
ConstraintError,DurationConstraint,AckException,Ok, andFailare nowfinal, so code outside Ack can no longer implement or extend them.
Fixed #
- Validate nested objects as they encode, avoiding repeated subtree checks between directly nested objects while observing nested changes made by earlier sibling encoders.
- Build imported schema locations from shared pointer segments, avoiding repeated ancestor-string copies during deeply nested compilation.
- Reuse the standard meta-schema index across imports while keeping compiled references and format assertions isolated to each schema.
- Deduplicate imported enum values with JSON equality and hashing, preserving first occurrences while keeping compilation linear in enum size.
- Check IDNA label-wide contextual rules in one pass, avoiding repeated scans for Japanese-script presence and mixed Arabic digit families. Encoded label length is still checked after punycode conversion.
- Reject malformed supplementary punycode input as a format failure during parsing and encoding instead of allowing decoder range errors to escape.
- Keep generated field defaults separate from defaults inside custom schemas; exported properties reflect the field's own presence and default policy.
- Apply IDNA ContextO rules using Unicode Script properties, including supplementary Han and Katakana extensions while excluding Common and Inherited characters from the Japanese-script condition.
- Validate internationalized hostname and email labels against the complete IANA IDNA2008 repertoire pinned to Unicode 12.0.0, rejecting disallowed and unassigned code points with matching Unicode contextual and Bidi data.
- Enforce RFC 5892 ContextJ using Unicode joining types and Virama data, including transparent marks in internationalized hostname and email labels.
- Enforce RFC 5893 Bidi rules using Unicode classes for internationalized hostnames and email domains, including decoded punycode labels.
- Preserve nested resource dialects for JSON pointers targeting schemas in extension containers, matching resource URI references during parse and encode.
- Reject a second unescaped fragment delimiter in URI and IRI formats.
- Accept colons in relative URI and IRI queries, fragments, and later path segments while rejecting them in a relative first path segment.
- Enforce RFC 3987 Unicode ranges for IRI format assertions, allowing private-use code points only in queries and rejecting forbidden code points.
- Accept line terminators in relative JSON pointer reference tokens.
- Validate plain ASCII hostname labels under RFC 1123, allowing internal double hyphens while retaining IDNA checks for internationalized labels.
2.0.0-beta.1 #
Breaking #
- Restrict
Ack.preserveBoundaryto JSON-object schemas (AckSchema<JsonMap, R>), such as objects, maps, discriminated unions, and lazy, default, or codec wrappers over them.BoundarySchemano longer takes a type argument. Compose list wire views asAck.list(X.wireSchema), and use a codec's input schema, such asAck.string().datetime(), for a scalar. - Return a detached, recursively unmodifiable copy of the input map from
BoundarySchemaparse, runtime validation, and encode instead of the caller's map instance.
Fixed #
- Accept union-owned discriminators in strict map-backed codec outputs while preserving declared discriminator rules and rejecting unrelated extra keys. Already-permissive intermediate outputs retain their policies and values. Lazy outputs preserve round trips, deferred resolution and recursion limits.
- Expose the shared
deepUnmodifiableCopyhelper for generated immutable constructors. It snapshots nested collections without validating data or changing opaque noncollection objects. - Honor explicit boundary-wrapper nullability consistently during parse and encode. Preserve non-null restrictions on wrappers and lazy references when exporting nullable primitives, unions, and imported JSON Schema resources.
- Validate discriminated codec output against its selected map branch or a matching typed runtime branch, including required fields and refinements, without decoding runtime values again or adding encode callback passes.
- Reject duration millisecond inputs that overflow the platform's
Durationrepresentation instead of silently decoding to a different duration. - Respect custom JSON Schema vocabularies during import and export: keep inactive keywords inert, preserve annotation payloads and explicit format assertions, and apply fluent nullability under an active assertion dialect. Identical caller-supplied standard meta-schemas can replace offline fallbacks without relaxing duplicate-ID checks between caller resources.
- Discover selected custom dialects bundled beneath their own active schema keywords, without interpreting inactive keyword payloads or annotation data as schemas.
- Return the same JSON from
BoundarySchemafor every string-keyed map container, includingjsonDecodeoutput, without running an encoder. Nested codec values keep their wire form, one-way transforms no longer reject valid input, and wrapped defaults are not injected. - Validate
BoundarySchemavalues with parse semantics during encode and runtime validation, so encode no longer accepts a value that parse rejects. - Return a schema that is already a wire view from
Ack.preserveBoundaryunchanged instead of validating its values twice. - Export a wrapper's non-null restriction as
allOf: [{not: {type: null}}]only when the narrowed schema can still acceptnull.
2.0.0-alpha.1 #
Breaking #
- Remove legacy 1.x generator annotations (
@AckType,@AckInfer,@AckModel,@AckField,JsonKeyCaseStyle,AckFieldPresence, and@Schemable.generatedJson). Use@Schemable()on both top-level schemas and hand-written classes/unions (#188,#189). - Remove top-level presence annotations (
@Optional,@Required,@NotNull), the 18@Deprecated1.x top-level constraint classes (@Min,@Max,@MultipleOf,@Positive,@Negative,@MinLength,@MaxLength,@Matches,@NotEmpty,@Email,@Url,@Uuid,@Date,@DateTime,@Uri,@Ip,@Ipv4,@Ipv6,@MinItems,@MaxItems,@UniqueItems), andpackage:ack/format_annotations.dartin favor of@Validate.*(#191). - Remove
Ack.enumCodecin favor ofAck.enumValuesand remove unusedStandardSchemaV1(#129). - Seal
SchemaErrorandAckSchemaso pattern matching across all error and schema subtypes is exhaustive without a wildcard branch. - Rethrow programmer
Errors (TypeError,StateError, etc.) with their original stack trace duringCodecSchemadecode (parse/safeParse), matchingencode/safeEncode(#163). Ack.fromJsonSchema()now defaults toassertFormats: falseto match JSON Schema Draft 2020-12's default Core/Applicator/Validation vocabularies; passassertFormats: true(or declare theformat-assertionvocabulary in$vocabulary) to enforce format assertions (#171,#186).schema.toJsonSchema()andschema.toSchemaModel()now preserve imported Draft 2020-12 resources by default ($defs,$dynamicRef,unevaluatedProperties,prefixItems, etc.). UsetoJsonSchemaDraft7()ortoSchemaModelDraft7()for legacy Draft-07definitionslowering (#171).
Added #
- Add unified
@Validate.*presence and constraint annotation namespace (final class Validate, including@Validate.optional(),@Validate.required(), and@Validate.notNull()) exported from bothpackage:ack/ack.dartandpackage:ack/annotations.dart(#191). - Add
sealed class JsonMaybe<T>(JsonAbsent<T>,JsonValue<T>) withJsonMaybe.absent(),JsonMaybe.value(T? value), andJsonMaybe.nullValue()for PATCH tri-state presence (#148). - Add
@Schemable(schemas: [...])(supported on classes, sealed unions, andlibrary;directives) and@AckKey('...')for custom schema registration and field wire-name overrides (#185,#189). - Make
.trim(),.toLowerCase(), and.toUpperCase()two-way normalizers directly onStringSchemathat execute in declaration order alongside constraints during bothparseandencode, preserveStringSchemachaining, and export astype: 'string'without'x-transformed': true. - Support the complete JSON Schema Draft 2020-12 validation runtime in
Ack.fromJsonSchema(), including$dynamicRef,$dynamicAnchor,unevaluatedProperties,unevaluatedItems,prefixItems,dependentRequired,dependentSchemas,patternProperties,minContains,maxContains, bundled offline 2020-12 meta-schemas, and the full Draft 2020-12 format suite (#171,#186).
Fixed #
- Explicit Draft-7 export (
toJsonSchemaDraft7()/toSchemaModelDraft7()) rejects unsupported Draft 2020-12 assertions rather than emitting keywords that Draft-7 validators ignore. - Imported schema exports preserve JSON Pointer targets through retrieval URI aliases and opt-in format assertions in nested resources.
- Composed imports share identical identified resources, retain occurrence-level
nullability and constraints (including source
allOfwhen layering conflicting constraints), and reject conflicting resource definitions.
1.7.0 #
Breaking #
- Remove
ack_annotations; annotations now ship inack:package:ack/ack.dartexports@Schemable()and core model annotations (AckField,Optional,Required,NotNull,AckCaseStyle,AckUnknownPropertyPolicy).package:ack/annotations.dartexports model and constraint annotations (plus deprecated aliases).package:ack/format_annotations.dartexports string format annotations.
- Rename
@Patternto@Matches(Patternremains a deprecated alias inpackage:ack/annotations.dart). - Remove the
json_annotationdependency andJsonKeyre-export fromack. - Compile imported JSON Schema
patternexpressions in ECMA-262 Unicode mode (u). Invalid Unicode-mode patterns (such as\-outside a character class) now fail import withinvalid_schema. NativeAck.string().matches()retains Dart regex semantics.
Added #
- Add
@Schemable()as the unified annotation for schema-first and class-first code generation,AckModelAdapter.modelSchema, andCodecSchema.canEncode. - Expand
Ack.fromJsonSchema()with:contains,if/then/else, andmultipleOf(sharing exact decimal division with native.multipleOf()).- Built-in string formats (
date-time,date,email,uuid,uri,ipv4,ipv6) and numeric formats (int32,int64,uint32,uint64,float,double). x-*vendor extension annotations (includingx-transformed) and Draft-07$schemaURIs.
- Add
JsonSchemaValidationError(keyword,keywordLocation,documentUri,pointer) for imported JSON Schema validation failures.
Changed #
- Speed up
safeParse,safeEncode,toJsonSchema(), imported JSON Schema compilation/validation, andAck.object()/Ack.list()/Ack.map()unmodifiable result views.
Fixed #
- Accept lowercase
tandzon announced leap seconds in RFC 3339 date-time validation. - Percent-encode URI fragments in imported JSON Schema error locations and
report the array path on imported
uniqueItemsfailures.
Deprecated #
- Deprecate
@AckInfer()and@AckModel()in favor of@Schemable().
1.6.2 #
Fixed #
Ack.fromJsonSchema()now compiles thepatternkeyword, restoring import of schemas exported from Ack. It uses an unanchored ECMA-262 search on strings and rejects invalid regular expressions at import time.
Added #
Ack.fromJsonSchema()now accepts the standardpropertyNameskeyword to validate every key of an object instance against its subschema. Both keywords round-trip through the Draft-7 export unchanged, raising the pinned upstream conformance selection to 631 cases.
1.6.1 #
Fixed #
- Correct the
safeParseAsdocumentation: mapperExceptions becomeSchemaTransformErrorfailures, while mapperErrors are rethrown with their original stack trace (the documented behavior never matched the code). - Encode now honors effective nullability instead of a schema's own
isNullableflag. A union with a nullable branch, and anyDefaultSchema,BoundarySchema, or codec wrapping one, now encodesnullwherever it already parsednull: at the root, as an object property, and when nested in another union..transform(),.codec(), andAck.codec()no longer rejectnullon parse or encode when their input schema accepts it, which matches thetype: nullbranch their export already advertised.
Changed #
- An optional object property whose schema effectively accepts
nullnow encodes a presentnullas{"key": null}instead of omitting the key. A missing key is still omitted. Ack.list(...)now throws its existing "nullable item schemas"ArgumentErrorfor item schemas whose null acceptance was previously hidden behind a wrapper — a nested nullable union, or a codec,withDefault(...), orAck.preserveBoundary(...)over a nullable union.- A codec or
Ack.preserveBoundary(...)over a nullable union now exports an outer{"type": "null"}branch, matching thenullit accepts. The branch is redundant with the union's own nullable branch but remains valid Draft-7. - An
Errorthrown by an encoder now propagates out ofsafeEncodewith its original stack trace at every nesting level. Previously only a root codec rethrew: nested inAck.object,Ack.list,Ack.map, orAck.discriminatedtheErrorbecame aSchemaEncodeErrorfailure, and inAck.anyOfit was swallowed entirely so a later branch could returnok. A union no longer tries later branches once a branch encoder raises anError. To signal a value a codec cannot encode, throw anExceptionor express the rule with anoutput:schema; do not catchError. - Constraints added to a codec are no longer projected onto its exported wire
schema, because they validate runtime values the encoder may map to a
different shape — a seconds codec's
.min(Duration(seconds: 5))used to exportminimum: 5000while encoding5. They are still enforced at runtime, and the export now carries acodec_runtime_constraint_not_exportedwarning naming the omitted constraint keys. Move rules the wire should advertise onto the input schema (Ack.string().minLength(5).codec(...)).Ack.duration().min()/.max()still exportminimum/maximumin milliseconds.
1.6.0 #
Added #
- Add strict
Ack.fromJsonSchema()returningAckSchema<Object, Object>for a documented draft 2020-12 subset. The runtime implementation is internal; failures expose immutable diagnostics throughJsonSchemaImportException. Supports supplied reference bundles, recursion, JSON-specific null/presence semantics, and exactallOf,oneOf, andnotcomposition. Exports are self-contained and reflect only enforced assertions. - Verify imports against 600 pinned upstream JSON Schema cases and selected
A2UI v0.9 protocol schemas. Support catalog JSON Pointer targets outside
$defs, normalize enums for valid Draft-7 output, and report unsupported assertions only when they are reachable from the imported root.
Fixed #
- Reject conflicting bundle documents with the same resolved retrieval URI, including conflicting copies of the root document.
- Accept the draft 2020-12 meta-schema URI with an empty fragment (
#). - Reject generated-definition name collisions between imported schemas and
Ack.lazy()targets instead of exporting a reference to the wrong schema. - Report duplicate anchors at the conflicting
$anchorkeyword rather than at the enclosing resource identifier. - Correct the executable reference-bundle example in the JSON Schema guide.
- Preserve imported JSON Schema definitions without adding an import-specific
variant to the sealed
AckSchemaModelhierarchy. Imported roots use the existing composition and reference models.
1.5.0 #
Added #
- Add
Ack.map(valueSchema)andMapSchemafor JSON objects with arbitrary string keys whose values all match one schema. Values may benullonly when the value schema is nullable, soAck.map(Ack.any().nullable())models aJsonMap. JSON Schema export emitsadditionalProperties: <value schema>.
Changed #
Ack.any()parsing now returns a detached, recursively unmodifiable snapshot of the input instead of the caller's own object, matching the unmodifiable results ofAck.object()andAck.list(). Encoding still returns the validated runtime value unchanged.
1.4.0 #
Changed #
- Align with the coordinated Ack 1.4 release adding class-first field annotations; this package has no runtime or public API changes from 1.3.0.
1.3.0 #
Changed #
- Align with the coordinated Ack 1.3 release introducing
ack_mcp_dart; this package has no runtime or public API changes from 1.2.0.
1.2.0 #
Added #
- Add
AckModelAdapteras the non-nullable runtime bridge used by generated immutable Ack models. The adapter keeps schema parse/encode around model mapping so public JSON methods remain schema-backed. - Add
Ack.preserveBoundary, which validates through a schema while returning the original wire value instead of values decoded by nested codecs. - Add
deepUnmodifiableJsonMap, which creates detached, recursively unmodifiable snapshots of nested maps, lists, and sets without validation.
Fixed #
- Preserve propagated
Errorobjects during validation instead of converting programming defects into recoverable schema failures. - Compare collection contents independently of growable or unmodifiable wrapper
implementations. Numerically equal
intanddoublevalues now compare and hash equally on native and web runtimes; other scalar types remain distinct. - Keep deep map-key equality consistent with
deepHashCode, and apply JSON Schema Draft 7 numeric equality touniqueItems(including nested values). - Reject the native minimum integer from
.safe()without overflowingabs().
Changed #
- Export
deepEquals,deepHashCode, anddeepUnmodifiableJsonMapfor generated Ack data classes and class-first constructors. Ack.integer()accepts losslessly representable numbers with no fractional part and normalizes them toint.Ack.double()accepts exactly representable numeric inputs and normalizes them todouble. NumericanyOfbranches can therefore overlap; the first matching branch determines the runtime representation. UseAck.number()to preserve the input's numeric representation and.safe()to require JavaScript's portable integer range.- Raise the minimum Dart SDK to 3.9.
1.1.0 #
Fixed #
- Keep
safeParsenon-throwing when refinements or constraints throw recoverableExceptions, while preservingErrorvalues such asStateErrorso programming defects are not masked as validation failures. - Decode RFC 3339 lowercase
t/zseparators inAck.datetime(), which its own string validation already accepts (previously they failed at the decode step with a misleading "Codec decode failed" message). - Bound direct, indirect, wrapper-mediated, and fluent-copy lazy-schema alias recursion (previously unbounded and prone to stack overflow).
- Snapshot factory collections so a caller mutating the passed list or map can no longer corrupt a constructed schema.
- Correct behavior-based schema and deep-collection equality.
Behavior changes #
No public API changed (verified with dart_apitool against 1.0.1); the following
now reject inputs that previously passed or misbehaved silently.
- Validate numeric
multipleOf, IPv6, and RFC 3339 date-time values strictly. Announced leap seconds are preserved byAck.string().datetime()but rejected byAck.datetime(), where Dart cannot represent them. (migration: some previously-accepted strings and numbers now fail validation.) - Reject invalid constraint configuration at construction — negative
lengths/item counts, non-finite numeric bounds,
min > maxranges,multipleOf <= 0, empty unions, empty or duplicate enum inputs, and unions that can yield nullable list items — all throwArgumentError. (migration: fix the schema definition; put nullability on the list viaAck.list(item).nullable().) toJsonSchema()merges conflicting duplicate keywords intoallOfand emitsmin/maxItemsandmin/maxPropertiesfor exact counts. (migration: refresh snapshot or golden tests of exported schemas.)parse()throwsAckException— instead of the raw callback error — when a constraint or refinement throws.
1.0.1 #
- See release notes for details.
1.0.0 #
- See release notes for details.
1.0.0-beta.12 #
Breaking Changes #
DoubleSchemaandNumberSchemanow reject non-finite values (NaN,Infinity,-Infinity) during runtime validation by default, aligning numeric schemas with JSON-safe values.- Remove the retired JSON Schema DTO converter APIs.
- Replace the interim JSON Schema model kind API with sealed
AckSchemaModelvariants and canonicalAckSchema.toSchemaModel()adapter conversion.
Added #
Ack.enumCodec<T extends Enum>(List<T> values)returns aCodecSchema<String, T>wrappingEnumSchema<T>. Use this when downstream code expects every value-shape to be aCodecSchema(e.g. a registry of codecs). Decode/encode are identity sinceEnumSchemaalready maps betweenTand the enum's.name.NumberSchemaExtensionsadds fluent numeric constraints toAck.number():.min,.max,.greaterThan,.lessThan,.positive,.negative, and.multipleOf.
Changed #
- Project discriminated schemas through union-owned discriminator branches.
- Preserve defaults, const values, extension keywords, transformed metadata, composition, and JSON Schema constraints through the schema model boundary.
Migration #
- Re-run tests for code paths that parse or encode
double/numvalues. If a boundary must acceptNaNor infinities, model that value outside the JSON numeric schema path before validation.
1.0.0-beta.11 #
- See release notes for details.
1.0.0-beta.10 #
- See release notes for details.
1.0.0-beta.9 #
- See release notes for details.
1.0.0-beta.8 #
- See release notes for details.
1.0.0-beta.7 #
- See release notes for details.
1.0.0-beta.6 #
Features #
- Discriminated unions: Enforce Map-returning child schemas in discriminated unions (#67).
- Schema mapping API: Add
AckSchema.parseAsandAckSchema.safeParseAsfor validated-value mapping with consistentSchemaTransformErrorhandling.
Improvements #
- Schemas: Centralize null/default handling and extract ObjectSchema helpers (#65).
Bug Fixes #
- Schemas: Fixes to schema correctness including transformed schema defaults and list unique items constraint (#50).
1.0.0-beta.5 - 2026-01-14 #
1.0.0-beta.4 - 2025-12-29 #
Breaking Changes #
- Format metadata: Reduced built-in format guidance to 7 core formats (
email,uri,uuid,date,dateTime,ipv4,ipv6). Custom format strings are still supported via theformatproperty. withDescriptiondeprecated: Usedescribe()instead for setting schema descriptions.
Bug Fixes #
- JSON Schema output: Now correctly adds null branch to
anyOf/oneOfcompositions whennullable: true, producing valid JSON Schema Draft-07 format.
Improvements #
- DRY refactoring: Consolidated duplicate primitive schema parsers into one.
- Hardened schema type handling: Improved map validation and schema type handling.
- Consolidated JSON schema utilities: Reduced duplication across JSON schema utilities.
1.0.0-beta.3 - 2025-10-27 #
- See release notes for details.
1.0.0-beta.2 - 2025-10-09 #
- See release notes for details.
1.0.0-beta.1 - 2025-10-06 #
- See release notes for details.