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

build_runner code generator for the Basalt Dart ORM — derives row readers and INSERT/UPDATE builders from @Queryable, @Insertable, and @AsChangeset.

basalt_codegen #

Dart Builder Part of

build_runner / source_gen code generation for basalt_dart — the Dart analog of derive macros. It derives row mappers, self-mapping join queries, and INSERT/UPDATE builders from the annotations in package:basalt.

Contents #

Setup #

dev_dependencies:
  basalt_codegen:
  build_runner: ^2.4.0

Add a part directive next to your annotated classes and run the builder:

import 'package:basalt/basalt.dart';
import 'schema.dart';

part 'user.g.dart';
dart run build_runner build          # one-shot
dart run build_runner watch          # rebuild on change

The builder is a SharedPartBuilder, so all generated code for a file lands in one <file>.g.dart. Three generators run — QueryableGenerator, InsertableGenerator, AsChangesetGenerator — and a class may carry any combination of the annotations.

What it generates #

Annotation Output
@Queryable(table) $XFromRow reader, const xMapper = RowMapper<X>(…), an xQuery getter, and a bare findX(pk) when the class maps a PrimaryKey
@Insertable(table) extension XInsert on X { InsertStatement<T> toInsert() }
@AsChangeset(table) extension XChangeset on X { UpdateStatement<T> toUpdate() } (the SET clause; you append .where(...))
@Column(col, {readOnly, writeOnly}) field → column mapping and read/write direction
@Relation(fk, {depth}) a joined, nested related object (read-side), unrolled depth levels with path aliases

For a class with @Relations, xQuery is a self-mapping join query — it wires up the joins, table aliases, and nested decoding for you and is still a chainable MappedQuery. For a class without relations, xQuery narrows the projection to exactly that class's columns (the "Selectable" analog).

Field mapping #

  • Fields map to columns by name (camelCase ↔ snake_case) unless @Column(SomeTable.col) overrides.
  • readOnly — read on SELECT, skipped on write (autoincrement PKs, server defaults).
  • writeOnly — written but skipped by the row reader (the field must be optional so its default is used).
  • Setting both is a generation error — a field that's neither read nor written isn't a column; use a getter.
  • @Relation fields must be nullable, optional, and named; the write derives skip them.

Full details and edge cases: packages/basalt/doc/annotations.md.

A worked example #

@Queryable(Users.table)
@Insertable(Users.table)
@AsChangeset(Users.table)
class User {
  final int id;
  final String name;
  final int age;
  @Relation(Users.managerId, depth: 2) // self-join, nested two levels
  final User? manager;
  const User(this.id, this.name, this.age, {this.manager});
}

generates (abridged) user.g.dart:

User $UserFromRow(RowReader r, [QuerySource<Users> src = Users.table, ...]) =>
    User(r.get(src.col(Users.id)), r.get(src.col(Users.name)), r.get(src.col(Users.age)),
         manager: /* nested join, alias-safe */);

const userMapper = RowMapper<User>($UserFromRow);
MappedQuery<User> get userQuery { /* leftJoin the manager, map */ }
// find by PK: userQuery.findBy(Users.id, id)

See example/ for a complete two-file model (cross-file @Relation) and its generated output.

How it works #

The pipeline is small and layered:

EdgeAnalyzer (analyzer elements → a plain model)
      → pure string emitters (reader_emitter, insert_emitter, changeset_emitter, relation emitters)
      → generators (thin GeneratorForAnnotation bridges) registered in builder.dart

Emitters are pure functions, unit-tested under test/ without the analyzer; the generators are thin analyzer bridges. Adding a new derive is a five-step recipe (annotation → TypeChecker/parsing → emitter → generator → register in builder.dart) — see CONTRIBUTING.md.

0
likes
160
points
39
downloads

Documentation

Documentation
API reference

Publisher

unverified uploader

Weekly Downloads

build_runner code generator for the Basalt Dart ORM — derives row readers and INSERT/UPDATE builders from @Queryable, @Insertable, and @AsChangeset.

Repository (GitHub)
View/report issues
Contributing

Topics

#orm #code-generation #build-runner #database

License

MIT (license)

Dependencies

analyzer, basalt, build, source_gen

More

Packages that depend on basalt_codegen