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
41 changes: 41 additions & 0 deletions CODE_OF_CONDUCT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Code of Conduct

## Our commitment

Ack's community is committed to a welcoming, respectful, and harassment-free
experience for everyone, regardless of background, identity, experience level,
or personal characteristics.

## Expected behavior

- Be kind, constructive, and specific when giving feedback.
- Assume good intent while taking responsibility for your impact.
- Respect differing viewpoints, boundaries, and levels of experience.
- Keep technical disagreements focused on the work.
- Protect private or sensitive information shared during a report.

## Unacceptable behavior

- Harassment, discrimination, threats, or personal attacks.
- Sexualized language, imagery, or unwelcome attention.
- Trolling, sustained disruption, or deliberately inflammatory comments.
- Publishing another person's private information without permission.
- Any conduct that would reasonably be considered inappropriate in a
professional community.

## Reporting and enforcement

If you experience or witness unacceptable behavior, report it privately to the
repository owner through the contact methods on their
[GitHub profile](https://github.com/btwld). Do not open a public issue for a
sensitive conduct report. If no private contact method is available, open an
issue that asks the owner to establish private contact, without including the
report details.

Maintainers will review reports fairly, protect the reporter's privacy as far as
possible, and may remove content, issue a warning, temporarily restrict
participation, or permanently ban a participant. Retaliation against anyone who
makes a good-faith report is not tolerated.

This policy applies in project spaces and when someone is publicly representing
the Ack community.
9 changes: 8 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# Contributing to Ack

Thanks for helping improve Ack. Keep changes focused, tested, and easy to
review.
review. By participating, you agree to follow the
[Code of Conduct](./CODE_OF_CONDUCT.md).

## Development setup

Expand Down Expand Up @@ -54,3 +55,9 @@ Use `!` or a `BREAKING CHANGE:` footer for breaking API changes.

User-facing changes should update the relevant package `CHANGELOG.md`. Release
publishing is handled by maintainers through `PUBLISHING.md`.

## Getting help and reporting security issues

Use [SUPPORT.md](./SUPPORT.md) for questions and public bug reports. Follow
[SECURITY.md](./SECURITY.md) for vulnerabilities; do not disclose suspected
security issues in a public issue.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,13 @@ This repository is a monorepo containing:
- **[ack_json_schema_builder](./packages/ack_json_schema_builder)**: Converter to `json_schema_builder` schemas
- **[example](./example)**: Example projects demonstrating usage of all packages

## Community and support

- Read [CONTRIBUTING.md](./CONTRIBUTING.md) before proposing a change.
- Use [SUPPORT.md](./SUPPORT.md) for questions, bug reports, and feature requests.
- Report vulnerabilities privately as described in [SECURITY.md](./SECURITY.md).
- Participation is governed by the [Code of Conduct](./CODE_OF_CONDUCT.md).

## Quick start

### Core library (ack)
Expand Down
34 changes: 34 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Security Policy

## Supported versions

Security fixes are made for the latest released Ack version. Users should
upgrade to the newest compatible release before reporting a problem or asking
for a backport. Older release lines may receive fixes at the maintainers'
discretion.

## Reporting a vulnerability

Do not report a suspected vulnerability in a public GitHub issue.

Contact the repository owner privately through the contact methods on their
[GitHub profile](https://github.com/btwld). Include:

- the affected package and version;
- a clear description of the impact;
- steps or a minimal program that reproduces the issue;
- any known workarounds; and
- whether the report or exploit details have been shared elsewhere.

If no private contact method is available, open an issue that requests a
private security contact without including vulnerability details.

Please allow maintainers time to confirm the report and coordinate a fix before
public disclosure. If the report is accepted, the project will credit the
reporter unless they prefer to remain anonymous.

## Scope

Security reports should describe a concrete confidentiality, integrity, or
availability impact. General bugs, unexpected validation results, and feature
requests belong in the public [issue tracker](https://github.com/btwld/ack/issues).
30 changes: 30 additions & 0 deletions SUPPORT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Support

## Start with the documentation

- [Ack documentation](https://docs.page/btwld/ack)
- [Quickstart tutorial](https://docs.page/btwld/ack/getting-started/quickstart-tutorial)
- [API quick reference](https://docs.page/btwld/ack/api-reference/)
- [Generated API documentation](https://pub.dev/documentation/ack/latest/ack/)

Search existing [GitHub issues](https://github.com/btwld/ack/issues) before
opening a new one; your question or bug may already have an answer.

## Ask a question

Open a [GitHub issue](https://github.com/btwld/ack/issues/new) and apply the
`question` label. Include the Ack package and version, your Dart or Flutter
version, what you are trying to accomplish, and a small reproducible example.

## Report a bug or request a feature

Use the [issue tracker](https://github.com/btwld/ack/issues) with the `bug` or
`enhancement` label. A minimal reproduction and the full error output make an
issue much easier to investigate.

For vulnerabilities, follow [SECURITY.md](./SECURITY.md) and do not open a
public issue. Conduct concerns should follow
[CODE_OF_CONDUCT.md](./CODE_OF_CONDUCT.md).

Ack is maintained by volunteers. Response times vary, and support is provided
on a best-effort basis.
13 changes: 13 additions & 0 deletions docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,19 @@
{ "title": "Configuration", "href": "/core-concepts/configuration" }
]
},
{
"group": "Adapter Authors",
"pages": [
{
"title": "Adapter Package Quickstart",
"href": "/guides/schema-converter-quickstart"
},
{
"title": "Creating Adapter Packages",
"href": "/guides/creating-schema-converter-packages"
}
]
},
{
"group": "Reference",
"pages": [{ "title": "API Reference", "href": "/api-reference/" }]
Expand Down
7 changes: 6 additions & 1 deletion docs/api-reference/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
title: API Reference
---

Quick reference for the core Ack classes, methods, and annotations. For detailed explanations and examples, see the specific guides linked below.
This page is a curated quick reference for the core Ack classes, methods, and
annotations. Use the [generated API documentation](https://pub.dev/documentation/ack/latest/ack/)
for every public declaration and exact signatures; use the linked guides here
for explanations and examples.

## Core `Ack` Class

Expand Down Expand Up @@ -83,6 +86,8 @@ Primitive schemas (`StringSchema`, `IntegerSchema`, `DoubleSchema`, `NumberSchem
### Utility Methods

- `Map<String, Object?> toJsonSchema()`: Returns a Draft-7 JSON Schema map via the canonical `AckSchemaModel` boundary.
- `AckSchemaModel toSchemaModel()`: Returns the canonical, target-independent
boundary model for schema adapters, including export warnings.
- `Map<String, Object?> toMap()`: Serializes the schema for debugging.

See also [Schema Types](../core-concepts/schemas.mdx) for detailed usage examples.
Expand Down
66 changes: 57 additions & 9 deletions docs/core-concepts/configuration.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,24 @@ Ack has no global configuration object. All behavior is configured at the schema

Define behavior when you create your schemas.

### Required fields
### Optional and nullable values

Fields in [`Ack.object`](./schemas.mdx#object) are required by default. Mark a field as optional with `.optional()`.
Fields in [`Ack.object`](./schemas.mdx#object) are required and non-nullable by
default. Use `.optional()` when a field may be omitted, `.nullable()` when a
present field may be `null`, or both when either state is valid.

```dart
Ack.object({
'id': Ack.integer(),
'name': Ack.string(),
'email': Ack.string().email().optional() // Email is optional (can be omitted)
}); // id and name are required by default
'nickname': Ack.string().optional(),
'middleName': Ack.string().nullable(),
'avatarUrl': Ack.string().url().optional().nullable(),
});
```

See [Optional vs nullable](./schemas.mdx#optional-vs-nullable) for the complete
presence and nullability matrix.

### Additional properties

Control how extra fields are handled with the `additionalProperties` parameter in [`Ack.object`](./schemas.mdx#object).
Expand All @@ -34,14 +40,49 @@ Ack.object({'id': Ack.integer()}, additionalProperties: false);
Ack.object({'id': Ack.integer()}, additionalProperties: true);
```

Use strict objects for data you own and want to detect drift in. At external
API boundaries, `additionalProperties: true` can make a schema resilient to
new response fields while still validating every field your application uses.

### Default values

Use `.withDefault(value)` when a `null` or missing object field should receive
a runtime value during parsing. The default must satisfy the schema's runtime
type and constraints.

```dart
final settingsSchema = Ack.object({
'theme': Ack.enumString(['light', 'dark']).withDefault('light'),
'pageSize': Ack.integer().min(1).max(100).withDefault(20),
});
```

Defaults change the parsed result; `.optional()` only changes whether an object
field is required.

### Schema metadata

Attach a description with `.describe()` when the schema is also used for JSON
Schema export or adapter packages.

```dart
final userIdSchema = Ack.string()
.uuid()
.describe('Stable identifier for a user account');
```

### Custom error messages

Built-in constraints provide default messages. To override them, use `.constrain()`.
See also: [Custom Error Messages in Error Handling](./error-handling.mdx#custom-error-messages).
Built-in constraints provide default messages. APIs that accept `message:`,
such as `.matches()`, can replace that message inline. Use `.constrain()` to
provide a message for a reusable custom constraint. See [Custom error
messages](./error-handling.mdx#custom-error-messages).

```dart
Ack.string().minLength(5); // Default: "Too short, min 5 characters"
Ack.integer().min(18); // Default: "Must be at least 18"
final usernameSchema = Ack.string().matches(
r'^[a-z0-9_]+$',
message: 'Use lowercase letters, numbers, and underscores only.',
);
```

### Custom validation logic
Expand All @@ -51,3 +92,10 @@ Use `.constrain()` for reusable value-level checks and `.refine()` for cross-fie
## Code generation

Annotate a top-level schema with `@AckType()` to generate a typed wrapper — see [TypeSafe Schemas](./typesafe-schemas.mdx) for setup and supported shapes.

## Related guides

- [Schema Types](./schemas.mdx) — factories, composition, and transformations
- [Validation Rules](./validation.mdx) — built-in constraints
- [Codecs](./codecs.mdx) — bidirectional boundary/runtime configuration
- [JSON Schema Integration](../guides/json-schema-integration.mdx) — exported metadata and defaults
55 changes: 51 additions & 4 deletions docs/core-concepts/json-serialization.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
title: JSON Serialization
---

Ack schemas validate JSON data and let you work with the validated data directly, wrap it with generated types, or pass it to your own model layer.
Ack validates decoded JSON at your application boundary. On the way back out,
plain schemas produce JSON-native Dart values directly, while
[codecs](./codecs.mdx) encode rich runtime values such as `DateTime` and `Uri`
back to their wire representation.

## Validating JSON data

Expand All @@ -24,8 +27,8 @@ final userSchema = Ack.object({

void processApiResponse(String jsonString) {
// 1. Decode JSON string into a Dart object.
// Note: jsonDecode returns dynamic, so the structure is unknown initially.
dynamic jsonData;
// jsonDecode returns an unknown structure until the schema validates it.
Object? jsonData;
try {
jsonData = jsonDecode(jsonString);
} catch (e) {
Expand Down Expand Up @@ -98,8 +101,52 @@ if (result.isOk) {
}
```

## Encoding validated data

For schemas whose runtime values are already JSON-native (`String`, `num`,
`bool`, `List`, `Map`, and `null`), pass the validated value to `jsonEncode`:

```dart
final result = userSchema.safeParse({
'name': 'Alice',
'age': 30,
'email': 'alice@example.com',
});

if (result.isOk) {
final validData = result.getOrThrow()!;
final jsonString = jsonEncode(validData);
print(jsonString);
}
```

When a schema decodes boundary values into richer Dart types, encode through
the schema before calling `jsonEncode`. This applies each codec in the nested
structure and restores the JSON-safe boundary shape:

```dart
final eventSchema = Ack.object({
'name': Ack.string(),
'startsAt': Ack.datetime(),
});

final event = eventSchema.parse({
'name': 'Launch',
'startsAt': '2026-01-15T14:00:00Z',
});

final boundaryData = eventSchema.encode(event);
final jsonString = jsonEncode(boundaryData);
```

Use `safeEncode()` when you want a `SchemaResult` instead of an exception.
See [Codecs](./codecs.mdx) for runtime invariants and custom bidirectional
conversions.

## Key considerations

- **`dart:convert`:** Use `jsonEncode`/`jsonDecode` for JSON string conversion. Ack handles validation only.
- **`dart:convert`:** Use `jsonDecode` and `jsonEncode` for JSON text. Ack
validates values and encodes codec runtime values back to their boundary
representation.
- **Type safety:** `jsonDecode` produces `dynamic`, but successful validation guarantees the structure and types of the resulting `Map<String, Object?>`.
- **Model conversion:** After validation, how you convert the validated map into an app model is up to you. Ack keeps validation and wrapper generation separate from your model layer.
6 changes: 3 additions & 3 deletions docs/core-concepts/schemas.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ final nameSchema = Ack.string();
final usernameSchema = Ack.string()
.minLength(3)
.maxLength(20)
.matches(r'[a-zA-Z0-9_]+');
.matches(r'^[a-zA-Z0-9_]+$');

// Email validation
final emailSchema = Ack.string().email();
Expand Down Expand Up @@ -136,7 +136,7 @@ final userSchema = Ack.object({
'address': Ack.object({
'street': Ack.string(),
'city': Ack.string(),
'zipCode': Ack.string().matches(r'\d{5}'),
'zipCode': Ack.string().matches(r'^\d{5}$'),
}),
});
```
Expand Down Expand Up @@ -439,7 +439,7 @@ final userWithAgeSchema = Ack.object({

// Type transformation
final dateSchema = Ack.string()
.matches(r'\d{4}-\d{2}-\d{2}')
.matches(r'^\d{4}-\d{2}-\d{2}$')
.transform<DateTime>((s) => DateTime.parse(s));
```

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 @@ -121,4 +121,4 @@ Conflicting discriminator fields, broad `Ack.string()`, and transformed or refin

- [JSON Serialization](./json-serialization.mdx) — parse JSON straight into generated types
- [Common Recipes](../guides/common-recipes.mdx) — patterns that combine schemas and generated types
- [API Reference](../api-reference/index.mdx) — the full surface
- [API Reference](../api-reference/index.mdx) — core API quick reference and generated API docs
2 changes: 1 addition & 1 deletion docs/core-concepts/validation.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@ You can chain multiple constraints. Ack evaluates them in the order you apply th
final usernameSchema = Ack.string()
.minLength(3) // First: check min length
.maxLength(20) // Second: check max length
.matches(r'[a-z0-9_]+') // Third: check pattern (lowercase alphanumeric/underscore)
.matches(r'^[a-z0-9_]+$') // Third: require only lowercase letters, digits, or underscores
.notEmpty(); // Redundant if minLength(>0) is used, but illustrates chaining

final quantitySchema = Ack.integer()
Expand Down
Loading
Loading