Attachments and Dirty Tracking
Goal: Understand how to inspect and control the internal change tracking set for a collection, force-mark items dirty, and transfer tracking metadata across DataStore instances.
When to use
- You need to persist an entity even if no properties changed (force dirty)
- You want to include/exclude specific entities from the next save
- You run multiple
DataStoreinstances and need to transfer the tracked set between them
Key ideas
- Attachments collection: Each collection exposes an attachments helper for interacting with the change-tracked set
- Dirty state: Use
getChangeType(entity)to inspect state andmarkDirty(entity)to force persistence - Add/Remove: Use
set(...entities)andremove(entity)to manage which entities are tracked - Transfer: Move attachments between
DataStoreinstances to keep tracking metadata in sync
Example
import { DataStore } from "@routier/datastore";
import { MemoryPlugin } from "@routier/memory-plugin";
import { s } from "@routier/core/schema";
const productSchema = s
.define("products", {
id: s.string().key().identity(),
name: s.string(),
category: s.string(),
price: s.number(),
inStock: s.boolean(),
})
.compile();
class Ctx extends DataStore {
products = this.collection(productSchema).create();
constructor(dbName: string) {
super(new MemoryPlugin(dbName));
}
}
// Two contexts pointing at the same database
const ctx1 = new Ctx("app-db");
const ctx2 = new Ctx("app-db");
// Seed and save
const [created] = await ctx1.products.addAsync({
name: "Mouse",
category: "accessory",
price: 49.99,
inStock: true,
});
await ctx1.saveChangesAsync();
// Force-mark an entity as dirty without changing fields
const first = await ctx1.products.firstAsync();
ctx1.products.attachments.markDirty(first);
// Save will include the entity even if no field changed
await ctx1.saveChangesAsync();
// Transfer attachments between contexts
// Attach in ctx2 so it can manage/save this entity's changes
ctx2.products.attachments.set(first);
// Change and save from ctx2
first.price = 44.99;
await ctx2.saveChangesAsync();
// Inspect attachment state
const changeType = ctx2.products.attachments.getChangeType(first);
// changeType could be: "notModified", "propertiesChanged", "markedDirty", etc.Notes
markDirtyis useful when a plugin requires an update write even if values are identical- Transferring attachments works best when both contexts reference the same physical database/plugin config
Related
- Change Tracking — how change tracking works
- State Management — patterns for working with collections and saves