Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/api-reference/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ Entry point for creating schemas. See [Schema Types](../core-concepts/schemas.md
- `Ack.boolean()`: Creates a `BooleanSchema` for validating booleans.
- `Ack.list(AckSchema itemSchema)`: Creates a `ListSchema` for validating arrays.
- `Ack.object(Map<String, AckSchema> properties)`: Creates an `ObjectSchema` for validating objects.
- `Ack.enumValues(List<T> values)`: Creates an `EnumSchema` for validating enum values.
- `Ack.enumString(List<String> values)`: Creates a string schema that only accepts specific values.
- `Ack.enumValues(List<T> values)`: Creates an `EnumSchema<T>` for Dart enum types. Accepts enum instances, string names, or indices. **Preferred over `enumString` when a Dart enum exists.**
- `Ack.enumString(List<String> values)`: Creates a `StringSchema` constrained to the given values. For ad-hoc string lists without a backing Dart enum.
- `Ack.anyOf(List<AckSchema> schemas)`: Creates an `AnyOfSchema` for union types.
- `Ack.any()`: Creates an `AnySchema` that accepts any value.
- `Ack.discriminated({required String discriminatorKey, required Map<String, AckSchema<Map<String, Object?>>> schemas})`: Creates a discriminated union schema.
Expand Down
3 changes: 2 additions & 1 deletion docs/core-concepts/schemas.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ final dateSchema = Ack.string().date(); // YYYY-MM-DD
final datetimeSchema = Ack.string().datetime(); // ISO 8601

// Enum values
final roleSchema = Ack.string().enumString(['admin', 'user', 'guest']);
enum Role { admin, user, guest }
final roleSchema = Ack.enumValues(Role.values);
```

### Number
Expand Down
2 changes: 1 addition & 1 deletion docs/core-concepts/typesafe-schemas.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ After running `dart run build_runner build`, the part file contains:
- `Ack.object(...)`
- Primitive schemas (`Ack.string`, `Ack.integer`, `Ack.double`, `Ack.boolean`)
- Lists of supported schemas (`Ack.list(...)`)
- Literal/enum helpers (`Ack.literal`, `Ack.enumString`, `Ack.enumValues`)
- Literal/enum helpers (`Ack.literal`, `Ack.enumValues`, `Ack.enumString`)

Unsupported helpers include `Ack.any`, `Ack.anyOf`, and `Ack.discriminated`.
Use `@AckModel` for discriminated unions instead.
Expand Down
2 changes: 1 addition & 1 deletion docs/core-concepts/validation.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ Ack.string().ipv6()


### `enumString(List<String> allowedValues)`
Requires the value to be one of `allowedValues`.
Requires the value to be one of `allowedValues`. Use this only for ad-hoc string lists. When a Dart enum exists, prefer `Ack.enumValues(MyEnum.values)` for type-safe validation.
```dart
Ack.enumString(['active', 'inactive', 'pending'])
```
Expand Down
16 changes: 6 additions & 10 deletions docs/guides/common-recipes.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -99,20 +99,16 @@ final postSchema = Ack.object({

## Enum Validation

Validate string values against allowed options:
Validate values against a set of allowed options using Dart enums:

```dart
// Status with specific allowed values
enum OrderStatus { pending, processing, shipped, delivered, cancelled }
enum Priority { low, medium, high }

final orderSchema = Ack.object({
'orderId': Ack.string(),
'status': Ack.string().enumString([
'pending',
'processing',
'shipped',
'delivered',
'cancelled',
]),
'priority': Ack.string().enumString(['low', 'medium', 'high']),
'status': Ack.enumValues(OrderStatus.values),
'priority': Ack.enumValues(Priority.values),
});

// Usage
Expand Down
4 changes: 2 additions & 2 deletions docs/guides/json-schema-integration.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ final userSchema = Ack.object({
'id': Ack.integer().positive().describe('Unique user identifier'),
'name': Ack.string().minLength(2).maxLength(50).describe('User\'s full name'),
'email': Ack.string().email().describe('User\'s email address'),
'role': Ack.enumString(['admin', 'user', 'guest']).withDefault('user'),
'role': Ack.enumValues(UserRole.values).withDefault(UserRole.user),
'isActive': Ack.boolean().withDefault(true),
'tags': Ack.list(Ack.string()).unique().describe('List of user tags').nullable(),
'age': Ack.integer().min(0).max(120).nullable().describe('User\'s age'),
Expand Down Expand Up @@ -217,7 +217,7 @@ Schemas with default values will include them in the generated JSON Schema:

```dart
final configSchema = Ack.object({
'theme': Ack.enumString(['light', 'dark']).withDefault('light'),
'theme': Ack.enumValues(Theme.values).withDefault(Theme.light),
'notifications': Ack.boolean().withDefault(true),
'maxItems': Ack.integer().min(1).max(100).withDefault(10),
});
Expand Down
19 changes: 9 additions & 10 deletions llms.txt
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ Ack.list(itemSchema) // ListSchema<T>
Ack.discriminated(discriminatorKey: ..., schemas: {...}) // DiscriminatedObjectSchema
Ack.anyOf([schema1, schema2]) // AnyOfSchema

// Enum schemas
Ack.enumString(['val1', 'val2']) // StringSchema with enum constraint
Ack.enumValues(MyEnum.values) // EnumSchema<T>
// Enum schemas (prefer enumValues when a Dart enum exists)
Ack.enumValues(MyEnum.values) // EnumSchema<T> - type-safe, preferred
Ack.enumString(['val1', 'val2']) // StringSchema with enum constraint (ad-hoc string lists only)
Ack.literal('exactValue') // StringSchema matching exact value

// Date/Time schemas (with transformation)
Expand All @@ -72,7 +72,7 @@ final userSchema = Ack.object({
'name': Ack.string().minLength(2).maxLength(50),
'email': Ack.string().email(),
'age': Ack.integer().min(0).max(120).optional(),
'role': Ack.enumString(['admin', 'user', 'guest']),
'role': Ack.enumValues(UserRole.values),
'active': Ack.boolean(),
});
```
Expand Down Expand Up @@ -116,7 +116,7 @@ Ack.string()
.email() // Email format validation
.url() // URL format validation
.matches(r'^[A-Z]+$') // Custom regex pattern
.enumString(['a', 'b']) // Allowed values
.enumString(['a', 'b']) // Allowed string values (prefer Ack.enumValues for Dart enums)
.literal('exact') // Exact value match
```

Expand Down Expand Up @@ -146,7 +146,7 @@ Ack.list(Ack.string())
### Default Values

```dart
'status': Ack.enumString(['draft', 'published']).withDefault('draft'),
'status': Ack.enumValues(Status.values).withDefault(Status.draft),
'count': Ack.integer().withDefault(0),
```

Expand Down Expand Up @@ -236,8 +236,7 @@ class User {
@Max(150)
final int? age;

@EnumString(['admin', 'user', 'guest'])
final String role;
final UserRole role; // Dart enum fields generate Ack.enumValues automatically

@Pattern(r'^[A-Z]{2}-\d{4}$')
final String code;
Expand All @@ -250,7 +249,7 @@ class User {
// 'username': Ack.string().minLength(3).maxLength(50),
// 'email': Ack.string().email(),
// 'age': Ack.integer().min(0).max(150).optional().nullable(),
// 'role': Ack.string().enumString(['admin', 'user', 'guest']),
// 'role': Ack.enumValues(UserRole.values),
// 'code': Ack.string().matches(r'^[A-Z]{2}-\d{4}$'),
// });
```
Expand Down Expand Up @@ -721,7 +720,7 @@ dart run build_runner build --delete-conflicting-outputs
| `@Email()` | Email format validation | `@Email()` |
| `@Url()` | URL format validation | `@Url()` |
| `@Pattern(regex)` | Custom regex pattern | `@Pattern(r'^[A-Z]+$')` |
| `@EnumString([...])` | Allowed string values | `@EnumString(['a', 'b'])` |
| `@EnumString([...])` | Allowed string values (prefer Dart enum fields instead) | `@EnumString(['a', 'b'])` |

### Numeric Constraints

Expand Down
Loading