All files / src/app/models model.js

92.59% Statements 25/27
100% Branches 8/8
71.42% Functions 5/7
92.59% Lines 25/27

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78      2x                 8x   8x 1x       7x     7x 5x   4x       5x 3x 6x     3x     2x       4x   4x   1x 1x           1x 2x     1x 1x       1x 1x 2x   1x                        
import { Schema, mongoose } from "mongoose";
import { ModelException } from "@common/exceptions/appExceptions.js";
import { newLogger } from "@common/utils/logger.js";
const logger = newLogger("Model|BaseModel");
 
// This class and all its children are instantiated as a promise
export default class BaseModel {
    #model; // Mongoose Model class      see: https://mongoosejs.com/docs/models.html
    #doc; // Mongoose Document class     see: https://mongoosejs.com/docs/documents.html
 
    constructor(id) {
        // Immediately Invoked Async Function Expression ;)
        return (async () => {
            // Throw an exception for models without schema
            if (!(this.constructor.SCHEMA instanceof Schema)) {
                throw new ModelException({ message: `Model "${this.constructor.name}" must have a valid schema` });
            }
 
            // Create and store the Mongoose model for this collection
            this.#model = mongoose.model(this.constructor.name, this.constructor.SCHEMA);
 
            // Existing document
            if (id) {
                if (mongoose.isValidObjectId(id)) {
                    // Don't try to find if it's not even a validObjectId
                    this.#doc = await this.#model.findById(id);
                }
 
                // Copy the properties from the Mongoose doc to the model object
                if (this.#doc) {
                    for (let k in this.#doc._doc) {
                        this[k] = this.#doc._doc[k];
                    }
 
                    return this;
                }
 
                logger.info("Document not found. Creating a new one.");
            }
 
            // New document
            this.#doc = new this.#model();
 
            return this;
        })().catch((err) => {
            logger.error("%s", err);
            throw new ModelException({ message: err });
        });
    }
 
    async save() {
        // Copy the model object properties back to Moongose doc
        for (let k in this) {
            this.#doc[k] = this[k];
        }
 
        await this.#doc.save();
        this._id = this.#doc._id;
    }
 
    async delete() {
        await this.#doc.deleteOne();
        for (let k in this) {
            delete this[k];
        }
        this.#doc = this.#model = null;
    }
 
    async find(filter) {
        return await this.#model.find(filter);
    }
 
    // Returns all distinct data in the specified field and returns in an array
    async distinct(field) {
        return await this.#model.distinct(field);
    }
}