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.

799 lines (792 loc) 28.1 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 { 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 };