turbo_serializable 0.2.0 copy "turbo_serializable: ^0.2.0" to clipboard
turbo_serializable: ^0.2.0 copied to clipboard

A serialization abstraction for the turbo ecosystem with multi-format support (JSON, YAML, Markdown, XML).

example/main.dart

// ignore_for_file: avoid_print
import 'package:turbo_serializable/turbo_serializable.dart';
import 'package:turbo_response/turbo_response.dart';

/// Full implementation with all serialization methods
class FullModel extends TurboSerializable<Object?> {
  final String name;
  final int age;

  FullModel({
    required this.name,
    required this.age,
  }) : super(
            config: TurboSerializableConfig(
          toJson: (instance) {
            final self = instance as FullModel;
            return {'name': self.name, 'age': self.age};
          },
          toYaml: (instance) {
            final self = instance as FullModel;
            return 'name: ${self.name}\nage: ${self.age}';
          },
          toMarkdown: (instance) {
            final self = instance as FullModel;
            return '# ${self.name}\n\nAge: ${self.age}';
          },
        ));

  @override
  TurboResponse<T>? validate<T>() {
    if (name.isEmpty) {
      return TurboResponse.fail(error: 'Name cannot be empty');
    }
    if (age < 0) {
      return TurboResponse.fail(error: 'Age cannot be negative');
    }
    return null;
  }
}

/// Partial implementation with only toJson
class PartialModel extends TurboSerializable<Object?> {
  final String name;

  PartialModel(this.name)
      : super(config: TurboSerializableConfig(
          toJson: (instance) {
            final self = instance as PartialModel;
            return {'name': self.name};
          },
        ));
}

/// Empty implementation - all methods return null
class EmptyModel extends TurboSerializable<Object?> {
  EmptyModel({super.metaData})
      : super(
            config: TurboSerializableConfig(
          toJson: (_) => null,
        ));
}

/// Full implementation with ID
class FullModelWithId extends TurboSerializableId<String, Object?> {
  final String _id;
  final String name;

  FullModelWithId({
    required String id,
    required this.name,
    super.isLocalDefault,
  })  : _id = id,
        super(config: TurboSerializableConfig(
          toJson: (instance) {
            final self = instance as FullModelWithId;
            return {'id': self.id, 'name': self.name};
          },
        ));

  @override
  String get id => _id;
}

/// Custom ID type implementation
class CustomId {
  final int value;
  const CustomId(this.value);
  @override
  String toString() => 'CustomId($value)';
}

class CustomIdModel extends TurboSerializableId<CustomId, Object?> {
  final CustomId _id;

  CustomIdModel(int idValue)
      : _id = CustomId(idValue),
        super(
            config: TurboSerializableConfig(
          toJson: (_) => null,
        ));

  @override
  CustomId get id => _id;
}

/// Frontmatter metadata example
class Frontmatter {
  final String title;
  final String description;
  final List<String> tags;
  final DateTime? publishedAt;

  Frontmatter({
    required this.title,
    required this.description,
    required this.tags,
    this.publishedAt,
  });
}

/// Document with frontmatter metadata
class Document extends TurboSerializable<Frontmatter> {
  final String content;

  Document({
    required this.content,
    super.metaData,
  }) : super(
            config: TurboSerializableConfig(
          toJson: (instance) {
            final self = instance as Document;
            return {'content': self.content};
          },
          toMarkdown: (instance) {
            final self = instance as Document;
            return self.content;
          },
        ));
}

/// Document with ID and frontmatter metadata
class DocumentWithId extends TurboSerializableId<String, Frontmatter> {
  final String _id;
  final String content;

  DocumentWithId({
    required String id,
    required this.content,
    super.metaData,
    super.isLocalDefault,
  })  : _id = id,
        super(config: TurboSerializableConfig(
          toJson: (instance) {
            final self = instance as DocumentWithId;
            return {'id': self.id, 'content': self.content};
          },
        ));

  @override
  String get id => _id;
}

void main() {
  print('=== turbo_serializable Validation Script ===\n');

  // Test 1: Full implementation
  print('Test 1: Full implementation');
  final full = FullModel(name: 'Alice', age: 30);
  assert(full.validate() == null, 'Valid model should have null validate');
  assert(full.toJson() != null, 'toJson should return a map');
  assert(full.toJson()!['name'] == 'Alice', 'toJson should contain name');
  assert(full.toYaml() != null, 'toYaml should return a string');
  assert(full.toMarkdown() != null, 'toMarkdown should return a string');
  print('  ✓ All full model methods work correctly');

  // Test 2: Full implementation with invalid data
  print('\nTest 2: Validation with invalid data');
  final invalid = FullModel(name: '', age: 30);
  assert(invalid.validate() is Fail, 'Invalid model should fail validation');
  print('  ✓ Validation correctly rejects empty name');

  // Test 3: Partial implementation with auto-conversion
  print('\nTest 3: Partial implementation with auto-conversion');
  final partial = PartialModel('Bob');
  assert(partial.validate() == null, 'Default validate returns null');
  assert(partial.toJson() != null, 'toJson should work');
  // Auto-conversion from JSON to other formats
  assert(partial.toYaml() != null, 'toYaml converts from JSON');
  assert(partial.toMarkdown() != null, 'toMarkdown converts from JSON');
  assert(partial.toXml() != null, 'toXml converts from JSON');
  print('  ✓ Partial implementation auto-converts to other formats');

  // Test 4: Empty implementation
  print('\nTest 4: Empty implementation (all null)');
  final empty = EmptyModel();
  assert(empty.validate() == null, 'Default validate returns null');
  assert(empty.toJson() == null, 'Default toJson returns null');
  assert(empty.toYaml() == null, 'Default toYaml returns null');
  assert(empty.toMarkdown() == null, 'Default toMarkdown returns null');
  assert(empty.metaData == null, 'Default metaData is null');
  print('  ✓ Empty implementation returns null for all methods');

  // Test 5: TurboSerializableId with String ID
  print('\nTest 5: TurboSerializableId with String ID');
  final withId = FullModelWithId(id: 'user-123', name: 'Charlie');
  assert(withId.id == 'user-123', 'ID getter should work');
  assert(withId.isLocalDefault == false, 'isLocalDefault defaults to false');
  assert(withId.toJson()!['id'] == 'user-123', 'toJson should include id');
  print('  ✓ TurboSerializableId works with String ID');

  // Test 6: TurboSerializableId with isLocalDefault
  print('\nTest 6: TurboSerializableId with isLocalDefault=true');
  final localDefault =
      FullModelWithId(id: 'temp-id', name: 'Temp', isLocalDefault: true);
  assert(localDefault.isLocalDefault == true, 'isLocalDefault should be true');
  print('  ✓ isLocalDefault can be set to true');

  // Test 7: Custom ID type
  print('\nTest 7: Custom ID type');
  final customId = CustomIdModel(42);
  assert(customId.id.value == 42, 'Custom ID value should work');
  print('  ✓ Custom ID types work correctly');

  // Test 8: Type inheritance verification
  print('\nTest 8: Type inheritance verification');
  assert(full.toJson() != null, 'FullModel inherits TurboSerializable methods');
  assert(withId.toJson() != null,
      'TurboSerializableId inherits TurboSerializable methods');
  assert(withId.id.isNotEmpty, 'TurboSerializableId provides typed id getter');
  print('  ✓ Type inheritance is correct');

  // Test 9: Metadata with TurboSerializable
  print('\nTest 9: Metadata with TurboSerializable');
  final docMeta = Frontmatter(
    title: 'My Document',
    description: 'A sample document with frontmatter',
    tags: ['example', 'test', 'demo'],
    publishedAt: DateTime(2026, 1, 9),
  );
  final doc =
      Document(content: '# Hello World\n\nThis is content.', metaData: docMeta);
  assert(doc.metaData != null, 'metaData should be set');
  assert(doc.metaData!.title == 'My Document', 'metaData title should match');
  assert(doc.metaData!.tags.length == 3, 'metaData tags should have 3 items');
  assert(doc.toMarkdown() == '# Hello World\n\nThis is content.',
      'toMarkdown should return content');
  print('  ✓ Metadata works with TurboSerializable');

  // Test 10: Metadata with TurboSerializableId
  print('\nTest 10: Metadata with TurboSerializableId');
  final docWithIdMeta = Frontmatter(
    title: 'Document With ID',
    description: 'Has both ID and metadata',
    tags: ['id', 'meta'],
  );
  final docWithId = DocumentWithId(
    id: 'doc-001',
    content: 'Content here',
    metaData: docWithIdMeta,
    isLocalDefault: false,
  );
  assert(docWithId.id == 'doc-001', 'ID should be set');
  assert(docWithId.metaData != null, 'metaData should be set');
  assert(docWithId.metaData!.title == 'Document With ID',
      'metaData title should match');
  assert(docWithId.isLocalDefault == false, 'isLocalDefault should be false');
  print('  ✓ Metadata works with TurboSerializableId');

  // Test 11: Null metadata is valid
  print('\nTest 11: Null metadata is valid');
  final docNoMeta = Document(content: 'No meta');
  assert(
      docNoMeta.metaData == null, 'metaData should be null when not provided');
  assert(docNoMeta.toJson() != null, 'toJson should still work');
  print('  ✓ Null metadata is handled correctly');

  // Test 12: Format converters
  print('\nTest 12: Format converters');
  final yaml = jsonToYaml({'name': 'Test', 'age': 25});
  assert(yaml.contains('name: Test'), 'YAML should contain name');
  final json = yamlToJson('name: Test\nage: 25');
  assert(json['name'] == 'Test', 'JSON should contain name');
  print('  ✓ Format converters work correctly');

  // Test 13: Markdown with frontmatter
  print('\nTest 13: Markdown with frontmatter');
  final mdWithFrontmatter = jsonToMarkdown(
    {'content': 'Hello'},
    metaData: {'title': 'Test', 'author': 'Me'},
  );
  assert(
      mdWithFrontmatter.contains('---'), 'Should have frontmatter delimiters');
  assert(mdWithFrontmatter.contains('title: Test'),
      'Should have frontmatter content');
  final parsedMd = markdownToJson('---\ntitle: Test\n---\n{"key": "value"}');
  assert(parsedMd['title'] == 'Test', 'Should parse frontmatter');
  assert(parsedMd['body']['key'] == 'value', 'Should parse JSON body');
  print('  ✓ Markdown frontmatter works correctly');

  print('\n=== All validations passed! ===');
}
0
likes
160
points
215
downloads

Publisher

verified publisherultrawideturbodev.com

Weekly Downloads

A serialization abstraction for the turbo ecosystem with multi-format support (JSON, YAML, Markdown, XML).

Repository (GitHub)
View/report issues

Topics

#serialization #json #yaml #markdown #xml

Documentation

API reference

License

MIT (license)

Dependencies

change_case, meta, turbo_response, xml, yaml

More

Packages that depend on turbo_serializable