UNPKG

@leapfrogtechnology/db-model

Version:

Low-footprint database abstraction layer and model built on top of Knex.

386 lines 16.2 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (_) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; Object.defineProperty(exports, "__esModule", { value: true }); var debug = require("debug"); var db = require("./db"); var constants_1 = require("./constants"); var ModelNotFoundError_1 = require("./ModelNotFoundError"); var ramda_1 = require("ramda"); var log = debug(constants_1.NS_MODEL); /** * Create Model for different connection * * @param {ConnectionResolver} [resolver] * @returns {typeof BaseModel} */ function createBaseModel(resolver) { var _a; return _a = /** @class */ (function () { function BaseModel() { } /** * Binds a database connection to the model. * * @param {Knex} connection * @returns {void} */ BaseModel.bindConnection = function (connection) { log('Binding database connection to the model (Lazy)'); this.connection = connection; }; /** * Binds a database connection to the model (chainable version of bindConnection()). * * @param {Knex} connection * @returns {any} */ BaseModel.bind = function (connection) { this.bindConnection(connection); return this; }; /** * Resolves a database connection. * * Note: It would throw an Error on the run time if it couldn't resolve the * connection by the time any DB methods are invoked on it. * @returns {Knex} */ BaseModel.getConnection = function () { if (this.connection) { return this.connection; } // Note: We need to resolve db connection everytime. if (resolver) { return resolver(); } throw new Error('Cannot resolve the database connection.'); }; /** * Generic query builder. * * @param {Transaction} [trx] * @returns {(Knex.Transaction | Knex)} */ BaseModel.queryBuilder = function (trx) { return db.queryBuilder(this.getConnection(), trx); }; /** * Finds a record based on the params. * * @param {object} [params={}] * @param {Function} callback * @param {Knex.Transaction} trx * @returns {Knex.QueryBuilder} */ BaseModel.find = function (params, callback, trx) { if (params === void 0) { params = {}; } return db.find(this.getConnection(), this.table, params, callback, trx); }; /** * Finds the first record based on the params. * * @param {object} [params={}] * @param {Function} callback * @param {Knex.Transaction} trx * @returns {Promise<T | null>} */ BaseModel.findFirst = function (params, callback, trx) { if (params === void 0) { params = {}; } return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { return [2 /*return*/, db.findFirst(this.getConnection(), this.table, params, ramda_1.any, trx)]; }); }); }; /** * Find record by it's id. * Throws an exception if not found. * * @param {any} id * @param {Function} callback * @param {Knex.Transaction} trx * @returns {Promise<T | null>} */ BaseModel.findById = function (id, callback, trx) { var idParams = this.buildIdParams(id); return db.findFirst(this.getConnection(), this.table, idParams, callback, trx); }; /** * Find record by it's id. * Throws an exception if not found. * * @param {any} id * @param {Function} callback * @param {Knex.Transaction} trx * @throws {ModelNotFoundError} * @returns {Promise<T | null>} */ BaseModel.findByIdOrFail = function (id, callback, trx) { var _this = this; var idParams = this.buildIdParams(id); return db.findFirst(this.getConnection(), this.table, idParams, callback, trx).then(function (result) { if (!result) { throw new ModelNotFoundError_1.default(_this.name + ' not found'); } return result; }); }; /** * Finds records based on the params with records limit. * * @param {object} [params={}] * @param {PaginationParams} pageParams * @param {OrderBy[]} sortParams * @param {Knex.Transaction} trx * @param {Function} callback * @returns {Knex.QueryBuilder} */ BaseModel.findWithPageAndSort = function (params, pageParams, sortParams, callback, trx) { if (params === void 0) { params = {}; } var offset = (pageParams.page - 1) * pageParams.pageSize; var qb = this.find(params, trx).offset(offset).limit(pageParams.pageSize); if (sortParams && sortParams.length > 0) { qb.clearOrder(); sortParams.forEach(function (item) { qb.orderBy(item.field, item.direction); }); } if (callback) callback(qb); return qb; }; /** * Count the total records. * * @param {object} [params={}] * @param {Function} callback * @param {Knex.Transaction} trx * @returns {Knex.QueryBuilder} */ BaseModel.count = function (params, callback, trx) { if (params === void 0) { params = {}; } var qb = this.find(params, trx).clearSelect().count('*').clearOrder(); if (callback) callback(qb); return qb.then(function (_a) { var result = _a[0]; return result.count; }); }; /** * Insert all records sent in data object. * * @param {(object | object[])} data * @param {Transaction} [trx] * @returns {Promise<T[]>} */ BaseModel.insert = function (data, trx) { return db.insert(this.getConnection(), this.table, data, trx); }; /** * Update records by id. * * @param {number} id * @param {object} params * @param {Transaction} transaction * @returns {Promise<object>} */ BaseModel.updateById = function (id, params, trx) { var idParams = this.buildIdParams(id); return db.update(this.getConnection(), this.table, idParams, params, trx); }; /** * Update records by where condition. * * @param {object} where * @param {object} params * @param {Transaction} transaction * @returns {Promise<T[]>} */ BaseModel.update = function (where, params, trx) { return db.update(this.getConnection(), this.table, where, params, trx); }; /** * Delete row in table. * * @param {object} params * @param {Transaction} trx * @returns {Promise<T[]>} */ BaseModel.deleteById = function (id, trx) { var idParams = this.buildIdParams(id); return db.remove(this.getConnection(), this.table, idParams, trx); }; /** * Delete row in table. * * @param {object} params * @param {Transaction} trx * @returns {Promise<T[]>} */ BaseModel.delete = function (params, trx) { return db.remove(this.getConnection(), this.table, params, trx); }; /** * Execute SQL raw query and return results. * * @param {string} sql * @param {RawBindingParams | ValueMap} params * @param {Transaction} trx * @returns {Promise<T[]>} */ BaseModel.query = function (sql, params, trx) { return db.query(this.getConnection(), sql, params, trx); }; /** * Method to perform a transactional query execution. * * @param {(trx: Transaction) => any} callback * @param {Transaction} trx * @returns {any} */ BaseModel.transaction = function (callback, trx) { if (trx) { return callback(trx); } return this.getConnection().transaction(callback); }; /** * Batch insert rows of data. * * @param {object[]} data * @param {Transaction} [trx] * @param {number} [chunksize=30] * @returns {Promise<T[]>} */ BaseModel.batchInsert = function (data, trx, chunksize) { if (chunksize === void 0) { chunksize = 30; } return db.batchInsert(this.getConnection(), this.table, data, chunksize, trx); }; /** * Execute SQL raw query and return scalar value. * * @param {string} sql * @param {any} params * @param {Transaction} trx * @returns {Promise<T | null>} */ BaseModel.getValue = function (sql, params, trx) { return db.getValue(this.getConnection(), sql, params, trx); }; /** * Execute SQL raw query returning a boolean result. * * @param {string} sql * @param {*} [params] * @param {Transaction} [trx] * @returns {Promise<boolean>} */ BaseModel.check = function (sql, params, trx) { return db.check(this.getConnection(), sql, params, trx); }; /** * Execute SQL raw query returning a JSON encoded result * and produce the parsed object. * * @param {string} sql * @param {*} [params] * @param {Transaction} [trx] * @returns {(Promise<T | null>)} */ BaseModel.getJson = function (sql, params, trx) { return db.getJson(this.getConnection(), sql, params, trx); }; /** * Invoke a scalar-valued function and return results. * * Example usage: * * const username = await User.invoke<string>('dbo.can_user_access_object', { userId: 10, objectId: 15 }); * * // => Runs SQL: SELECT dbo.can_user_access_object(:userId, :objectId) * // => Binds params: { userId: 10, objectId: 15 } * * @param {string} objectName * @param {RawBindingParams | ValueMap} [params] * @param {Knex.Transaction} [trx] * @returns {Promise<T | null>} */ BaseModel.invoke = function (objectName, params, trx) { return db.invoke(trx || this.getConnection(), objectName, params); }; /** * Execute a procedure and return the results returned (if any). * * Example usage: * * await Recommendation.exec<string>('dbo.update_top_recommendations', { userId: 10, type }); * * // => Runs SQL: EXEC dbo.update_top_recommendations :userId, :type * // => Binds params: { userId: 10, type } * * @param {string} objectName * @param {RawBindingParams | ValueMap} [params] * @param {Knex.Transaction} [trx] * @returns {Promise<T[]>} */ BaseModel.exec = function (objectName, params, trx) { return db.exec(trx || this.getConnection(), objectName, params); }; /** * Build param object for given id. * * @param {any} id * @returns {object} */ BaseModel.buildIdParams = function (id) { var _a; if (typeof id === 'number' || typeof id === 'string') { return _a = {}, _a[this.id] = id, _a; } return id; }; return BaseModel; }()), _a.defaultOrderBy = [{ field: 'id', direction: 'asc' }], _a.id = 'id', _a; } exports.createBaseModel = createBaseModel; exports.Model = createBaseModel(); //# sourceMappingURL=model.js.map