UNPKG

@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.

217 lines (213 loc) 8.23 kB
/* * 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 { AsyncLocalStorage } from 'node:async_hooks'; /** * Type representing the store object used in AsyncLocalStorage. * Keys must be unique symbols to ensure isolation and prevent collisions. */ interface Store { [key: symbol]: unknown; } /** * Predefined symbols used as keys in AsyncLocalStorage. * Add new symbols here to avoid duplication. */ declare const StoreKeys: { LOGGER: symbol; REQUEST_ID: symbol; USER: symbol; SESSION: symbol; TRANSACTION_ID: symbol; USER_ID: symbol; TENANT_ID: symbol; TRACE_ID: symbol; CORRELATION_ID: symbol; }; /** * Retrieves the current request ID from the async context, if available. * * @returns {string | undefined} The request ID string or undefined if not present in the current context. */ declare function getRequestId(): string | undefined; /** * Type-safe getter for common context values. * * @param key The store key symbol * @returns The typed value from the store */ declare function getFromContext<T>(key: symbol): T | undefined; /** * ContextStore manages per-request scoped context using AsyncLocalStorage. * It allows storing and retrieving data across async calls (e.g., request ID, logger). * * Example (Express middleware): * ``` * // Middleware to initialize context and logger * app.use((req, res, next) => { * const requestId = req.headers["x-request-id"]?.toString() || crypto.randomUUID(); * ContextStore.run({ [StoreKeys.REQUEST_ID]: requestId }, () => { * ContextStore.set(StoreKeys.LOGGER, getLogger().child({ requestId })); * next(); * }); * }); * ``` */ declare class ContextStore { /** * The underlying AsyncLocalStorage instance for context. * @private */ private static readonly storage; /** * Returns the raw AsyncLocalStorage instance for advanced access. * * @returns {AsyncLocalStorage<Store>} The AsyncLocalStorage instance. */ static getInstance(): AsyncLocalStorage<Store>; /** * Retrieves a value from the async context store by symbol key. * * @typeParam T - The expected return type of the value. * @param {symbol} key - Unique symbol used as the store key. * @returns {T | undefined} The value found (typed) or undefined if not present. */ static get<T>(key: symbol): T | undefined; /** * Sets a value in the current context store by symbol key. * * @typeParam T - The value type to set. * @param {symbol} key - Unique symbol key. * @param {T} value - Value to set in context. * @throws {Error} If called outside an active context (not within a .run call or in the wrong async boundaries). */ static set<T>(key: symbol, value: T): void; /** * Retrieves the entire context store object for the current async context. * * @returns {Store | undefined} The current store object or undefined if called outside a context. */ static getAll(): Store | undefined; /** * Initializes a new async context and executes a callback within it. * This must be called at the beginning of a request or logical async flow. * * @typeParam T - The callback's return type. * @param {Store} store - The initial key-value store object. * @param {() => T} callback - The function to run within the new context. * @returns {T} The result of the callback function. */ static run<T>(store: Store, callback: () => T): T; /** * Checks if a key exists in the current context store. * * @param {symbol} key - The symbol key to check. * @returns {boolean} True if the key exists, false otherwise. */ static has(key: symbol): boolean; /** * Removes a value from the current context store by symbol key. * * @param {symbol} key - The symbol key to delete. * @returns {boolean} True if the key was deleted, false if the key wasn't found or no active context. * @throws {Error} If called outside an active context. */ static delete(key: symbol): boolean; /** * Updates multiple values in the current context store at once. * * @param {Partial<Record<symbol, unknown>>} values - Object containing symbol keys and values to update. * @throws {Error} If called outside an active context. */ static patch(values: Partial<Record<symbol, unknown>>): void; /** * Executes a callback with a temporary store value that only exists during execution. * Original store is restored after callback completes. * * @typeParam T - The callback's return type. * @param {symbol} key - The symbol key to temporarily set. * @param {unknown} value - The temporary value. * @param {() => T} callback - The function to execute with the temporary value. * @returns {T} The result of the callback function. * @throws {Error} If called outside an active context. */ static withValue<T>(key: symbol, value: unknown, callback: () => T): T; /** * Creates a new context that inherits values from the current context. * * @typeParam T - The callback's return type. * @param {Partial<Record<symbol, unknown>>} newValues - New values to add to or override in the context. * @param {() => T} callback - The function to execute in the new context. * @returns {T} The result of the callback function. */ static extend<T>(newValues: Partial<Record<symbol, unknown>>, callback: () => T): T; /** * Creates Express middleware that initializes a context for each request. * * @param {(req: any) => Partial<Record<symbol, unknown>>} initialValuesFactory - Function that returns initial context values. * @returns Express middleware function. */ static createExpressMiddleware(initialValuesFactory?: (req: any) => Partial<Record<symbol, unknown>>): (req: any, _res: any, next: any) => void; } /** * Type-safe wrapper for accessing and modifying context values with specific types. * * @typeParam T - The value type. */ declare class TypedContextKey<T> { private readonly symbol; private readonly defaultValue?; /** * Creates a new typed context key. * * @param symbol - The unique symbol for this key * @param defaultValue - Optional default value if key is not found */ constructor(symbol: symbol, defaultValue?: T | undefined); /** * Gets the current value for this key. * * @returns The value or defaultValue if not found */ get(): T | undefined; /** * Sets the value for this key. * * @param value The value to set */ set(value: T): void; /** * Checks if this key exists in the context. * * @returns True if the key exists */ exists(): boolean; /** * Deletes this key from the context. * * @returns True if the key was deleted */ delete(): boolean; } export { ContextStore, StoreKeys, TypedContextKey, getFromContext, getRequestId }; export type { Store };