Cindel Generator
Source generator for Cindel schemas, serializers, typed collections, query builders, filters, projections, and native typed document hooks.
Overview | Setup | Model Shape | Generated API | Indexes | Embedded Objects | Enums
Most applications use
cindel_generatoras adev_dependencytogether withbuild_runner. It reads annotations from your model classes and emits the*.g.dartfiles consumed by thecindelruntime.
Overview
cindel_generator turns annotated Dart classes into the code Cindel needs for
typed database access:
- Collection schema metadata.
- Manual document serializers and deserializers.
- Compact binary document serializers and deserializers.
- Native typed document readers and writers when the field layout supports it.
- Typed collection accessors on
CindelDatabase. - Indexed
where()query helpers. filter()query helpers for persisted fields.- Sorting, distinct, property projection, and aggregate helpers.
- Composite index equality helpers.
- Embedded object conversion helpers.
The package is a build-time tool. It does not open databases and it does not ship native binaries.
Setup
For Flutter apps, depend on Cindel and the native library package at runtime, then add the generator as a dev dependency:
dependencies:
cindel: ^0.5.4
cindel_flutter_libs: ^0.5.4
dev_dependencies:
build_runner: ^2.15.0
cindel_generator: ^0.5.4
Pure Dart packages can depend on cindel directly and provide a native library
path with CINDEL_NATIVE_LIBRARY when needed.
Basic Usage
Create a model file with a part directive and Cindel annotations:
import 'package:cindel/cindel.dart';
part 'user.g.dart';
@Collection(name: 'users')
class User {
Id id = autoIncrement;
@Index(unique: true)
late String email;
@index
late String name;
bool active = true;
}
Run the generator:
dart run build_runner build --delete-conflicting-outputs
Then use the generated schema and typed collection API:
final db = await Cindel.open(
directory: directory.path,
schemas: [UserSchema],
);
final user = User()
..name = 'Jhon Doe'
..email = 'jhon@example.com';
await db.users.put(user);
final saved = await db.users.where().emailEqualTo('jhon@example.com').findFirst();
Model Shape
Generated collections must follow the rules enforced by the generator:
@Collectioncan only be used on concrete classes.- A collection must declare at least one persisted field.
- A collection must declare exactly one persisted field named
id. - A collection needs either an unnamed constructor with no parameters or an unnamed constructor with parameters for every persisted field.
- Collections with final persisted fields need constructor parameters for every persisted field.
- Fields annotated with
@ignoreare excluded from persistence.
Supported persisted field shapes are:
bool,int,double, andString.DateTimeandDuration.- Enums.
- Embedded objects annotated with
@Embedded. - Nullable variants of supported shapes.
- Lists of supported non-list shapes.
Nested lists are not supported.
Generated API
For a User collection, the generator emits a schema named UserSchema and a
typed database accessor:
final users = db.users;
It also emits conversion functions used by the runtime:
- Dart object to manual Cindel document.
- Manual Cindel document to Dart object.
- Dart object to compact binary document.
- Compact binary document to Dart object.
- Native typed writer and reader hooks when supported by the field layout.
- Id getter, and an id setter when the model can assign generated ids.
Generated query access starts from where() for indexed fields and
collection-level composite indexes:
final user = await db.users.where().emailEqualTo('jhon@example.com').findFirst();
Generated filter() helpers are available for persisted fields:
final activeUsers = await db.users
.filter()
.activeEqualTo(true)
.sortByName()
.findAll();
Generated query modifiers include field sorting, descending sorting, distinct helpers, and property query accessors:
final names = await db.users
.filter()
.activeEqualTo(true)
.sortByName()
.nameProperty()
.findAll();
Indexes
The generator reads @index, @Index(...), and collection-level
CompositeIndex(...) annotations.
Value Indexes
@index
late String name;
Value indexes generate equality helpers and range-style helpers when the field type supports range queries.
Unique Indexes
@Index(unique: true)
late String email;
Unique indexes generate the same lookup helpers and tell the runtime to enforce unique values.
Hash Indexes
@Index(type: CindelIndexType.hash)
late String externalId;
Hash indexes generate equality helpers only.
Word Indexes
@Index(type: CindelIndexType.words)
late String bio;
Word indexes are supported for string fields.
Multi-Entry Indexes
@Index(type: CindelIndexType.multiEntry)
late List<String> tags;
Multi-entry indexes are supported for lists of primitive values, DateTime,
Duration, or enums.
Composite Indexes
@Collection(
indexes: [
CompositeIndex(['teamId', 'email'], unique: true),
],
)
class TeamMember {
Id id = autoIncrement;
late int teamId;
late String email;
late String name;
}
Composite indexes generate equality helpers for the configured field set.
Embedded Objects
Embedded classes are converted as part of their parent document.
@embedded
class Address {
late String city;
late String country;
}
@collection
class User {
Id id = autoIncrement;
late String name;
late Address address;
}
Embedded indexes are not supported by the generator. Index the parent collection field instead when you need indexed lookups.
Enums
The generator supports enum fields and @Enumerated(...) strategies.
enum UserRole { admin, editor, viewer }
@collection
class User {
Id id = autoIncrement;
@Enumerated(CindelEnumType.name)
late UserRole role;
}
For value-based enum persistence:
enum AccountStatus {
active('A'),
suspended('S');
const AccountStatus(this.code);
final String code;
}
@collection
class Account {
Id id = autoIncrement;
@Enumerated(CindelEnumType.value, valueField: 'code')
late AccountStatus status;
}
Builder Details
The package registers a build_runner builder named cindel_generator.
It uses source_gen as a shared part builder:
- Input:
.dartfiles. - Intermediate output:
.cindel.g.part. - Final user-facing output: the combined
*.g.dartpart file.
In normal projects, adding the dependency and running build_runner is enough.
Status
Cindel is in active pre-1.0 development. This generator follows the same release line as the runtime package and emits the native typed readers, writers, query helpers, and hydration hooks used by the optimized Cindel runtime.
Libraries
- cindel_generator
- Source generator entrypoints for Cindel schema and typed API generation.