import type Schema from 'libs/Schema' import type { Model, ModelInfer, SchemaInfer } from 'libs/Schema' import type { Query } from '../Query' export interface DBPull { /** * total number of rows that are valid with the specified query */ rows: number /** * total number of rows in the table */ rowsTotal: number /** * current page number */ page: number /** * total amount of pages */ pageTotal: number /** * the data fetched */ data: Array> } /** * the DaoAdapter is the object that connect the Database or source to the application layer * * you MUST call it through the `DaoFactory` file */ export default abstract class DaoAdapter { /** * insert a new object into the source * * @param obj the object to create * @returns the object with it's id filled if create or null otherwise */ abstract create(obj: Partial>): Promise | null> /** * insert a new object into the source * * @param obj the object to create * @returns the object with it's id filled if create or null otherwise */ public insert: DaoAdapter>['create'] = (obj: Parameters>['create']>[0]) => this.create(obj) /** * find the list of objects having elements from the query * * @param query a partial object which filter depending on the elements, if not set it will fetch everything * @returns an array containing the list of elements that match with the query */ abstract read(query?: Query> | undefined): Promise>> /** * find the list of objects having elements from the query * * @param query a partial object which filter depending on the elements, if not set it will fetch everything * @returns an array containing the list of elements that match with the query */ public findAll: DaoAdapter>['read'] = (query: Parameters>['read']>[0]) => this.read(query) /** * find the list of objects having elements from the query * * @param query a partial object which filter depending on the elements, if not set it will fetch everything * @returns an array containing the list of elements that match with the query */ public find: DaoAdapter>['read'] = (query: Parameters>['read']>[0]) => this.read(query) /** * find an object by it's id * * (shortcut to findOne({id: id})) * * @param id the id of the object * @returns */ public findById(id: ModelInfer['id']): Promise | null> { return this.findOne({ id: id } as Partial>) } /** * find an object by it's id * * (shortcut to findOne({id: id})) * * @param id the id of the object * @returns */ public get(id: ModelInfer['id']) { return this.findById(id) } /** * find the first element that match `query` * * @param query a partial object which filter depending on the elements, if not set it will fetch everything * @returns the first element matching with the query or null otherwise */ public async findOne(query?: Partial>): Promise | null> { return (await this.findAll(query)).data[0] ?? null } /** * update the remote reference of the object * * note: it will not try to insert an item (use `upsert` to handle this) * * @param obj the object to update * @returns an object if it was able to update or null otherwise */ abstract update(obj: Partial>): Promise | null> /** * change some elements from the object and return the object updated * @param id the id of the object * @param changegs the change to make */ public async patch(id: ModelInfer['id'], changes: Partial>): Promise | null> { const query = await this.findById(id) if (!query) { return null } return await this.update({ ...query, ...changes }) } /** * update the remote reference of the object or create it if not found * @param obj the object to update/insert * @returns the object is updated/inserted or null otherwise */ public async upsert( object: Partial> ): Promise | null> { if ('id' in object) { return this.update(object) } return this.insert(object) } /** * Delete the object * @param obj the object to delete * * @returns if the object was deleted or not (if object is not in db it will return true) */ abstract delete(obj: ModelInfer): Promise }