Skip to content

Commit

Permalink
Merge pull request #46 from AthennaIO/develop
Browse files Browse the repository at this point in the history
feat(model): add a lot of new methods
  • Loading branch information
jlenon7 authored Nov 11, 2022
2 parents f1177f8 + d2d50e4 commit cfc37a7
Show file tree
Hide file tree
Showing 10 changed files with 507 additions and 159 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@athenna/database",
"version": "1.3.0",
"version": "1.3.1",
"description": "The Athenna database handler for SQL/NoSQL.",
"license": "MIT",
"author": "João Lenon <lenon@athenna.io>",
Expand Down
11 changes: 11 additions & 0 deletions src/Database/Builders/QueryBuilder.js
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,17 @@ export class QueryBuilder {
return this.#driver.findOrFail()
}

/**
* Return a single model instance or, if no results are found,
* execute the given closure.
*
* @param callback {() => Promise<any>}
* @return {Promise<any>}
*/
async findOr(callback) {
return this.#driver.findOr(callback)
}

/**
* Find a value in database.
*
Expand Down
17 changes: 17 additions & 0 deletions src/Drivers/MySqlDriver.js
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,23 @@ export class MySqlDriver {
return data
}

/**
* Return a single model instance or, if no results are found,
* execute the given closure.
*
* @param callback {() => Promise<any>}
* @return {Promise<any>}
*/
async findOr(callback) {
const data = await this.find()

if (!data) {
return callback()
}

return data
}

/**
* Find a value in database.
*
Expand Down
17 changes: 17 additions & 0 deletions src/Drivers/PostgresDriver.js
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,23 @@ export class PostgresDriver {
return data
}

/**
* Return a single model instance or, if no results are found,
* execute the given closure.
*
* @param callback {() => Promise<any>}
* @return {Promise<any>}
*/
async findOr(callback) {
const data = await this.find()

if (!data) {
return callback()
}

return data
}

/**
* Find a value in database.
*
Expand Down
61 changes: 61 additions & 0 deletions src/Models/Model.js
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,24 @@ export class Model {
return query.where(where).findOrFail()
}

/**
* Return a single model instance or, if no results are found,
* execute the given closure.
*
* @param where {any}
* @param callback {() => Promise<any>}
* @return {Promise<any>}
*/
static async findOr(where = {}, callback) {
const query = this.query()

if (Object.keys(where).length) {
query.where(where)
}

return query.where(where).findOr(callback)
}

/**
* Get one data in DB and return as a subclass instance.
*
Expand Down Expand Up @@ -275,6 +293,7 @@ export class Model {
* @param [page] {boolean}
* @param [limit] {boolean}
* @param [resourceUrl] {string}
* @param [where] {any}
* @return {Promise<{
* data: InstanceType<this>[],
* meta: {
Expand Down Expand Up @@ -465,6 +484,48 @@ export class Model {
return this
}

/**
* Re-retrieve the model from the database. The existing
* model instance will not be affected.
*
* @return {Promise<this>}
*/
async fresh() {
const Model = this.constructor

return Model.query()
.where({ [Model.primaryKey]: this[Model.primaryKey] })
.find()
}

/**
* Re-retrieve the model from the database. The existing
* model instance will not be affected.
*
* @return {Promise<this>}
*/
async refresh() {
const Model = this.constructor

const relations = Model.getSchema().relations.map(r => r.name)

const query = Model.query().where({
[Model.primaryKey]: this[Model.primaryKey],
})

Object.keys(this).forEach(key => {
if (!relations.includes(key)) {
return
}

query.includes(key)
})

const data = await query.find()

Object.keys(data).forEach(key => (this[key] = data[key]))
}

/**
* Save all sub schema models inside instance and
* return the json data without these schemas.
Expand Down
147 changes: 136 additions & 11 deletions src/Models/ModelQueryBuilder.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,124 @@ export class ModelQueryBuilder {
return this.#QB.getQueryBuilder()
}

/**
* Calculate the average of a given column.
*
* @param {string} column
* @return {Promise<number>}
*/
async avg(column) {
this.#setCriterias()

return this.#QB.avg(this.#parseNames(column))
}

/**
* Calculate the average of a given column.
*
* @param {string} column
* @return {Promise<number>}
*/
async avgDistinct(column) {
this.#setCriterias()

return this.#QB.avgDistinct(this.#parseNames(column))
}

/**
* Get the max number of a given column.
*
* @param {string} column
* @return {Promise<number>}
*/
async max(column) {
this.#setCriterias()

return this.#QB.max(this.#parseNames(column))
}

/**
* Get the min number of a given column.
*
* @param {string} column
* @return {Promise<number>}
*/
async min(column) {
this.#setCriterias()

return this.#QB.min(this.#parseNames(column))
}

/**
* Sum all numbers of a given column.
*
* @param {string} column
* @return {Promise<number>}
*/
async sum(column) {
this.#setCriterias()

return this.#QB.sum(this.#parseNames(column))
}

/**
* Sum all numbers of a given column.
*
* @param {string} column
* @return {Promise<number>}
*/
async sumDistinct(column) {
this.#setCriterias()

return this.#QB.sumDistinct(this.#parseNames(column))
}

/**
* Increment a value of a given column.
*
* @param {string} column
* @return {Promise<number | number[]>}
*/
async increment(column) {
this.#setCriterias()

return this.#QB.increment(this.#parseNames(column))
}

/**
* Decrement a value of a given column.
*
* @param {string} column
* @return {Promise<number | number[]>}
*/
async decrement(column) {
this.#setCriterias()

return this.#QB.decrement(this.#parseNames(column))
}

/**
* Calculate the average of a given column using distinct.
*
* @param {string} column
* @return {Promise<number>}
*/
async count(column = '*') {
this.#setCriterias()

return this.#QB.count(column === '*' ? column : this.#parseNames(column))
}

/**
* Calculate the average of a given column using distinct.
*
* @param {string} column
* @return {Promise<number>}
*/
async countDistinct(column) {
return this.#QB.countDistinct(this.#parseNames(column))
}

/**
* Find one data in database or throw exception if undefined.
*
Expand All @@ -100,6 +218,24 @@ export class ModelQueryBuilder {
return this.#generator.generateOne(await this.#QB.findOrFail())
}

/**
* Return a single model instance or, if no results are found,
* execute the given closure.
*
* @return {Promise<any>}
*/
async findOr(callback) {
this.#setCriterias()

const data = await this.#QB.find()

if (data) {
return this.#generator.generateOne(data)
}

return callback()
}

/**
* Find one data in database.
*
Expand Down Expand Up @@ -184,17 +320,6 @@ export class ModelQueryBuilder {
return { data: await this.#generator.generateMany(data), meta, links }
}

/**
* Count the number of models in database.
*
* @return {Promise<number>}
*/
async count() {
this.#setCriterias()

return this.#QB.count()
}

/**
* Create one model in database.
*
Expand Down
Loading

0 comments on commit cfc37a7

Please sign in to comment.