/**
* @module flitter-orm/src/proxy/model/ModelProxy
*/
const CursorBuilder = require('../../model/CursorBuilder')
const { ObjectId } = require('mongodb')
/**
* A proxy class for adding restrictive layers to a model.
*/
class ModelProxy {
/**
* Instantiates the proxy.
* @param {module:flitter-orm/src/model/Model~Model|module:flitter-orm/src/proxy/model/ModelProxy~ModelProxy} reference - the parent reference
* @param {module:flitter-orm/src/model/CursorBuilder~CursorBuilder} [builder] - optionally, the cursor builder to use
*/
constructor(reference, builder = new CursorBuilder()) {
/**
* The cursor builder applied by this proxy.
* @type {module:flitter-orm/src/model/CursorBuilder~CursorBuilder}
*/
this.builder = builder
/**
* The parent reference of this proxy.
* @type {module:flitter-orm/src/model/Model~Model|module:flitter-orm/src/proxy/model/ModelProxy~ModelProxy}
*/
this.reference = reference
}
/**
* Get the collection instance for the proxy reference.
* @returns {Promise<mongodb/Collection>}
* @private
*/
async __collection() {
return this.reference.__collection()
}
/**
* Get a cursor for the reference, and apply the proxy's builder.
* @param {object} [filter = {}] - mongodb filter options
* @param {object} [opts = {}] - optional mongodb params
* @returns {Promise<*>}
*/
async cursor(filter = {}, opts = {}) {
const cursor = await this.reference.cursor(filter, opts)
return await this.builder.apply(cursor)
}
/**
* Find a set of records subject to this proxy's restrictions.
* @param {object} [filter = {}] - mongodb filters to apply
* @param {object} [opts = {}] - optional mongodb params
* @returns {Promise<Array<module:flitter-orm/src/model/Model~Model>>}
*/
async find(filter = {}, opts = {}) {
const cursor = await this.cursor(filter, opts)
return this.reference.from_cursor(cursor)
}
/**
* Find a single record subject to this proxy's restrictions.
* @param {object} [filter = {}] - mongodb filters to apply
* @param {object} [opts = {}] - optional mongodb params
* @returns {Promise<module:flitter-orm/src/model/Model~Model>}
*/
async findOne(filter, opts) {
const cursor = await this.cursor(filter, opts)
return (await this.reference.from_cursor(cursor.limit(1)))[0]
}
/**
* Delete the set of records subject to this proxy's restrictions.
* @param {object} [filter = {}] - mongodb filters to apply
* @param {object} [opts = {}] - optional mongodb params
* @returns {Promise<void>}
*/
async deleteMany(filter, opts) {
const cursor = await this.cursor(filter, opts)
let ids = (await cursor.toArray()).map(x => x._id)
ids = ids.map(x => {
if ( typeof x === 'string' ) return ObjectId(x)
return x
})
const coll = await this.__collection()
await coll.deleteMany({_id: {$in: ids}})
}
/**
* Delete a single record subject to this proxy's restrictions.
* @param {object} [filter = {}] - mongodb filters to apply
* @param {object} [opts = {}] - optional mongodb params
* @returns {Promise<module:flitter-orm/src/model/Model~Model>} - the deleted model
*/
async deleteOne(filter, opts) {
const cursor = await this.cursor(filter, opts)
const rec = (await this.reference.from_cursor(cursor))[0]
return rec.delete()
}
/**
* Get an array of model instances from the provided cursor.
* @param {mongodb/cursor} cursor
* @returns {Promise<Array<module:flitter-orm/src/model/Model~Model>>}
*/
async from_cursor(cursor) {
return this.reference.from_cursor(cursor)
}
// ----------- Helpers for building proxy chains --------------- //
/**
* Limit the results to a specified number of records.
* @param {number} to
* @returns {module:flitter-orm/src/proxy/model/LimitProxy~LimitProxy}
*/
limit(to) {
const LimitProxy = require('./LimitProxy')
return new LimitProxy(this, to)
}
/**
* Sort the result set by the provided field(s).
* @param {string} sorts... - variable number of fields to sort
* @example
* Model.sort('+first_name', '+last_name', '-create_date')
* @returns {module:flitter-orm/src/proxy/model/SortProxy~SortProxy}
*/
sort(...sorts) {
const SortProxy = require('./SortProxy')
return new SortProxy(this, sorts)
}
/**
* Get a filter object whose reference is this proxy.
* @param {module:flitter-orm/src/model/Model|module:flitter-orm/src/proxy/model/ModelProxy} ref
* @returns {Promise<module:flitter-orm/src/filter/Filter~Filter>}
*/
async filter(ref = false) {
if ( !ref ) ref = this
return this.reference.filter(ref)
}
}
module.exports = exports = ModelProxy