syntropylog
Version:
An instance manager with observability for Node.js applications
1,367 lines (1,352 loc) • 113 kB
TypeScript
import { z } from 'zod';
import { RedisClientType, RedisModules, RedisFunctions, RedisScripts, RedisClusterType } from 'redis';
import { EventEmitter } from 'events';
import chalk from 'chalk';
/**
* 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[];
/**
* Helper function to convert unknown error to JsonValue
* Moved from @syntropylog/types to internal types
*/
declare function errorToJsonValue(error: unknown): JsonValue;
/**
* Type for log metadata objects that can be passed to logging methods
*/
type LogMetadata = Record<string, JsonValue>;
/**
* Type for log bindings that are attached to logger instances
*/
type LogBindings = Record<string, JsonValue>;
/**
* Type for retention rules that can be attached to loggers
*/
type LogRetentionRules = {
ttl?: number;
maxSize?: number;
maxEntries?: number;
archiveAfter?: number;
deleteAfter?: number;
[key: string]: JsonValue | number | undefined;
};
/**
* Type for format arguments that can be passed to logging methods
*/
type LogFormatArg = string | number | boolean | null | undefined;
/**
* Type for the arguments that can be passed to logging methods
* This follows the Pino-like signature: (obj, msg, ...args) or (msg, ...args)
*/
type LogArguments = [LogMetadata, string?, ...LogFormatArg[]] | [string, ...LogFormatArg[]] | [];
/**
* 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 any object that can be used as metadata
*/
type MetadataObject = Record<string, JsonValue>;
/**
* Context object for logging operations
*/
type LogContext = {
correlationId?: string;
userId?: string | number;
sessionId?: string;
requestId?: string;
[key: string]: JsonValue | undefined;
};
/**
* Context for pipeline operations (serialization, sanitization, etc.)
*/
type PipelineContext = {
correlationId?: string;
operation?: string;
metadata?: Record<string, JsonValue>;
timestamp?: number;
};
/**
* Context for sanitization operations
*/
type SanitizationContext = {
sensitiveFields?: string[];
maskPatterns?: Record<string, string>;
depth?: number;
maxDepth?: number;
};
/**
* 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;
};
/**
* Type for Redis pipeline operations
*/
type RedisPipelineOperation = {
command: string;
args: RedisValue[];
};
/**
* Type for Redis connection parameters
*/
type RedisConnectionParams = {
host?: string;
port?: number;
password?: string;
db?: number;
[key: string]: unknown;
};
/**
* Type for serialized data
*/
type SerializedData = any;
/**
* Type for serialization context configuration
*/
type SerializationContextConfig = {
depth: number;
maxDepth: number;
sensitiveFields: string[];
sanitize: boolean;
customTimeout?: number;
};
/**
* Type for sanitization configuration
*/
type SanitizationConfig = {
sensitiveFields: string[];
redactPatterns: RegExp[];
maxStringLength: number;
enableDeepSanitization: boolean;
};
/**
* Type for serialization pipeline context
*/
type SerializationPipelineContext = {
serializationContext: SerializationContextConfig;
sanitizeSensitiveData: boolean;
sanitizationContext: SanitizationConfig;
enableMetrics: boolean;
};
/**
* Type for step durations in serialization pipeline
*/
type StepDurations = {
serialization?: number;
sanitization?: number;
timeout?: number;
};
/**
* Type for serialization metadata
*/
type SerializationMetadata = {
stepDurations?: StepDurations;
operationTimeout?: number;
complexity?: string;
serializer?: string;
timeoutStrategy?: string;
};
/**
* Type for serialization result
*/
type SerializationResult = {
data: SerializedData;
serializer: string;
duration: number;
complexity: string;
sanitized: boolean;
success: boolean;
metadata: SerializationMetadata;
error?: string;
};
/**
* Type for complexity distribution
*/
type ComplexityDistribution = {
low: number;
medium: number;
high: number;
};
/**
* Type for serializer distribution
*/
type SerializerDistribution = Record<string, number>;
/**
* Type for timeout strategy distribution
*/
type TimeoutStrategyDistribution = Record<string, number>;
/**
* Type for serialization metrics
*/
type SerializationMetrics = {
totalSerializations: number;
successfulSerializations: number;
failedSerializations: number;
averageSerializationDuration: number;
averageOperationTimeout: number;
maxSerializationDuration: number;
minSerializationDuration: number;
complexityDistribution: ComplexityDistribution;
serializerDistribution: SerializerDistribution;
timeoutStrategyDistribution: TimeoutStrategyDistribution;
};
/**
* Type for logger dependencies (internal)
*/
type LoggerDependencies = {
contextManager: unknown;
serializerRegistry: unknown;
maskingEngine: unknown;
syntropyLogInstance: unknown;
};
/**
* Interface for HTTP request in adapters
*/
interface AdapterHttpRequest$1 {
/** The full URL for the request. */
url: string;
/** The HTTP method. */
method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS';
/** A record of request headers. */
headers: Record<string, string | number | string[]>;
/** The request body, if any. */
body?: unknown;
/** A record of URL query parameters. */
queryParams?: Record<string, any>;
}
/**
* Interface for HTTP response in adapters
*/
interface AdapterHttpResponse$1<T = any> {
/** The HTTP status code of the response. */
statusCode: number;
/** The response body data. */
data: T;
/** A record of response headers. */
headers: Record<string, string | number | string[]>;
}
/**
* Interface for HTTP error in adapters
*/
interface AdapterHttpError extends Error {
/** The original request that caused the error. */
request: AdapterHttpRequest$1;
/** The response received, if any. */
response?: AdapterHttpResponse$1;
/** A flag to identify this as a normalized adapter error. */
isAdapterError: true;
}
/**
* @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 LoggerOptions = {
level?: LogLevel;
serviceName?: string;
transports?: unknown[];
bindings?: Record<string, any>;
};
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/http/adapters/adapter.types.ts
* @description Defines the "Universal HTTP Contract" for any HTTP client that
* wants to be instrumented by SyntropyLog. These generic interfaces are key
* to decoupling the framework from specific implementations like axios or got.
*/
/**
* @interface AdapterHttpRequest
* @description Represents a generic, normalized HTTP request that the framework
* can understand. The adapter is responsible for converting this to the
* specific format of the underlying library (e.g., AxiosRequestConfig).
*/
interface AdapterHttpRequest {
/** The full URL for the request. */
url: string;
/** The HTTP method. */
method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS';
/** A record of request headers. */
headers: Record<string, string | number | string[]>;
/** The request body, if any. */
body?: unknown;
/** A record of URL query parameters. */
queryParams?: Record<string, any>;
}
/**
* @interface AdapterHttpResponse
* @description Represents a generic, normalized HTTP response. The adapter
* will convert the library-specific response into this format.
* @template T The expected type of the response body data.
*/
interface AdapterHttpResponse<T = any> {
/** The HTTP status code of the response. */
statusCode: number;
/** The response body data. */
data: T;
/** A record of response headers. */
headers: Record<string, string | number | string[]>;
}
/**
* @interface IHttpClientAdapter
* @description The interface that every HTTP Client Adapter must implement.
* This is the "plug" where users will connect their clients.
*/
interface IHttpClientAdapter {
/**
* The core method that the SyntropyLog instrumenter needs. It executes an
* HTTP request and returns a normalized response, or throws a normalized error.
* @template T The expected type of the response body data.
* @param {AdapterHttpRequest} request The generic HTTP request to execute.
* @returns {Promise<AdapterHttpResponse<T>>} A promise that resolves with the normalized response.
*/
request<T>(request: AdapterHttpRequest): Promise<AdapterHttpResponse<T>>;
}
/**
* @file src/brokers/adapter.types.ts
* @description Defines the "Universal Broker Contract" for any messaging client
* that wants to be instrumented by SyntropyLog. These generic interfaces
* are key to decoupling the framework from specific implementations like
* RabbitMQ or Kafka.
*/
/**
* @interface BrokerMessage
* @description Represents a standard message format that the framework understands.
* The adapter is responsible for converting the broker-specific message
* format to this structure, and vice-versa.
*/
interface BrokerMessage {
/**
* The actual content of the message. Using `Buffer` is the most flexible
* approach as it supports any type of serialization (JSON, Avro, Protobuf, etc.).
*/
payload: Buffer;
/**
* Key-value metadata attached to the message.
* This is where SyntropyLog will inject tracing headers like `correlation-id`.
*/
headers?: Record<string, string | Buffer>;
}
/**
* @interface MessageLifecycleControls
* @description Defines the controls for handling a received message's lifecycle.
* An instance of this is passed to the user's message handler, allowing them
* to confirm or reject the message.
*/
interface MessageLifecycleControls {
/**
* Acknowledges that the message has been successfully processed.
* This typically removes the message from the queue.
* @returns {Promise<void>}
*/
ack: () => Promise<void>;
/**
* Negatively acknowledges the message, indicating a processing failure.
* @param {boolean} [requeue=false] - If true, asks the broker to re-queue the message
* for another attempt. If false (or omitted), the broker might move it to a dead-letter queue
* or discard it, depending on its configuration.
* @returns {Promise<void>}
*/
nack: (requeue?: boolean) => Promise<void>;
}
/**
* @type MessageHandler
* @description The signature for the user-provided function that will process incoming messages.
* @param {BrokerMessage} message - The received message in the framework's standard format.
* @param {MessageLifecycleControls} controls - The functions to manage the message's lifecycle (ack/nack).
* @returns {Promise<void>}
*/
type MessageHandler = (message: BrokerMessage, controls: MessageLifecycleControls) => Promise<void>;
/**
* @interface IBrokerAdapter
* @description The interface that every Broker Client Adapter must implement.
* This is the "plug" where users will connect their specific messaging clients
* (e.g., `amqplib`, `kafkajs`).
*/
interface IBrokerAdapter {
/**
* Establishes a connection to the message broker.
* @returns {Promise<void>}
*/
connect(): Promise<void>;
/**
* Gracefully disconnects from the broker.
*/
/**
* Gracefully disconnects from the message broker.
* @returns {Promise<void>}
*/
disconnect(): Promise<void>;
/**
* Publishes a message to a specific topic or routing key.
* @param {string} topic - The destination for the message (e.g., a topic name, queue name, or routing key).
* @param {BrokerMessage} message - The message to be sent, in the framework's standard format.
* @returns {Promise<void>}
*/
publish(topic: string, message: BrokerMessage): Promise<void>;
/**
* Subscribes to a topic or queue to receive messages.
* @param {string} topic - The source of messages to listen to (e.g., a topic name or queue name).
* @param {MessageHandler} handler - The user's function that will be called for each incoming message.
* @returns {Promise<void>}
*/
subscribe(topic: string, handler: MessageHandler): Promise<void>;
}
/**
* FILE: src/config.schema.ts
* DESCRIPTION: Defines the Zod validation schemas for the entire library's configuration.
* These schemas are the single source of truth for the configuration's structure and types.
*/
/**
* @description Schema for a single HTTP client instance.
*/
declare const httpInstanceConfigSchema: z.ZodObject<{
instanceName: z.ZodString;
adapter: z.ZodType<IHttpClientAdapter, z.ZodTypeDef, IHttpClientAdapter>;
isDefault: z.ZodOptional<z.ZodBoolean>;
propagate: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
propagateFullContext: z.ZodOptional<z.ZodBoolean>;
logging: z.ZodOptional<z.ZodObject<{
onSuccess: z.ZodOptional<z.ZodDefault<z.ZodEnum<["trace", "debug", "info"]>>>;
onError: z.ZodOptional<z.ZodDefault<z.ZodEnum<["warn", "error", "fatal"]>>>;
logSuccessBody: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
logSuccessHeaders: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
onRequest: z.ZodOptional<z.ZodDefault<z.ZodEnum<["trace", "debug", "info"]>>>;
logRequestBody: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
logRequestHeaders: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
}, "strip", z.ZodTypeAny, {
onSuccess?: "info" | "debug" | "trace" | undefined;
onError?: "fatal" | "error" | "warn" | undefined;
logSuccessBody?: boolean | undefined;
logSuccessHeaders?: boolean | undefined;
onRequest?: "info" | "debug" | "trace" | undefined;
logRequestBody?: boolean | undefined;
logRequestHeaders?: boolean | undefined;
}, {
onSuccess?: "info" | "debug" | "trace" | undefined;
onError?: "fatal" | "error" | "warn" | undefined;
logSuccessBody?: boolean | undefined;
logSuccessHeaders?: boolean | undefined;
onRequest?: "info" | "debug" | "trace" | undefined;
logRequestBody?: boolean | undefined;
logRequestHeaders?: boolean | undefined;
}>>;
}, "strip", z.ZodTypeAny, {
instanceName: string;
adapter: IHttpClientAdapter;
logging?: {
onSuccess?: "info" | "debug" | "trace" | undefined;
onError?: "fatal" | "error" | "warn" | undefined;
logSuccessBody?: boolean | undefined;
logSuccessHeaders?: boolean | undefined;
onRequest?: "info" | "debug" | "trace" | undefined;
logRequestBody?: boolean | undefined;
logRequestHeaders?: boolean | undefined;
} | undefined;
isDefault?: boolean | undefined;
propagate?: string[] | undefined;
propagateFullContext?: boolean | undefined;
}, {
instanceName: string;
adapter: IHttpClientAdapter;
logging?: {
onSuccess?: "info" | "debug" | "trace" | undefined;
onError?: "fatal" | "error" | "warn" | undefined;
logSuccessBody?: boolean | undefined;
logSuccessHeaders?: boolean | undefined;
onRequest?: "info" | "debug" | "trace" | undefined;
logRequestBody?: boolean | undefined;
logRequestHeaders?: boolean | undefined;
} | undefined;
isDefault?: boolean | undefined;
propagate?: string[] | undefined;
propagateFullContext?: boolean | undefined;
}>;
/**
* @description Schema for a single message broker client instance.
* It validates that a valid `IBrokerAdapter` is provided.
* @private
*/
declare const brokerInstanceConfigSchema: z.ZodObject<{
instanceName: z.ZodString;
adapter: z.ZodType<IBrokerAdapter, z.ZodTypeDef, IBrokerAdapter>;
/**
* An array of context keys to propagate as message headers/properties.
* To propagate all keys, provide an array with a single wildcard: `['*']`.
* If not provided, only `correlationId` and `transactionId` are propagated by default.
*/
propagate: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
/**
* @deprecated Use `propagate` instead.
* If true, propagates the entire asynchronous context map as headers.
* If false (default), only propagates `correlationId` and `transactionId`.
*/
propagateFullContext: z.ZodOptional<z.ZodBoolean>;
isDefault: z.ZodOptional<z.ZodBoolean>;
}, "strip", z.ZodTypeAny, {
instanceName: string;
adapter: IBrokerAdapter;
isDefault?: boolean | undefined;
propagate?: string[] | undefined;
propagateFullContext?: boolean | undefined;
}, {
instanceName: string;
adapter: IBrokerAdapter;
isDefault?: boolean | undefined;
propagate?: string[] | undefined;
propagateFullContext?: boolean | undefined;
}>;
/**
* @description The main schema for the entire SyntropyLog configuration.
* This is the single source of truth for validating the user's configuration object.
*/
declare const syntropyLogConfigSchema: z.ZodObject<{
/** Logger-specific configuration. */
logger: z.ZodOptional<z.ZodObject<{
name: z.ZodOptional<z.ZodString>;
level: z.ZodOptional<z.ZodEnum<["fatal", "error", "warn", "info", "debug", "trace", "silent"]>>;
serviceName: z.ZodOptional<z.ZodString>;
/**
* An array of transport instances to be used by the logger.
*/
transports: z.ZodOptional<z.ZodArray<z.ZodType<Transport, z.ZodTypeDef, Transport>, "many">>;
/**
* A dictionary of custom serializer functions. The key is the field
* to look for in the log object, and the value is the function that transforms it.
*/
serializers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodFunction<z.ZodTuple<[z.ZodAny], z.ZodUnknown>, z.ZodString>>>;
/**
* The maximum time in milliseconds a custom serializer can run before being timed out.
* @default 50
*/
serializerTimeoutMs: z.ZodDefault<z.ZodNumber>;
/** Configuration for pretty printing logs in development. */
prettyPrint: z.ZodOptional<z.ZodObject<{
enabled: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
}, "strip", z.ZodTypeAny, {
enabled: boolean;
}, {
enabled?: boolean | undefined;
}>>;
}, "strip", z.ZodTypeAny, {
serializerTimeoutMs: number;
name?: string | undefined;
level?: "fatal" | "error" | "warn" | "info" | "debug" | "trace" | "silent" | undefined;
serviceName?: string | undefined;
transports?: Transport[] | undefined;
serializers?: Record<string, (args_0: any, ...args: unknown[]) => string> | undefined;
prettyPrint?: {
enabled: boolean;
} | undefined;
}, {
name?: string | undefined;
level?: "fatal" | "error" | "warn" | "info" | "debug" | "trace" | "silent" | undefined;
serviceName?: string | undefined;
transports?: Transport[] | undefined;
serializers?: Record<string, (args_0: any, ...args: unknown[]) => string> | undefined;
serializerTimeoutMs?: number | undefined;
prettyPrint?: {
enabled?: boolean | undefined;
} | undefined;
}>>;
/** Declarative matrix to control context data in logs. */
loggingMatrix: z.ZodOptional<z.ZodObject<{
/** An array of context keys to include in logs by default. Can be overridden by level-specific rules. */
default: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
/** An array of context keys to include for 'trace' level logs. Use `['*']` to include all context properties. */
trace: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
/** An array of context keys to include for 'debug' level logs. Use `['*']` to include all context properties. */
debug: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
/** An array of context keys to include for 'info' level logs. Use `['*']` to include all context properties. */
info: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
/** An array of context keys to include for 'warn' level logs. Use `['*']` to include all context properties. */
warn: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
/** An array of context keys to include for 'error' level logs. Use `['*']` to include all context properties. */
error: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
/** An array of context keys to include for 'fatal' level logs. Use `['*']` to include all context properties. */
fatal: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
}, "strip", z.ZodTypeAny, {
fatal?: string[] | undefined;
error?: string[] | undefined;
warn?: string[] | undefined;
info?: string[] | undefined;
debug?: string[] | undefined;
trace?: string[] | undefined;
default?: string[] | undefined;
}, {
fatal?: string[] | undefined;
error?: string[] | undefined;
warn?: string[] | undefined;
info?: string[] | undefined;
debug?: string[] | undefined;
trace?: string[] | undefined;
default?: string[] | undefined;
}>>;
/** Redis client configuration. */
redis: z.ZodOptional<z.ZodObject<{
/** An array of Redis instance configurations. */
instances: z.ZodArray<z.ZodDiscriminatedUnion<"mode", [z.ZodObject<{
mode: z.ZodLiteral<"single">;
instanceName: z.ZodString;
url: z.ZodString;
retryOptions: z.ZodOptional<z.ZodObject<{
maxRetries: z.ZodOptional<z.ZodNumber>;
retryDelay: z.ZodOptional<z.ZodNumber>;
}, "strip", z.ZodTypeAny, {
maxRetries?: number | undefined;
retryDelay?: number | undefined;
}, {
maxRetries?: number | undefined;
retryDelay?: number | undefined;
}>>;
logging: z.ZodOptional<z.ZodObject<{
/** Level for successful commands. @default 'debug' */
onSuccess: z.ZodDefault<z.ZodEnum<["trace", "debug", "info"]>>;
/** Level for failed commands. @default 'error' */
onError: z.ZodDefault<z.ZodEnum<["warn", "error", "fatal"]>>;
/** Whether to log command parameters. @default true */
logCommandValues: z.ZodDefault<z.ZodBoolean>;
/** Whether to log the return value of commands. @default false */
logReturnValue: z.ZodDefault<z.ZodBoolean>;
}, "strip", z.ZodTypeAny, {
onSuccess: "info" | "debug" | "trace";
onError: "fatal" | "error" | "warn";
logCommandValues: boolean;
logReturnValue: boolean;
}, {
onSuccess?: "info" | "debug" | "trace" | undefined;
onError?: "fatal" | "error" | "warn" | undefined;
logCommandValues?: boolean | undefined;
logReturnValue?: boolean | undefined;
}>>;
}, "strip", z.ZodTypeAny, {
mode: "single";
instanceName: string;
url: string;
retryOptions?: {
maxRetries?: number | undefined;
retryDelay?: number | undefined;
} | undefined;
logging?: {
onSuccess: "info" | "debug" | "trace";
onError: "fatal" | "error" | "warn";
logCommandValues: boolean;
logReturnValue: boolean;
} | undefined;
}, {
mode: "single";
instanceName: string;
url: string;
retryOptions?: {
maxRetries?: number | undefined;
retryDelay?: number | undefined;
} | undefined;
logging?: {
onSuccess?: "info" | "debug" | "trace" | undefined;
onError?: "fatal" | "error" | "warn" | undefined;
logCommandValues?: boolean | undefined;
logReturnValue?: boolean | undefined;
} | undefined;
}>, z.ZodObject<{
mode: z.ZodLiteral<"sentinel">;
instanceName: z.ZodString;
name: z.ZodString;
sentinels: z.ZodArray<z.ZodObject<{
host: z.ZodString;
port: z.ZodNumber;
}, "strip", z.ZodTypeAny, {
host: string;
port: number;
}, {
host: string;
port: number;
}>, "many">;
sentinelPassword: z.ZodOptional<z.ZodString>;
retryOptions: z.ZodOptional<z.ZodObject<{
maxRetries: z.ZodOptional<z.ZodNumber>;
retryDelay: z.ZodOptional<z.ZodNumber>;
}, "strip", z.ZodTypeAny, {
maxRetries?: number | undefined;
retryDelay?: number | undefined;
}, {
maxRetries?: number | undefined;
retryDelay?: number | undefined;
}>>;
logging: z.ZodOptional<z.ZodObject<{
onSuccess: z.ZodDefault<z.ZodEnum<["trace", "debug", "info"]>>;
onError: z.ZodDefault<z.ZodEnum<["warn", "error", "fatal"]>>;
logCommandValues: z.ZodDefault<z.ZodBoolean>;
logReturnValue: z.ZodDefault<z.ZodBoolean>;
}, "strip", z.ZodTypeAny, {
onSuccess: "info" | "debug" | "trace";
onError: "fatal" | "error" | "warn";
logCommandValues: boolean;
logReturnValue: boolean;
}, {
onSuccess?: "info" | "debug" | "trace" | undefined;
onError?: "fatal" | "error" | "warn" | undefined;
logCommandValues?: boolean | undefined;
logReturnValue?: boolean | undefined;
}>>;
}, "strip", z.ZodTypeAny, {
name: string;
mode: "sentinel";
instanceName: string;
sentinels: {
host: string;
port: number;
}[];
retryOptions?: {
maxRetries?: number | undefined;
retryDelay?: number | undefined;
} | undefined;
logging?: {
onSuccess: "info" | "debug" | "trace";
onError: "fatal" | "error" | "warn";
logCommandValues: boolean;
logReturnValue: boolean;
} | undefined;
sentinelPassword?: string | undefined;
}, {
name: string;
mode: "sentinel";
instanceName: string;
sentinels: {
host: string;
port: number;
}[];
retryOptions?: {
maxRetries?: number | undefined;
retryDelay?: number | undefined;
} | undefined;
logging?: {
onSuccess?: "info" | "debug" | "trace" | undefined;
onError?: "fatal" | "error" | "warn" | undefined;
logCommandValues?: boolean | undefined;
logReturnValue?: boolean | undefined;
} | undefined;
sentinelPassword?: string | undefined;
}>, z.ZodObject<{
mode: z.ZodLiteral<"cluster">;
instanceName: z.ZodString;
rootNodes: z.ZodArray<z.ZodObject<{
host: z.ZodString;
port: z.ZodNumber;
}, "strip", z.ZodTypeAny, {
host: string;
port: number;
}, {
host: string;
port: number;
}>, "many">;
logging: z.ZodOptional<z.ZodObject<{
/** Level for successful commands. @default 'debug' */
onSuccess: z.ZodDefault<z.ZodEnum<["trace", "debug", "info"]>>;
/** Level for failed commands. @default 'error' */
onError: z.ZodDefault<z.ZodEnum<["warn", "error", "fatal"]>>;
/** Whether to log command parameters. @default true */
logCommandValues: z.ZodDefault<z.ZodBoolean>;
/** Whether to log the return value of commands. @default false */
logReturnValue: z.ZodDefault<z.ZodBoolean>;
}, "strip", z.ZodTypeAny, {
onSuccess: "info" | "debug" | "trace";
onError: "fatal" | "error" | "warn";
logCommandValues: boolean;
logReturnValue: boolean;
}, {
onSuccess?: "info" | "debug" | "trace" | undefined;
onError?: "fatal" | "error" | "warn" | undefined;
logCommandValues?: boolean | undefined;
logReturnValue?: boolean | undefined;
}>>;
}, "strip", z.ZodTypeAny, {
mode: "cluster";
instanceName: string;
rootNodes: {
host: string;
port: number;
}[];
logging?: {
onSuccess: "info" | "debug" | "trace";
onError: "fatal" | "error" | "warn";
logCommandValues: boolean;
logReturnValue: boolean;
} | undefined;
}, {
mode: "cluster";
instanceName: string;
rootNodes: {
host: string;
port: number;
}[];
logging?: {
onSuccess?: "info" | "debug" | "trace" | undefined;
onError?: "fatal" | "error" | "warn" | undefined;
logCommandValues?: boolean | undefined;
logReturnValue?: boolean | undefined;
} | undefined;
}>]>, "many">;
/** The name of the default Redis instance to use when no name is provided to `getInstance()`. */
default: z.ZodOptional<z.ZodString>;
}, "strip", z.ZodTypeAny, {
instances: ({
mode: "single";
instanceName: string;
url: string;
retryOptions?: {
maxRetries?: number | undefined;
retryDelay?: number | undefined;
} | undefined;
logging?: {
onSuccess: "info" | "debug" | "trace";
onError: "fatal" | "error" | "warn";
logCommandValues: boolean;
logReturnValue: boolean;
} | undefined;
} | {
name: string;
mode: "sentinel";
instanceName: string;
sentinels: {
host: string;
port: number;
}[];
retryOptions?: {
maxRetries?: number | undefined;
retryDelay?: number | undefined;
} | undefined;
logging?: {
onSuccess: "info" | "debug" | "trace";
onError: "fatal" | "error" | "warn";
logCommandValues: boolean;
logReturnValue: boolean;
} | undefined;
sentinelPassword?: string | undefined;
} | {
mode: "cluster";
instanceName: string;
rootNodes: {
host: string;
port: number;
}[];
logging?: {
onSuccess: "info" | "debug" | "trace";
onError: "fatal" | "error" | "warn";
logCommandValues: boolean;
logReturnValue: boolean;
} | undefined;
})[];
default?: string | undefined;
}, {
instances: ({
mode: "single";
instanceName: string;
url: string;
retryOptions?: {
maxRetries?: number | undefined;
retryDelay?: number | undefined;
} | undefined;
logging?: {
onSuccess?: "info" | "debug" | "trace" | undefined;
onError?: "fatal" | "error" | "warn" | undefined;
logCommandValues?: boolean | undefined;
logReturnValue?: boolean | undefined;
} | undefined;
} | {
name: string;
mode: "sentinel";
instanceName: string;
sentinels: {
host: string;
port: number;
}[];
retryOptions?: {
maxRetries?: number | undefined;
retryDelay?: number | undefined;
} | undefined;
logging?: {
onSuccess?: "info" | "debug" | "trace" | undefined;
onError?: "fatal" | "error" | "warn" | undefined;
logCommandValues?: boolean | undefined;
logReturnValue?: boolean | undefined;
} | undefined;
sentinelPassword?: string | undefined;
} | {
mode: "cluster";
instanceName: string;
rootNodes: {
host: string;
port: number;
}[];
logging?: {
onSuccess?: "info" | "debug" | "trace" | undefined;
onError?: "fatal" | "error" | "warn" | undefined;
logCommandValues?: boolean | undefined;
logReturnValue?: boolean | undefined;
} | undefined;
})[];
default?: string | undefined;
}>>;
/** HTTP client configuration. */
http: z.ZodOptional<z.ZodObject<{
/** An array of HTTP client instance configurations. */
instances: z.ZodArray<z.ZodObject<{
instanceName: z.ZodString;
adapter: z.ZodType<IHttpClientAdapter, z.ZodTypeDef, IHttpClientAdapter>;
isDefault: z.ZodOptional<z.ZodBoolean>;
propagate: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
propagateFullContext: z.ZodOptional<z.ZodBoolean>;
logging: z.ZodOptional<z.ZodObject<{
onSuccess: z.ZodOptional<z.ZodDefault<z.ZodEnum<["trace", "debug", "info"]>>>;
onError: z.ZodOptional<z.ZodDefault<z.ZodEnum<["warn", "error", "fatal"]>>>;
logSuccessBody: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
logSuccessHeaders: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
onRequest: z.ZodOptional<z.ZodDefault<z.ZodEnum<["trace", "debug", "info"]>>>;
logRequestBody: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
logRequestHeaders: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
}, "strip", z.ZodTypeAny, {
onSuccess?: "info" | "debug" | "trace" | undefined;
onError?: "fatal" | "error" | "warn" | undefined;
logSuccessBody?: boolean | undefined;
logSuccessHeaders?: boolean | undefined;
onRequest?: "info" | "debug" | "trace" | undefined;
logRequestBody?: boolean | undefined;
logRequestHeaders?: boolean | undefined;
}, {
onSuccess?: "info" | "debug" | "trace" | undefined;
onError?: "fatal" | "error" | "warn" | undefined;
logSuccessBody?: boolean | undefined;
logSuccessHeaders?: boolean | undefined;
onRequest?: "info" | "debug" | "trace" | undefined;
logRequestBody?: boolean | undefined;
logRequestHeaders?: boolean | undefined;
}>>;
}, "strip", z.ZodTypeAny, {
instanceName: string;
adapter: IHttpClientAdapter;
logging?: {
onSuccess?: "info" | "debug" | "trace" | undefined;
onError?: "fatal" | "error" | "warn" | undefined;
logSuccessBody?: boolean | undefined;
logSuccessHeaders?: boolean | undefined;
onRequest?: "info" | "debug" | "trace" | undefined;
logRequestBody?: boolean | undefined;
logRequestHeaders?: boolean | undefined;
} | undefined;
isDefault?: boolean | undefined;
propagate?: string[] | undefined;
propagateFullContext?: boolean | undefined;
}, {
instanceName: string;
adapter: IHttpClientAdapter;
logging?: {
onSuccess?: "info" | "debug" | "trace" | undefined;
onError?: "fatal" | "error" | "warn" | undefined;
logSuccessBody?: boolean | undefined;
logSuccessHeaders?: boolean | undefined;
onRequest?: "info" | "debug" | "trace" | undefined;
logRequestBody?: boolean | undefined;
logRequestHeaders?: boolean | undefined;
} | undefined;
isDefault?: boolean | undefined;
propagate?: string[] | undefined;
propagateFullContext?: boolean | undefined;
}>, "many">;
/** The name of the default HTTP client instance to use when no name is provided to `getInstance()`. */
default: z.ZodOptional<z.ZodString>;
}, "strip", z.ZodTypeAny, {
instances: {
instanceName: string;
adapter: IHttpClientAdapter;
logging?: {
onSuccess?: "info" | "debug" | "trace" | undefined;
onError?: "fatal" | "error" | "warn" | undefined;
logSuccessBody?: boolean | undefined;
logS