UNPKG

syntropylog

Version:

An instance manager with observability for Node.js applications

1,309 lines (1,284 loc) 54 kB
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