UNPKG

better-sqlite3-orm

Version:

Object Relational Mapper for Better-Sqlite3-Cypher

252 lines (220 loc) 7.92 kB
// model.js: ("use strict"); /*** check to be sure database is defined and is connected */ function checkDB(db, table, method) { if (!db) { throw new Error(`Database is undefined! (${table}.${method})`); } else if (!db.connected) { throw new error(`Database is not connected! (${table}.${method})`); } } /** * Represents a base Model class for ORM-like functionality. */ class Model { /** * Constructs a new Model instance. * @param {Database} db - The database instance. * @param {string} table - The name of the table. * @param {object[]} Array of column definitions. * @param {object} [options={}] - Additional options for the model. */ constructor(db, table, columns, options = {}) { // ensure the db param is a valid database and that it is connected checkDB(db, table, "constructor"); /*** * @type {Database} * @description The database instance. For internal use only. */ this.db = db; /*** * @type {string} * @description The name of the table. For internal use only. */ this.table = table; /*** * @type {object[]} * @description The column definitions. For internal use only. */ this.columns = columns; /*** * @type {object} * @description Additional options for the model. For internal use only. */ this.options = options; } /** * Creates the table for the model in the database. * @param {Database} [dbInstance] - Optional database instance to use. */ createTable(dbInstance = this.db) { checkDB(dbInstance, this.table, "createTable"); dbInstance.createTable(this.table, this.columns); } /** * Drops the table for the model in the database. * @param {Database} [dbInstance] - Optional database instance to use. */ dropTable(dbInstance = this.db) { checkDB(dbInstance, this.table, "dropTable"); dbInstance.dropTable(this.table); } /** * Finds a record by its ID. * @param {number} id - The ID of the record to find. * @param {Database} [dbInstance] - Optional database instance to use. * @returns {object|null} The record if found, or null if not. */ findById(id, dbInstance = this.db) { checkDB(dbInstance, this.table, "findByIdd"); let data = dbInstance.findById(this.table, this.columns, id); this.setData(data); return data; } /** * Finds a record by a specified column name and value. * @param {string} name - The name of the column to look up a record to find. * @param {variant} value - the value to find in the specified column * @param {Database} [dbInstance] - Optional database instance to use. * @returns {object|null} The record if found, or null if not. */ findByColumn(name, value, dbInstance = this.db) { checkDB(dbInstance, this.table, "findByColumn"); let data = dbInstance.findByColumn(this.table, this.columns, name, value); if (data !== null) { this.setData(data); } return data; } /** * Finds a single record based on a condition. * @param {string} criteria - The condition to match (SQL WHERE clause). * @param {object} params - The parameters for the condition. * @param {Database} [dbInstance] - Optional database instance to use. * @returns {object|null} The record if found, or null if not. */ findOne(criteria = "", params = {}, options = {}, dbInstance = this.db) { checkDB(dbInstance, this.table, "findOne"); let data = dbInstance.findOne( this.table, this.columns, criteria, params, options ); this.setData(data); return data; } /** * Finds multiple records based on a condition. * @param {string} criteria - The condition to match (SQL WHERE clause). * @param {object} params - name/value pairs for named parameters defined in criteria @param {object} options - optional parameters like limit and offset * @param {Database} [dbInstance] - Optional database instance to use. * @returns {object[]} An array of matching records. */ findMany(criteria = "", params = {}, options = {}, dbInstance = this.db) { checkDB(dbInstance, this.table, "findMany"); return dbInstance.findMany( this.table, this.columns, criteria, params, options ); } /** * creates a new instance of the model * @param {object} values - The values to initialize record with * @param {Database} [dbInstance] - Optional database instance to use. * @returns {object} The empty record */ create(values = {}, dbInstance = this.db) { checkDB(dbInstance, this.table, "create"); const newInstance = new this( dbInstance, this.table, this.columns, this.options ); newInstance.setData(values); return newInstance; } /** * Deletes a record by its ID. * @param {number} [id] - The ID of the record to delete. Defaults to the instance's ID. * @param {Database} [dbInstance] - Optional database instance to use. * @returns {boolean} True if the record was deleted, false otherwise. * @throws {Error} If no ID is provided or the instance has no ID. */ delete(id = this.id, dbInstance = this.db) { checkDB(dbInstance, this.table, "delete"); if (!id) { throw new Error(`No ID provided to ${this.constructor.name}.delete()`); } return dbInstance.delete(this.table, id); } /** * inserts the current model instance into the database. * @param {Database} [dbInstance] - Optional database instance to use. * @returns {Object} The saved record values from the database. */ insert(dbInstance = this.db) { // first ensure the database is connected checkDB(dbInstance, this.table, "insert"); // pass parameters to database to perform insert and return fully populated newly inserted row let values = dbInstance.insert(this.table, this.columns, this.getData()); // now assign the new values to this instances properties this.setData(values); // use the get data method to return all column properties return this.getData(); } /** * updates the current model instance in the database. * @param {Database} [dbInstance] - Optional database instance to use. * @returns {Object} The updated record values in the database. */ update(dbInstance = this.db) { // first ensure the database is connected checkDB(dbInstance, this.table, "update"); // pass parameters to database to perform update and return fully populated newly updated row let values = dbInstance.update(this.table, this.columns, this.getData()); // now assign the new values to this instances properties this.setData(values); // use the get data method to return all column properties return this.getData(); } /*** * Prepares instance data for saving to the database. * @returns {object} The data for the current instance. */ getData() { const data = {}; // get an array of uppercase column names let colNames = []; this.columns.forEach((col) => colNames.push(col.name.toUpperCase())); // loop thru all properties on "this" Object.keys(this).forEach((key) => { // see if the key name exists in the array of column names let match = colNames.some((name) => name === key.toUpperCase()); // if property is in columns then assign it to the return data if (match) { data[key] = this[key]; } }); // return the populated data return data; } // Assign data values to this instance setData(data) { // ensure the data parameter is valid if (!data) { throw new Error( `${this.constructor.name}.setData must be passed a valid object` ); } // loop thru all properties in data assigning them to this instance Object.keys(data).forEach((key) => (this[key] = data[key])); } } module.exports = Model;