@catbee/utils
Version:
A modular, production-grade utility toolkit for Node.js and TypeScript, designed for robust, scalable applications (including Express-based services). All utilities are tree-shakable and can be imported independently.
799 lines (792 loc) • 28.1 kB
TypeScript
/*
* The MIT License
*
* Copyright (c) 2026 Catbee Technologies. https://catbee.in/license
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
import { json, urlencoded, Request, Response, Express, NextFunction } from 'express';
import http from 'node:http';
import { ExpressServer } from '@catbee/utils/server';
import { HelmetOptions } from 'helmet';
import { CompressionOptions } from 'compression';
import { CookieParseOptions } from 'cookie-parser';
import { CorsOptions } from 'cors';
import { LoggerLevels } from '@catbee/utils/logger';
/**
* A type that represents a configurable toggle.
* Can be `true`, `false`, or a custom configuration object `T`.
*/
type ToggleConfig<T> = boolean | T;
/**
* A type representing a value that can be `null` or `undefined`.
*/
type Nullable<T> = T | null | undefined;
/**
* A type representing a value that may or may not be present.
*/
type Optional<T> = T | undefined;
/**
* A type that makes all properties of `T` deeply optional.
*/
type DeepPartial<T> = {
[P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
};
/**
* A type that makes all properties of `T` readonly, recursively.
*/
type DeepReadonly<T> = {
readonly [P in keyof T]: T[P] extends object ? DeepReadonly<T[P]> : T[P];
};
/**
* A type that converts a union of types into an intersection.
*/
type UnionToIntersection<U> = (U extends any ? (x: U) => void : never) extends (x: infer I) => void ? I : never;
/**
* A type representing a promise or a plain value.
*/
type MaybePromise<T> = T | Promise<T>;
/**
* A type representing a record with string keys and values of type `T`.
*/
type StringKeyedRecord<T> = Record<string, T>;
/**
* A type representing a function that returns `R` and optionally receives arguments `A`.
*/
type Func<A extends any[] = any[], R = any> = (...args: A) => R;
/**
* A type representing a partial pick from `T` (like Partial + Pick combined)
*/
type PartialPick<T, K extends keyof T> = Partial<Pick<T, K>> & Omit<T, K>;
/**
* A type that deeply stringifies all properties of T or makes them null.
*/
type DeepStringifyOrNull<T> = T extends string | number | bigint | boolean | symbol | null | undefined ? string | null : T extends Array<infer U> ? Array<DeepStringifyOrNull<U>> : T extends object ? {
[K in keyof T]: DeepStringifyOrNull<T[K]>;
} : string | null;
/**
* A type representing a non-empty array of T.
*/
type NonEmptyArray<T> = [T, ...T[]];
/**
* A type representing the union of all property values of T.
*/
type ValueOf<T> = T[keyof T];
/**
* A type that makes all properties of T mutable (removes readonly).
*/
type Mutable<T> = {
-readonly [P in keyof T]: T[P];
};
/**
* A type that gets the keys of T whose values are assignable to U.
*/
type KeysOfType<T, U> = {
[K in keyof T]: T[K] extends U ? K : never;
}[keyof T];
/**
* Require at least one of the keys in K to be present in T.
*/
type RequireAtLeastOne<T, K extends keyof T = keyof T> = K extends keyof T ? {
[P in K]-?: T[P];
} & Omit<T, K> : never;
/**
* A record type with optional keys.
*/
type RecordOptional<K extends string | number | symbol, T> = {
[P in K]?: T;
};
/**
* Primitive types in TypeScript.
*/
type Primitive = string | number | boolean | bigint | symbol | undefined | null;
/**
* Recursively unwraps Promise types to get their resolved value type.
*/
type Awaited<T> = T extends Promise<infer U> ? Awaited<U> : T;
/**
* Picks properties from T that are of type U.
*/
type PickByType<T, U> = {
[P in keyof T as T[P] extends U ? P : never]: T[P];
};
/**
* Makes all properties of T required recursively.
*/
type DeepRequired<T> = {
[P in keyof T]-?: T[P] extends object ? DeepRequired<T[P]> : T[P];
};
/**
* Checks if two types are exactly equal.
* Returns true or false as type.
*/
type IsEqual<T, U> = (<G>() => G extends T ? 1 : 2) extends <G>() => G extends U ? 1 : 2 ? true : false;
/**
* Makes all properties of an object writable (removes readonly).
*/
type Writable<T> = {
-readonly [P in keyof T]: T[P];
};
/**
* Makes specific keys K of type T optional.
*/
type Optional2<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
/**
* Creates a type with all properties of T except those with types assignable to U.
*/
type Without<T, U> = {
[P in keyof T as T[P] extends U ? never : P]: T[P];
};
/**
* Server configuration for Catbee HTTP/Express server.
* Designed with secure and high-performance defaults for production use.
* All features remain fully overridable by consumers.
*/
interface CatbeeServerConfig {
/** Server port
* - **default**: `3000`
* - **env**: `SERVER_PORT` || `PORT`
*/
port: number;
/** Host address to bind the server
* - **default**: `'0.0.0.0'`
* - **env**: `SERVER_HOST` || `HOST`
*/
host?: string;
/** CORS configuration toggle or options
* - **default**: `false`
* - **env**: `SERVER_CORS_ENABLE`
* - `true` -> enable with default settings
* - `CorsOptions` -> enable with custom settings
*
* **example**:
* ```ts
* cors: {
* origin: 'https://example.com',
* methods: ['GET', 'POST'],
* credentials: true
* }
* ```
*/
cors?: ToggleConfig<CorsOptions>;
/** Helmet security headers toggle or options
* - **default**: `false`
* - **env**: `SERVER_HELMET_ENABLE`
* - `true` -> enable with default settings
* - `HelmetOptions` -> enable with custom settings
*
* **example**:
* ```ts
* helmet: {
* contentSecurityPolicy: {
* directives: {
* defaultSrc: ["'self'"],
* scriptSrc: ["'self'", 'trusted.com']
* }
* }
* }
* ```
*/
helmet?: ToggleConfig<HelmetOptions>;
/** HTTP response compression toggle or options
* - **default**: `false`
* - **env**: `SERVER_COMPRESSION_ENABLE`
* - `true` -> enable with default settings
* - `CompressionOptions` -> enable with custom settings
*
* **example**:
* ```ts
* compression: { level: 6 }
* ```
*/
compression?: ToggleConfig<CompressionOptions>;
/** Body parser configuration for incoming requests
* - **default**: `{ json: { limit: '1mb' }, urlencoded: { extended: true, limit: '1mb' } }`
* - **env**:
* - `SERVER_BODY_PARSER_JSON_LIMIT`
* - `SERVER_BODY_PARSER_URLENCODED_LIMIT`
*/
bodyParser?: {
/** JSON body parser options
* - **default**: `{ limit: '1mb' }`
*/
json?: Parameters<typeof json>[0];
/** URL-encoded body parser options
* - **default**: `{ extended: true, limit: '1mb' }`
*/
urlencoded?: Parameters<typeof urlencoded>[0];
};
/** Cookie parser toggle or options
* - **default**: `false`
* - **env**: `SERVER_COOKIE_PARSER_ENABLE`
* - `true` -> enable with default decode
* - `CookieParseOptions` -> enable with custom settings
*
* **example**:
* ```ts
* cookieParser: {
* decode: (val) => decodeURIComponent(val)
* }
* ```
*/
cookieParser?: ToggleConfig<CookieParseOptions>;
/** Trust proxy configuration
* - **default**: `false`
* - **env**: `SERVER_TRUST_PROXY_ENABLE`
* - `true` -> trust first proxy
* - `number` -> trust N proxies
* - `string | string[]` -> trust specific proxy IP(s)
*/
trustProxy?: boolean | number | string | string[];
/** Static folder serving configuration
* - **path**: file system path to serve
* - **route**: URL route prefix (default: "/")
* - **maxAge**: cache max age (default: 0)
* - **etag**: enable ETag headers (default: true)
* - **immutable**: enable immutable caching (default: false)
* - **lastModified**: enable last-modified caching (default: true)
* - **cacheControl**: enable Cache-Control headers (default: true)
*/
staticFolders?: Array<{
/** URL mount path prefix
* - **default**: `/`
*/
path?: string;
/** Local directory path to serve (required) */
directory: string;
/** Cache-Control max-age value
* - **default**: `0`
*/
maxAge?: string;
/** Enable ETag header
* - **default**: `true`
*/
etag?: boolean;
/** Immutable caching
* - **default**: `false`
*/
immutable?: boolean;
/** Last-Modified header support
* - **default**: `true`
*/
lastModified?: boolean;
/** Include Cache-Control header
* - **default**: `true`
*/
cacheControl?: boolean;
}>;
/** Enable microservice mode
* - **default**: `false`
* - **env**: `SERVER_IS_MICROSERVICE`
*/
isMicroservice?: boolean;
/** Application/service name used for logs, headers, and metrics
* - **default**: `'catbee_server'`
* - **env**: `SERVER_APP_NAME` or `npm_package_name`
*/
appName?: string;
/** Global headers applied to all responses
* - **default**: {}
* - **env**: `SERVER_GLOBAL_HEADERS` (JSON)
*/
globalHeaders?: Record<string, string | (() => string)>;
/** Rate limiting settings
* - **enable**: `false` - **env**: `SERVER_RATE_LIMIT_ENABLE`
* - **windowMs**: `900000` (15 minutes) - **env**: `SERVER_RATE_LIMIT_WINDOW_MS`
* - **max**: `100` - **env**: `SERVER_RATE_LIMIT_MAX`
* - **message**: `'Too many requests'` - **env**: `SERVER_RATE_LIMIT_MESSAGE`
* - **standardHeaders**: `true` - **env**: `SERVER_RATE_LIMIT_STANDARD_HEADERS`
* - **legacyHeaders**: `false` - **env**: `SERVER_RATE_LIMIT_LEGACY_HEADERS`
*/
rateLimit?: {
/** Enable rate-limiting
* - **default**: `false`
* - **env**: `SERVER_RATE_LIMIT_ENABLE`
*/
enable: boolean;
/** Window duration in ms
* - **default**: `900000` (15 minutes)
* - **env**: `SERVER_RATE_LIMIT_WINDOW_MS`
*/
windowMs?: number;
/** Max requests per window
* - **default**: `100`
* - **env**: `SERVER_RATE_LIMIT_MAX`
*/
max?: number;
/** Custom message when limit is reached
* - **default**: `'Too many requests'`
* - **env**: `SERVER_RATE_LIMIT_MESSAGE`
*/
message?: string;
/** Include standard rate-limit headers
* - **default**: `true`
* - **env**: `SERVER_RATE_LIMIT_STANDARD_HEADERS`
*/
standardHeaders?: boolean;
/** Include legacy rate-limit headers
* - **default**: `false`
* - **env**: `SERVER_RATE_LIMIT_LEGACY_HEADERS`
*/
legacyHeaders?: boolean;
};
/** Request logging configuration
* - **enable**: `true` in `development`, `false` in `production` - **env**: `SERVER_REQUEST_LOGGING_ENABLE`
* - **ignorePaths**: skips `/healthz`, `/favicon.ico`, `/metrics`, `/docs`, `/.well-known`
* - **skipNotFoundRoutes**: `false` - **env**: `SERVER_REQUEST_LOGGING_SKIP_NOT_FOUND_ROUTES`
*/
requestLogging?: {
/** Enable request logging
* - **default**: `true` in `development`, `false` in `production`
* - **env**: `SERVER_REQUEST_LOGGING_ENABLE`
*/
enable: boolean;
/** Ignore specific paths or apply custom logic to skip logging */
ignorePaths?: string[] | ((req: Request, res: Response) => boolean);
/** Skip 404 routes from logs
* - **default**: `false`
* - **env**: `SERVER_REQUEST_LOGGING_SKIP_NOT_FOUND_ROUTES`
*/
skipNotFoundRoutes?: boolean;
};
/** Health-check configuration
* - **path**: `/healthz`
* - **detailed**: `true`
* - **withGlobalPrefix**: `false`
*/
healthCheck?: {
/** Health-check endpoint path
* - **default**: `'/healthz'`
* - **env**: `SERVER_HEALTH_CHECK_PATH`
*/
path?: string;
/** Include detailed check results in the response
* - **default**: `true`
* - **env**: `SERVER_HEALTH_CHECK_DETAILED_OUTPUT`
*/
detailed?: boolean;
/** Apply global route prefix
* - **default**: `false`
* - **env**: `SERVER_HEALTH_CHECK_WITH_GLOBAL_PREFIX`
*/
withGlobalPrefix?: boolean;
/** Custom health checks */
checks?: Array<{
/** Name of the health check */
name: string;
/** Check function that returns boolean or Promise<boolean> */
check: () => Promise<boolean> | boolean;
}>;
};
/** Request timeout in ms
* - **default**: `30000` (30 seconds)
* - **env**: `SERVER_REQUEST_TIMEOUT_MS`
*/
requestTimeout?: number;
/** Response timing configuration
* - **enable**: `false`
* - **addHeader**: `true`
* - **logOnComplete**: `false`
*/
responseTime?: {
/** Enable timing
* - **default**: `false`
* - **env**: `SERVER_RESPONSE_TIME_ENABLE`
*/
enable: boolean;
/** Add X-Response-Time header
* - **default**: `true`
* - **env**: `SERVER_RESPONSE_TIME_ADD_HEADER`
*/
addHeader?: boolean;
/** Log completion time
* - **default**: `false`
* - **env**: `SERVER_RESPONSE_TIME_LOG_ON_COMPLETE`
*/
logOnComplete?: boolean;
};
/** Request ID tracking configuration
* - **enable**: `false` - **env**: `SERVER_REQUEST_ID_ENABLE`
* - **headerName**: `'x-request-id'` - **env**: `SERVER_REQUEST_ID_HEADER_NAME`
* - **exposeHeader**: `true` - **env**: `SERVER_REQUEST_ID_EXPOSE_HEADER`
* - **generator**: `uuid()`
*/
requestId?: {
/** Header name for request tracing
* - **default**: `'x-request-id'`
* - **env**: `SERVER_REQUEST_ID_HEADER_NAME`
*/
headerName?: string;
/** Expose request ID in response headers
* - **default**: `true`
* - **env**: `SERVER_REQUEST_ID_EXPOSE_HEADER`
*/
exposeHeader?: boolean;
/** Function to generate request ID
* - **default**: `uuid()`
*/
generator?: () => string;
};
/** Global route prefix for all endpoints
* - **default**: `/`
*/
globalPrefix?: string;
/** OpenAPI/Swagger documentation config
* - **enable**: `false` - **env**: `SERVER_OPENAPI_ENABLE`
* - **mountPath**: `'/docs'` - **env**: `SERVER_OPENAPI_MOUNT_PATH`
* - **verbose**: `false` - **env**: `SERVER_OPENAPI_VERBOSE`
* - **withGlobalPrefix**: `false` - **env**: `SERVER_OPENAPI_WITH_GLOBAL_PREFIX`
*/
openApi?: {
/** Enable OpenAPI spec serving
* - **default**: `false`
* - **env**: `SERVER_OPENAPI_ENABLE`
*/
enable: boolean;
/** Mount path for API docs UI
* - **default**: `'/docs'`
* - **env**: `SERVER_OPENAPI_MOUNT_PATH`
*/
mountPath?: string;
/** Local OpenAPI spec file path (required if enabled)
* - **env**: `SERVER_OPENAPI_FILE_PATH`
*/
filePath?: string;
/** Verbose OpenAPI logs
* - **default**: `false`
* - **env**: `SERVER_OPENAPI_VERBOSE`
*/
verbose?: boolean;
/** Apply global prefix to docs route
* - **default**: `false`
* - **env**: `SERVER_OPENAPI_WITH_GLOBAL_PREFIX`
*/
withGlobalPrefix?: boolean;
};
/** Prometheus metrics config
* - **enable**: `false` - **env**: `SERVER_METRICS_ENABLE`
* - **path**: `'/metrics'` - **env**: `SERVER_METRICS_PATH`
* - **withGlobalPrefix**: `false` - **env**: `SERVER_METRICS_WITH_GLOBAL_PREFIX`
*/
metrics?: {
/** Enable metrics endpoint
* - **default**: `false`
* - **env**: `SERVER_METRICS_ENABLE`
*/
enable: boolean;
/** Metrics endpoint path
* - **default**: `'/metrics'`
* - **env**: `SERVER_METRICS_PATH`
*/
path?: string;
/** Apply global prefix
* - **default**: `false`
* - **env**: `SERVER_METRICS_WITH_GLOBAL_PREFIX`
*/
withGlobalPrefix?: boolean;
};
/** Service version header config
* - **enable**: `false` - **env**: `SERVER_SERVICE_VERSION_ENABLE`
* - **headerName**: `'x-service-version'` - **env**: `SERVER_SERVICE_VERSION_HEADER_NAME`
* - **version**: `'0.0.0'` - **env**: `SERVER_SERVICE_VERSION`
*/
serviceVersion?: {
/** Enable version header
* - **default**: `false`
*/
enable: boolean;
/** Header name
* - **default**: `'x-service-version'`
* - **env**: `SERVER_SERVICE_VERSION_HEADER_NAME`
*/
headerName?: string;
/** Version value
* - **default**: `'0.0.0'`
* - **env**: `SERVER_SERVICE_VERSION`
*/
version?: string | (() => string);
};
/**
* HTTPS configuration (if provided, server will use HTTPS)
* Requires 'key' and 'cert' at minimum.
* @command - to generate self-signed certificates
* ```bash
* choco install mkcert
* mkcert -key-file localhost-key.pem -cert-file localhost-cert.pem localhost 127.0.0.1 ::1
* ```
*/
https?: {
/** SSL private key file path (PEM) */
key: string;
/** SSL certificate file path (PEM) */
cert: string;
/** Optional CA bundle path (PEM) */
ca?: string;
/** Optional private key passphrase */
passphrase?: string;
/** Additional Node.js `https.ServerOptions` */
[key: string]: any;
};
}
/**
* Lifecycle hooks for Catbee server runtime.
* Allows injecting custom behavior without modifying Catbee core internals.
*/
interface CatbeeServerHooks {
/** Called before middleware & routes initialize */
beforeInit?: (server: ExpressServer) => Promise<void> | void;
/** Called after middleware & routes initialize */
afterInit?: (server: ExpressServer) => Promise<void> | void;
/** Called before server starts listening */
beforeStart?: (app: Express) => Promise<void> | void;
/** Called after server is ready */
afterStart?: (server: http.Server) => Promise<void> | void;
/** Called before graceful shutdown */
beforeStop?: (server: http.Server) => Promise<void> | void;
/** Called after server stops */
afterStop?: () => Promise<void> | void;
/** Custom error handler (overrides Catbee default if provided) */
onError?: (error: Error, req: Request, res: Response, next: NextFunction) => void;
/** Called when a request is received (middleware-style injection) */
onRequest?: (req: Request, res: Response, next: NextFunction) => void;
/** Called before response is sent */
onResponse?: (req: Request, res: Response, next: NextFunction) => void;
}
interface GlobalServerAddons {
/**
* Skip healthz endpoint even if health checks are configured
* - **default**: `false`
* - **env**: `SERVER_SKIP_HEALTHZ_CHECKS_VALIDATION`
*
* @additionalInfo
* Set to true to return `200 OK` for `/healthz` without checks
* Useful in environments where a simple liveness probe is needed
* without performing actual health checks
* Example: Kubernetes liveness probe
* Note: This does not disable the health check functionality itself
* Health checks can still be performed programmatically
* or via other endpoints if needed
*/
skipHealthzChecksValidation: boolean;
}
/** Combined global server configuration type */
type CatbeeGlobalServerConfig = CatbeeServerConfig & GlobalServerAddons;
/**
* Generic API response format.
* Used to wrap any successful or failed response from the server.
*/
interface ApiResponse<T = any> {
/** Payload returned from the API. Can be any shape depending on the endpoint. */
data: T | null;
/** Indicates whether an error occurred (true = error, false = success). */
error: boolean;
/** Success message describing the result of the operation. */
message: string;
/** Unique request ID for traceability in logs (e.g., from a middleware). */
requestId: string;
/** ISO timestamp when the response was generated. */
timestamp: string;
}
/**
* Generic pagination structure used for paged lists (e.g., /users?page=1).
*/
interface Pagination<T = any> {
/** List of records for the current page. */
content: T[];
/** Metadata about the pagination state. */
pagination: {
/** Total number of records across all pages. */
totalRecords: number;
/** Total number of pages available. */
totalPages: number;
/** Current page number (1-based index). */
page: number;
/** Number of records per page. */
limit: number;
/** Field by which the data is sorted. */
sortBy: string;
/** Sort order: ascending or descending. */
sortOrder: 'asc' | 'desc';
};
}
/**
* Alias for paginated API response.
* Allows semantic naming like `PaginationResponse<User>` or `PaginationResponse<Post>`.
*/
type PaginationResponse<T = any> = Pagination<T>;
/**
* Error response structure with additional metadata.
* Used for providing richer error information to clients.
*/
interface ApiErrorResponse extends Omit<ApiResponse<never>, 'data'> {
/** Error always true for error responses */
error: true;
/** HTTP status code */
status: number;
/** Path to the resource that caused the error */
path: string;
/** Stack trace of the error (if available) */
stack?: string[];
}
/**
* Success response structure with strongly typed data.
* Used for providing successful responses to clients.
*/
interface ApiSuccessResponse<T = any> extends ApiResponse<T> {
/** Error always false for success responses */
error: false;
/** HTTP status code (usually 200) */
status?: number;
}
/**
* Response structure for batch operations.
* Used when multiple operations are performed in a single request.
*/
interface BatchResponse<T = any> {
/** Overall success/failure indicator */
success: boolean;
/** Total number of operations */
total: number;
/** Number of successful operations */
successful: number;
/** Number of failed operations */
failed: number;
/** Results of individual operations */
results: Array<{
/** Identifier for this operation */
id: string | number;
/** Success/failure indicator for this operation */
success: boolean;
/** Response data for this operation */
data?: T;
/** Error information if this operation failed */
error?: {
message: string;
code?: string;
};
}>;
}
/**
* Response structure for asynchronous operations.
* Used when the operation will complete in the future.
*/
interface AsyncOperationResponse {
/** Always true for async operations */
async: true;
/** Job or task ID to check status later */
jobId: string;
/** Estimated completion time in seconds (if known) */
estimatedTime?: number;
/** URL to check status */
statusUrl: string;
}
/**
* Response structure for streaming operations.
* Used when data is returned as a stream rather than all at once.
*/
interface StreamResponse {
/** Stream identifier */
streamId: string;
/** Stream type (e.g., 'json', 'binary') */
streamType: string;
/** Total size in bytes (if known) */
totalSize?: number;
/** Chunk size in bytes */
chunkSize: number;
}
/**
* Sort direction enumeration.
*/
declare enum SortDirection {
/** Ascending sort order */
ASC = "asc",
/** Descending sort order */
DESC = "desc"
}
/**
* Pagination parameters for API requests.
*/
interface PaginationParams {
/** Current page number (1-based index) */
page: number;
/** Number of records per page */
limit: number;
/** Field by which the data is sorted */
sortBy: string;
/** Sort order: ascending or descending */
sortOrder: SortDirection;
/** Optional search query */
search?: string;
}
/**
* Type that combines pagination parameters with additional data.
*/
type WithPagination<T = {}> = PaginationParams & T;
interface CatbeeConfig {
logger?: {
/**
* Logging level (e.g., 'info', 'debug', 'warn', 'error')
* Environment variable: LOGGER_LEVEL
* Default: 'info' in production, 'debug' in development
*/
level?: LoggerLevels;
/**
* Name of the logger instance (defaults to npm package name)
* Environment variable: LOGGER_NAME
* Default: value of npm_package_name or '@catbee/utils'
*/
name?: string;
/**
* Enables pretty-print logging in development.
* Has no effect in production.
* Environment variable: LOGGER_PRETTY
* Default: true in development, false in production
*/
pretty?: boolean;
/**
* Enables colorized output for pretty-print (default: true)
* Environment variable: LOGGER_PRETTY_COLORIZE
*/
colorize?: boolean;
/**
* Single line output for pretty-print (default: false)
* Environment variable: LOGGER_PRETTY_SINGLE_LINE
*/
singleLine?: boolean;
/**
* Directory to write log files to (if empty, file logging is disabled)
* Environment variable: LOGGER_DIR
* Eg: process.cwd() + '/logs'
* Note: Directory must exist, it is not created automatically
*/
dir?: string;
};
cache: {
/**
* Default TTL (time to live) for cache entries in milliseconds
* Environment variable: CACHE_DEFAULT_TTL_SECONDS
* Default: 3600000 (1 hour)
*/
defaultTtl: number;
};
/** Server configuration */
server: CatbeeGlobalServerConfig;
}
export { SortDirection };
export type { ApiErrorResponse, ApiResponse, ApiSuccessResponse, AsyncOperationResponse, Awaited, BatchResponse, CatbeeConfig, CatbeeGlobalServerConfig, CatbeeServerConfig, CatbeeServerHooks, DeepPartial, DeepReadonly, DeepRequired, DeepStringifyOrNull, Func, GlobalServerAddons, IsEqual, KeysOfType, MaybePromise, Mutable, NonEmptyArray, Nullable, Optional, Optional2, Pagination, PaginationParams, PaginationResponse, PartialPick, PickByType, Primitive, RecordOptional, RequireAtLeastOne, StreamResponse, StringKeyedRecord, ToggleConfig, UnionToIntersection, ValueOf, WithPagination, Without, Writable };