Orionjs schemas seamlessly integrate with MongoDB through the @orion-js/mongodb
package, providing type-safe database operations.
Defining Collections
To create a MongoDB collection with schema validation:
import {createCollection} from '@orion-js/mongodb'
import {schemaWithName, InferSchemaType} from '@orion-js/schema'
// Define your schema
export const UserSchema = schemaWithName('UserSchema', {
_id: {type: String},
name: {type: String},
email: {type: String},
createdAt: {type: Date}
})
// Infer the TypeScript type from the schema
export type UserType = InferSchemaType<typeof UserSchema>
// Create a typed collection
const Users = createCollection({
name: 'users',
schema: UserSchema
})
// Now you have type-safe database operations
const user: UserType = await Users.findOne({email: 'user@example.com'})
TypedId Support
Orionjs MongoDB has built-in support for typed IDs with automatic prefixing:
import {typedId} from '@orion-js/mongodb'
import {schemaWithName, InferSchemaType} from '@orion-js/schema'
export const ProductSchema = schemaWithName('ProductSchema', {
_id: {type: typedId('product')}, // Will create IDs like 'product-abc123'
name: {type: String},
price: {type: Number}
})
export type ProductType = InferSchemaType<typeof ProductSchema>
// The type for _id will be `product-${string}`
Collection Operations
All MongoDB collection operations are typed based on your schema:
import {createCollection} from '@orion-js/mongodb'
import {OptionalId} from '@orion-js/mongodb'
// OptionalId makes the _id field optional for insert operations
const newUser: OptionalId<UserType> = {
name: 'John Doe',
email: 'john@example.com',
createdAt: new Date()
}
// Insert with type safety
const userId = await Users.insertOne(newUser)
// Update with type checking
await Users.updateOne(
{_id: userId},
{$set: {name: 'John Smith'}}
)
// Find with type safety
const user = await Users.findOne({_id: userId})
console.log(user.name) // TypeScript knows the structure
Schema Validation in MongoDB
When you create a collection with a schema, Orionjs automatically:
- Creates a MongoDB validation schema based on your Orionjs schema
- Applies validation on all insert and update operations
- Enforces types and constraints defined in your schema
// This will throw a validation error
try {
await Users.insertOne({
name: 123, // Type error: should be string
email: 'invalid-email' // Validation error if email type is used
})
} catch (error) {
console.error('Validation failed:', error)
}
Repository Pattern
For better organization, you can create a repository class for each collection:
import {createCollection} from '@orion-js/mongodb'
import {schemaWithName, InferSchemaType} from '@orion-js/schema'
import {Service} from '@orion-js/services'
export const UserSchema = schemaWithName('UserSchema', {
_id: {type: typedId('user')},
name: {type: String},
email: {type: String},
createdAt: {type: Date}
})
export type UserType = InferSchemaType<typeof UserSchema>
@Service()
export class UserRepository {
private users = createCollection({
name: 'users',
schema: UserSchema
})
async findById(id: string) {
return this.users.findOne({_id: id})
}
async findByEmail(email: string) {
return this.users.findOne({email})
}
async create(user: Omit<UserType, '_id'>) {
return this.users.insertOne(user)
}
async updateName(id: string, name: string) {
await this.users.updateOne({_id: id}, {$set: {name}})
}
}
Index Management
You can define indices for your collections:
import {createCollection} from '@orion-js/mongodb'
import {UserSchema} from './schemas/UserSchema'
const Users = createCollection({
name: 'users',
schema: UserSchema,
indexes: [
{
keys: {email: 1},
options: {unique: true}
},
{
keys: {name: 1, createdAt: -1}
}
]
})