Whenever you add a field, rename a collection, change a field type, or make any other structural change to your Cindel models, existing databases on user devices hold data in the old layout. Cindel’s migration system lets you declare a versioned plan that is evaluated every time the database opens. Completed steps are skipped automatically, and the final database handle is only returned after all applicable steps have succeeded.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/mainser/cindel/llms.txt
Use this file to discover all available pages before exploring further.
Why Migrations
Dart code regenerated after a schema change understands the new field layout, but on-device databases still contain documents written with the old layout. Without a migration step the mismatch between stored bytes and the new schema reader can corrupt objects or silently drop fields. A migration step opens the database with the old schema, exports data, rewrites it to match the new schema, and replaces the stored documents before the application ever reads them.CindelMigrationPlan
Create a CindelMigrationPlan and pass it to Cindel.open on every application start:
Parameters
| Parameter | Description |
|---|---|
targetVersion | The final data version expected after all steps complete. Must not be negative. |
steps | Ordered list of CindelMigrationStep values. Cindel selects the step whose fromVersion matches the current stored version. |
baselineVersion | Version to assume for a database that already has schemas but no stored migration marker. Defaults to 0. |
compactOnSuccess | Compact the backend after a successful migration run. Defaults to true. |
Version Tracking
Cindel stores the data version inside the database itself. On open it reads the stored version, compares it totargetVersion, and runs only the steps whose fromVersion matches the current version in order. A fresh database with no schemas and no version marker is initialized directly to targetVersion so no steps run for new installs.
The baselineVersion parameter handles databases that were created before you introduced migrations. If the database has schemas but no version marker, Cindel treats it as being at baselineVersion and runs any applicable steps from there.
CindelMigrationStep
Each step advances the database from one version to the next:
| Parameter | Description |
|---|---|
fromVersion | Data version before this step runs. |
toVersion | Data version persisted after this step succeeds. Must be greater than fromVersion. |
openSchemas | Schemas used to open and read the database in its pre-migration layout. |
targetSchemas | Schemas registered by registerTargetSchemas. Defaults to the top-level targetSchemas from Cindel.open. |
verifyBefore | Optional callback called before migrate. Use it to assert preconditions on the old data. |
migrate | Required callback that exports old data, registers the new schema, and imports rewritten data. |
verifyAfter | Optional callback called after migrate. Use it to assert postconditions on the new data. |
CindelMigrationContext
The context object is passed to every callback in a step. It provides the open database handle and helpers for reading and writing documents:
context.database
The CindelDatabase handle opened with openSchemas. You can call documentIds, schemaVersion, or use any other low-level database API on it.
context.exportObjects(schema)
Reads all typed objects from a collection in id order. Returns a List<T> using the provided schema’s deserializer. Internally batches reads to avoid loading the entire collection into memory at once:
context.exportDocuments(schema)
Like exportObjects, but returns each object as a raw Map<String, Object?>. Useful when you want to inspect or transform documents without a fully typed old model class:
context.registerTargetSchemas()
Clears the target collection storage and registers the new schema, preparing the collection to accept documents in the new layout. Call this after exporting old data and before importing rewritten data.
context.importObjects(schema, objects)
Bulk-writes a list of typed objects into the target collection in batches. The objects must conform to the targetSchemas registered by registerTargetSchemas():
context.importDocuments(schema, documents)
Like importObjects, but accepts raw maps. Cindel uses the schema’s fromDocument deserializer and preserves the original id from the map’s id field when present.
Complete Migration Example
The example below migrates ausers collection from OldUserSchema (version 1) to UserSchema (version 2). The User.fromLegacy constructor on the new class accepts an OldUser and maps its fields to the new layout:
Compaction
WhencompactOnSuccess is true (the default), Cindel calls the backend’s compact operation after each step succeeds. Compaction reclaims space freed by replacing or deleting old documents and is especially useful after migrations that rewrite large collections.