Skip to main content
An adapter is one table passed to Adapters.Register. This page is the whole of it.

Descriptor fields

string
required
vendor.domain. Must match ^[a-z0-9_]+%.[a-z0-9_]+$ and be at most 48 characters. No hyphens. The vetra vendor is reserved.Permanent. It prefixes every object id you emit and is written into every Version.
string
required
Display only, at most 64 characters. Rename it freely: nothing matches on it.
number
required
A positive integer. Your implementation iteration, not a semantic version and not the shape of your data.Compared only for equality and never gates an operation. It warns when a migration’s source Version was captured under a different build of your adapter, and it is hashed into restore and deployment plan fingerprints so a plan computed before an adapter update is never applied after one.Bump it whenever you change anything. It costs nothing.
number
default:"1"
The schema of the records you emit: your type, localId and properties.It moves only when an older record can no longer be read correctly by your current code. See Compatibility.
number
default:"dataVersion"
The oldest record shape you can still read. Defaults to dataVersion, which is the honest default: an adapter that has not said it can read older records is assumed not to.Must not exceed dataVersion.
table
required
{ scope = "persistent" | "session" | "weak" }.The weakest guarantee any id you emit may carry. Enforced as a floor: a record claiming a weaker scope than you declared fails the capture. See Identity.
table
Optional. Declares another addon your adapter bridges to, so Blueprints can start without it.
table
required
{ snapshot = true, ... }. snapshot is required.Unknown keys are warned about and ignored, not rejected: an adapter written for a newer Blueprints still loads on an older one, losing that ability rather than its whole domain.

Capability functions

Each of these is required if and only if you declare the capability it belongs to. Registration refuses a declared capability with a missing function, and names it.

snapshot

-> table
required
Returns an array of normalized objects: every object in your domain, on this map.All of them or none. If you cannot answer, error().May have side effects (assigning identity on first sight is one), but two consecutive calls on an unchanged world must name the same objects and describe them identically.See Records.

transform

-> boolean ok, string|nil reason
Position and orientation only.Returning true and moving nothing is a contract violation, and it is checked by reading the position back rather than by trusting the return value.An unknown localId must return false plus a non-empty reason. Returning nil, or true, is a failure.See Transform.

materialize

-> table
Phase 1. Answers, never writes. Called for previews, so it runs often and must be cheap.
-> table
Phase 2. Creates exactly one object, or none.
identity is required, and never the source’s identity.
-> boolean ok, string|nil reason
Undoes exactly one materialization from the running operation. Not a general delete.Without it, an all-or-nothing group materialization becomes a lie the moment a later member fails, so registration refuses materialize without it.
See Materialize.

properties

-> table
Phase 1. Answers, never writes.
-> boolean ok, string|nil reason
Conforms an existing object to a record you captured. Write the values, read them back, and return false if they did not take.Two functions, not three: the inverse of ApplyProperties is ApplyProperties, called with the earlier record.
See Properties.

remove

-> table
Phase 1. Answers, never writes.An object that is already absent is not a refusal: the postcondition is satisfiable, so return { ok = true }.
-> boolean ok, string|nil reason
Destroys one existing object your adapter owns.
See Removal.

self, and what is on it

Every capability function is called with the descriptor as self. That descriptor is Blueprints’ copy, built at registration from exactly these fields:
Anything else you put on the descriptor is not copied. A helper function or a config table parked there is nil on self.Registration logs a warning naming any field it did not carry, so this is loud rather than silent. Keep your state in your own upvalues.
The copy is also why validation cannot be defeated: the registry holds its own table, so rewriting capabilities or id on the table you passed in changes nothing.

The ctx argument

Some capability functions receive a trailing ctx table describing the operation in progress. It is informational, its shape is not part of the stable contract, and you can ignore it. It is passed to:
and not to Collect, ApplyTransform or ReleaseMaterialized.