@js-ak/db-manager
Version:
440 lines (439 loc) • 18.2 kB
JavaScript
"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;