ack_generator 0.3.0-beta.1 copy "ack_generator: ^0.3.0-beta.1" to clipboard
ack_generator: ^0.3.0-beta.1 copied to clipboard

Code generator for ACK validation schemas

ACK Generator #

Code generator for the ACK validation framework. This generator creates type-safe schema classes from your Dart model classes, providing validation without serialization.

Breaking Changes in v2.0 #

The toModel() method has been removed from generated schemas. ACK is now a pure validation library, giving you complete control over how you create model instances from validated data.

Migration Guide #

Before (v1.x)

final schema = UserSchema().parse(jsonData);
if (schema.isValid) {
  final user = schema.toModel(); // This method no longer exists
}

After (v2.0)

Option 1: Direct Property Access

final schema = UserSchema().parse(jsonData);
if (schema.isValid) {
  // Access properties directly
  print(schema.name);
  print(schema.email);

  // Create model manually
  final user = User(
    name: schema.name,
    email: schema.email,
    address: Address(
      street: schema.address.street,
      city: schema.address.city,
    ),
  );
}

Option 2: Factory Method Pattern

class User {
  factory User.fromSchema(UserSchema schema) {
    if (!schema.isValid) {
      throw AckException(schema.getErrors() ?? throw StateError('Invalid schema with no error'));
    }
    return User(
      name: schema.name,
      email: schema.email,
      address: Address.fromSchema(schema.address),
    );
  }
}

// Usage
final user = User.fromSchema(schema);

Option 3: Extension Methods

extension UserSchemaX on UserSchema {
  User toUser() {
    if (!isValid) throw AckException(getErrors() ?? throw StateError('Invalid schema with no error'));
    return User(name: name, email: email);
  }
}

// Usage
final user = schema.toUser();

Option 4: With dart_mappable Integration

import 'package:dart_mappable/dart_mappable.dart';
import 'package:ack/ack.dart';

part 'user.mapper.dart';  // dart_mappable
part 'user.g.dart';       // ack_generator

@MappableClass(caseStyle: CaseStyle.snakeCase)
@Schema()
class User with UserMappable {
  final String firstName;   // -> 'first_name' in both JSON and schema
  final String lastName;    // -> 'last_name' in both JSON and schema

  @MappableField(key: 'email_address')
  @IsEmail()
  final String email;       // -> 'email_address' in both

  User({required this.firstName, required this.lastName, required this.email});
}

// Validation and serialization use the same field names automatically
factory User.fromJson(Map<String, dynamic> json) {
  // Validate first with transformed field names
  final schema = UserSchema(json);
  if (!schema.isValid) {
    throw AckException(schema.getErrors() ?? throw StateError('Invalid schema with no error'));
  }
  // Then deserialize with dart_mappable (same field names)
  return UserMapper.fromMap(json);
}

Option 5: With Other Serialization Libraries

// Works seamlessly with json_serializable, freezed, etc.
factory User.fromJson(Map<String, dynamic> json) {
  // Validate first
  final schema = UserSchema(json);
  if (!schema.isValid) {
    throw AckException(schema.getErrors() ?? throw StateError('Invalid schema with no error'));
  }
  // Then use your preferred serialization
  return _$UserFromJson(json);
}

dart_mappable Integration #

ACK Generator now provides seamless integration with dart_mappable, automatically synchronizing field names and case styles between validation schemas and serialization.

Key Features #

  • Automatic Case Style Transformation: Supports snake_case, camelCase, kebab-case, and all other dart_mappable case styles
  • Custom Field Key Support: Respects @MappableField(key: 'custom_name') annotations
  • Zero Configuration: Just add dart_mappable annotations and ACK automatically applies the same transformations
  • Backward Compatible: Existing schemas continue to work unchanged

Supported Case Styles #

  • camelCase (default, no transformation)
  • snake_case
  • kebab-case / param-case
  • PascalCase
  • CONSTANT_CASE
  • dot.case
  • path/case
  • Sentence case
  • Header-Case

Example #

@MappableClass(caseStyle: CaseStyle.snakeCase)
@Schema()
class User with UserMappable {
  final String firstName;   // Becomes 'first_name' in JSON and schema
  final String lastName;    // Becomes 'last_name' in JSON and schema

  @MappableField(key: 'email_addr')
  @IsEmail()
  final String email;       // Becomes 'email_addr' in JSON and schema
}

Both dart_mappable serialization and ACK validation will use the same transformed field names automatically.

Benefits of This Change #

  1. Flexibility: Choose your own serialization strategy
  2. Smaller Generated Code: ~30% reduction in file size
  3. Better Separation of Concerns: Validation is separate from object creation
  4. Framework Agnostic: Works with any Dart serialization library
  5. Simpler Mental Model: Schemas validate, they don't create
  6. dart_mappable Integration: Seamless compatibility with automatic field name synchronization

Implementation Status #

✅ Core files created:

  • lib/builder.dart - Builder registration
  • lib/src/generator.dart - Main generator using code_builder
  • test/generator_test.dart - Golden file tests
  • ack_generator_plan_v2.md - Simple migration plan

Next Steps to Complete Setup #

1. Copy Analyzers from Current Generator #

# From ack_generator directory:
cp -r ../ack_generator/lib/src/analyzers ./lib/src/
cp -r ../ack_generator/lib/src/models ./lib/src/  # If exists

# Or create models directory and copy individual files:
mkdir -p lib/src/models
cp ../ack_generator/lib/src/schema_data.dart ./lib/src/models/  # If not in analyzers

2. Create Test Directories #

mkdir -p test/fixtures
mkdir -p test/golden

3. Copy Test Fixtures #

# Copy test models as fixtures
cp ../ack_generator/test/models/user_model.dart ./test/fixtures/
cp ../ack_generator/test/models/product_model.dart ./test/fixtures/
cp ../ack_generator/test/models/block_model.dart ./test/fixtures/

# Copy generated files as golden files
cp ../ack_generator/test/models/user_model.g.dart ./test/golden/user_model.golden
cp ../ack_generator/test/models/product_model.g.dart ./test/golden/product_model.golden
cp ../ack_generator/test/models/block_model.g.dart ./test/golden/block_model.golden

4. Create pubspec.yaml #

name: ack_generator
description: Code generator for ACK validation schemas
version: 0.1.0

environment:
  sdk: '>=3.0.0 <4.0.0'

dependencies:
  analyzer: ^6.3.0
  build: ^2.4.1
  code_builder: ^4.10.0
  source_gen: ^1.4.0
  dart_style: ^2.3.4
  ack: ^0.2.0-beta.1

dev_dependencies:
  build_runner: ^2.4.6
  build_test: ^2.2.0
  test: ^1.25.0

5. Create build.yaml #

builders:
  ack_schema:
    import: "package:ack_generator/builder.dart"
    builder_factories: ["ackSchemaBuilder"]
    build_extensions: {".dart": [".ack.dart"]}
    auto_apply: dependents
    build_to: source
    applies_builders: ["source_gen|combining_builder"]

6. Run Tests #

# Install dependencies
dart pub get

# Run tests (will fail until golden files exist)
dart test

# Create/update golden files
UPDATE_GOLDEN=true dart test

# Run tests again to verify
dart test

Key Implementation Notes #

  • The generator reuses ALL existing analyzers unchanged
  • Uses code_builder for type-safe generation instead of strings
  • Maintains exact same output as current generator
  • Discriminated unions temporarily use string generation (TODO for phase 2)
  • Total new code: ~400 lines (vs 900+ in over-engineered version)

Architecture #

ack_generator/
├── lib/
│   ├── builder.dart (17 lines)
│   └── src/
│       ├── generator.dart (~400 lines)
│       └── analyzers/ (copied from ack_generator)
├── test/
│   ├── generator_test.dart (86 lines)
│   ├── fixtures/ (input dart files)
│   └── golden/ (expected output files)
└── pubspec.yaml

This is a true MVP - minimal new code, maximum reuse, same functionality.

0
likes
130
points
188
downloads

Publisher

unverified uploader

Weekly Downloads

Code generator for ACK validation schemas

Documentation

API reference

License

BSD-3-Clause (license)

Dependencies

ack, analyzer, build, code_builder, collection, dart_style, recase, source_gen

More

Packages that depend on ack_generator