Scope a collection (single physical store)
For single-table/collection backends (e.g., PouchDB, Local Storage), scope each collection so queries only return documents for that logical collection.
Quick Navigation
Steps
- Add a tracked computed discriminator to your schema that stores the logical collection name (for example,
documentType). - Apply a global scope when creating the collection so all queries are constrained to that discriminator.
import { s } from "@routier/core/schema";
import { DataStore } from "@routier/datastore";
// Define a discriminator that tags each record with its logical collection name
export const productsSchema = s
.define("products", {
id: s.string().key().identity(),
name: s.string(),
})
.modify((x) => ({
// Persist the logical collection name for single-table/collection backends
documentType: x.computed((_, collectionName) => collectionName).tracked(),
}))
.compile();
// Apply a global scope so all queries are constrained to this collection
export class AppDataStore extends DataStore {
products = this.collection(productsSchema)
.scope(([e, p]) => e.documentType === p.collectionName, { ...productsSchema })
.create();
}Runtime Scope + Inferred Types
When the scope value is only known at runtime (for example, current userSub), initialize those collections in the constructor via factory functions.
Use ReturnType<...> on the collection properties to keep the same inferred collection types you would get from direct property initialization.
import { DataStore } from "@routier/datastore";
import { userSchema, userOrganizationSchema } from "./schemas";
export class AppDataStore extends DataStore {
constructor(private readonly userSub: string) {
super();
this.users = this.usersFactory(userSub);
this.userOrganizations = this.userOrganizationsFactory(userSub);
}
usersFactory = (userSub: string) =>
this.collection(userSchema)
.scope(([x, p]) => x.userRef === p.userSub, { userSub })
.create();
userOrganizationsFactory = (userSub: string) =>
this.collection(userOrganizationSchema)
.scope(([x, p]) => x.userRef === p.userSub, { userSub })
.create();
// Keep strong inferred collection types from the factory return types.
users: ReturnType<AppDataStore["usersFactory"]>;
userOrganizations: ReturnType<AppDataStore["userOrganizationsFactory"]>;
}Why
This prevents cross-type collisions when multiple entity types share a single physical table/collection.
Related
- Concepts: Data Collections
- Integration: PouchDB Plugin