sqlite_records 0.1.0 copy "sqlite_records: ^0.1.0" to clipboard
sqlite_records: ^0.1.0 copied to clipboard

A minimal, functional wrapper for SQLite/PowerSync using Dart 3 records.

SqliteRecords #

A minimal, functional wrapper for SQLite (designed for PowerSync) that prioritizes type safety for parameters, "best-effort" result validation, and a "declare-what-you-use" strategy using Dart 3 Records.

Features #

  • Type-Safe Parameters: Use Dart Records to define query parameters, ensuring compile-time safety at the call site.
  • Schema-Aware Results: Define expected result schemas using standard Dart types.
  • SafeRow Access: Access row data with get<T>, getOptional<T>, and parse<T, DB>, catching schema or type drift immediately.
  • Reactive Queries: Built-in support for watch to receive streams of result sets.
  • Batch Operations: Efficient executeBatch for bulk mutations.
  • Zero Boilerplate: No code generation required.

Core Concepts #

1. Define Queries and Commands #

Queries and Commands encapsulate SQL, parameter mapping, and schema tokens.

// Define the query with typed parameters (P) and a result token (R)
final activeUsersQuery = Query<({String status}), ({String name, int age})>(
  'SELECT name, age FROM users WHERE status = @status',
  schema: {'name': String, 'age': int},
  params: (p) => {'status': p.status},
);

2. Execute via SqliteRecords #

Wrap your PowerSyncDatabase and use the typed definitions.

final db = SqliteRecords.fromPowerSync(powersyncDb);

// Result is a SafeResultSet containing SafeRows
final rows = await db.getAll(activeUsersQuery, (status: 'active'));

for (final row in rows) {
  final name = row.get<String>('name');
  final age = row.getOptional<int>('age');
}

3. Transactions #

Support for both read-only and read-write transactions with dedicated contexts.

// Read-only transaction (uses SqliteRecordsReadonly context)
await db.readTransaction((tx) async {
  final user = await tx.get(userQuery, (id: '123'));
  final settings = await tx.getAll(settingsQuery, (userId: '123'));
});

// Read-write transaction (uses SqliteRecords context)
await db.writeTransaction((tx) async {
  await tx.execute(updateUserCommand, (id: '123', name: 'New Name'));
  await tx.execute(logChangeCommand, (userId: '123', action: 'update'));
});

4. Safe Parsing #

Use built-in extensions for common types like Enums and DateTime.

final status = row.parseEnumByName('status', UserStatus.values);
final createdAt = row.parseDateTime('created_at');

Caveats #

  • Named Parameters: Parameters use @name syntax in SQL. The implementation translates these to positional ? parameters. Ensure every @name in the SQL has a corresponding key in the params map.
  • Runtime Validation: While parameters are type-safe at compile-time, result validation (schema and types) happens at runtime during access.
  • Record Tokens: The R record type in Query<P, R> is currently a "linting token." It provides context for developers and potential custom linters but does not enable dot-access to fields on the row.

Organize queries in a private _Queries class within your repository files to keep SQL and mapping logic co-located with their usage.

1
likes
0
points
165
downloads

Publisher

unverified uploader

Weekly Downloads

A minimal, functional wrapper for SQLite/PowerSync using Dart 3 records.

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

powersync, sqlite3, sqlite_async

More

Packages that depend on sqlite_records