UNPKG

@js-ak/db-manager

Version:
440 lines (439 loc) 18.2 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; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.BaseView = void 0; const Helpers = __importStar(require("../helpers/index.js")); const connection = __importStar(require("../connection.js")); const index_js_1 = require("../query-builder/index.js"); const queries_js_1 = __importDefault(require("./queries.js")); const index_js_2 = require("../helpers/index.js"); /** * @experimental * The `BaseView` class provides methods to interact with and manage views * in a PostgreSQL database. It includes functionality for querying and counting data of views. */ class BaseView { #sortingOrders = new Set(["ASC", "DESC"]); #coreFieldsSet; #isLoggerEnabled; #logger; #executeSql; #executeSqlStream; #initialArgs; /** * The PostgreSQL executor. * - pg.Pool * - pg.PoolClient * - pg.Client */ #executor; /** * The name of the view. */ name; /** * The core fields of the view. */ coreFields; /** * Creates an instance of `BaseMaterializedView`. * * @param data - Data for initializing the view. * @param data.coreFields - The core fields of the view. * @param data.name - The name of the view. * @param [data.additionalSortingFields] - Additional fields allowed for sorting. * @param [dbCreds] - Database credentials. * @param [options] - Additional options. */ constructor(data, dbCreds, options) { const { client } = options || {}; if (client) { this.#executor = client; } else if (dbCreds) { this.#executor = connection.getStandardPool(dbCreds); } else { throw new Error("No client or dbCreds provided"); } this.name = data.name; this.coreFields = data.coreFields; this.#coreFieldsSet = new Set([ ...this.coreFields, ...(data.additionalSortingFields || []), ]); this.#initialArgs = { data, dbCreds, options }; const { isLoggerEnabled, logger } = options || {}; const preparedOptions = (0, index_js_2.setLoggerAndExecutor)(this.#executor, { isLoggerEnabled, logger }); const { executeSqlStream } = Helpers.setStreamExecutor(this.#executor, { isLoggerEnabled, logger }); this.#executeSql = preparedOptions.executeSql; this.#executeSqlStream = executeSqlStream; this.#isLoggerEnabled = preparedOptions.isLoggerEnabled; this.#logger = preparedOptions.logger; } /** * Gets the database client for the view. * * @returns The database client for the view. */ get pool() { return this.#executor; } /** * Gets the PostgreSQL executor for the view. * * @returns The PostgreSQL executor for the view. */ get executor() { return this.#executor; } /** * Sets the logger for the view. * * @param logger - The logger to use for the view. */ setLogger(logger) { const preparedOptions = (0, index_js_2.setLoggerAndExecutor)(this.#executor, { isLoggerEnabled: true, logger }); const { executeSqlStream } = Helpers.setStreamExecutor(this.#executor, { isLoggerEnabled: true, logger }); this.#executeSql = preparedOptions.executeSql; this.#executeSqlStream = executeSqlStream; this.#isLoggerEnabled = preparedOptions.isLoggerEnabled; this.#logger = preparedOptions.logger; } /** * Sets the executor for the view. * * @param executor - The executor to use for the view. */ setExecutor(executor) { const preparedOptions = (0, index_js_2.setLoggerAndExecutor)(executor, { isLoggerEnabled: this.#isLoggerEnabled, logger: this.#logger }); const { executeSqlStream } = Helpers.setStreamExecutor(executor, { isLoggerEnabled: this.#isLoggerEnabled, logger: this.#logger }); this.#executeSql = preparedOptions.executeSql; this.#executeSqlStream = executeSqlStream; this.#isLoggerEnabled = preparedOptions.isLoggerEnabled; this.#logger = preparedOptions.logger; this.#executor = executor; } get isLoggerEnabled() { return this.#isLoggerEnabled; } get executeSql() { return this.#executeSql; } get executeSqlStream() { return this.#executeSqlStream; } /** * Sets the client in the current class. * * @experimental * * @param client - The client connection to set. * * @returns The current instance with the new connection client. */ setClientInCurrentClass(client) { return new this.constructor({ ...this.#initialArgs.data }, this.#initialArgs.dbCreds ? { ...this.#initialArgs.dbCreds } : undefined, { ...this.#initialArgs.options, client }); } /** * Sets the client in the base class. * * @experimental * * @param client - The client connection to set. * * @returns A new instance of the base class with the new connection client. */ setClientInBaseClass(client) { return new BaseView({ ...this.#initialArgs.data }, this.#initialArgs.dbCreds ? { ...this.#initialArgs.dbCreds } : undefined, { ...this.#initialArgs.options, client }); } /** * Compare fields for queries. */ compareFields = Helpers.compareFields; /** * Get fields to search in queries. */ getFieldsToSearch = Helpers.getFieldsToSearch; /** * Set of methods for generating comparison queries. */ compareQuery = { /** * Generates a SQL query and values for selecting an array of records based on search parameters. * * @param params - Search parameters. * @param params.$and - AND conditions for the search. * @param [params.$or] - OR conditions for the search. * @param [selected=["*"]] - Fields to be selected. * @param [pagination] - Pagination details. * @param [order] - Order by details. * @param order.orderBy - Field to order by. * @param order.ordering - Ordering direction ("ASC" or "DESC"). * * @returns An object containing the query string and values array. */ getArrByParams: ({ $and = {}, $or }, selected = ["*"], pagination, order) => { if (order?.length) { for (const o of order) { if (!this.#coreFieldsSet.has(o.orderBy)) { const allowedFields = Array.from(this.#coreFieldsSet).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.name, selectedFields, searchFields, orderByFields, paginationFields), values, }; }, /** * Generates a SQL query and values for counting records based on search parameters. * * @param params - Search parameters. * @param params.$and - AND conditions for the search. * @param [params.$or] - OR conditions for the search. * * @returns An object containing the query string and values array. */ 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.name, searchFields), values, }; }, /** * Generates a SQL query and values for selecting a single record based on search parameters. * * @param params - Search parameters. * @param params.$and - AND conditions for the search. * @param [params.$or] - OR conditions for the search. * @param [selected=["*"]] - Fields to be selected. * * @returns An object containing the query string and values array. */ 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.name, selectedFields, searchFields, orderByFields, paginationFields), values, }; }, /** * Generates a SQL query and values for selecting an array of records based on search parameters. * * @param params - Search parameters. * @param params.$and - AND conditions for the search. * @param [params.$or] - OR conditions for the search. * @param [selected=["*"]] - Fields to be selected. * @param [pagination] - Pagination details. * @param [order] - Order by details. * @param order.orderBy - Field to order by. * @param order.ordering - Ordering direction ("ASC" or "DESC"). * * @returns An object containing the query string and values array. */ streamArrByParams: ({ $and = {}, $or }, selected = ["*"], pagination, order) => { if (order?.length) { for (const o of order) { if (!this.#coreFieldsSet.has(o.orderBy)) { const allowedFields = Array.from(this.#coreFieldsSet).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.name, selectedFields, searchFields, orderByFields, paginationFields), values, }; }, }; /** * Executes a query to get an array of records based on provided parameters. * * @param params - Search parameters. * @param params.$and - AND conditions for the search. * @param [params.$or] - OR conditions for the search. * @param [selected=["*"]] - Fields to be selected. * @param [pagination] - Pagination details. * @param [order] - Order by details. * @param order.orderBy - Field to order by. * @param order.ordering - Ordering direction ("ASC" or "DESC"). * * @returns A promise that resolves to an array of records. */ async getArrByParams(params, selected = ["*"], pagination, order) { const sql = this.compareQuery.getArrByParams(params, selected, pagination, order); const { rows } = await this.#executeSql(sql); return rows; } /** * Executes a query to count records based on provided parameters. * * @param params - Search parameters. * @param params.$and - AND conditions for the search. * @param [params.$or] - OR conditions for the search. * * @returns A promise that resolves to the count of records. */ async getCountByParams(params) { const sql = this.compareQuery.getCountByParams(params); const { rows } = await this.#executeSql(sql); return Number(rows[0]?.count) || 0; } /** * Executes a query to get a single record based on provided parameters. * * @param params - Search parameters. * @param params.$and - AND conditions for the search. * @param [params.$or] - OR conditions for the search. * @param [selected=["*"]] - Fields to be selected. * * @returns A promise that resolves to a single record or undefined if no record is found. */ async getOneByParams(params, selected = ["*"]) { const sql = this.compareQuery.getOneByParams(params, selected); const { rows } = await this.#executeSql(sql); return rows[0]; } /** * Returns a stream of records from the database based on the provided search parameters. * Useful for handling large result sets efficiently without loading all data into memory. * * @param params - The filter conditions for the query. * @param params.$and - Required set of conditions combined with AND. * @param [params.$or] - Optional set of conditions combined with OR. * * @param [selected=["*"]] - List of field names to select from each record. * * @param [pagination] - Controls the offset and limit of the query. * * @param [order] - Specifies sorting rules for the result set. * @param order[].orderBy - Field to sort the results by. * @param order[].ordering - Sorting direction: `"ASC"` or `"DESC"`. * * @param [streamOptions] - Optional configuration for stream behavior: * - `batchSize`: Number of rows fetched from the database per batch. * - `highWaterMark`: Maximum number of rows buffered internally before pausing reads. * - `rowMode`: If set to `"array"`, rows are returned as arrays instead of objects. * - `types`: Custom type parser map for PostgreSQL data types. * * @returns A readable stream that emits rows of type `T` on the `"data"` event. */ async streamArrByParams(params, selected = ["*"], pagination, order, streamOptions) { const sql = this.compareQuery.streamArrByParams(params, selected, pagination, order); return this.#executeSqlStream(sql, streamOptions); } /** * Returns a new QueryBuilder instance for building SQL queries. * * @param [options] - Optional settings for the query builder. * @param [options.client] - Optional database client or pool to use for query execution. * @param [options.isLoggerEnabled] - Whether to enable logging for this query builder. * @param [options.logger] - Optional custom logger instance. * @param [options.name] - Optional view name to use (defaults to this.name). * * @returns A configured QueryBuilder instance. */ queryBuilder(options) { const { client, isLoggerEnabled, logger, name } = options || {}; return new index_js_1.QueryBuilder(name ?? this.name, client ?? this.#executor, { isLoggerEnabled: isLoggerEnabled ?? this.#isLoggerEnabled, logger: logger ?? this.#logger, }); } // STATIC METHODS /** * Gets a standard connection pool. * * @static * @param creds - Database credentials. * @param [poolName] - Optional pool name. * * @returns A new PostgreSQL connection pool. */ static getStandardPool(creds, poolName) { return connection.getStandardPool(creds, poolName); } /** * Removes a standard connection pool. * * @static * @param creds - Database credentials. * @param [poolName] - Optional pool name. * * @returns A promise that resolves when the pool is removed. */ static async removeStandardPool(creds, poolName) { return connection.removeStandardPool(creds, poolName); } /** * Gets a transaction connection pool. * * @static * @param creds - Database credentials. * @param [poolName] - Optional pool name. * * @returns A new PostgreSQL transaction connection pool. */ static getTransactionPool(creds, poolName) { return connection.getTransactionPool(creds, poolName); } /** * Removes a transaction connection pool. * * @static * @param creds - Database credentials. * @param [poolName] - Optional pool name. * * @returns A promise that resolves when the pool is removed. */ static async removeTransactionPool(creds, poolName) { return connection.removeTransactionPool(creds, poolName); } } exports.BaseView = BaseView;