syntropylog
Version:
An instance manager with observability for Node.js applications
1,309 lines (1,284 loc) • 54 kB
TypeScript
import { RedisClientType, RedisModules, RedisFunctions, RedisScripts, RedisClusterType } from 'redis';
/**
* Internal Types for SyntropyLog Framework
*
* These types and utilities are for advanced usage and internal framework operations.
* Use with caution - they may change between versions.
*/
/**
* Represents any value that can be safely serialized to JSON.
* This is a recursive type used to ensure type safety for log metadata.
*/
type JsonValue = string | number | boolean | null | {
[key: string]: JsonValue;
} | JsonValue[];
/**
* Type for values that can be stored in context
*/
type ContextValue = string | number | boolean | null | undefined | Buffer | JsonValue;
/**
* Type for context data structure
*/
type ContextData = Record<string, ContextValue>;
/**
* Type for context configuration options
*/
type ContextConfig = {
correlationIdHeader?: string;
transactionIdHeader?: string;
[key: string]: ContextValue;
};
/**
* Type for context headers used in HTTP requests
*/
type ContextHeaders = Record<string, string>;
/**
* Type for context callback functions
*/
type ContextCallback = () => void | Promise<void>;
/**
* Type for logging matrix configuration
*/
type LoggingMatrix = Partial<Record<string, string[]>>;
/**
* Type for filtered context based on log level
*/
type FilteredContext = Record<string, unknown>;
/**
* Type for Redis values - covers all valid Redis data types
*/
type RedisValue = string | number | boolean | Buffer | null | undefined | RedisValue[] | {
[key: string]: RedisValue;
};
/**
* Type for Redis list elements
*/
type RedisListElement = string | number | Buffer | null | undefined;
/**
* Type for Redis set members
*/
type RedisSetMember = string | number | Buffer;
/**
* Type for Redis sorted set members with scores
*/
type RedisSortedSetMember = {
score: number;
value: RedisValue;
};
/**
* Type for Redis hash field values
*/
type RedisHashValue = string | number | Buffer;
/**
* Type for Redis command options
*/
type RedisCommandOptions = {
[key: string]: JsonValue;
};
/**
* @file src/logger/levels.ts
* @description Defines the available log levels, their names, and their severity weights.
*/
/**
* @description A mapping of log level names to their severity weights.
* Higher numbers indicate higher severity.
*/
declare const LOG_LEVEL_WEIGHTS: {
readonly fatal: 60;
readonly error: 50;
readonly warn: 40;
readonly info: 30;
readonly debug: 20;
readonly trace: 10;
readonly silent: 0;
};
/**
* @description The type representing a valid log level name.
*/
type LogLevel = keyof typeof LOG_LEVEL_WEIGHTS;
/**
* SyntropyLog Types - Internal types for the framework
*
* This file now uses internal types and only contains types specific to this module.
*/
type LogEntry = {
/** The severity level of the log. */
level: LogLevel;
/** The main log message, formatted from the arguments. */
message: string;
/** The ISO 8601 timestamp of when the log was created. */
timestamp: string;
/** Any other properties are treated as structured metadata. */
[key: string]: any;
};
/**
* FILE: src/masking/MaskingEngine.ts
* DESCRIPTION: Ultra-fast data masking engine using JSON flattening strategy.
*
* This engine flattens complex nested objects into linear key-value pairs,
* applies masking rules, and then reconstructs the original structure.
* This approach provides extreme processing speed for any object depth.
*/
/**
* @enum MaskingStrategy
* @description Different masking strategies for various data types.
*/
declare enum MaskingStrategy {
CREDIT_CARD = "credit_card",
SSN = "ssn",
EMAIL = "email",
PHONE = "phone",
PASSWORD = "password",
TOKEN = "token",
CUSTOM = "custom"
}
/**
* @interface MaskingRule
* @description Configuration for a masking rule.
*/
interface MaskingRule {
/** Regex pattern to match field names */
pattern: string | RegExp;
/** Masking strategy to apply */
strategy: MaskingStrategy;
/** Custom masking function (for CUSTOM strategy) */
customMask?: (value: string) => string;
/** Whether to preserve original length */
preserveLength?: boolean;
/** Character to use for masking */
maskChar?: string;
/** Compiled regex pattern for performance */
_compiledPattern?: RegExp;
}
/**
* @interface MaskingEngineOptions
* @description Options for configuring the MaskingEngine.
*/
interface MaskingEngineOptions {
/** Array of masking rules */
rules?: MaskingRule[];
/** Default mask character */
maskChar?: string;
/** Whether to preserve original length by default */
preserveLength?: boolean;
/** Enable default rules for common data types */
enableDefaultRules?: boolean;
}
/**
* @class MaskingEngine
* Ultra-fast data masking engine using JSON flattening strategy.
*
* Instead of processing nested objects recursively, we flatten them to a linear
* structure for extreme processing speed. This approach provides O(n) performance
* regardless of object depth or complexity.
*/
declare class MaskingEngine {
/** @private Array of masking rules */
private rules;
/** @private Default mask character */
private readonly maskChar;
/** @private Whether to preserve original length by default */
private readonly preserveLength;
/** @private Whether the engine is initialized */
private initialized;
/** @private Secure regex tester with timeout */
private readonly regexTest;
constructor(options?: MaskingEngineOptions);
/**
* Adds default masking rules for common data types.
* @private
*/
private addDefaultRules;
/**
* Adds a custom masking rule.
* @param rule - The masking rule to add
*/
addRule(rule: MaskingRule): void;
/**
* Processes a metadata object and applies the configured masking rules.
* Uses JSON flattening strategy for extreme performance.
* @param meta - The metadata object to process
* @returns A new object with the masked data
*/
process(meta: Record<string, unknown>): Record<string, unknown>;
/**
* Applies masking rules to data recursively.
* @param data - Data to mask
* @returns Masked data
* @private
*/
private applyMaskingRules;
/**
* Applies specific masking strategy to a value.
* @param value - Value to mask
* @param rule - Masking rule to apply
* @returns Masked value
* @private
*/
private applyStrategy;
/**
* Masks credit card number.
* @param value - Credit card number
* @param rule - Masking rule
* @returns Masked credit card
* @private
*/
private maskCreditCard;
/**
* Masks SSN.
* @param value - SSN
* @param rule - Masking rule
* @returns Masked SSN
* @private
*/
private maskSSN;
/**
* Masks email address.
* @param value - Email address
* @param rule - Masking rule
* @returns Masked email
* @private
*/
private maskEmail;
/**
* Masks phone number.
* @param value - Phone number
* @param rule - Masking rule
* @returns Masked phone number
* @private
*/
private maskPhone;
/**
* Masks password.
* @param value - Password
* @param rule - Masking rule
* @returns Masked password
* @private
*/
private maskPassword;
/**
* Masks token.
* @param value - Token
* @param rule - Masking rule
* @returns Masked token
* @private
*/
private maskToken;
/**
* Default masking strategy.
* @param value - Value to mask
* @param rule - Masking rule
* @returns Masked value
* @private
*/
private maskDefault;
/**
* Gets masking engine statistics.
* @returns Dictionary with masking statistics
*/
getStats(): Record<string, any>;
/**
* Checks if the masking engine is initialized.
* @returns True if initialized
*/
isInitialized(): boolean;
/**
* Shutdown the masking engine.
*/
shutdown(): void;
}
/**
* @file src/sanitization/SanitizationEngine.ts
* @description Final security layer that sanitizes log entries before they are written by a transport.
*/
/**
* @class SanitizationEngine
* A security engine that makes log entries safe for printing by stripping
* potentially malicious control characters, such as ANSI escape codes.
* This prevents log injection attacks that could exploit terminal vulnerabilities.
*/
declare class SanitizationEngine {
private readonly maskingEngine?;
/** @private This regex matches ANSI escape codes used for colors, cursor movement, etc. */
private readonly ansiRegex;
/**
* @constructor
* The engine is currently not configurable, but the constructor is in place for future enhancements.
*/
constructor(maskingEngine?: MaskingEngine);
/**
* Processes a log metadata object, sanitizing all its string values.
* @param {Record<string, any>} meta - The metadata object to sanitize.
* @returns {Record<string, any>} A new, sanitized metadata object.
*/
process(meta: Record<string, any>): Record<string, any>;
/**
* @private
* Recursively traverses an object or array to sanitize all string values.
* @param {any} data - The data to process.
* @returns {any} The sanitized data.
*/
private sanitizeRecursively;
}
/**
* @file src/logger/transports/formatters/LogFormatter.ts
* @description Defines the public contract for log entry formatters.
*/
/**
* @interface LogFormatter
* @description Defines the interface for a log formatter.
* A formatter is responsible for transforming a standard LogEntry object
* into a specific structure required by a target destination (e.g., Datadog JSON, Elastic Common Schema).
*/
interface LogFormatter {
/**
* Transforms a LogEntry object into a new object with the desired format.
* @param {LogEntry} entry - The standard log entry object to be transformed.
* @returns {Record<string, JsonValue>} A new object representing the log in the target format.
*/
format(entry: LogEntry): Record<string, JsonValue>;
}
/**
* @file src/logger/transports/Transport.ts
* @description Defines the abstract base class for all log transports.
*/
/**
* @interface TransportOptions
* @description Defines the options for configuring a transport.
*/
interface TransportOptions {
/**
* The minimum log level this transport will handle.
* If not specified, the transport will handle all levels defined by the logger.
*/
level?: LogLevel;
/**
* An optional formatter to transform the log entry before output.
*/
formatter?: LogFormatter;
/**
* An optional, pre-configured sanitization engine.
* If provided, the transport will use it to sanitize logs. This is typically
* used by production-safe transports like `ConsoleTransport`.
*/
sanitizationEngine?: SanitizationEngine;
/**
* An optional name for the transport, useful for debugging.
*/
name?: string;
}
/**
* @class Transport
* @description The abstract base class for all log transports. A transport is
* responsible for the final output of a log entry, whether it's to the console,
* a file, or a remote service.
*/
declare abstract class Transport {
level: LogLevel;
name: string;
/** The formatter instance to transform log entries. */
protected readonly formatter?: LogFormatter;
/** The engine used to sanitize sensitive data. */
protected readonly sanitizationEngine?: SanitizationEngine;
/**
* @constructor
* @param {TransportOptions} [options] - The configuration options for this transport.
*/
constructor(options?: TransportOptions);
/**
* Determines if the transport should process a log entry based on its log level.
* @param level - The level of the log entry to check.
* @returns {boolean} - True if the transport is enabled for this level, false otherwise.
*/
isLevelEnabled(level: LogLevel): boolean;
/**
* The core method that all concrete transports must implement. This method
* handles the actual sending/writing of the log entry.
* @param {LogEntry} entry - The final, processed log entry to be outputted.
* @returns {Promise<void>}
*/
abstract log(entry: LogEntry): Promise<void>;
/**
* A method to ensure all buffered logs are written before the application exits.
* Subclasses should override this if they perform I/O buffering.
* @returns {Promise<void>} A promise that resolves when flushing is complete.
*/
flush(): Promise<void>;
}
/**
* @file src/logger/transports/SpyTransport.ts
* @description A transport designed for testing purposes.
*/
/**
* @class SpyTransport
* A transport designed for testing. It captures log entries in memory,
* allowing you to make assertions on what has been logged.
* @extends {Transport}
*/
declare class SpyTransport extends Transport {
private entries;
/**
* @constructor
* @param {TransportOptions} [options] - Options for the transport, such as level.
*/
constructor(options?: TransportOptions);
/**
* Stores the log entry in an in-memory array.
* @param {LogEntry} entry - The log entry to capture.
* @returns {Promise<void>}
*/
log(entry: LogEntry): Promise<void>;
/**
* Returns all log entries captured by this transport.
* @returns {LogEntry[]} A copy of all captured log entries.
*/
getEntries(): LogEntry[];
/**
* Finds log entries where the properties match the given predicate.
* Note: This performs a shallow comparison on the entry's properties.
* @param {Partial<LogEntry> | ((entry: LogEntry) => boolean)} predicate - An object with properties to match or a function that returns true for matching entries.
* @returns {LogEntry[]} An array of matching log entries.
*/
findEntries(predicate: Partial<LogEntry> | ((entry: LogEntry) => boolean)): LogEntry[];
/**
* Clears all captured log entries. Call this in your test setup
* (e.g., `beforeEach`) to ensure test isolation.
* @returns {void}
*/
clear(): void;
/**
* Returns the first log entry that was captured.
* @returns {LogEntry | undefined} The first entry, or undefined if none were captured.
*/
getFirstEntry(): LogEntry | undefined;
/**
* Returns the most recent log entry that was captured.
* @returns {LogEntry | undefined} The last entry, or undefined if none were captured.
*/
getLastEntry(): LogEntry | undefined;
}
/**
* The collection of tools returned by `syntropyLog.setupTestHarness()`,
* designed to facilitate testing of application logic that uses SyntropyLog.
*/
interface SyntropyLogTestHarness {
/**
* A spy transport that captures all log entries in memory.
* Use its methods (`getEntries`, `findEntries`, `clear`) to make
* assertions about what has been logged.
*/
spyTransport: SpyTransport;
}
/**
* @interface IContextManager
* @description The contract for managing asynchronous context.
*/
interface IContextManager {
/**
* Configures the context manager with specific options.
* This should be called once during initialization.
* @param options The configuration options.
* @param options.correlationIdHeader The custom header name to use for the correlation ID.
* @param options.transactionIdHeader The custom header name for the transaction ID.
*/
configure(options: ContextConfig): void;
/**
* Executes a function within a new, isolated asynchronous context.
* The new context can inherit data from the parent context.
* @template T The return type of the callback function.
* @param callback The function to execute within the new context.
* @returns The return value of the callback function.
*/
run(fn: ContextCallback): Promise<void>;
/**
* Sets a value in the current asynchronous context.
* @param key The key for the value.
* @param value The value to store.
*/
set(key: string, value: ContextValue): void;
/**
* Gets a value from the current asynchronous context.
* @template T The expected type of the value.
* @param key The key of the value to retrieve.
* @returns The value associated with the key, or `undefined` if not found.
*/
get<T = ContextValue>(key: string): T | undefined;
/**
* Gets the entire key-value store from the current context.
* @returns {ContextData} An object containing all context data.
*/
getAll(): ContextData;
/**
* A convenience method to get the correlation ID from the current context.
* If no correlation ID exists, generates one automatically to ensure tracing continuity.
* @returns {string} The correlation ID (never undefined).
*/
getCorrelationId(): string;
/**
* Gets the configured HTTP header name used for the correlation ID.
* @returns {string} The header name.
*/
getCorrelationIdHeaderName(): string;
/**
* Gets the configured HTTP header name used for the transaction ID.
* @returns {string} The header name.
*/
getTransactionIdHeaderName(): string;
/**
* A convenience method to get the transaction ID from the current context.
* @returns {string | undefined} The transaction ID, or undefined if not set.
*/
getTransactionId(): string | undefined;
/**
* A convenience method to set the transaction ID in the current context.
* @param transactionId The transaction ID to set.
*/
setTransactionId(transactionId: string): void;
/** Gets the tracing headers to propagate the context (e.g., W3C Trace Context). */
getTraceContextHeaders(): ContextHeaders;
/**
* Gets a filtered context based on the specified log level.
* This is useful for logging purposes to ensure only relevant context is included.
* @param level The log level to filter by.
* @returns A record containing only the context data relevant for the specified level.
*/
getFilteredContext(level: LogLevel): FilteredContext;
/**
* Reconfigures the logging matrix dynamically.
* This method allows changing which context fields are included in logs
* without affecting security configurations like masking or log levels.
* @param newMatrix The new logging matrix configuration
*/
reconfigureLoggingMatrix(newMatrix: LoggingMatrix): void;
}
/**
* @class MockContextManager
* @description A mock implementation of `IContextManager` for testing purposes.
* It uses a simple in-memory object instead of AsyncLocalStorage,
* making context management predictable and synchronous in tests.
* @implements {IContextManager}
*/
declare class MockContextManager$1 implements IContextManager {
/** @private The in-memory key-value store for the context. */
private store;
/** @private The HTTP header name used for the correlation ID. */
private correlationIdHeader;
/** @private The HTTP header name used for the transaction ID. */
private transactionIdHeader;
/**
* Configures the mock context manager.
* @param options The configuration options.
* @param options.correlationIdHeader The custom header name to use for the correlation ID.
* @param options.transactionIdHeader The custom header name for the transaction ID.
*/
configure(options?: ContextConfig): void;
/**
* Simulates running a function within a new, isolated context.
* It saves the current context, creates a new one inheriting the parent's values,
* runs the callback, and then restores the original context. This process
* correctly handles both synchronous and asynchronous callbacks.
* @template T The return type of the callback.
* @param {() => T} callback The function to execute within the new context.
* @returns {T} The result of the callback.
*/
run(fn: ContextCallback): Promise<void>;
/**
* Gets a value from the mock context by its key.
* @template T The expected type of the value.
* @param {string} key The key of the value to retrieve.
* @returns The value, or `undefined` if not found.
*/
get<T = ContextValue>(key: string): T | undefined;
/**
* Gets a shallow copy of the entire mock context store.
* @returns {ContextData} An object containing all context data.
*/
getAll(): ContextData;
/**
* Sets a key-value pair in the mock context.
* @param {string} key The key for the value.
* @param {ContextValue} value The value to store.
* @returns {void}
*/
set(key: string, value: ContextValue): void;
/**
* Clears the in-memory store.
* Useful for resetting state between tests (e.g., in a `beforeEach` hook).
* @returns {void}
*/
clear(): void;
/**
* A convenience method to get the correlation ID from the mock context.
* @returns {string} The correlation ID, or a generated one if not set.
*/
getCorrelationId(): string;
/**
* A convenience method to get the transaction ID from the mock context.
* @returns {string | undefined} The transaction ID, or undefined if not set.
*/
getTransactionId(): string | undefined;
/**
* A convenience method to set the transaction ID in the mock context.
* @param {string} transactionId The transaction ID to set.
*/
setTransactionId(transactionId: string): void;
/**
* Gets the configured HTTP header name used for the correlation ID.
* @returns {string} The header name.
*/
getCorrelationIdHeaderName(): string;
/**
* Gets the configured HTTP header name used for the transaction ID.
* @returns {string} The header name.
*/
getTransactionIdHeaderName(): string;
/**
* Mock implementation for getting trace context headers.
* In a real tracing scenario, this would be populated.
* @returns `undefined` as this mock does not implement tracing.
*/
getTraceContextHeaders(): ContextHeaders;
getFilteredContext(): FilteredContext;
/**
* Reconfigures the logging matrix dynamically.
* This method allows changing which context fields are included in logs
* without affecting security configurations like masking or log levels.
* @param newMatrix The new logging matrix configuration
*/
reconfigureLoggingMatrix(newMatrix: LoggingMatrix): void;
}
/**
* Mock implementation of SyntropyLog for testing
*
* This mock provides a complete simulation of SyntropyLog functionality
* without depending on the actual framework state, making tests more reliable
* and avoiding initialization/shutdown issues.
*
* Similar to BeaconRedisMock, this is designed to be flexible and configurable
* for different testing scenarios.
*/
interface MockLogger {
info: (message: string, metadata?: any) => void;
warn: (message: string, metadata?: any) => void;
error: (message: string, metadata?: any) => void;
debug: (message: string, metadata?: any) => void;
trace: (message: string, metadata?: any) => void;
fatal: (message: string, metadata?: any) => void;
withSource: (source: string) => MockLogger;
}
interface MockContextManager {
run: <T>(fn: () => Promise<T> | T) => Promise<T>;
set: (key: string, value: any) => void;
get: (key: string) => any;
getCorrelationIdHeaderName: () => string;
getTransactionIdHeaderName: () => string;
}
interface MockSyntropyLog {
init: (config?: any) => Promise<void>;
shutdown: () => Promise<void>;
getLogger: (serviceName?: string) => MockLogger;
getContextManager: () => MockContextManager;
getHttpManager: () => any;
getBrokerManager: () => any;
getSerializationManager: () => any;
}
/**
* Create a mock logger instance
*/
declare function createMockLogger(): MockLogger;
/**
* Create a mock context manager instance
*/
declare function createMockContextManager(): MockContextManager;
/**
* Create a mock HTTP manager instance
*/
declare function createMockHttpManager(): {
createClient: () => {
get: () => Promise<{
data: {};
}>;
post: () => Promise<{
data: {};
}>;
put: () => Promise<{
data: {};
}>;
delete: () => Promise<{
data: {};
}>;
};
};
/**
* Create a mock broker manager instance
*/
declare function createMockBrokerManager(): {
createClient: () => {
publish: () => Promise<undefined>;
subscribe: () => Promise<undefined>;
};
};
/**
* Create a mock serialization manager instance
*/
declare function createMockSerializationManager(): {
serialize: () => Promise<string>;
deserialize: () => Promise<{}>;
};
/**
* Get or create mock logger instance
*/
declare function getMockLogger(): MockLogger;
/**
* Get or create mock context manager instance
*/
declare function getMockContextManager(): MockContextManager;
/**
* Get or create mock HTTP manager instance
*/
declare function getMockHttpManager(): any;
/**
* Get or create mock broker manager instance
*/
declare function getMockBrokerManager(): any;
/**
* Get or create mock serialization manager instance
*/
declare function getMockSerializationManager(): any;
/**
* Create a complete mock of SyntropyLog
*
* @param spyFn - Optional spy function for framework compatibility (vi.fn, jest.fn, etc.)
*/
declare function createSyntropyLogMock(spyFn?: (implementation?: any) => any): MockSyntropyLog;
/**
* Reset all mock instances
*/
declare function resetSyntropyLogMocks(): void;
/**
* Test helper for SyntropyLog applications
*
* This helper provides a simple way to set up tests with SyntropyLog mocks
* without dealing with initialization/shutdown issues.
*/
interface TestHelper {
mockSyntropyLog: any;
beforeEach: () => void;
afterEach: () => void;
}
/**
* Create a test helper for SyntropyLog testing
*
* @param spyFn - Optional spy function for framework compatibility (vi.fn, jest.fn, etc.)
*
* @example
* ```typescript
* // For Vitest
* const testHelper = createTestHelper(vi.fn);
*
* // For Jest
* const testHelper = createTestHelper(jest.fn);
*
* // For Jasmine
* const testHelper = createTestHelper(jasmine.createSpy);
*
* // Without spy (basic functionality only)
* const testHelper = createTestHelper();
*
* describe('MyService', () => {
* beforeEach(() => testHelper.beforeEach());
* afterEach(() => testHelper.afterEach());
*
* it('should work', () => {
* const service = new MyService(testHelper.mockSyntropyLog);
* // ... test logic
* });
* });
* ```
*/
declare function createTestHelper(spyFn?: (implementation?: any) => any): TestHelper;
/**
* Create a service with SyntropyLog mock for testing
*
* @param ServiceClass - The service class to instantiate
* @param mockSyntropyLog - The mock SyntropyLog instance
* @returns Instance of the service with mock injected
*
* @example
* ```typescript
* const mockSyntropyLog = createSyntropyLogMock();
* const userService = createServiceWithMock(UserService, mockSyntropyLog);
* ```
*/
declare function createServiceWithMock<T>(ServiceClass: new (syntropyLog?: any) => T, mockSyntropyLog: any): T;
/**
* MockBrokerAdapter - Framework Agnostic Mock
*
* This mock provides a testing-agnostic version of IBrokerAdapter
* that can be used with both Vitest and Jest without conflicts.
*/
interface BrokerMessage {
id: string;
data: any;
metadata?: Record<string, any>;
timestamp?: string;
}
type MessageHandler = (message: BrokerMessage) => Promise<void> | void;
interface IBrokerAdapter {
connect(): Promise<void>;
disconnect(): Promise<void>;
publish(topic: string, message: BrokerMessage): Promise<void>;
subscribe(topic: string, handler: MessageHandler): Promise<void>;
}
declare class MockBrokerAdapter implements IBrokerAdapter {
private spyFn;
private errors;
private timeouts;
readonly connect: any;
readonly disconnect: any;
readonly publish: any;
readonly subscribe: any;
readonly setError: any;
readonly setTimeout: any;
readonly reset: any;
constructor(spyFn?: (implementation?: any) => any);
private createMock;
}
/**
* MockHttpClient - Framework Agnostic Mock
*
* This mock provides a testing-agnostic version of IHttpClientAdapter
* that can be used with both Vitest and Jest without conflicts.
*/
interface AdapterHttpRequest {
url: string;
method: string;
headers: Record<string, any>;
body?: any;
timeout?: number;
}
interface AdapterHttpResponse<T = any> {
statusCode: number;
data: T;
headers: Record<string, any>;
}
interface IHttpClientAdapter {
request(request: AdapterHttpRequest): Promise<AdapterHttpResponse<any>>;
get(url: string, headers?: Record<string, any>): Promise<AdapterHttpResponse<any>>;
post(url: string, body?: any, headers?: Record<string, any>): Promise<AdapterHttpResponse<any>>;
put(url: string, body?: any, headers?: Record<string, any>): Promise<AdapterHttpResponse<any>>;
delete(url: string, headers?: Record<string, any>): Promise<AdapterHttpResponse<any>>;
patch(url: string, body?: any, headers?: Record<string, any>): Promise<AdapterHttpResponse<any>>;
}
declare class MockHttpClient implements IHttpClientAdapter {
private spyFn;
private timeouts;
readonly request: any;
readonly get: any;
readonly post: any;
readonly put: any;
readonly delete: any;
readonly patch: any;
readonly setResponse: any;
readonly setError: any;
readonly setTimeout: any;
readonly reset: any;
constructor(spyFn?: (implementation?: any) => any);
private updateMethodImplementations;
private createMock;
}
declare class MockSerializerRegistry {
private serializers;
private errorKeys;
private timeoutMs;
private spyFn;
readonly process: any;
readonly setSerializer: any;
readonly setError: any;
readonly setTimeout: any;
readonly reset: any;
constructor(spyFn?: (implementation?: any) => any);
private createMock;
}
/**
* FILE: src/redis/redis.types.ts
* DESCRIPTION: Defines fundamental types extracted from `redis@v4` for use throughout the library.
*/
/**
* Represents a Redis client instance, which can be either a single-node (standalone) or a cluster client.
* This is the core client type used internally by `BeaconRedis` and `RedisManager`.
*/
type NodeRedisClient = RedisClientType<RedisModules, RedisFunctions, RedisScripts> | RedisClusterType<RedisModules, RedisFunctions, RedisScripts>;
/**
* Defines the structure of a Sorted Set member when returned with its score.
*/
type RedisZMember = {
score: number;
value: string;
};
/**
* Represents the native transaction (multi) object from the `redis` client.
* It is extracted using `ReturnType` to ensure it always matches the native library's type.
*/
type RedisTransaction = ReturnType<NodeRedisClient['multi']>;
/**
* Represents the result of a transaction's execution (EXEC).
* It is an array containing the results of each command within the transaction.
*/
type TransactionResult = Awaited<ReturnType<RedisTransaction['exec']>>;
/**
* @file src/redis/IBeaconRedis.ts
* @description Defines the contract for an instrumented Redis client.
* It exposes common Redis commands and methods for lifecycle management.
*/
/**
* Defines the contract for a Redis transaction (MULTI/EXEC).
* All command methods are chainable, returning `this` to queue further commands.
*/
interface IBeaconRedisTransaction {
/** Queues a GET command. */
get(key: string): this;
/** Queues a SET command. */
set(key: string, value: RedisValue, ttlSeconds?: number): this;
/** Queues a DEL command. */
del(key: string | string[]): this;
/** Queues an EXISTS command. */
exists(keys: string | string[]): this;
/** Queues an EXPIRE command. */
expire(key: string, seconds: number): this;
/** Queues a TTL command. */
ttl(key: string): this;
/** Queues an INCR command. */
incr(key: string): this;
/** Queues a DECR command. */
decr(key: string): this;
/** Queues an INCRBY command. */
incrBy(key: string, increment: number): this;
/** Queues a DECRBY command. */
decrBy(key: string, decrement: number): this;
/** Queues an HGET command. */
hGet(key: string, field: string): this;
/** Queues an HSET command for a single field. */
hSet(key: string, field: string, value: RedisHashValue): this;
/** Queues an HSET command for multiple fields. */
hSet(key: string, fieldsAndValues: Record<string, RedisHashValue>): this;
/** Queues an HGETALL command. */
hGetAll(key: string): this;
/** Queues an HDEL command. */
hDel(key: string, fields: string | string[]): this;
/** Queues an HEXISTS command. */
hExists(key: string, field: string): this;
/** Queues an HINCRBY command. */
hIncrBy(key: string, field: string, increment: number): this;
/** Queues an LPUSH command. */
lPush(key: string, elements: RedisListElement | RedisListElement[]): this;
/** Queues an RPUSH command. */
rPush(key: string, elements: RedisListElement | RedisListElement[]): this;
/** Queues an LPOP command. */
lPop(key: string): this;
/** Queues an RPOP command. */
rPop(key: string): this;
/** Queues an LRANGE command. */
lRange(key: string, start: number, stop: number): this;
/** Queues an LLEN command. */
lLen(key: string): this;
/** Queues an LTRIM command. */
lTrim(key: string, start: number, stop: number): this;
/** Queues an SADD command. */
sAdd(key: string, members: RedisSetMember | RedisSetMember[]): this;
/** Queues an SMEMBERS command. */
sMembers(key: string): this;
/** Queues an SISMEMBER command. */
sIsMember(key: string, member: RedisSetMember): this;
/** Queues an SREM command. */
sRem(key: string, members: RedisSetMember | RedisSetMember[]): this;
/** Queues an SCARD command. */
sCard(key: string): this;
/** Queues a ZADD command for a single member. */
zAdd(key: string, score: number, member: RedisValue): this;
/** Queues a ZADD command for multiple members. */
zAdd(key: string, members: RedisSortedSetMember[]): this;
/** Queues a ZRANGE command. */
zRange(key: string, min: string | number, max: string | number, options?: RedisCommandOptions): this;
/** Queues a ZRANGE command with scores. */
zRangeWithScores(key: string, min: string | number, max: string | number, options?: RedisCommandOptions): this;
/** Queues a ZREM command. */
zRem(key: string, members: RedisValue | RedisValue[]): this;
/** Queues a ZCARD command. */
zCard(key: string): this;
/** Queues a ZSCORE command. */
zScore(key: string, member: RedisValue): this;
/** Queues a PING command. */
ping(message?: string): this;
/** Queues an INFO command. */
info(section?: string): this;
/**
* Executes all queued commands in the transaction.
* @returns A promise that resolves with an array of results from each command.
*/
exec(): Promise<TransactionResult>;
/**
* Discards the transaction, clearing all queued commands.
* @returns A promise that resolves when the transaction is discarded.
*/
discard(): Promise<void>;
}
/**
* Defines the main interface for an instrumented Redis client, providing a unified API
* for various Redis commands and lifecycle management.
*/
interface IBeaconRedis {
/**
* Gets the configured name of this Redis instance.
* @returns The instance name.
*/
getInstanceName(): string;
/**
* Dynamically updates the configuration for this Redis instance.
* @param newConfig A partial configuration object with the new values.
*/
updateConfig(newConfig: Partial<Record<string, unknown>>): void;
/**
* Establishes a connection to the Redis server if not already connected.
* @returns {Promise<void>} A promise that resolves when the client is connected and ready.
*/
connect(): Promise<void>;
/**
* Closes the connection to the Redis server.
* @returns {Promise<void>} A promise that resolves when the connection is successfully closed.
*/
quit(): Promise<void>;
/**
* Initiates a new transaction block (MULTI).
* @returns {IBeaconRedisTransaction} An instance for queueing commands.
*/
multi(): IBeaconRedisTransaction;
/**
* Gets the value of a key. Corresponds to the Redis GET command.
* @param {string} key The key to retrieve.
* @returns {Promise<string | null>} A promise that resolves with the value of the key, or null if the key does not exist.
*/
get(key: string): Promise<string | null>;
/**
* Sets the string value of a key. Corresponds to the Redis SET command.
* @param {string} key The key to set.
* @param {string} value The value to set for the key.
* @param {number} [ttlSeconds] Optional. The time-to-live for the key in seconds.
* @returns {Promise<string | null>} A promise that resolves with 'OK' on success.
*/
set(key: string, value: string, ttlSeconds?: number): Promise<string | null>;
/**
* Deletes one or more keys. Corresponds to the Redis DEL command.
* @param {string | string[]} keys A single key or an array of keys to delete.
* @returns {Promise<number>} A promise that resolves with the number of keys that were deleted.
*/
del(keys: string | string[]): Promise<number>;
/**
* Determines if one or more keys exist. Corresponds to the Redis EXISTS command.
* @param {string | string[]} keys A single key or an array of keys to check.
* @returns {Promise<number>} A promise that resolves with the number of keys that exist.
*/
exists(keys: string | string[]): Promise<number>;
/**
* Sets a key's time to live in seconds. Corresponds to the Redis EXPIRE command.
* @param {string} key The key to set the expiration for.
* @param {number} seconds The time-to-live in seconds.
* @returns {Promise<boolean>} A promise that resolves with true if the timeout was set, false otherwise.
*/
expire(key: string, seconds: number): Promise<boolean>;
/**
* Gets the time to live for a key. Corresponds to the Redis TTL command.
* @param {string} key The key to check.
* @returns {Promise<number>} A promise that resolves with the remaining time to live in seconds.
*/
ttl(key: string): Promise<number>;
/**
* Increments the integer value of a key by one. Corresponds to the Redis INCR command.
* @param {string} key The key to increment.
* @returns {Promise<number>} A promise that resolves with the value of the key after the increment.
*/
incr(key: string): Promise<number>;
/**
* Decrements the integer value of a key by one. Corresponds to the Redis DECR command.
* @param {string} key The key to decrement.
* @returns {Promise<number>} A promise that resolves with the value of the key after the decrement.
*/
decr(key: string): Promise<number>;
/**
* Increments the integer value of a key by the given amount. Corresponds to the Redis INCRBY command.
* @param {string} key The key to increment.
* @param {number} increment The amount to increment by.
* @returns {Promise<number>} A promise that resolves with the value of the key after the increment.
*/
incrBy(key: string, increment: number): Promise<number>;
/**
* Decrements the integer value of a key by the given amount. Corresponds to the Redis DECRBY command.
* @param {string} key The key to decrement.
* @param {number} decrement The amount to decrement by.
* @returns {Promise<number>} A promise that resolves with the value of the key after the decrement.
*/
decrBy(key: string, decrement: number): Promise<number>;
/**
* Gets the value of a hash field. Corresponds to the Redis HGET command.
* @param {string} key The key of the hash.
* @param {string} field The field to get from the hash.
* @returns {Promise<string | null>} A promise that resolves with the value of the field, or null if the field or key does not exist.
*/
hGet(key: string, field: string): Promise<string | null>;
/**
* Sets the string value of a hash field. Corresponds to the Redis HSET command.
* @param {string} key The key of the hash.
* @param {string} field The field to set in the hash.
* @param {RedisHashValue} value The value to set for the field.
* @returns {Promise<number>} A promise that resolves with the number of fields that were added.
*/
hSet(key: string, field: string, value: RedisHashValue): Promise<number>;
/**
* Sets multiple hash fields to multiple values. Corresponds to the Redis HSET command.
* @param {string} key The key of the hash.
* @param {Record<string, RedisHashValue>} fieldsAndValues An object of field-value pairs to set.
* @returns {Promise<number>} A promise that resolves with the number of fields that were added.
*/
hSet(key: string, fieldsAndValues: Record<string, RedisHashValue>): Promise<number>;
/**
* Gets all the fields and values in a hash. Corresponds to the Redis HGETALL command.
* @param {string} key The key of the hash.
* @returns {Promise<Record<string, string>>} A promise that resolves with an object containing all fields and values.
*/
hGetAll(key: string): Promise<Record<string, string>>;
/**
* Deletes one or more hash fields. Corresponds to the Redis HDEL command.
* @param {string} key The key of the hash.
* @param {string | string[]} fields The field or fields to delete.
* @returns {Promise<number>} A promise that resolves with the number of fields that were removed.
*/
hDel(key: string, fields: string | string[]): Promise<number>;
/**
* Determines if a hash field exists. Corresponds to the Redis HEXISTS command.
* @param {string} key The key of the hash.
* @param {string} field The field to check.
* @returns {Promise<boolean>} A promise that resolves with true if the field exists, false otherwise.
*/
hExists(key: string, field: string): Promise<boolean>;
/**
* Increments the integer value of a hash field by the given number. Corresponds to the Redis HINCRBY command.
* @param {string} key The key of the hash.
* @param {string} field The field to increment.
* @param {number} increment The amount to increment by.
* @returns {Promise<number>} A promise that resolves with the value of the field after the increment.
*/
hIncrBy(key: string, field: string, increment: number): Promise<number>;
/**
* Prepends one or multiple values to a list. Corresponds to the Redis LPUSH command.
* @param {string} key The key of the list.
* @param {RedisListElement | RedisListElement[]} elements The value or values to prepend.
* @returns {Promise<number>} A promise that resolves with the length of the list after the push operation.
*/
lPush(key: string, elements: RedisListElement | RedisListElement[]): Promise<number>;
/**
* Appends one or multiple values to a list. Corresponds to the Redis RPUSH command.
* @param {string} key The key of the list.
* @param {RedisListElement | RedisListElement[]} elements The value or values to append.
* @returns {Promise<number>} A promise that resolves with the length of the list after the push operation.
*/
rPush(key: string, elements: RedisListElement | RedisListElement[]): Promise<number>;
/**
* Removes and gets the first element in a list. Corresponds to the Redis LPOP command.
* @param {string} key The key of the list.
* @returns {Promise<string | null>} A promise that resolves with the value of the first element, or null if the list is empty.
*/
lPop(key: string): Promise<string | null>;
/**
* Removes and gets the last element in a list. Corresponds to the Redis RPOP command.
* @param {string} key The key of the list.
* @returns {Promise<string | null>} A promise that resolves with the value of the last element, or null if the list is empty.
*/
rPop(key: string): Promise<string | null>;
/**
* Gets a range of elements from a list. Corresponds to the Redis LRANGE command.
* @param {string} key The key of the list.
* @param {number} start The starting index.
* @param {number} stop The ending index.
* @returns {Promise<string[]>} A promise that resolves with an array of elements in the specified range.
*/
lRange(key: string, start: number, stop: number): Promise<string[]>;
/**
* Gets the length of a list. Corresponds to the Redis LLEN command.
* @param {string} key The key of the list.
* @returns {Promise<number>} A promise that resolves with the length of the list.
*/
lLen(key: string): Promise<number>;
/**
* Trims a list to the specified range. Corresponds to the Redis LTRIM command.
* @param {string} key The key of the list.
* @param {number} start The starting index.
* @param {number} stop The ending index.
* @returns {Promise<string>} A promise that resolves with 'OK'.
*/
lTrim(key: string, start: number, stop: number): Promise<string>;
/**
* Adds one or more members to a set. Corresponds to the Redis SADD command.
* @param {string} key The key of the set.
* @param {RedisSetMember | RedisSetMember[]} members The member or members to add.
* @returns {Promise<number>} A promise that resolves with the number of members that were added to the set.
*/
sAdd(key: string, members: RedisSetMember | RedisSetMember[]): Promise<number>;
/**
* Gets all the members in a set. Corresponds to the Redis SMEMBERS command.
* @param {string} key The key of the set.
* @returns {Promise<string[]>} A promise that resolves with an array of all the members in the set.
*/
sMembers(key: string): Promise<string[]>;
/**
* Determines if a given value is a member of a set. Corresponds to the Redis SISMEMBER command.
* @param {string} key The key of the set.
* @param {RedisSetMember} member The member to check for.
* @returns {Promise<boolean>} A promise that resolves with true if the member exists in the set, false otherwise.
*/
sIsMember(key: string, member: RedisSetMember): Promise<boolean>;
/**
* Removes one or more members from a set. Corresponds to the Redis SREM command.
* @param {string} key The key of the set.
* @param {RedisSetMember | RedisSetMember[]} members The member or members to remove.
* @returns {Promise<number>} A promise that resolves with the number of members that were removed from the set.
*/
sRem(key: string, members: RedisSetMember | RedisSetMember[]): Promise<number>;
/**
* Gets the number of members in a set. Corresponds to the Redis SCARD command.
* @param {string} key The key of the set.
* @returns {Promise<number>} A promise that resolves with the number of members in the set.
*/
sCard(key: string): Promise<number>;
/**
* Adds a member to a sorted set, or updates its score if it already exists. Corresponds to the Redis ZADD command.
* @param {string} key The key of the sorted set.
* @param {number} score The score for the member.
* @param {RedisValue} member The member to add.
* @returns {Promise<number>} A promise that resolves with the number of elements added to the sorted set.
*/
zAdd(key: string, score: number, member: RedisValue): Promise<number>;
/**
* Adds multiple members to a sorted set, or updates their scores if they already exist. Corresponds to the Redis ZADD command.
* @param {string} key The key of the sorted set.
* @param {RedisSortedSetMember[]} members An array of member-score objects to add.
* @returns {Promise<number>} A promise that resolves with the number of elements added to the sorted set.
*/
zAdd(key: string, members: RedisSortedSetMember[]): Promise<number>;
/**
* Returns a range of members in a sorted set, by index. Corresponds to the Redis ZRANGE command.
* @param {string} key The key of the sorted set.
* @param {string | number} min The minimum index or score.
* @param {string | number} max The maximum index or score.
* @param {RedisCommandOptions} [options] Additional options (e.g., { REV: true }).
* @returns {Promise<string[]>} A promise that resolves with an array of members in the specified range.
*/
zRange(key: string, min: string | number, max: string | number, options?: RedisCommandOptions): Promise<string[]>;
/**
* Returns a range of members in a sorted set, by index, with scores. Corresponds to the Redis ZRANGE command with WITHSCORES.
* @param {string} key The key of the sorted set.
* @param {string | number} min The minimum index or score.
* @param {string | number} max The maximum index or score.
* @param {RedisCommandOptions} [options] Additional options (e.g., { REV: true }).
* @returns {Promise<RedisZMember[]>} A promise that resolves with an array of members and their scores.
*/
zRangeWithScores(key: string, min: string