EntitySchemaRegistry provides a centralized mapping between your domain entities and database tables. It handles field name translations, foreign key relationships, and collection configurations - making your mappers cleaner and more maintainable.
Configure how collections (1:N and N:N) should be handled:
registry.register({ entity: "Post", table: "posts", parentFk: { field: "author_id", parentEntity: "User" }, collections: { // 1:N owned relationship - comments belong to post comments: { type: "owned" }, // Field name related to the relationship in the domain; // 'posts.tags' <- Domain Relation field name is 'tags' tags: { // N:N reference relationship - tags exist independently type: "reference", entity: "Tag", // Optional: use when the Prisma relation field name differs from the domain property name // e.g. domain: "tags", Prisma schema field: "post_tags" relationName: "post_tags", // Optional: junction table config (for ORMs that need it) junction: { table: "post_tags", sourceKey: "post_id", targetKey: "tag_id", }, }, },});
When the domain property name and the ORM relation field name differ, use relationName to configure the mapping. ORM adapters such as PrismaBatchExecutor use getRelationFieldName() to resolve the correct field for connect/disconnect operations.
// Prisma schema// model Post {// id String @id// post_tags Tag[] @relation("PostToTag")// }// Domain entity has a property named "tags", but Prisma expects "post_tags"registry.register({ entity: "Post", table: "post", collections: { tags: { type: "reference", entity: "Tag", relationName: "post_tags", // ← ORM field name used for connect/disconnect }, },});// Resolve the ORM field name at runtimeregistry.getRelationFieldName("Post", "tags"); // "post_tags"// Without relationName it falls back to the domain property nameregistry.getRelationFieldName("Post", "comments"); // "comments"
If you omit relationName and your Prisma relation field name differs from the domain property name, PrismaBatchExecutor will pass the wrong field to Prisma’s connect/disconnect operations and the call will fail. Always set relationName when the names diverge.
// Check if entity is registeredregistry.has("User"); // trueregistry.has("Order"); // false// Get schema (throws if not found)const schema = registry.getSchema("User");// Try get schema (returns null if not found)const schema = registry.tryGetSchema("Order"); // null// Get table nameregistry.getTable("User"); // "users"// Get all registered entity namesregistry.getRegisteredEntities(); // ["User", "Post", "Comment"]// Get all schemasregistry.getAllSchemas(); // [{ entity: "User", ... }, ...]// Clear all registrationsregistry.clear();
interface EntitySchema { entity: string; // Domain entity name table: string; // Database table name fields?: Record<string, string>; // Field name mappings parentFk?: { field: string; // FK column name parentEntity: string; // Parent entity name }; collections?: Record<string, CollectionConfig>;}interface CollectionConfig { type: "owned" | "reference"; entity?: string; // Target entity (for reference) relationName?: string; // ORM relation field name when it differs from the domain property name junction?: { table: string; // Junction table name sourceKey: string; // FK to source entity targetKey: string; // FK to target entity };}