UNPKG

@js-ak/db-manager

Version:
410 lines (409 loc) 17.6 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.BaseModel = void 0; const Helpers = __importStar(require("../helpers/index.js")); const SharedHelpers = __importStar(require("../../../shared-helpers/index.js")); const connection = __importStar(require("../connection.js")); const queries_js_1 = __importStar(require("./queries.js")); const index_js_1 = require("../query-builder/index.js"); const index_js_2 = require("../helpers/index.js"); class BaseModel { #insertOptions; #sortingOrders = new Set(["ASC", "DESC"]); #tableFieldsSet; #isLoggerEnabled; #logger; #executeSql; /** * The MySQL executor. * - mysql.Pool * - mysql.PoolClient * - mysql.Client */ #executor; createField; isPKAutoIncremented; primaryKey; tableName; tableFields; updateField; constructor(data, dbCreds, options) { this.createField = data.createField; this.#executor = connection.getStandardPool(dbCreds); this.primaryKey = data.primaryKey; this.isPKAutoIncremented = typeof data.isPKAutoIncremented === "boolean" ? data.isPKAutoIncremented : true; this.tableName = data.tableName; this.tableFields = [...data.tableFields]; this.updateField = data.updateField; this.#tableFieldsSet = new Set([ ...this.tableFields, ...(data.additionalSortingFields || []), ]); const { insertOptions, isLoggerEnabled, logger } = options || {}; const preparedOptions = (0, index_js_2.setLoggerAndExecutor)(this.#executor, { isLoggerEnabled, logger }); this.#insertOptions = insertOptions; this.#executeSql = preparedOptions.executeSql; this.#isLoggerEnabled = preparedOptions.isLoggerEnabled; this.#logger = preparedOptions.logger; } /** * Gets the database client for the model. * * @returns The database client for the model. */ get pool() { return this.#executor; } /** * Gets the MySQL executor for the model. * * @returns The MySQL executor for the model. */ get executor() { return this.#executor; } /** * Sets the logger for the model. * * @param logger - The logger to use for the model. */ setLogger(logger) { const preparedOptions = (0, index_js_2.setLoggerAndExecutor)(this.#executor, { isLoggerEnabled: true, logger }); this.#executeSql = preparedOptions.executeSql; this.#isLoggerEnabled = preparedOptions.isLoggerEnabled; this.#logger = preparedOptions.logger; } /** * Sets the executor for the model. * * @param executor - The executor to use for the model. */ setExecutor(executor) { const preparedOptions = (0, index_js_2.setLoggerAndExecutor)(executor, { isLoggerEnabled: this.#isLoggerEnabled, logger: this.#logger }); this.#executeSql = preparedOptions.executeSql; this.#isLoggerEnabled = preparedOptions.isLoggerEnabled; this.#logger = preparedOptions.logger; this.#executor = executor; } get isLoggerEnabled() { return this.#isLoggerEnabled; } get executeSql() { return this.#executeSql; } compareFields = Helpers.compareFields; getFieldsToSearch = Helpers.getFieldsToSearch; compareQuery = { deleteAll: () => { return { query: queries_js_1.default.deleteAll(this.tableName) }; }, deleteByParams: ({ $and = {}, $or }) => { const { queryArray, queryOrArray, values } = this.compareFields($and, $or); const { searchFields } = this.getFieldsToSearch({ queryArray, queryOrArray }); return { query: queries_js_1.default.deleteByParams(this.tableName, searchFields), values, }; }, deleteOneByPk: (primaryKey) => { if (!this.primaryKey) { throw new Error("Primary key not specified"); } return { query: queries_js_1.default.deleteByPk(this.tableName, this.primaryKey), values: Array.isArray(primaryKey) ? primaryKey : [primaryKey], }; }, getArrByParams: ({ $and = {}, $or }, selected = ["*"], pagination, order) => { if (order?.length) { for (const o of order) { if (!this.#tableFieldsSet.has(o.orderBy)) { const allowedFields = Array.from(this.#tableFieldsSet).join(", "); throw new Error(`Invalid orderBy: ${o.orderBy}. Allowed fields are: ${allowedFields}`); } if (!this.#sortingOrders.has(o.ordering)) { throw new Error("Invalid ordering"); } } } if (!selected.length) selected.push("*"); const { queryArray, queryOrArray, values } = this.compareFields($and, $or); const { orderByFields, paginationFields, searchFields, selectedFields } = this.getFieldsToSearch({ queryArray, queryOrArray }, selected, pagination, order); return { query: queries_js_1.default.getByParams(this.tableName, selectedFields, searchFields, orderByFields, paginationFields), values, }; }, getCountByParams: ({ $and = {}, $or }) => { const { queryArray, queryOrArray, values } = this.compareFields($and, $or); const { searchFields } = this.getFieldsToSearch({ queryArray, queryOrArray }); return { query: queries_js_1.default.getCountByParams(this.tableName, searchFields), values, }; }, getCountByPks: (pks) => { if (!this.primaryKey) { throw new Error("Primary key not specified"); } if (Array.isArray(pks[0])) { if (!Array.isArray(this.primaryKey)) { throw new Error("invalid primary key type"); } return { query: queries_js_1.default.getCountByCompositePks(this.primaryKey, this.tableName, pks.length), values: [pks.flat()], }; } if (Array.isArray(this.primaryKey)) { throw new Error("invalid primary key type"); } return { query: queries_js_1.default.getCountByPks(this.primaryKey, this.tableName), values: [pks], }; }, getCountByPksAndParams: (pks, { $and = {}, $or }) => { if (!this.primaryKey) { throw new Error("Primary key not specified"); } const { queryArray, queryOrArray, values } = this.compareFields($and, $or); const { searchFields } = this.getFieldsToSearch({ queryArray, queryOrArray }); if (Array.isArray(pks[0])) { if (!Array.isArray(this.primaryKey)) { throw new Error("invalid primary key type"); } return { query: queries_js_1.default.getCountByCompositePksAndParams(this.primaryKey, this.tableName, searchFields, pks.length), values: pks.flat(), }; } if (Array.isArray(this.primaryKey)) { throw new Error("invalid primary key type"); } return { query: queries_js_1.default.getCountByPksAndParams(this.primaryKey, this.tableName, searchFields), values: [...values, pks], }; }, getOneByParams: ({ $and = {}, $or }, selected = ["*"]) => { if (!selected.length) selected.push("*"); const { queryArray, queryOrArray, values } = this.compareFields($and, $or); const { orderByFields, paginationFields, searchFields, selectedFields } = this.getFieldsToSearch({ queryArray, queryOrArray }, selected, { limit: 1, offset: 0 }); return { query: queries_js_1.default.getByParams(this.tableName, selectedFields, searchFields, orderByFields, paginationFields), values, }; }, getOneByPk: (pk) => { if (!this.primaryKey) { throw new Error("Primary key not specified"); } return { query: queries_js_1.default.getOneByPk(this.tableName, this.primaryKey), values: [pk], }; }, save: (recordParams = {}) => { const clearedParams = SharedHelpers.clearUndefinedFields(recordParams); const fields = Object.keys(clearedParams); const onConflict = this.#insertOptions?.onConflict || ""; if (!fields.length) { throw new Error("No one save field arrived"); } return { query: queries_js_1.default.createOne(this.tableName, fields, this.createField, onConflict), values: Object.values(clearedParams), }; }, updateByParams: (queryConditions, updateFields = {}) => { const { queryArray, queryOrArray, values } = this.compareFields(queryConditions.$and, queryConditions.$or); const { searchFields } = this.getFieldsToSearch({ queryArray, queryOrArray }); const clearedUpdate = SharedHelpers.clearUndefinedFields(updateFields); const fieldsToUpdate = Object.keys(clearedUpdate); if (!queryArray.length) throw new Error("No one update field arrived"); return { query: queries_js_1.default.updateByParams(this.tableName, fieldsToUpdate, searchFields, this.updateField), values: [...Object.values(clearedUpdate), ...values], }; }, updateOneByPk: (primaryKeyValue, updateFields = {}) => { if (!this.primaryKey) { throw new Error("Primary key not specified"); } const clearedParams = SharedHelpers.clearUndefinedFields(updateFields); const fields = Object.keys(clearedParams); if (!fields.length) throw new Error("No one update field arrived"); return { query: queries_js_1.default.updateByPk(this.tableName, fields, this.primaryKey, this.updateField), values: [...Object.values(clearedParams), primaryKeyValue], }; }, }; async deleteAll() { const sql = this.compareQuery.deleteAll(); await this.#executeSql(sql); return; } async deleteOneByPk(primaryKey) { const sql = this.compareQuery.deleteOneByPk(primaryKey); await this.#executeSql(sql); return; } async deleteByParams(params) { const sql = this.compareQuery.deleteByParams(params); await this.#executeSql(sql); return; } async getArrByParams(params, selected = ["*"], pagination, order) { const sql = this.compareQuery.getArrByParams(params, selected, pagination, order); const result = await this.#executeSql(sql); return result[0]; } async getCountByPks(pks) { const sql = this.compareQuery.getCountByPks(pks); const result = await this.#executeSql(sql); return Number(result[0][0]?.count) || 0; } async getCountByPksAndParams(pks, params) { const sql = this.compareQuery.getCountByPksAndParams(pks, params); const result = await this.#executeSql(sql); return Number(result[0][0]?.count) || 0; } async getCountByParams(params) { const sql = this.compareQuery.getCountByParams(params); const result = await this.#executeSql(sql); return Number(result[0][0]?.count) || 0; } async getOneByParams(params, selected = ["*"]) { const sql = this.compareQuery.getOneByParams(params, selected); const result = await this.#executeSql(sql); return result[0][0]; } async getOneByPk(pk) { const sql = this.compareQuery.getOneByPk(pk); const result = await this.#executeSql(sql); return result[0][0]; } async save(recordParams = {}) { const sql = this.compareQuery.save(recordParams); const result = await this.#executeSql(sql); if (!this.isPKAutoIncremented) { return -1; } return result[0]?.insertId || -1; } async updateByParams(queryConditions, updateFields = {}) { const sql = this.compareQuery.updateByParams(queryConditions, updateFields); await this.#executeSql(sql); return; } async updateOneByPk(primaryKeyValue, updateFields = {}) { const sql = this.compareQuery.updateOneByPk(primaryKeyValue, updateFields); await this.#executeSql(sql); return; } /** * @experimental */ queryBuilder(options) { const { client, isLoggerEnabled, logger, tableName } = options || {}; return new index_js_1.QueryBuilder(tableName ?? this.tableName, client ?? this.#executor, { isLoggerEnabled: isLoggerEnabled ?? this.#isLoggerEnabled, logger: logger ?? this.#logger, }); } // STATIC METHODS static getStandardPool(creds, poolName) { return connection.getStandardPool(creds, poolName); } static async removeStandardPool(creds, poolName) { return connection.removeStandardPool(creds, poolName); } static getTransactionPool(creds, poolName) { return connection.getTransactionPool(creds, poolName); } static async removeTransactionPool(creds, poolName) { return connection.removeTransactionPool(creds, poolName); } static getInsertFields(data) { const { params: paramsRaw, tableName, } = data; if (Array.isArray(paramsRaw)) { const v = []; const k = []; const headers = new Set(); const example = paramsRaw[0]; if (!example) throw new Error("Invalid parameters"); const params = SharedHelpers.clearUndefinedFields(example); Object.keys(params).forEach((e) => headers.add(e)); for (const pR of paramsRaw) { const params = SharedHelpers.clearUndefinedFields(pR); const keys = Object.keys(params); k.push(keys); v.push(...Object.values(params)); if (!k.length) { throw new Error(`Invalid params, all fields are undefined - ${Object.keys(paramsRaw).join(", ")}`); } for (const key of keys) { if (!headers.has(key)) { throw new Error(`Invalid params, all fields are undefined - ${Object.keys(pR).join(", ")}`); } } } const query = `INSERT INTO ${tableName}(${Array.from(headers).join(",")}) VALUES(${k.map((e) => e.map(() => "?")).join("),(")});`; return { query, values: v }; } const params = SharedHelpers.clearUndefinedFields(paramsRaw); const k = Object.keys(params); const v = Object.values(params); if (!k.length) throw new Error(`Invalid params, all fields are undefined - ${Object.keys(paramsRaw).join(", ")}`); const query = `INSERT INTO ${tableName}(${k.join(",")}) VALUES(${k.map(() => "?").join(",")});`; return { query, values: v }; } static getUpdateFields(data) { const { params: paramsRaw, primaryKey, tableName, updateField, } = data; const params = SharedHelpers.clearUndefinedFields(paramsRaw); const k = Object.keys(params); const v = Object.values(params); if (!k.length) throw new Error(`Invalid params, all fields are undefined - ${Object.keys(paramsRaw).join(", ")}`); let updateFields = k.map((e) => `${e} = ?`).join(","); if (updateField) { updateFields += `, ${updateField.title} = ${(0, queries_js_1.generateTimestampQuery)(updateField.type)}`; } const query = `UPDATE ${tableName} SET ${updateFields} WHERE ${primaryKey.field} = ?;`; return { query, values: [...v, primaryKey.value] }; } } exports.BaseModel = BaseModel;