import {createCollection, MongoFilter, Repository, OptionalId, MongoDB} from '@orion-js/mongodb'
import {InferSchemaType, schemaWithName, typedId} from '@orion-js/schema'
// Define the schema with typedId
export const typedCardId = typedId('crd')
export type CardId = typeof typedCardId.__tsFieldType
export const CardSchema = schemaWithName('Card', {
_id: {type: typedCardId},
name: {type: String},
status: {type: String, optional: true},
createdAt: {type: Date}
})
export type Card = InferSchemaType<typeof CardSchema>
// Define query params schema
export const CardsListQueryParamsSchema = schemaWithName('CardsListQueryParams', {
filter: {type: String, optional: true},
})
export type CardsListQueryParamsType = InferSchemaType<typeof CardsListQueryParamsSchema>
@Repository()
export class CardsRepo {
// Collection is public only to allow access during migrations.
// Never access this collection directly outside this repository.
collection = createCollection({
name: 'gaming.pokemon_cards',
schema: CardSchema,
indexes: [],
})
async createCard(doc: OptionalId<Card>) {
return await this.collection.insertAndFind(doc)
}
// "get" prefix: direct read from primary, guaranteed fresh data
async getCardById(docId: CardId) {
return await this.collection.findOne(docId)
}
// "load" prefix: uses DataLoader (batched/deduplicated, may return cached data within request)
async loadCardById(docId: CardId) {
return await this.collection.loadById(docId)
}
async updateCard(docId: CardId, doc: MongoDB.UpdateFilter<Card>['$set']) {
return await this.collection.updateAndFind(docId, {$set: doc})
}
async deleteCard(docId: CardId) {
await this.collection.updateOne(docId, {$set: {deletedAt: new Date()}})
}
private async getCardsListQuery(params: CardsListQueryParamsType) {
const queries: MongoFilter<Card>[] = []
if (params.filter) {
queries.push({name: {$regex: params.filter, $options: 'i'}})
}
return queries.length ? {$and: queries} : {}
}
// "load" prefix: uses secondaryPreferred (data may be slightly stale)
async loadCardsListCursor(params: CardsListQueryParamsType) {
const query = await this.getCardsListQuery(params)
return this.collection.find(query, {readPreference: 'secondaryPreferred'})
}
// "load" prefix: uses secondaryPreferred
async loadCardsListCount(params: CardsListQueryParamsType) {
const query = await this.getCardsListQuery(params)
return this.collection.countDocuments(query, {readPreference: 'secondaryPreferred'})
}
// "load" prefix: aggregation on secondary
async loadCardsStats() {
return this.collection.aggregate([
{$group: {_id: '$status', count: {$sum: 1}}}
], {readPreference: 'secondaryPreferred'})
}
}