node-caching-mysql-connector-with-redis
Version:
MySQL caching connector with Redis, auto key generation, auto invalidation, transaction support, and TypeScript
610 lines (570 loc) • 19.3 kB
TypeScript
/**
* Type definitions for node-caching-mysql-connector-with-redis
* Project: https://github.com/hayatialikeles/NODE-CACHING-MYSQL-CONNECTOR-WITH-REDIS
* Definitions by: Ali Hayati Keleş
*/
/// <reference types="node" />
declare module 'node-caching-mysql-connector-with-redis' {
/**
* MySQL query result type
*/
export interface QueryResult {
affectedRows?: number;
insertId?: number;
warningCount?: number;
message?: string;
protocol41?: boolean;
changedRows?: number;
fieldCount?: number;
serverStatus?: number;
}
/**
* Pagination result structure
*/
export interface PaginationResult<T = any> {
totalCount: number;
pageCount: number;
detail: T[];
}
/**
* Redis client interface
*/
export interface RedisClient {
[key: string]: any;
}
// ==================== DATABASE FUNCTIONS ====================
/**
* Executes a SQL query and returns the result from the cache or the database.
* If a resetCacheName is provided, it deletes the cache item before executing the query.
*
* @param sql - The SQL query to execute
* @param parameters - The parameters to be passed to the SQL query
* @param resetCacheName - The name of the cache item to reset (optional)
* @param database - The database name to switch to (optional)
* @returns A promise that resolves with the result of the query
*
* @example
* ```typescript
* const result = await QuaryCache(
* "INSERT INTO users SET name = ?, email = ?",
* ["John", "john@example.com"],
* "users-cache"
* );
* console.log(result.insertId);
* ```
*/
export function QuaryCache(
sql: string,
parameters: any[],
resetCacheName?: string | null,
database?: string | null
): Promise<QueryResult>;
/**
* Retrieves data from cache or database based on the provided SQL query and parameters.
* If the data is found in the cache, it is returned. Otherwise, the data is fetched from the database,
* stored in the cache, and then returned.
*
* **v2.6.0:** cacheName is now optional when CORE_AUTO_FEATURES=true.
* The cache key will be auto-generated from the SQL query and parameters.
*
* @param sql - The SQL query to be executed
* @param parameters - The parameters to be passed to the SQL query
* @param cacheName - The name of the cache to store the data (optional if auto key enabled)
* @param database - The database name to switch to (optional)
* @returns A promise that resolves to the retrieved data
*
* @example
* ```typescript
* interface User {
* id: number;
* name: string;
* email: string;
* }
*
* // v2.5.3 style (still works)
* const users = await getCacheQuery<User>(
* "SELECT * FROM users WHERE company_id = ?",
* [123],
* "users-company-123"
* );
*
* // v2.6.0 style (auto key) - Requires CORE_AUTO_FEATURES=true
* const users = await getCacheQuery<User>(
* "SELECT * FROM users WHERE company_id = ?",
* [123]
* );
* // Auto key: "users:company_id:a7b3c2d1"
* ```
*/
export function getCacheQuery<T = any>(
sql: string,
parameters: any[],
cacheName?: string | null,
database?: string | null
): Promise<T[]>;
/**
* Retrieves paginated data from cache or database based on the provided SQL query and parameters.
* If the data is available in cache, it is returned directly. Otherwise, the data is fetched from the database,
* paginated, and then stored in the cache for future use.
*
* @param sql - The SQL query to execute
* @param parameters - The parameters to be used in the SQL query
* @param cacheName - The name of the cache to store the data
* @param page - The page number of the data to retrieve (0-based)
* @param pageSize - The number of records per page (default: 30)
* @param database - The database name to switch to (optional)
* @returns A promise that resolves to an object containing the paginated data
*
* @example
* ```typescript
* interface Product {
* id: number;
* name: string;
* price: number;
* }
*
* const result = await getCacheQueryPagination<Product>(
* "SELECT * FROM products WHERE category = ?",
* [5],
* "products-cat-5-page-0",
* 0,
* 25
* );
*
* console.log(`Total: ${result.totalCount}`);
* console.log(`Pages: ${result.pageCount}`);
* result.detail.forEach(product => console.log(product.name));
* ```
*/
export function getCacheQueryPagination<T = any>(
sql: string,
parameters: any[],
cacheName: string,
page: number,
pageSize?: number,
database?: string | null
): Promise<PaginationResult<T>>;
// ==================== REDIS FUNCTIONS ====================
/**
* Retrieves an item from Redis cache
*
* @param key - The cache key
* @returns A promise that resolves to the cached data or empty array if not found
*
* @example
* ```typescript
* const userData = await getArrayItem<User>('user-123');
* if (userData.length > 0) {
* console.log(userData);
* }
* ```
*/
export function getArrayItem<T = any>(key: string): Promise<T[]>;
/**
* Stores an item in Redis cache with optional expiry
*
* @param key - The cache key
* @param array - The data to cache
* @param expiryDate - Time to live in seconds (default: 40000)
* @returns A promise that resolves to the cached data
*
* @example
* ```typescript
* await addArrayItem('user-123', userData, 3600); // 1 hour TTL
* ```
*/
export function addArrayItem<T = any>(
key: string,
array: T[],
expiryDate?: number
): Promise<T[]>;
/**
* Deletes one or more keys from Redis cache
*
* @param keys - Single key or array of keys to delete
* @returns A promise that resolves when deletion is complete
*
* @example
* ```typescript
* // Delete single key
* await delKeyItem('user-123');
*
* // Delete multiple keys
* await delKeyItem(['user-123', 'user-456', 'user-789']);
* ```
*/
export function delKeyItem(keys: string | string[]): Promise<void>;
/**
* Deletes all keys matching a prefix pattern from Redis cache
*
* @param keys - Single prefix or array of prefixes
* @returns A promise that resolves when deletion is complete
*
* @example
* ```typescript
* // Delete all keys starting with "users-"
* await delPrefixKeyItem('users-');
*
* // Delete multiple prefixes
* await delPrefixKeyItem(['users-', 'products-', 'orders-']);
* ```
*/
export function delPrefixKeyItem(keys: string | string[]): Promise<void>;
/**
* Returns the raw Redis client instance
*
* @returns The Redis client
*
* @example
* ```typescript
* const client = getRedisClient();
* client.set('custom-key', 'value');
* ```
*/
export function getRedisClient(): RedisClient;
// ==================== PRODUCTION-GRADE FEATURES (v2.5.3+) ====================
/**
* Bulk insert options
*/
export interface BulkInsertOptions {
/** Database name to switch to */
database?: string | null;
/** Number of records per chunk (default: 1000) */
chunkSize?: number;
/** Cache name prefix to reset after insert */
resetCacheName?: string | null;
}
/**
* Bulk insert result
*/
export interface BulkInsertResult {
/** Total number of rows inserted */
insertedRows: number;
/** Number of chunks processed */
chunks: number;
}
/**
* Query timeout options
*/
export interface QueryTimeoutOptions {
/** Query timeout in milliseconds (default: 30000) */
timeout?: number;
/** Database name to switch to */
database?: string | null;
}
/**
* Pool statistics
*/
export interface PoolStats {
/** Total number of connections in the pool */
totalConnections: number;
/** Number of active connections currently in use */
activeConnections: number;
/** Number of free connections available */
freeConnections: number;
/** Number of queued requests waiting for a connection */
queuedRequests: number;
}
/**
* Executes a bulk insert operation with automatic chunking for large datasets.
* Prevents memory issues by splitting large datasets into manageable chunks.
*
* @param table - The table name to insert into
* @param records - Array of objects with column-value pairs
* @param options - Optional settings for bulk insert
* @returns Promise resolving to insert statistics
*
* @example
* ```typescript
* const users = [
* { name: 'Alice', email: 'alice@example.com' },
* { name: 'Bob', email: 'bob@example.com' }
* ];
*
* const result = await bulkInsert('users', users, {
* chunkSize: 500,
* resetCacheName: 'users_'
* });
* // { insertedRows: 2, chunks: 1 }
* ```
*/
export function bulkInsert<T = any>(
table: string,
records: T[],
options?: BulkInsertOptions
): Promise<BulkInsertResult>;
/**
* Executes a query with timeout protection to prevent long-running queries.
* Automatically retries on connection errors with exponential backoff.
*
* @param sql - The SQL query to execute
* @param parameters - Query parameters
* @param cacheName - Cache key for storing results
* @param options - Optional timeout and database settings
* @returns Promise resolving to query results
*
* @example
* ```typescript
* const users = await getCacheQueryWithTimeout<User>(
* 'SELECT * FROM users WHERE status = ?',
* ['active'],
* 'active_users',
* { timeout: 5000, database: 'analytics_db' }
* );
* ```
*/
export function getCacheQueryWithTimeout<T = any>(
sql: string,
parameters: any[],
cacheName: string,
options?: QueryTimeoutOptions
): Promise<T[]>;
/**
* Gracefully closes all database connections.
* Should be called during application shutdown to prevent connection leaks.
*
* @example
* ```typescript
* process.on('SIGTERM', async () => {
* await closeConnections();
* process.exit(0);
* });
* ```
*/
export function closeConnections(): Promise<void>;
/**
* Gets current connection pool statistics for monitoring and debugging.
* Useful for detecting connection leaks or pool exhaustion.
*
* @returns Current pool statistics
*
* @example
* ```typescript
* const stats = getPoolStats();
* console.log(`Active: ${stats.activeConnections}/${stats.totalConnections}`);
* ```
*/
export function getPoolStats(): PoolStats;
// ==================== v2.6.0 SMART AUTO FEATURES ====================
/**
* Auto key generation configuration
*/
export interface AutoKeyConfig {
/** Enable auto key generation */
enabled?: boolean;
}
/**
* Auto invalidation configuration
*/
export interface AutoInvalidationConfig {
/** Enable auto invalidation */
enabled?: boolean;
/** Table-specific invalidation patterns */
tables?: Record<string, string | string[]>;
}
/**
* All-in-one configuration interface
*/
export interface CoreConfig {
/** Auto key generation config */
autoKey?: AutoKeyConfig;
/** Auto invalidation config */
autoInvalidation?: AutoInvalidationConfig;
}
/**
* Enables auto cache key generation feature.
* When enabled, cacheName parameter becomes optional in getCacheQuery().
*
* @param config - Auto key configuration
*
* @example
* ```typescript
* enableAutoKey({ enabled: true });
*
* // Now cacheName is optional
* const users = await getCacheQuery('SELECT * FROM users WHERE id = ?', [123]);
* ```
*/
export function enableAutoKey(config?: AutoKeyConfig): void;
/**
* Enables auto cache invalidation feature.
* When enabled, cache will be automatically cleared on write operations.
*
* @param config - Auto invalidation configuration
*
* @example
* ```typescript
* enableAutoInvalidation({
* enabled: true,
* tables: {
* users: ['users_*', 'profiles_*'],
* orders: ['orders_*']
* }
* });
*
* // Now resetCacheName is optional
* await QuaryCache('INSERT INTO users...', [data]);
* // Auto-clears: users_*, profiles_*
* ```
*/
export function enableAutoInvalidation(config?: AutoInvalidationConfig): void;
/**
* All-in-one configuration helper for v2.6.0 features.
*
* @param config - Core configuration object
*
* @example
* ```typescript
* configure({
* autoKey: { enabled: true },
* autoInvalidation: {
* enabled: true,
* tables: {
* users: ['users_*', 'profiles_*']
* }
* }
* });
* ```
*/
export function configure(config?: CoreConfig): void;
// ==================== TRANSACTION SUPPORT (v2.7.0+) ====================
/**
* Transaction context object provided to transaction callback.
* Contains methods to execute queries within the transaction.
*/
export interface TransactionContext {
/**
* Executes a query within the transaction.
* Cache invalidation is buffered and applied only on successful commit.
*
* @param sql - SQL query to execute
* @param parameters - Query parameters
* @param resetCacheName - Optional cache patterns to invalidate on commit
* @returns Promise resolving to query result
*
* @example
* ```typescript
* await tx.query('INSERT INTO users (name) VALUES (?)', ['John']);
* await tx.query('UPDATE orders SET user_id = ?', [123], 'orders_*');
* ```
*/
query<T = any>(
sql: string,
parameters: any[],
resetCacheName?: string | string[] | null
): Promise<T>;
/**
* Executes a cached read query within the transaction.
* Note: Reads from cache but doesn't guarantee transaction isolation.
*
* @param sql - SQL query to execute
* @param parameters - Query parameters
* @param cacheName - Cache key (optional if auto-key enabled)
* @returns Promise resolving to query results
*
* @example
* ```typescript
* const user = await tx.getCacheQuery('SELECT * FROM users WHERE id = ?', [123], 'user-123');
* ```
*/
getCacheQuery<T = any>(
sql: string,
parameters: any[],
cacheName?: string | null
): Promise<T[]>;
/**
* Gets the underlying MySQL connection object.
* For advanced use cases requiring direct connection access.
*
* @returns MySQL connection object
*/
getConnection(): any;
}
/**
* Transaction options
*/
export interface TransactionOptions {
/** Database name to switch to for the transaction */
database?: string | null;
}
/**
* Executes queries within a database transaction.
* Automatically commits on success or rolls back on error.
* Cache invalidation is buffered and applied only on successful commit.
*
* @param callback - Async function that receives transaction context
* @param options - Transaction options
* @returns Promise resolving to callback return value
* @throws Error if transaction fails or is rolled back
*
* @example
* ```typescript
* // Basic transaction
* await withTransaction(async (tx) => {
* await tx.query('INSERT INTO users (name) VALUES (?)', ['John']);
* await tx.query('INSERT INTO orders (user_id) VALUES (?)', [123]);
* // Auto commit on success, auto rollback on error
* });
*
* // With database switching
* await withTransaction(async (tx) => {
* await tx.query('INSERT INTO logs...', [data]);
* }, { database: 'analytics_db' });
*
* // With return value
* const userId = await withTransaction(async (tx) => {
* const result = await tx.query('INSERT INTO users...', [data]);
* return result.insertId;
* });
*
* // Error handling (automatic rollback)
* try {
* await withTransaction(async (tx) => {
* await tx.query('INSERT INTO users...', [data]);
* throw new Error('Business logic error');
* // Transaction automatically rolled back
* });
* } catch (error) {
* console.error('Transaction failed:', error);
* }
* ```
*/
export function withTransaction<T = any>(
callback: (tx: TransactionContext) => Promise<T>,
options?: TransactionOptions
): Promise<T>;
// ==================== BACKWARD COMPATIBILITY ====================
/**
* Default export for backward compatibility with v2.4.x
*
* @example
* ```typescript
* // v2.4.x style (still supported)
* import dbConnector = require('node-caching-mysql-connector-with-redis');
* dbConnector.QuaryCache(...);
*
* // v2.5.0 style (recommended)
* import { QuaryCache, getCacheQuery } from 'node-caching-mysql-connector-with-redis';
* QuaryCache(...);
* ```
*/
const connector: {
QuaryCache: typeof QuaryCache;
getCacheQuery: typeof getCacheQuery;
getCacheQueryPagination: typeof getCacheQueryPagination;
bulkInsert: typeof bulkInsert;
getCacheQueryWithTimeout: typeof getCacheQueryWithTimeout;
closeConnections: typeof closeConnections;
getPoolStats: typeof getPoolStats;
withTransaction: typeof withTransaction;
enableAutoKey: typeof enableAutoKey;
enableAutoInvalidation: typeof enableAutoInvalidation;
configure: typeof configure;
getArrayItem: typeof getArrayItem;
addArrayItem: typeof addArrayItem;
delKeyItem: typeof delKeyItem;
delPrefixKeyItem: typeof delPrefixKeyItem;
getRedisClient: typeof getRedisClient;
};
export default connector;
}