Files
adam-acs/database/base_model.ts
T

110 lines
4.0 KiB
TypeScript

import {
type Db,
type Collection,
ObjectId,
type Filter,
type UpdateFilter,
type Sort,
} from 'mongodb'
import { getMongoDb } from '#providers/mongodb_provider'
export abstract class BaseModel {
static collectionName: string
static getDb(): Db {
return getMongoDb()
}
static getCollection(this: { collectionName: string; getDb(): Db }): Collection {
return this.getDb().collection(this.collectionName)
}
static async find(
this: { collectionName: string; getDb(): Db },
filter: Filter<any> = {}
): Promise<any[]> {
const collection = this.getDb().collection(this.collectionName)
return collection.find(filter).toArray()
}
static async findById(this: { collectionName: string; getDb(): Db }, id: string | ObjectId): Promise<any | null> {
const collection = this.getDb().collection(this.collectionName)
const objectId = typeof id === 'string' ? new ObjectId(id) : id
return collection.findOne({ _id: objectId })
}
static async findOne(this: { collectionName: string; getDb(): Db }, filter: Filter<any>): Promise<any | null> {
const collection = this.getDb().collection(this.collectionName)
return collection.findOne(filter)
}
static async create(this: { collectionName: string; getDb(): Db }, data: Partial<any>): Promise<any> {
const collection = this.getDb().collection(this.collectionName)
const now = new Date()
const doc = { ...data, createdAt: now, updatedAt: now }
const result = await collection.insertOne(doc)
return { ...doc, _id: result.insertedId }
}
static async createMany(this: { collectionName: string; getDb(): Db }, data: Partial<any>[]): Promise<any[]> {
const collection = this.getDb().collection(this.collectionName)
const now = new Date()
const docs = data.map((d) => ({ ...d, createdAt: now, updatedAt: now }))
const result = await collection.insertMany(docs)
return docs.map((doc, i) => ({ ...doc, _id: result.insertedIds[i] }))
}
static async updateOne(
this: { collectionName: string; getDb(): Db },
filter: Filter<any>,
update: UpdateFilter<any> | Partial<any>
): Promise<any> {
const collection = this.getDb().collection(this.collectionName)
const updateDoc = '$set' in update ? update : { $set: { ...update, updatedAt: new Date() } }
return collection.updateOne(filter, updateDoc)
}
static async updateMany(
this: { collectionName: string; getDb(): Db },
filter: Filter<any>,
update: UpdateFilter<any> | Partial<any>
): Promise<any> {
const collection = this.getDb().collection(this.collectionName)
const updateDoc = '$set' in update ? update : { $set: { ...update, updatedAt: new Date() } }
return collection.updateMany(filter, updateDoc)
}
static async deleteOne(this: { collectionName: string; getDb(): Db }, filter: Filter<any>): Promise<boolean> {
const collection = this.getDb().collection(this.collectionName)
const result = await collection.deleteOne(filter)
return result.deletedCount === 1
}
static async deleteMany(this: { collectionName: string; getDb(): Db }, filter: Filter<any>): Promise<number> {
const collection = this.getDb().collection(this.collectionName)
const result = await collection.deleteMany(filter)
return result.deletedCount
}
static async paginate(
this: { collectionName: string; getDb(): Db },
page: number,
perPage: number,
filter: Filter<any> = {},
sort: Sort = {}
): Promise<{ data: any[]; total: number; page: number; perPage: number; lastPage: number }> {
const collection = this.getDb().collection(this.collectionName)
const total = await collection.countDocuments(filter)
const lastPage = Math.max(1, Math.ceil(total / perPage))
const skip = (page - 1) * perPage
const data = await collection.find(filter).sort(sort).skip(skip).limit(perPage).toArray()
return { data, total, page, perPage, lastPage }
}
static query(this: { collectionName: string; getDb(): Db }) {
const collection = this.getDb().collection(this.collectionName)
return collection
}
}