@projectpac/records
v0.6.0
Published
Part of PAC: @projectpac/records.
Readme
@projectpac/records
The record store: a plugin's durable memory of what it is in the middle of,
claiming ctx.records.
A flow runs no loop, so between one event and the next everything it knows has
to be written down. A flow opens a store by name, hands over the schema its
records satisfy and says which field is the key, and gets back synchronous
reads and writes -- all, get, put, update, remove, find, first,
newest first. The shape is the flow's; durability is this service's. A write
lands before the call returns, one record changing does not rewrite the rest,
and a read cannot see a half-written record.
static readonly inject = ["records"];
const calls = ctx.records.open<Call>("calls", {
schema: callSchema,
key: (call) => call.call,
});Whose records they are is never said. The calling plugin is derived off the
accessing context, so a store lives in the caller's own folder -- one sqlite
file, <data dir>/<plugin>/records.db -- and there is no argument by which one
plugin could open another's. A core plugin is refused: the components keep
their own stores, and a guess here would put a file where nothing finds it
again. The file is opened when the plugin first asks and closed as an effect of
the plugin's own scope, so disabling a plugin closes its records and enabling
it opens them again.
Why it left the host
This was ctx.self.records(...), on the binding the host hands every plugin,
and the host was the wrong owner. The kernel was writing a database into every
plugin's folder for a schema it never read, running migrations over a table
whose shape it could not change, and a node that ran no flow paid for a store
nothing used. Nothing about it needed the kernel: the one thing it does that a
plain file could not -- attribute the store to the caller -- is the same
derivation every flow service makes. So it is one, installed like any other,
and the sdk holds one contract fewer. A flow that keeps records injects
records and waits for this to be installed, which GET /plugins shows as
waitingFor: ["records"].
Compatibility
Plain better-sqlite3, one CREATE TABLE IF NOT EXISTS, no drizzle and no
migrations: the table is generic, so there is nothing a migration could ever
change. The file, the table and the index keep the names the host's version
gave them -- records.db, records (store, key, body, at),
records_store_idx -- so a records.db the host wrote opens unchanged, with
drizzle's own ledger table sitting beside it unread.
