Repositories in Orionjs are specialized services that handle data access operations. They follow the repository pattern, which separates data access logic from business logic, making your code more maintainable and testable.
Basic Usage
Repositories use the @Repository
decorator, which is a semantic distinction from @Service
to clarify the component’s purpose:
import {Repository} from '@orion-js/mongodb'
import {schemaWithName, InferSchemaType} from '@orion-js/schema'
import {createCollection, typedId} from '@orion-js/mongodb'
// Define your schema with types
const UserSchema = schemaWithName('User', {
_id: {
type: typedId('user')
},
name: {
type: String
},
email: {
type: String
}
})
// Infer the type from the schema
type UserType = InferSchemaType<typeof UserSchema>
@Repository()
export class UserRepository {
// Define your collection
private users = createCollection({
name: 'users',
schema: UserSchema
})
async findById(id: string): Promise<UserType | null> {
return await this.users.findOne({_id: id})
}
async create(userData: Omit<UserType, '_id'>) {
return await this.users.insertAndFind(userData)
}
}
Why Use Repositories?
While repositories are functionally similar to services (both use dependency injection), they serve different purposes:
- Services handle business logic, orchestration, and use cases
- Repositories focus exclusively on data access and persistence
This separation of concerns leads to:
- Cleaner code organization
- Easier testing
- Better maintainability
- Clearer dependencies
Dependency Injection
Like services, repositories can be injected into other components using the factory function pattern:
import {Service, Inject} from '@orion-js/services'
import {UserRepository} from './UserRepository'
@Service()
export class UserService {
@Inject(() => UserRepository)
private userRepository: UserRepository
async validateAndCreateUser(userData: {name: string; email: string}) {
// Business logic and validation here
// Use repository for data operations
return this.userRepository.create(userData)
}
}