Model Embedding
Model embedding in Hysteria ORM allows you to attach models directly to a SQL data source instance, providing a convenient way to access your models through the data source. This feature is similar to Prisma's client model access pattern.
Overview
When you embed models in a SQL data source instance, they become available as properties on the data source object, allowing you to access them directly without importing the model classes separately.
Basic Usage
Connecting with Embedded Models
import { SqlDataSource } from "hysteria-orm";
import { User } from "./models/User";
import { Post } from "./models/Post";
// Connect with embedded models
const sql = await SqlDataSource.connect({
models: {
user: User,
post: Post,
},
});
// Access models directly through the data source
const users = await sql.user.query().many();
const posts = await sql.post.query().many();
Using with Secondary Connections
// Create a secondary connection with embedded models
const anotherSql = await SqlDataSource.connectToSecondarySource({
models: {
user: User,
post: Post,
},
});
// Use the embedded models with the specific connection
const user = await anotherSql.user.insert(
{ name: "John Doe" },
{ useConnection: anotherSql }
);
Using with Temporary Connections
await SqlDataSource.useConnection(
{
type: "postgres",
host: "localhost",
port: 5432,
username: "user",
password: "password",
database: "mydb",
models: {
user: User,
post: Post,
},
},
async (sql) => {
const user = await sql.user.insert({ name: "John Doe" });
const posts = await sql.post.query().many();
}
);
TypeScript Support
For proper TypeScript support when using embedded models, use the AugmentedSqlDataSource
type:
import { AugmentedSqlDataSource } from "hysteria-orm";
import { User } from "./models/User";
import { Post } from "./models/Post";
let sql: AugmentedSqlDataSource<{
user: typeof User;
post: typeof Post;
}>;
beforeAll(async () => {
sql = await SqlDataSource.connect({
models: {
user: User,
post: Post,
},
});
});
Error Handling
Duplicate Model Keys
The most common error occurs when you try to use a model key that conflicts with existing SqlDataSource properties or methods. The following will throw a HysteriaError
:
// ❌ This will throw an error - 'connect' is a reserved method
await SqlDataSource.connect({
models: {
connect: User, // Error: Duplicate model keys while instantiating models
},
});
// ❌ This will also throw an error - 'query' is a reserved method
await SqlDataSource.connect({
models: {
query: User, // Error: Duplicate model keys while instantiating models
},
});
// ✅ This works correctly
await SqlDataSource.connect({
models: {
user: User,
post: Post,
},
});
Reserved Keywords
The following keywords are reserved and cannot be used as model keys:
connect
query
disconnect
startGlobalTransaction
commitGlobalTransaction
rollbackGlobalTransaction
closeConnection
isConnected
getDbType
rawQuery
useConnection
connectToSecondarySource
Important Notes
Static Singleton Connection Limitation
Important: Model embedding is not available with the static singleton connection pattern. You must use a SQL data source instance to embed models.
// ❌ This does NOT support model embedding
import { sql } from "hysteria-orm";
await sql.connect();
// Models are not embedded in the global sql instance
// ✅ This supports model embedding
const sqlInstance = await SqlDataSource.connect({
models: {
user: User,
post: Post,
},
});
// Models are embedded in sqlInstance
Model Independence
Embedded models can still be used as standalone entities. Embedding them in a data source instance is optional and provides convenience but doesn't change their core functionality.
// Models work both ways
const sql = await SqlDataSource.connect({
models: { user: User },
});
// Using embedded model
const user1 = await sql.user.query().first();
// Using standalone model (still works)
const user2 = await User.query().first();
Best Practices
-
Use descriptive model keys: Choose meaningful names for your model keys that reflect the model's purpose.
-
Type your data sources: Always use
AugmentedSqlDataSource<T>
for proper TypeScript support when embedding models. -
Avoid reserved keywords: Check that your model keys don't conflict with SqlDataSource methods or properties.
-
Consider connection scope: Use embedded models when you need model access within a specific connection context.
-
Error handling: Always handle potential
HysteriaError
exceptions when connecting with embedded models.