API reference › @evolu/common › local‑first/Schema › MutationOptions
Defined in: packages/common/src/local-first/Schema.ts:515
Options accepted by every Mutation.
Properties
onComplete?
readonly optional onComplete?: () => void;
Defined in: packages/common/src/local-first/Schema.ts:537
Called after the mutation's changes are stored and subscribed queries reflect them. Useful for follow-up work (e.g., notifications, navigation) after insert, update, or upsert. It never runs when the database is unavailable or the mutation could not be stored, which EvoluErrorDep.evoluError reports.
An Evolu instance stores its mutations in batches, each in one transaction. A batch holds the mutations made before Evolu sends it in a microtask, usually one synchronous block, and Evolu.requestSync sends it early. When one mutation cannot be stored, none of its batch is.
Stored does not always mean visible. A change quarantined for
QuarantineReason.TimestampDrift is stored in
evolu_message_quarantine without changing application rows. onComplete
still fires after storage commits; no drift error is reported. Applications
can subscribe to the quarantine table; those query results reflect the
change before onComplete runs. See the
Timestamp module for drift
and release behavior.
ownerId?
readonly optional ownerId?: string & Brand<"Id"> & Brand<"OwnerId">;
Defined in: packages/common/src/local-first/Schema.ts:597
Specifies the owner ID for this mutation. If omitted, the default AppOwner is used.
The owner must be used with evolu.useOwner() to enable sync. Mutations
with unused owners are stored locally but not synced until the owner is
used.
Example
import {
assertEqual,
createAppOwner,
createOwnerSecret,
createRandomBytes,
createSharedOwner,
deriveShardOwner,
id,
NonEmptyTrimmedString100,
type Evolu,
} from "@evolu/common";
const Schema = {
task: { id: id("Task"), title: NonEmptyTrimmedString100 },
comment: { id: id("Comment"), text: NonEmptyTrimmedString100 },
};
const randomBytes = createRandomBytes();
// Create once, persist the mnemonic securely, and restore it on later runs.
const appOwner = createAppOwner(createOwnerSecret({ randomBytes }));
const projectOwner = deriveShardOwner(appOwner, ["project", "project-1"]);
const sharedOwner = createSharedOwner(createOwnerSecret({ randomBytes }));
const _insertOwnedRows = (evolu: Evolu<typeof Schema>): void => {
// Partition app data by project.
evolu.insert(
"task",
{ title: NonEmptyTrimmedString100.orThrow("Task 1") },
{ ownerId: projectOwner.id },
);
// Put collaborative data under a shared owner.
evolu.insert(
"comment",
{ text: NonEmptyTrimmedString100.orThrow("Hello") },
{ ownerId: sharedOwner.id },
);
};
assertEqual(projectOwner.type, "ShardOwner");
assertEqual(sharedOwner.type, "SharedOwner");