# Ack > A schema validation library for Dart and Flutter with a fluent runtime API and `@AckType()`-driven extension-type generation. Version 1.0.0-beta.11. Ack validates external data with hand-written schemas built using the `Ack` factory. When you want typed wrappers over validated values, annotate top-level schema variables or getters with `@AckType()` and run `ack_generator`. ## Packages 1. `ack`: core runtime validation library 2. `ack_annotations`: exposes `@AckType()` 3. `ack_generator`: generates extension types for annotated top-level schemas 4. `ack_firebase_ai`: converts Ack schemas to Firebase AI structured-output schemas ## Core runtime usage ```dart import 'package:ack/ack.dart'; final userSchema = Ack.object({ 'name': Ack.string().minLength(2), 'email': Ack.string().email(), 'age': Ack.integer().min(0).optional(), }); final result = userSchema.safeParse({ 'name': 'Alice', 'email': 'alice@example.com', }); ``` ## AckType generation `@AckType()` is supported only on: - top-level schema variables - top-level schema getters It is not supported on classes or instance members. Example: ```dart import 'package:ack/ack.dart'; import 'package:ack_annotations/ack_annotations.dart'; part 'user_schema.g.dart'; @AckType() final addressSchema = Ack.object({ 'street': Ack.string(), 'city': Ack.string(), }); @AckType() final userSchema = Ack.object({ 'name': Ack.string(), 'address': addressSchema, }); ``` Generated capabilities: - `UserType.parse(data)` - `UserType.safeParse(data)` - typed getters such as `String get name` and `AddressType get address` ## Supported AckType schema shapes - `Ack.object(...)` - `Ack.string()` - `Ack.integer()` - `Ack.double()` - `Ack.boolean()` - `Ack.list(...)` - `Ack.literal(...)` - `Ack.enumString(...)` - `Ack.enumValues(...)` - explicit transforms such as `.transform(...)` - `Ack.discriminated(...)` with the constraints below Not supported for extension-type generation: - `Ack.any()` - `Ack.anyOf()` - transformed object schemas - transformed discriminated schemas ## Discriminated AckType schemas `Ack.discriminated(...)` works with `@AckType()` when: - the base schema is a top-level `@AckType()` declaration - `schemas` is a non-empty map literal - each branch is a top-level schema variable/getter reference - each branch is an `@AckType()` object schema - each branch is non-nullable - each branch is declared in the same library as the base - each branch defines the discriminator field with `Ack.literal(...)` - the literal value matches the branch key Example: ```dart @AckType() final catSchema = Ack.object({ 'type': Ack.literal('cat'), 'lives': Ack.integer(), }); @AckType() final dogSchema = Ack.object({ 'type': Ack.literal('dog'), 'breed': Ack.string(), }); @AckType() final petSchema = Ack.discriminated( discriminatorKey: 'type', schemas: { 'cat': catSchema, 'dog': dogSchema, }, ); ``` ## Resolution rules AckType generation is intentionally strict: - nested object fields must reference named top-level schemas - inline anonymous object schemas are rejected for typed generation - cross-file direct imports, prefixed imports, and re-exports are supported - unannotated object schema references fail generation instead of silently falling back to raw maps - circular schema alias/reference chains fail generation ## Runtime API reminders - `schema.parse(data)` throws on invalid input - `schema.safeParse(data)` returns `SchemaResult` - `SchemaResult.getOrThrow()` returns the validated value or throws `AckException` - `.optional()` allows a field to be omitted - `.nullable()` allows a present field to hold `null` - object schemas support `additionalProperties: true` ## Build command ```bash dart run build_runner build --delete-conflicting-outputs ```