DatabaseAdapter class
One database, described by what flutterware may do with it.
DatabaseAdapter(
query: (sql, args) => db.getAll(sql, args),
updates: db.updates.map((u) => u.tables),
watch: (sql) => db.watch(sql),
)
A database that is not open yet
Plenty of apps have no database at runApp: it is opened at login, closed
at logout, and replaced when the user switches environment. There is
nothing to hand this constructor at the moment the devbar is built.
The adapter is the shape; the session is the data. Close over the lookup rather than over the database, and resolve it inside each function:
DatabaseAdapter(
query: (sql, args) => _db().getAll(sql, args),
watch: (sql) => _db().watch(sql),
updates: _updates.stream,
)
Database _db() {
var db = session?.database;
if (db == null) {
throw DatabaseUnavailable('No session is open — sign in to reach the '
'database.');
}
return db;
}
Two things about that are not optional. Presence is read once, when the panel is described: an adapter that leaves execute null while logged out declares an app with no write door, permanently, and the same goes for watch and updates. Pass every function the app will ever offer, and let the ones with nothing to work on throw. And updates is the one field that cannot be resolved late — it is a stream, handed over once, not a function called per query. Own a broadcast controller that outlives every session and forward the current database into it:
final _updates = StreamController<Set<String>>.broadcast();
StreamSubscription<void>? _forwarding;
void _sessionChanged(Session? session) {
unawaited(_forwarding?.cancel());
_forwarding = session?.database.updates
.listen((update) => _updates.add(update.tables));
}
Why a panel that answers rather than one that disappears. The other
shape — declaring the panel only while a session is open, which
AddDevbarPanel and DevbarPanels make possible — leaves the absence
unexplained. Ask for
db:main when it is gone and every surface says the same thing, "this app
declares no panel db:main", whether the app has no database at all or the
user is one tap from opening one. A panel that is always listed and answers
DatabaseUnavailable tells those apart, and it is the same call flutterware
makes for an app that never reached runApp: say what is wrong, do not go
missing.
Constructors
-
DatabaseAdapter({String name = 'main', required DatabaseQuery query, Stream<
Set< ? updates, DatabaseWatch? watch, DatabaseQuery? execute, DatabaseSync? sync})String> >
Properties
- execute → DatabaseQuery?
-
Presence is the write opt-in. No function, no
executeaction, on any surface — an agent cannot even see it.final - hashCode → int
-
The hash code for this object.
no setterinherited
- name → String
-
Names the panel —
db:main— and nothing else. Two databases are two adapters with two names.final - query → DatabaseQuery
-
final
- runtimeType → Type
-
A representation of the runtime type of the object.
no setterinherited
- sync → DatabaseSync?
-
The sync engine that keeps this database, when one does. Said, not
guessed: an app on plain sqlite gets nothing it has no use for.
final
-
updates
→ Stream<
Set< ?String> > -
Table names touched, per write transaction. Feeds the
changesfeed and the watch fallback; without it neither exists.final - watch → DatabaseWatch?
-
Optional native live query. When absent, a watch falls back to re-running
its SQL on every coalesced updates tick — correct, just wasteful.
final
Methods
-
noSuchMethod(
Invocation invocation) → dynamic -
Invoked when a nonexistent method or property is accessed.
inherited
-
toString(
) → String -
A string representation of this object.
inherited
Operators
-
operator ==(
Object other) → bool -
The equality operator.
inherited