Skip to main content

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.

CindelBackup provides a full-database export and import API that streams a typed archive to or from any Dart StreamConsumer<List<int>> or Stream<List<int>>. The archive format is JSONL — one JSON object per line — optionally compressed with gzip. An FNV-1a checksum written into the footer is verified on every import, making it safe to transport archives across networks or store them at rest and detect corruption before restoring.

Archive Format

After decompression, a Cindel archive is a sequence of UTF-8 JSONL records:
Record typeContents
headerFormat identifier, version, backend name, creation timestamp, and migration version
schemaCollection name and schema version, one per exported collection
docCollection name, document id, and the full document map, one per object
footerTotal document count and FNV-1a checksum over all preceding records
The checksum is computed over every record except the footer itself. importDatabase recomputes the checksum while reading and throws a StateError if the value does not match the footer.

Exporting a Database

Call CindelBackup.exportDatabase with the open database handle, a list of CindelBackupCollection wrappers, and any StreamConsumer<List<int>> as the output sink. The method returns a CindelBackupReport when the stream is fully drained:
final output = File('backup.cindelbak').openWrite();

final report = await CindelBackup.exportDatabase(
  database: db,
  collections: [
    CindelBackupCollection(UserSchema),
    CindelBackupCollection(OrderSchema),
  ],
  output: output,
);

print('Exported ${report.documents} documents');
print('Archive size: ${report.archiveBytes} bytes');
print('Checksum: ${report.checksum}');

CindelBackupCollection

Wrap each generated schema with CindelBackupCollection(schema) to include it in the archive. The schema must match the one used to open the database:
CindelBackupCollection(UserSchema)

Compression

On native Dart platforms, CindelBackup defaults to CindelBackupCompression.gzip. On Web it defaults to CindelBackupCompression.none. You can override the default by passing the compression parameter explicitly:
await CindelBackup.exportDatabase(
  database: db,
  collections: [CindelBackupCollection(UserSchema)],
  output: output,
  compression: CindelBackupCompression.none,
);
Use CindelBackupCompression.none when you need to share an archive across platforms, inspect the raw JSONL for debugging, or run the backup in an environment where gzip is not available. The uncompressed archive is plain UTF-8 JSONL and can be opened in any text editor after the export.

CindelBackupReport

Both exportDatabase and importDatabase return a CindelBackupReport:
FieldDescription
documentsNumber of document records in the archive
uncompressedBytesSize of the JSONL byte stream before compression
archiveBytesSize read from or written to the caller-provided stream
checksumFNV-1a checksum of non-footer JSONL records
compressionCompression mode used for the stream

Importing a Database

Call CindelBackup.importDatabase with an empty database opened with the matching schemas and a Stream<List<int>> pointing at the archive:
final restoredDb = await Cindel.open(
  directory: restoreDirectory.path,
  schemas: [UserSchema, OrderSchema],
);

await CindelBackup.importDatabase(
  database: restoredDb,
  collections: [
    CindelBackupCollection(UserSchema),
    CindelBackupCollection(OrderSchema),
  ],
  input: File('backup.cindelbak').openRead(),
);
The restore target must be empty. importDatabase checks each collection before importing and throws a StateError if any collection contains existing documents. Open a fresh database or use a new directory to restore into.
If the archive was exported with a migration version marker, importDatabase writes that version into the restored database so Cindel does not re-run migrations on next open.

Progress Callbacks

Both export and import accept an optional onProgress callback. It receives a CindelBackupProgress snapshot with the current phase (export or import), the collection name being processed, and the total document count so far:
await CindelBackup.exportDatabase(
  database: db,
  collections: [CindelBackupCollection(UserSchema)],
  output: output,
  onProgress: (progress) {
    print('[${progress.phase.name}] ${progress.collection}: '
          '${progress.documents} documents');
  },
);

Paged ID Scans for Custom Tooling

Lower-level tooling that needs to iterate over a large collection without materializing everything at once can use documentIdsPage. It returns a bounded, ascending page of document ids without fetching the documents themselves:
int? afterId;
while (true) {
  final page = await db.documentIdsPage(
    'orders',
    afterId: afterId,
    limit: 1000,
  );
  if (page.isEmpty) break;

  final orders = await db.orders.getAll(page);
  // Export, verify, or copy this page however you need.

  afterId = page.last;
}
Each call returns at most limit ids that are strictly greater than afterId. When the returned list is empty, you have reached the end of the collection. This pattern works on SQLite native, MDBX, and Web SQLite backends. documentIds() (without the page parameters) is also available when loading the full id list is acceptable for the collection size you are working with.

Build docs developers (and LLMs) love