CRUD and queries with policy
Expose create, get, update, remove, find, and all operations through a typed library instance.
Core defines the operation contract. Registry finds the right instances. Lib turns those pieces into application-facing libraries with validation, hooks, finders, actions, facets, and primary/contained behavior for the User graph.
Lib is where generic Item operations become domain behavior. It wraps the lower-level operations and gives your application one coherent place to say what a User, Address, Company, Team, or Membership is allowed to do.
Expose create, get, update, remove, find, and all operations through a typed library instance.
Reject an invalid User update, an Address without required fields, or a Membership with an unsupported role.
Normalize names before create, enrich an Address, emit an audit event, or enforce a policy around updates.
Ask for Alex's manager memberships, find Users by Company, or expose a deliberate domain action instead of leaking storage queries.
const users = createLibrary(
registry,
userCoordinate, // ["user"]
userOperations,
{
validators: {
onCreate: async user =>
!!user.firstName && !!user.lastName,
},
hooks: {
preCreate: async user => ({
...user,
firstName: user.firstName.trim(),
}),
},
},
);
const addresses = createLibrary(
registry,
addressCoordinate, // ["address", "user"]
addressOperations,
{ /* Address-specific rules */ },
);A User library owns User behavior. An Address library owns Address behavior. Neither needs to become a giant service containing every related object. Relationships are composed through coordinates, parent locations, and explicit domain operations.
A Team membership is not merely a link. It has a role, joined date, and possibly permissions. Lib is the right place to express actions such as “promote Alex to manager,” “add Alex to the Platform team,” or “list all managers for this Team.”
await memberships.operations.action(
{ kt: "membership", pk: "alex-platform" },
"promote",
{ role: "manager" },
);Adapters decide how Items are persisted.
HTTP and Express routers decide how requests become operations.
Client API, cache, and providers decide how consumers load and retain results.
Your application defines User fields and business policy; Lib supplies the consistent operation boundary.
Start with the object graph, see how Core defines the runtime, and understand how the Registry composes instances. From here, follow the request into Express Router and persistence adapters.
Previous: registry →Next: Express Router →See the full architecture →