@catbee/utils 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +303 -107
- package/build/esm/config.d.ts +12 -0
- package/build/esm/config.js +12 -0
- package/build/esm/config.js.map +1 -1
- package/build/esm/index.d.ts +1 -0
- package/build/esm/index.js +1 -0
- package/build/esm/index.js.map +1 -1
- package/build/esm/types/api-response.d.ts +82 -0
- package/build/esm/types/api-response.js.map +1 -1
- package/build/esm/utils/array.utils.d.ts +64 -1
- package/build/esm/utils/array.utils.js +139 -2
- package/build/esm/utils/array.utils.js.map +1 -1
- package/build/esm/utils/async.utils.d.ts +60 -1
- package/build/esm/utils/async.utils.js +160 -2
- package/build/esm/utils/async.utils.js.map +1 -1
- package/build/esm/utils/cache.utils.d.ts +67 -4
- package/build/esm/utils/cache.utils.js +210 -28
- package/build/esm/utils/cache.utils.js.map +1 -1
- package/build/esm/utils/context-store.utils.d.ts +101 -0
- package/build/esm/utils/context-store.utils.js +182 -0
- package/build/esm/utils/context-store.utils.js.map +1 -1
- package/build/esm/utils/crypto.utils.d.ts +110 -8
- package/build/esm/utils/crypto.utils.js +298 -15
- package/build/esm/utils/crypto.utils.js.map +1 -1
- package/build/esm/utils/decorators.utils.d.ts +40 -0
- package/build/esm/utils/decorators.utils.js +312 -0
- package/build/esm/utils/decorators.utils.js.map +1 -0
- package/build/esm/utils/dir.utils.d.ts +121 -0
- package/build/esm/utils/dir.utils.js +577 -0
- package/build/esm/utils/dir.utils.js.map +1 -1
- package/build/esm/utils/env.utils.d.ts +83 -0
- package/build/esm/utils/env.utils.js +233 -0
- package/build/esm/utils/env.utils.js.map +1 -1
- package/build/esm/utils/exception.utils.d.ts +116 -0
- package/build/esm/utils/exception.utils.js +322 -0
- package/build/esm/utils/exception.utils.js.map +1 -1
- package/build/esm/utils/fs.utils.d.ts +132 -0
- package/build/esm/utils/fs.utils.js +421 -0
- package/build/esm/utils/fs.utils.js.map +1 -1
- package/build/esm/utils/http-status-codes.d.ts +87 -178
- package/build/esm/utils/http-status-codes.js +92 -178
- package/build/esm/utils/http-status-codes.js.map +1 -1
- package/build/esm/utils/id.utils.d.ts +11 -10
- package/build/esm/utils/id.utils.js +29 -20
- package/build/esm/utils/id.utils.js.map +1 -1
- package/build/esm/utils/logger.utils.d.ts +24 -0
- package/build/esm/utils/logger.utils.js +54 -0
- package/build/esm/utils/logger.utils.js.map +1 -1
- package/build/esm/utils/middleware.utils.d.ts +72 -0
- package/build/esm/utils/middleware.utils.js +158 -0
- package/build/esm/utils/middleware.utils.js.map +1 -0
- package/build/esm/utils/obj.utils.d.ts +65 -3
- package/build/esm/utils/obj.utils.js +205 -6
- package/build/esm/utils/obj.utils.js.map +1 -1
- package/build/esm/utils/response.utils.d.ts +101 -0
- package/build/esm/utils/response.utils.js +153 -0
- package/build/esm/utils/response.utils.js.map +1 -1
- package/build/esm/utils/string.utils.d.ts +61 -5
- package/build/esm/utils/string.utils.js +101 -11
- package/build/esm/utils/string.utils.js.map +1 -1
- package/build/esm/utils/url.utils.d.ts +117 -0
- package/build/esm/utils/url.utils.js +287 -0
- package/build/esm/utils/url.utils.js.map +1 -1
- package/build/esm/utils/validate.utils.d.ts +110 -0
- package/build/esm/utils/validate.utils.js +186 -0
- package/build/esm/utils/validate.utils.js.map +1 -1
- package/build/esnext/config.d.ts +12 -0
- package/build/esnext/config.js +12 -0
- package/build/esnext/config.js.map +1 -1
- package/build/esnext/index.d.ts +1 -0
- package/build/esnext/index.js +1 -0
- package/build/esnext/index.js.map +1 -1
- package/build/esnext/types/api-response.d.ts +82 -0
- package/build/esnext/types/api-response.js.map +1 -1
- package/build/esnext/utils/array.utils.d.ts +64 -1
- package/build/esnext/utils/array.utils.js +129 -2
- package/build/esnext/utils/array.utils.js.map +1 -1
- package/build/esnext/utils/async.utils.d.ts +60 -1
- package/build/esnext/utils/async.utils.js +117 -1
- package/build/esnext/utils/async.utils.js.map +1 -1
- package/build/esnext/utils/cache.utils.d.ts +67 -4
- package/build/esnext/utils/cache.utils.js +137 -9
- package/build/esnext/utils/cache.utils.js.map +1 -1
- package/build/esnext/utils/context-store.utils.d.ts +101 -0
- package/build/esnext/utils/context-store.utils.js +168 -0
- package/build/esnext/utils/context-store.utils.js.map +1 -1
- package/build/esnext/utils/crypto.utils.d.ts +110 -8
- package/build/esnext/utils/crypto.utils.js +205 -15
- package/build/esnext/utils/crypto.utils.js.map +1 -1
- package/build/esnext/utils/decorators.utils.d.ts +40 -0
- package/build/esnext/utils/decorators.utils.js +155 -0
- package/build/esnext/utils/decorators.utils.js.map +1 -0
- package/build/esnext/utils/dir.utils.d.ts +121 -0
- package/build/esnext/utils/dir.utils.js +306 -0
- package/build/esnext/utils/dir.utils.js.map +1 -1
- package/build/esnext/utils/env.utils.d.ts +83 -0
- package/build/esnext/utils/env.utils.js +185 -0
- package/build/esnext/utils/env.utils.js.map +1 -1
- package/build/esnext/utils/exception.utils.d.ts +116 -0
- package/build/esnext/utils/exception.utils.js +213 -0
- package/build/esnext/utils/exception.utils.js.map +1 -1
- package/build/esnext/utils/fs.utils.d.ts +132 -0
- package/build/esnext/utils/fs.utils.js +268 -0
- package/build/esnext/utils/fs.utils.js.map +1 -1
- package/build/esnext/utils/http-status-codes.d.ts +87 -178
- package/build/esnext/utils/http-status-codes.js +92 -178
- package/build/esnext/utils/http-status-codes.js.map +1 -1
- package/build/esnext/utils/id.utils.d.ts +11 -10
- package/build/esnext/utils/id.utils.js +27 -19
- package/build/esnext/utils/id.utils.js.map +1 -1
- package/build/esnext/utils/logger.utils.d.ts +24 -0
- package/build/esnext/utils/logger.utils.js +42 -0
- package/build/esnext/utils/logger.utils.js.map +1 -1
- package/build/esnext/utils/middleware.utils.d.ts +72 -0
- package/build/esnext/utils/middleware.utils.js +157 -0
- package/build/esnext/utils/middleware.utils.js.map +1 -0
- package/build/esnext/utils/obj.utils.d.ts +65 -3
- package/build/esnext/utils/obj.utils.js +167 -3
- package/build/esnext/utils/obj.utils.js.map +1 -1
- package/build/esnext/utils/response.utils.d.ts +101 -0
- package/build/esnext/utils/response.utils.js +138 -0
- package/build/esnext/utils/response.utils.js.map +1 -1
- package/build/esnext/utils/string.utils.d.ts +61 -5
- package/build/esnext/utils/string.utils.js +110 -14
- package/build/esnext/utils/string.utils.js.map +1 -1
- package/build/esnext/utils/url.utils.d.ts +117 -0
- package/build/esnext/utils/url.utils.js +248 -0
- package/build/esnext/utils/url.utils.js.map +1 -1
- package/build/esnext/utils/validate.utils.d.ts +110 -0
- package/build/esnext/utils/validate.utils.js +184 -0
- package/build/esnext/utils/validate.utils.js.map +1 -1
- package/build/src/config.d.ts +12 -0
- package/build/src/config.js +12 -0
- package/build/src/config.js.map +1 -1
- package/build/src/index.d.ts +1 -0
- package/build/src/index.js +1 -0
- package/build/src/index.js.map +1 -1
- package/build/src/types/api-response.d.ts +82 -0
- package/build/src/types/api-response.js.map +1 -1
- package/build/src/utils/array.utils.d.ts +64 -1
- package/build/src/utils/array.utils.js +137 -4
- package/build/src/utils/array.utils.js.map +1 -1
- package/build/src/utils/async.utils.d.ts +60 -1
- package/build/src/utils/async.utils.js +124 -4
- package/build/src/utils/async.utils.js.map +1 -1
- package/build/src/utils/cache.utils.d.ts +67 -4
- package/build/src/utils/cache.utils.js +137 -9
- package/build/src/utils/cache.utils.js.map +1 -1
- package/build/src/utils/context-store.utils.d.ts +101 -0
- package/build/src/utils/context-store.utils.js +171 -1
- package/build/src/utils/context-store.utils.js.map +1 -1
- package/build/src/utils/crypto.utils.d.ts +110 -8
- package/build/src/utils/crypto.utils.js +224 -27
- package/build/src/utils/crypto.utils.js.map +1 -1
- package/build/src/utils/decorators.utils.d.ts +40 -0
- package/build/src/utils/decorators.utils.js +165 -0
- package/build/src/utils/decorators.utils.js.map +1 -0
- package/build/src/utils/dir.utils.d.ts +121 -0
- package/build/src/utils/dir.utils.js +316 -0
- package/build/src/utils/dir.utils.js.map +1 -1
- package/build/src/utils/env.utils.d.ts +83 -0
- package/build/src/utils/env.utils.js +186 -1
- package/build/src/utils/env.utils.js.map +1 -1
- package/build/src/utils/exception.utils.d.ts +116 -0
- package/build/src/utils/exception.utils.js +226 -1
- package/build/src/utils/exception.utils.js.map +1 -1
- package/build/src/utils/fs.utils.d.ts +132 -0
- package/build/src/utils/fs.utils.js +282 -0
- package/build/src/utils/fs.utils.js.map +1 -1
- package/build/src/utils/http-status-codes.d.ts +87 -178
- package/build/src/utils/http-status-codes.js +92 -178
- package/build/src/utils/http-status-codes.js.map +1 -1
- package/build/src/utils/id.utils.d.ts +11 -10
- package/build/src/utils/id.utils.js +27 -19
- package/build/src/utils/id.utils.js.map +1 -1
- package/build/src/utils/logger.utils.d.ts +24 -0
- package/build/src/utils/logger.utils.js +45 -0
- package/build/src/utils/logger.utils.js.map +1 -1
- package/build/src/utils/middleware.utils.d.ts +72 -0
- package/build/src/utils/middleware.utils.js +163 -0
- package/build/src/utils/middleware.utils.js.map +1 -0
- package/build/src/utils/obj.utils.d.ts +65 -3
- package/build/src/utils/obj.utils.js +177 -7
- package/build/src/utils/obj.utils.js.map +1 -1
- package/build/src/utils/response.utils.d.ts +101 -0
- package/build/src/utils/response.utils.js +146 -1
- package/build/src/utils/response.utils.js.map +1 -1
- package/build/src/utils/string.utils.d.ts +61 -5
- package/build/src/utils/string.utils.js +122 -20
- package/build/src/utils/string.utils.js.map +1 -1
- package/build/src/utils/url.utils.d.ts +117 -0
- package/build/src/utils/url.utils.js +257 -0
- package/build/src/utils/url.utils.js.map +1 -1
- package/build/src/utils/validate.utils.d.ts +110 -0
- package/build/src/utils/validate.utils.js +198 -0
- package/build/src/utils/validate.utils.js.map +1 -1
- package/package.json +20 -12
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
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.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
[build](https://github.com/catbee-technologies/catbee-utils/actions/workflows/node-build.yml/badge.svg)   
|
|
8
8
|
|
|
9
9
|
## 📦 Installation
|
|
10
10
|
|
|
@@ -31,7 +31,6 @@ console.log(uuid()); // e.g. 2a563ec1-caf6-4fe2-b60c-9cf7fb1bdb7f
|
|
|
31
31
|
|
|
32
32
|
// Basic validation
|
|
33
33
|
console.log(isEmail("user@example.com")); // true
|
|
34
|
-
|
|
35
34
|
```
|
|
36
35
|
|
|
37
36
|
## 📦 Modules Overview
|
|
@@ -39,6 +38,7 @@ console.log(isEmail("user@example.com")); // true
|
|
|
39
38
|
- [**Array Utilities**](#-array-utilities)
|
|
40
39
|
- [**Async Utilities**](#-async-utilities)
|
|
41
40
|
- [**Cache Utilities**](#-cache-utilities)
|
|
41
|
+
- [**Config**](#-config)
|
|
42
42
|
- [**Context Store**](#-context-store)
|
|
43
43
|
- [**Crypto Utilities**](#-crypto-utilities)
|
|
44
44
|
- [**Directory Utilities**](#-directory-utilities)
|
|
@@ -47,76 +47,104 @@ console.log(isEmail("user@example.com")); // true
|
|
|
47
47
|
- [**File System Utilities**](#-file-system-utilities)
|
|
48
48
|
- [**HTTP Status Codes**](#-http-status-codes)
|
|
49
49
|
- [**ID Utilities**](#-id-utilities)
|
|
50
|
-
- [**Logger Utilities**](#-logger-
|
|
50
|
+
- [**Logger Utilities**](#-logger-utilities)
|
|
51
|
+
- [**Middleware Utilities**](#-middleware-utilities)
|
|
51
52
|
- [**Object Utilities**](#-object-utilities)
|
|
52
53
|
- [**Response Utilities**](#-response-utilities)
|
|
53
54
|
- [**String Utilities**](#-string-utilities)
|
|
54
55
|
- [**URL Utilities**](#-url-utilities)
|
|
55
56
|
- [**Validate Utilities**](#-validate-utilities)
|
|
57
|
+
- [**Decorators Utilities**](#decorators-utilities)
|
|
58
|
+
|
|
59
|
+
---
|
|
56
60
|
|
|
57
61
|
## 📦 Array Utilities
|
|
58
62
|
|
|
59
|
-
- `chunk<T>(
|
|
60
|
-
- `unique<T>(array: T[]): T[]` – Remove duplicates.
|
|
63
|
+
- `chunk<T>(array: T[], size: number): T[][]` – Split array into chunks.
|
|
64
|
+
- `unique<T>(array: T[], keyFn?: (item: T) => unknown): T[]` – Remove duplicates.
|
|
61
65
|
- `flattenDeep<T>(array: any[]): T[]` – Deep flatten nested arrays.
|
|
62
66
|
- `random<T>(array: T[]): T | undefined` – Random element.
|
|
63
|
-
- `groupBy<T
|
|
67
|
+
- `groupBy<T>(array: T[], keyOrFn: keyof T | ((item: T) => string | number | symbol)): Record<string | number | symbol, T[]>` – Group by key.
|
|
64
68
|
- `shuffle<T>(array: T[]): T[]` – Fisher-Yates shuffle.
|
|
69
|
+
- `pluck<T, K extends keyof T>(array: T[], key: K): T[K][]` – Pluck values by key.
|
|
65
70
|
- `difference<T>(a: T[], b: T[]): T[]` – Elements in `a` not in `b`.
|
|
66
71
|
- `intersect<T>(a: T[], b: T[]): T[]` – Intersection.
|
|
67
|
-
- `mergeSort<T
|
|
72
|
+
- `mergeSort<T>(array: T[], key: string | ((item: T) => any), direction?: "asc" | "desc"): T[]` – Merge sort by nested key.
|
|
73
|
+
- `zip<T>(...arrays: T[][]): T[][]` – Zip arrays together.
|
|
74
|
+
- `partition<T>(array: T[], predicate: (item: T, index: number, array: T[]) => boolean): [T[], T[]]` – Partition array by predicate.
|
|
75
|
+
- `range(start: number, end: number, step?: number): number[]` – Generate a range of numbers.
|
|
76
|
+
- `take<T>(array: T[], n?: number): T[]` – Take first `n` elements.
|
|
77
|
+
- `takeWhile<T>(array: T[], predicate: (item: T, index: number) => boolean): T[]` – Take elements while predicate is true.
|
|
78
|
+
- `compact<T>(array: T[]): NonNullable<T>[]` – Remove falsy values.
|
|
79
|
+
- `countBy<T>(array: T[], keyFn: (item: T) => string | number | symbol): Record<string, number>` – Count occurrences by key.
|
|
80
|
+
- `sample<T>(array: T[], n?: number): T[]` – Sample `n` elements.
|
|
68
81
|
|
|
69
82
|
## ⏳ Async Utilities
|
|
70
83
|
|
|
71
84
|
- `sleep(ms: number): Promise<void>`
|
|
72
|
-
- `debounce<T>(fn: T,
|
|
73
|
-
- `throttle<T>(fn: T,
|
|
74
|
-
- `retry<T>(fn: () => Promise<T>, retries?: number): Promise<T>`
|
|
75
|
-
- `withTimeout<T>(promise: Promise<T>, ms: number): Promise<T>`
|
|
76
|
-
- `runInBatches<T>(tasks: (() => Promise<T>)[],
|
|
77
|
-
- `singletonAsync<TArgs, TResult>(fn: (...args: TArgs) => Promise<TResult
|
|
78
|
-
- `settleAll<T>(tasks: (() => Promise<T>)[]): Promise<
|
|
79
|
-
- `createTaskQueue(limit: number)`
|
|
85
|
+
- `debounce<T>(fn: T, delay: number): T & { cancel(): void; flush(): void }`
|
|
86
|
+
- `throttle<T>(fn: T, limit: number, opts?): (...args: Parameters<T>) => void`
|
|
87
|
+
- `retry<T>(fn: () => Promise<T>, retries?: number, delay?: number, backoff?: boolean, onRetry?): Promise<T>`
|
|
88
|
+
- `withTimeout<T>(promise: Promise<T>, ms: number, message?: string): Promise<T>`
|
|
89
|
+
- `runInBatches<T>(tasks: (() => Promise<T>)[], limit: number): Promise<T[]>`
|
|
90
|
+
- `singletonAsync<TArgs extends unknown[], TResult>(fn: (...args: TArgs) => Promise<TResult>, drop?: boolean): (...args: TArgs) => Promise<TResult>`
|
|
91
|
+
- `settleAll<T>(tasks: (() => Promise<T>)[]): Promise<PromiseSettledResult<T>[]>`
|
|
92
|
+
- `createTaskQueue(limit: number): TaskQueue`
|
|
80
93
|
- `runInSeries<T>(tasks: (() => Promise<T>)[]): Promise<T[]>`
|
|
94
|
+
- `memoizeAsync<T, Args extends any[]>(fn: (...args: Args) => Promise<T>, options?): (...args: Args) => Promise<T>`
|
|
95
|
+
- `abortable<T>(promise: Promise<T>, signal: AbortSignal, abortValue?: any): Promise<T>`
|
|
96
|
+
- `createDeferred<T>(): [Promise<T>, (value: T | PromiseLike<T>) => void, (reason?: any) => void]`
|
|
97
|
+
- `waterfall<T>(fns: Array<(input: any) => Promise<any>>): (initialValue: any) => Promise<T>`
|
|
98
|
+
- `rateLimit<T>(fn: (...args: any[]) => Promise<T>, maxCalls: number, interval: number): (...args: any[]) => Promise<T>`
|
|
81
99
|
|
|
82
100
|
## 🗃️ Cache Utilities
|
|
83
101
|
|
|
84
|
-
- `TTLCache<K, V>(
|
|
85
|
-
|
|
86
|
-
You can use it like:
|
|
102
|
+
- `TTLCache<K, V>(options?: TTLCacheOptions)` – In-memory TTL cache with `.set`, `.get`, `.has`, `.delete`, `.clear`, `.cleanup`, `.entries`, `.keys`, `.values`, `.refresh`, `.stats`, `.destroy`, `.setMany`, `.getMany`, `.getOrCompute`.
|
|
87
103
|
|
|
104
|
+
**Example:**
|
|
88
105
|
```ts
|
|
89
|
-
const cache = new TTLCache<string, number>(3600_000);
|
|
106
|
+
const cache = new TTLCache<string, number>({ ttlMs: 3600_000 });
|
|
90
107
|
cache.set("foo", 42);
|
|
91
108
|
cache.get("foo"); // 42
|
|
92
109
|
cache.has("foo"); // true
|
|
93
110
|
cache.cleanup(); // cleans expired
|
|
94
111
|
```
|
|
95
112
|
|
|
113
|
+
## ⚙️ Config
|
|
114
|
+
|
|
115
|
+
- `Config.Logger.level` – Logging level (e.g., 'info', 'debug')
|
|
116
|
+
- `Config.Logger.name` – Logger name
|
|
117
|
+
- `Config.Logger.isoTimestamp` – Use ISO timestamps in logs
|
|
118
|
+
- `Config.Http.timeout` – HTTP request timeout (ms)
|
|
119
|
+
- `Config.Cache.defaultTtl` – Default cache TTL (seconds)
|
|
120
|
+
|
|
96
121
|
## 🧩 Context Store
|
|
97
122
|
|
|
98
123
|
- `ContextStore` – Per-request context using AsyncLocalStorage.
|
|
99
124
|
|
|
100
125
|
**Static Methods:**
|
|
101
|
-
- `getInstance(): AsyncLocalStorage<Store>`
|
|
126
|
+
- `getInstance(): AsyncLocalStorage<Store>`
|
|
102
127
|
- `getAll(): Store | undefined` – Get the current context store.
|
|
103
|
-
- `run(store: Store, callback: () => void): void`
|
|
104
|
-
- `set
|
|
105
|
-
- `get<
|
|
128
|
+
- `run(store: Store, callback: () => void): void`
|
|
129
|
+
- `set(key: symbol, value: unknown): void`
|
|
130
|
+
- `get<T>(key: symbol): T | undefined`
|
|
131
|
+
- `has(key: symbol): boolean`
|
|
132
|
+
- `delete(key: symbol): boolean`
|
|
133
|
+
- `patch(values: Partial<Record<symbol, unknown>>): void`
|
|
134
|
+
- `withValue(key: symbol, value: unknown, callback: () => T): T`
|
|
135
|
+
- `extend(newValues: Partial<Record<symbol, unknown>>, callback: () => T): T`
|
|
136
|
+
- `createExpressMiddleware(initialValuesFactory?): Middleware`
|
|
106
137
|
|
|
107
138
|
- `StoreKeys` – Common context keys.
|
|
108
139
|
- `getRequestId(): string | undefined` – Get the current request ID from context.
|
|
109
140
|
|
|
110
|
-
|
|
111
|
-
|
|
141
|
+
**Example (Express middleware usage):**
|
|
112
142
|
```ts
|
|
113
|
-
// ✅ Recommended: Unified middleware to initialize context and logger
|
|
114
143
|
import { ContextStore, StoreKeys, getLogger } from "@catbee/utils";
|
|
115
144
|
import crypto from "crypto";
|
|
116
145
|
|
|
117
|
-
export function setupRequestContext(req
|
|
146
|
+
export function setupRequestContext(req, res, next) {
|
|
118
147
|
const requestId = req.headers["x-request-id"]?.toString() || crypto.randomUUID();
|
|
119
|
-
|
|
120
148
|
ContextStore.run({ [StoreKeys.REQUEST_ID]: requestId }, () => {
|
|
121
149
|
const logger = getLogger().child({ reqId: requestId });
|
|
122
150
|
ContextStore.set(StoreKeys.LOGGER, logger);
|
|
@@ -124,52 +152,48 @@ export function setupRequestContext(req: Request, res: Response, next: NextFunct
|
|
|
124
152
|
next();
|
|
125
153
|
});
|
|
126
154
|
}
|
|
127
|
-
|
|
128
|
-
// In your app entry point
|
|
129
155
|
app.use(setupRequestContext);
|
|
130
156
|
```
|
|
131
157
|
|
|
132
|
-
👇 Alternatively, split it into two separate middlewares:
|
|
133
|
-
|
|
134
|
-
```ts
|
|
135
|
-
// First: Initialize context with request ID
|
|
136
|
-
app.use((req, res, next) => {
|
|
137
|
-
const requestId = req.headers["x-request-id"] || crypto.randomUUID();
|
|
138
|
-
ContextStore.run({ [StoreKeys.REQUEST_ID]: requestId }, () => next());
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
// Second: Inject logger into the context
|
|
142
|
-
app.use((req, res, next) => {
|
|
143
|
-
const logger = getLogger().child({ reqId: req.headers["x-request-id"] });
|
|
144
|
-
ContextStore.set(StoreKeys.LOGGER, logger);
|
|
145
|
-
logger.info("Request started");
|
|
146
|
-
next();
|
|
147
|
-
});
|
|
148
|
-
```
|
|
149
|
-
|
|
150
158
|
## 🔐 Crypto Utilities
|
|
151
159
|
|
|
152
|
-
- `hmac(algorithm: string, input: string, secret: string): string`
|
|
153
|
-
- `hash(algorithm: string, input: string): string`
|
|
160
|
+
- `hmac(algorithm: string, input: string, secret: string, encoding?: BinaryToTextEncoding): string`
|
|
161
|
+
- `hash(algorithm: string, input: string, encoding?: BinaryToTextEncoding): string`
|
|
154
162
|
- `sha256Hmac(input: string, secret: string): string`
|
|
155
|
-
- `sha1(input: string): string`
|
|
156
|
-
- `sha256(input: string): string`
|
|
163
|
+
- `sha1(input: string, encoding?: BinaryToTextEncoding): string`
|
|
164
|
+
- `sha256(input: string, encoding?: BinaryToTextEncoding): string`
|
|
157
165
|
- `md5(input: string): string`
|
|
158
166
|
- `randomString(): string`
|
|
159
|
-
|
|
167
|
+
- `generateRandomBytes(byteLength?: number): Buffer`
|
|
168
|
+
- `generateRandomBytesAsString(byteLength?: number, encoding?: BinaryToTextEncoding): string`
|
|
169
|
+
- `generateApiKey(prefix?: string, byteLength?: number): string`
|
|
170
|
+
- `safeCompare(a: string | Buffer | Uint8Array, b: string | Buffer | Uint8Array): boolean`
|
|
171
|
+
- `encrypt(data: string | Buffer, key: string | Buffer, options?): Promise<EncryptionResult>`
|
|
172
|
+
- `decrypt(encryptedData: EncryptionResult, key: string | Buffer, options?): Promise<string | Buffer>`
|
|
173
|
+
- `createSignedToken(payload: object, secret: string, expiresInSeconds?: number): string`
|
|
174
|
+
- `verifySignedToken(token: string, secret: string): object | null`
|
|
160
175
|
|
|
161
176
|
## 📂 Directory Utilities
|
|
162
177
|
|
|
163
178
|
- `ensureDir(dirPath: string): Promise<void>`
|
|
164
|
-
- `listFiles(dirPath: string,
|
|
179
|
+
- `listFiles(dirPath: string, recursive?: boolean): Promise<string[]>`
|
|
165
180
|
- `deleteDirRecursive(dirPath: string): Promise<void>`
|
|
166
|
-
- `isDirectory(
|
|
181
|
+
- `isDirectory(pathStr: string): Promise<boolean>`
|
|
167
182
|
- `copyDir(src: string, dest: string): Promise<void>`
|
|
168
183
|
- `moveDir(src: string, dest: string): Promise<void>`
|
|
169
184
|
- `emptyDir(dirPath: string): Promise<void>`
|
|
170
185
|
- `getDirSize(dirPath: string): Promise<number>`
|
|
171
|
-
- `watchDir(dirPath: string,
|
|
172
|
-
|
|
186
|
+
- `watchDir(dirPath: string, callback): () => void`
|
|
187
|
+
- `findFilesByPattern(pattern: string, options?): Promise<string[]>`
|
|
188
|
+
- `getSubdirectories(dirPath: string, recursive?: boolean): Promise<string[]>`
|
|
189
|
+
- `ensureEmptyDir(dirPath: string): Promise<void>`
|
|
190
|
+
- `createTempDir(options?): Promise<{ path: string, cleanup: () => Promise<void> }>`
|
|
191
|
+
- `findNewestFile(dirPath: string, recursive?: boolean): Promise<string | null>`
|
|
192
|
+
- `findOldestFile(dirPath: string, recursive?: boolean): Promise<string | null>`
|
|
193
|
+
- `findInDir(dirPath: string, predicate, recursive?: boolean): Promise<string[]>`
|
|
194
|
+
- `watchDirRecursive(dirPath: string, callback, includeSubdirs?: boolean): Promise<() => void>`
|
|
195
|
+
- `getDirStats(dirPath: string): Promise<{ fileCount: number, dirCount: number, totalSize: number }>`
|
|
196
|
+
- `walkDir(dirPath: string, options): Promise<void>`
|
|
173
197
|
|
|
174
198
|
## 🌱 Environment Utilities
|
|
175
199
|
|
|
@@ -177,83 +201,141 @@ app.use((req, res, next) => {
|
|
|
177
201
|
- `Env` class – Environment variable helpers.
|
|
178
202
|
|
|
179
203
|
**Static Methods:**
|
|
180
|
-
- `isDev(): boolean`
|
|
181
|
-
- `
|
|
182
|
-
- `
|
|
183
|
-
- `
|
|
184
|
-
- `
|
|
185
|
-
- `
|
|
186
|
-
- `
|
|
187
|
-
- `
|
|
188
|
-
- `
|
|
189
|
-
- `
|
|
190
|
-
- `
|
|
191
|
-
- `
|
|
192
|
-
- `
|
|
193
|
-
- `
|
|
194
|
-
|
|
204
|
+
- `isDev(): boolean`
|
|
205
|
+
- `isProd(): boolean`
|
|
206
|
+
- `isTest(): boolean`
|
|
207
|
+
- `isStaging(): boolean`
|
|
208
|
+
- `set(key: string, value: string): void`
|
|
209
|
+
- `getAll(): object`
|
|
210
|
+
- `get(key: string, defaultValue?: string): string | undefined`
|
|
211
|
+
- `getRequired(key: string): string`
|
|
212
|
+
- `getNumber(key: string, defaultValue: number): number`
|
|
213
|
+
- `getNumberRequired(key: string): number`
|
|
214
|
+
- `getBoolean(key: string, defaultValue?: boolean): boolean`
|
|
215
|
+
- `getBooleanRequired(key: string): boolean`
|
|
216
|
+
- `getJSON<T>(key: string, defaultValue: T): T`
|
|
217
|
+
- `getArray<T = string>(key: string, defaultValue?: T[], splitter?: string): string[] | T[]`
|
|
218
|
+
- `getEnum<T extends string>(key: string, allowedValues: T[], defaultValue?: T): T`
|
|
219
|
+
- `getUrl(key: string, defaultValue?: string, options?): string`
|
|
220
|
+
- `getEmail(key: string, defaultValue?: string): string`
|
|
221
|
+
- `getPath(key: string, defaultValue?: string, options?): string`
|
|
222
|
+
- `getPort(key: string, defaultValue?: number): number`
|
|
223
|
+
- `getDuration(key: string, defaultValue?: string | number): number`
|
|
224
|
+
- `getSafeEnv(sensitiveKeys?: string[]): Record<string, string>`
|
|
225
|
+
- `getWithDefault(key: string, defaultFn: () => string): string`
|
|
226
|
+
- `has(key: string): boolean`
|
|
227
|
+
- `delete(key: string): void`
|
|
195
228
|
|
|
196
229
|
## 🚨 Exception Utilities
|
|
197
230
|
|
|
198
|
-
- `HttpError`, `InternalServerErrorException`, `UnauthorizedException`, `BadRequestException`, `NotFoundException`, `ForbiddenException`, `ConflictException`, `BadGatewayException`, `TooManyRequestsException`, `ServiceUnavailableException`, `GatewayTimeoutException`
|
|
199
|
-
|
|
231
|
+
- `HttpError`, `InternalServerErrorException`, `UnauthorizedException`, `BadRequestException`, `NotFoundException`, `ForbiddenException`, `ConflictException`, `BadGatewayException`, `TooManyRequestsException`, `ServiceUnavailableException`, `GatewayTimeoutException`, `UnprocessableEntityException`, `MethodNotAllowedException`, `NotAcceptableException`, `RequestTimeoutException`, `UnsupportedMediaTypeException`, `PayloadTooLargeException`, `InsufficientStorageException`
|
|
232
|
+
- `isHttpError(error: unknown): error is ErrorResponse`
|
|
233
|
+
- `createHttpError(status: number, message?: string): ErrorResponse`
|
|
234
|
+
- `hasErrorShape(error: unknown): error is { message: string; status?: number; code?: string }`
|
|
235
|
+
- `getErrorMessage(error: unknown): string`
|
|
236
|
+
- `withErrorHandling<T extends (...args: any[]) => Promise<any>>(handler: T): (...args: Parameters<T>) => Promise<Awaited<ReturnType<T>>>`
|
|
200
237
|
|
|
201
238
|
## 📁 File System Utilities
|
|
202
239
|
|
|
203
240
|
- `fileExists(path: string): Promise<boolean>`
|
|
204
241
|
- `readJsonFile<T>(path: string): Promise<T | null>`
|
|
205
|
-
- `writeJsonFile(path: string, data: any): Promise<void>`
|
|
242
|
+
- `writeJsonFile(path: string, data: any, space?: number): Promise<void>`
|
|
206
243
|
- `deleteFileIfExists(path: string): Promise<boolean>`
|
|
207
|
-
|
|
244
|
+
- `readTextFile(path: string, encoding?: BufferEncoding): Promise<string | null>`
|
|
245
|
+
- `writeTextFile(path: string, content: string, encoding?: BufferEncoding): Promise<boolean>`
|
|
246
|
+
- `appendTextFile(path: string, content: string, encoding?: BufferEncoding): Promise<boolean>`
|
|
247
|
+
- `copyFile(source: string, destination: string, overwrite?: boolean): Promise<boolean>`
|
|
248
|
+
- `moveFile(oldPath: string, newPath: string): Promise<boolean>`
|
|
249
|
+
- `getFileStats(path: string): Promise<fs.Stats | null>`
|
|
250
|
+
- `createTempFile(options?): Promise<string>`
|
|
251
|
+
- `streamFile(source: string, destination: string): Promise<void>`
|
|
252
|
+
- `readDirectory(dirPath: string, options?): Promise<string[]>`
|
|
253
|
+
- `createDirectory(dirPath: string, recursive?: boolean): Promise<boolean>`
|
|
254
|
+
- `safeReadJsonFile<T>(path: string): Promise<{ data: T | null; error: Error | null }>`
|
|
255
|
+
- `isFile(path: string): Promise<boolean>`
|
|
256
|
+
- `getFileSize(path: string): Promise<number>`
|
|
257
|
+
- `readFileBuffer(path: string): Promise<Buffer | null>`
|
|
208
258
|
|
|
209
259
|
## 📊 HTTP Status Codes
|
|
210
260
|
|
|
211
|
-
A typed
|
|
261
|
+
A typed enum with all HTTP status codes and their standard messages.
|
|
212
262
|
|
|
213
263
|
- `HttpStatusCodes.OK === 200`
|
|
214
264
|
- `HttpStatusCodes.NOT_FOUND === 404`
|
|
215
265
|
- ...and so on.
|
|
216
266
|
|
|
217
|
-
|
|
218
|
-
|
|
267
|
+
**Example:**
|
|
219
268
|
```ts
|
|
220
269
|
import { HttpStatusCodes } from "@catbee/utils";
|
|
221
|
-
|
|
222
270
|
res.status(HttpStatusCodes.BAD_REQUEST).send("Invalid payload");
|
|
223
271
|
```
|
|
224
272
|
|
|
225
273
|
## 🆔 ID Utilities
|
|
226
274
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
- `
|
|
230
|
-
- `
|
|
231
|
-
- `
|
|
232
|
-
- `randomHex(byteLength?: number): string` — Generate a cryptographically strong random hex string of given length in bytes.
|
|
233
|
-
- `randomInt(min: number, max: number): number` — Generate a secure random integer between min and max, inclusive.
|
|
234
|
-
|
|
275
|
+
- `uuid(): string`
|
|
276
|
+
- `nanoId(size?: number): string`
|
|
277
|
+
- `randomHex(byteLength?: number): string`
|
|
278
|
+
- `randomInt(min: number, max: number): number`
|
|
279
|
+
- `randomBase64(byteLength?: number): number`
|
|
235
280
|
|
|
236
281
|
## 📄 Logger Utilities
|
|
237
282
|
|
|
238
|
-
- `getLogger(): Logger`
|
|
239
|
-
|
|
283
|
+
- `getLogger(): Logger`
|
|
284
|
+
- `createChildLogger(bindings: Record<string, any>, parentLogger?: Logger): Logger`
|
|
285
|
+
- `createRequestLogger(requestId: string, additionalContext?: Record<string, any>): Logger`
|
|
286
|
+
- `logError(error: Error | unknown, message?: string, context?: Record<string, any>): void`
|
|
287
|
+
- `resetLogger(): void`
|
|
288
|
+
|
|
289
|
+
## 🧩 Middleware Utilities
|
|
290
|
+
|
|
291
|
+
- `requestId(options?): Middleware`
|
|
292
|
+
- `responseTime(options?): Middleware`
|
|
293
|
+
- `timeout(timeoutMs?: number): Middleware`
|
|
294
|
+
- `errorHandler(options?): Middleware`
|
|
295
|
+
- `cors(options?): Middleware`
|
|
296
|
+
- `validateRequest(schema, location?): Middleware`
|
|
297
|
+
- `rateLimit(options?): Middleware`
|
|
298
|
+
- `securityHeaders(options?): Middleware`
|
|
299
|
+
- `basicAuth(validator, realm?): Middleware`
|
|
300
|
+
|
|
301
|
+
**Example:**
|
|
302
|
+
```ts
|
|
303
|
+
import { requestId, responseTime, errorHandler } from "@catbee/utils";
|
|
304
|
+
app.use(requestId());
|
|
305
|
+
app.use(responseTime());
|
|
306
|
+
app.use(errorHandler());
|
|
307
|
+
```
|
|
240
308
|
|
|
241
309
|
## 🧩 Object Utilities
|
|
242
310
|
|
|
243
311
|
- `isObjEmpty(obj: Record<any, any>): boolean`
|
|
244
312
|
- `pick<T, K extends keyof T>(obj: T, keys: K[]): Pick<T, K>`
|
|
245
313
|
- `omit<T, K extends keyof T>(obj: T, keys: K[]): Omit<T, K>`
|
|
246
|
-
- `deepObjMerge<T>(
|
|
247
|
-
- `flattenObject<T>(obj: T): Record<string, any>`
|
|
248
|
-
- `getValueByPath<T>(obj: T, path: string)`
|
|
249
|
-
|
|
314
|
+
- `deepObjMerge<T>(target: T, source: Partial<T>): T`
|
|
315
|
+
- `flattenObject<T>(obj: T, prefix?: string): Record<string, any>`
|
|
316
|
+
- `getValueByPath<T>(obj: T, path: string): any`
|
|
317
|
+
- `setValueByPath<T>(obj: T, path: string, value: any): T`
|
|
318
|
+
- `deepClone<T>(obj: T): T`
|
|
319
|
+
- `unflattenObject(obj: Record<string, any>): Record<string, any>`
|
|
320
|
+
- `isEqual(a: any, b: any): boolean`
|
|
321
|
+
- `filterObject<T>(obj: T, predicate): Partial<T>`
|
|
322
|
+
- `mapObject<T, U>(obj: T, mapFn): Record<keyof T, U>`
|
|
323
|
+
- `deepFreeze<T>(obj: T): Readonly<T>`
|
|
324
|
+
- `isObject(value: unknown): value is Record<string, any>`
|
|
325
|
+
- `getAllPaths(obj: Record<string, any>, parentPath?: string): string[]`
|
|
250
326
|
|
|
251
327
|
## 📝 Response Utilities
|
|
252
328
|
|
|
253
329
|
- `SuccessResponse<T>` – Standard API success wrapper.
|
|
254
330
|
- `ErrorResponse` – Standard API error wrapper.
|
|
255
|
-
-
|
|
256
|
-
|
|
331
|
+
- `PaginatedResponse<T>` – Paginated API response.
|
|
332
|
+
- `NoContentResponse` – 204 No Content response.
|
|
333
|
+
- `RedirectResponse` – Redirect response.
|
|
334
|
+
- `createSuccessResponse<T>(data: T, message?: string): SuccessResponse<T>`
|
|
335
|
+
- `createErrorResponse(message: string, statusCode?: number): ErrorResponse`
|
|
336
|
+
- `createPaginatedResponse<T>(allItems: T[], page: number, pageSize: number, message?: string): PaginatedResponse<T>`
|
|
337
|
+
- `sendResponse(res, apiResponse): void`
|
|
338
|
+
- `isApiResponse(value: any): value is ApiResponse<any>`
|
|
257
339
|
|
|
258
340
|
## 🧵 String Utilities
|
|
259
341
|
|
|
@@ -262,25 +344,139 @@ Helpers for generating unique and random identifiers, covering popular formats f
|
|
|
262
344
|
- `toCamelCase(str: string): string`
|
|
263
345
|
- `slugify(str: string): string`
|
|
264
346
|
- `truncate(str: string, len: number): string`
|
|
265
|
-
|
|
347
|
+
- `toPascalCase(str: string): string`
|
|
348
|
+
- `toSnakeCase(str: string): string`
|
|
349
|
+
- `format(template: string, values: Record<string, any> | any[]): string`
|
|
350
|
+
- `isValidEmail(str: string): boolean`
|
|
351
|
+
- `isValidUrl(str: string, requireProtocol?: boolean): boolean`
|
|
352
|
+
- `mask(str: string, visibleStart?: number, visibleEnd?: number, maskChar?: string): string`
|
|
353
|
+
- `stripHtml(str: string): string`
|
|
354
|
+
- `equalsIgnoreCase(a: string, b: string): boolean`
|
|
355
|
+
- `reverse(str: string): string`
|
|
356
|
+
- `countOccurrences(str: string, substring: string, caseSensitive?: boolean): number`
|
|
357
|
+
- `randomString(length?: number, charset?: string): string`
|
|
358
|
+
- `pluralize(singular: string, count: number, plural?: string): string`
|
|
359
|
+
- `toTitleCase(str: string): string`
|
|
360
|
+
- `pad(str: string, length: number, padChar?: string, padEnd?: boolean): string`
|
|
266
361
|
|
|
267
362
|
## 🌐 URL Utilities
|
|
268
363
|
|
|
269
|
-
- `appendQueryParams(url: string, params:
|
|
364
|
+
- `appendQueryParams(url: string, params: Record<string, string | number>): string`
|
|
270
365
|
- `parseQueryString(query: string): Record<string, string>`
|
|
271
|
-
|
|
366
|
+
- `isValidUrl(url: string, requireHttps?: boolean): boolean`
|
|
367
|
+
- `getDomain(url: string, removeSubdomains?: boolean): string`
|
|
368
|
+
- `joinPaths(...segments: string[]): string`
|
|
369
|
+
- `normalizeUrl(url: string, base?: string): string`
|
|
370
|
+
- `createUrlBuilder(baseUrl: string): { path(path: string, params?: Record<string, any>): string; query(params: Record<string, any>): string }`
|
|
371
|
+
- `extractQueryParams(url: string, paramNames: string[]): Record<string, string>`
|
|
372
|
+
- `removeQueryParams(url: string, paramsToRemove: string[]): string`
|
|
373
|
+
- `getExtension(url: string): string`
|
|
374
|
+
- `parseTypedQueryParams<T>(url: string, converters?: Record<keyof T, (val: string) => any>): Partial<T>`
|
|
375
|
+
|
|
376
|
+
**Example:**
|
|
377
|
+
```ts
|
|
378
|
+
const url = appendQueryParams('https://example.com', { page: 1, limit: 10 });
|
|
379
|
+
// → 'https://example.com/?page=1&limit=10'
|
|
380
|
+
```
|
|
272
381
|
|
|
273
382
|
## ✅ Validate Utilities
|
|
383
|
+
|
|
274
384
|
A comprehensive suite of string/format validators for safe input and API checks.
|
|
275
385
|
|
|
276
|
-
- `isEmail(str: string): boolean`
|
|
277
|
-
- `isUUID(str: string): boolean`
|
|
278
|
-
- `isURL(str: string): boolean`
|
|
279
|
-
- `isPhone(str: string): boolean`
|
|
280
|
-
- `isAlphanumeric(str: string): boolean`
|
|
281
|
-
- `isNumeric(
|
|
282
|
-
- `isHexColor(str: string): boolean`
|
|
283
|
-
- `isISODate(str: string): boolean`
|
|
386
|
+
- `isEmail(str: string): boolean`
|
|
387
|
+
- `isUUID(str: string): boolean`
|
|
388
|
+
- `isURL(str: string): boolean`
|
|
389
|
+
- `isPhone(str: string): boolean`
|
|
390
|
+
- `isAlphanumeric(str: string): boolean`
|
|
391
|
+
- `isNumeric(value: string | number): boolean`
|
|
392
|
+
- `isHexColor(str: string): boolean`
|
|
393
|
+
- `isISODate(str: string): boolean`
|
|
394
|
+
- `isLengthBetween(str: string, min: number, max: number): boolean`
|
|
395
|
+
- `isNumberBetween(value: number, min: number, max: number): boolean`
|
|
396
|
+
- `isAlpha(str: string): boolean`
|
|
397
|
+
- `isStrongPassword(str: string): boolean`
|
|
398
|
+
- `isIPv4(str: string): boolean`
|
|
399
|
+
- `isIPv6(str: string): boolean`
|
|
400
|
+
- `isCreditCard(str: string): boolean`
|
|
401
|
+
- `isValidJSON(str: string): boolean`
|
|
402
|
+
- `isObject(value: unknown): value is Record<string, unknown>`
|
|
403
|
+
- `isArray<T = unknown>(value: unknown, itemGuard?: (item: unknown) => item is T): value is T[]`
|
|
404
|
+
- `isBase64(str: string): boolean`
|
|
405
|
+
- `hasRequiredProps(obj: Record<string, unknown>, requiredProps: string[]): boolean`
|
|
406
|
+
- `isDateInRange(date: Date, minDate?: Date, maxDate?: Date): boolean`
|
|
407
|
+
- `matchesPattern(str: string, pattern: RegExp): boolean`
|
|
408
|
+
- `validateAll(value: unknown, validators: Array<(value: unknown) => boolean>): boolean`
|
|
409
|
+
|
|
410
|
+
---
|
|
411
|
+
|
|
412
|
+
# 📧 Decorators Utilities
|
|
413
|
+
|
|
414
|
+
## Available Decorators
|
|
415
|
+
|
|
416
|
+
- `@Controller(basePath: string)` – Class decorator to set the base route.
|
|
417
|
+
- `@Get(path)`, `@Post(path)`, `@Put(path)`, `@Patch(path)`, `@Delete(path)`, `@Options(path)`, `@Head(path)`, `@Trace(path)`, `@Connect(path)` – Method decorators for HTTP verbs.
|
|
418
|
+
- `@Use(...middlewares)` – Attach Express-style middleware to a route handler.
|
|
419
|
+
- `@Query(key?)`, `@Param(key?)`, `@Body(key?)`, `@Req()`, `@Res()` – Parameter decorators for extracting request data.
|
|
420
|
+
- `@HttpCode(status)` – Set custom HTTP status code for the response.
|
|
421
|
+
- `@Header(name, value)` – Set custom response headers.
|
|
422
|
+
- `@Before(fn)`, `@After(fn)` – Register before/after hooks for a route handler.
|
|
423
|
+
|
|
424
|
+
## Example Usage
|
|
425
|
+
|
|
426
|
+
```typescript
|
|
427
|
+
import {
|
|
428
|
+
Controller, Get, Post, Use, Query, Param, Body, Req, Res,
|
|
429
|
+
HttpCode, Header, Before, After, registerControllers, Request, Response, NextFunction
|
|
430
|
+
} from './src/utils/decorators.utils';
|
|
431
|
+
|
|
432
|
+
// Example middleware
|
|
433
|
+
function logMiddleware(req: Request, res: Response, next: NextFunction) {
|
|
434
|
+
console.log('Request:', req.method, req.url);
|
|
435
|
+
next();
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
// Example before/after hooks
|
|
439
|
+
function beforeHook(req: Request, res: Response) {
|
|
440
|
+
console.log('Before handler');
|
|
441
|
+
}
|
|
442
|
+
function afterHook(req: Request, res: Response, result: any) {
|
|
443
|
+
console.log('After handler', result);
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
@Controller('/api')
|
|
447
|
+
class ExampleController {
|
|
448
|
+
@Get('/items/:id')
|
|
449
|
+
@Use(logMiddleware)
|
|
450
|
+
@HttpCode(200)
|
|
451
|
+
@Header('X-Example', 'yes')
|
|
452
|
+
@Before(beforeHook)
|
|
453
|
+
@After(afterHook)
|
|
454
|
+
getItem(
|
|
455
|
+
@Query('q') q: string,
|
|
456
|
+
@Param('id') id: string,
|
|
457
|
+
@Body('name') name: string,
|
|
458
|
+
@Req() req: Request,
|
|
459
|
+
@Res() res: Response
|
|
460
|
+
) {
|
|
461
|
+
return { q, id, name };
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
@Post('/items')
|
|
465
|
+
createItem(@Body() body: any) {
|
|
466
|
+
return { created: true, ...body };
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
// Register controllers with your router (Express-like)
|
|
471
|
+
const router = /* your router instance */;
|
|
472
|
+
registerControllers(router, [ExampleController]);
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
## Notes
|
|
476
|
+
|
|
477
|
+
- Decorated methods **must** use standard method syntax, not arrow functions or property initializers.
|
|
478
|
+
- All parameter decorators (`@Query`, `@Param`, etc.) are optional and can be used in any order.
|
|
479
|
+
- `registerControllers(router, controllers)` will register all routes and apply middlewares, hooks, status codes, and headers as defined.
|
|
284
480
|
|
|
285
481
|
## 🏁 Usage
|
|
286
482
|
|
package/build/esm/config.d.ts
CHANGED
|
@@ -17,6 +17,18 @@ export declare const Config: {
|
|
|
17
17
|
*/
|
|
18
18
|
isoTimestamp: boolean;
|
|
19
19
|
};
|
|
20
|
+
Http: {
|
|
21
|
+
/**
|
|
22
|
+
* Timeout for HTTP requests in milliseconds
|
|
23
|
+
*/
|
|
24
|
+
timeout: number;
|
|
25
|
+
};
|
|
26
|
+
Cache: {
|
|
27
|
+
/**
|
|
28
|
+
* Default TTL (time to live) for cache entries in seconds
|
|
29
|
+
*/
|
|
30
|
+
defaultTtl: number;
|
|
31
|
+
};
|
|
20
32
|
};
|
|
21
33
|
export {};
|
|
22
34
|
//# sourceMappingURL=config.d.ts.map
|
package/build/esm/config.js
CHANGED
|
@@ -17,5 +17,17 @@ export var Config = {
|
|
|
17
17
|
*/
|
|
18
18
|
isoTimestamp: Env.getBoolean("LOGGER_ISO_TIMESTAMP", false),
|
|
19
19
|
},
|
|
20
|
+
Http: {
|
|
21
|
+
/**
|
|
22
|
+
* Timeout for HTTP requests in milliseconds
|
|
23
|
+
*/
|
|
24
|
+
timeout: Env.getNumber("HTTP_TIMEOUT", 30000),
|
|
25
|
+
},
|
|
26
|
+
Cache: {
|
|
27
|
+
/**
|
|
28
|
+
* Default TTL (time to live) for cache entries in seconds
|
|
29
|
+
*/
|
|
30
|
+
defaultTtl: Env.getNumber("CACHE_DEFAULT_TTL", 300),
|
|
31
|
+
},
|
|
20
32
|
};
|
|
21
33
|
//# sourceMappingURL=config.js.map
|
package/build/esm/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AAWxC;;GAEG;AACH,MAAM,CAAC,IAAM,MAAM,GAAG;IACpB,MAAM,EAAE;QACN;;WAEG;QACH,KAAK,EAAE,GAAG,CAAC,GAAG,CAAC,cAAc,EAAE,MAAM,CAAa;QAElD;;WAEG;QACH,IAAI,EAAE,GAAG,CAAC,GAAG,CAAC,aAAa,EAAE,GAAG,CAAC,GAAG,CAAC,kBAAkB,EAAE,eAAe,CAAC,CAAC;QAE1E;;WAEG;QACH,YAAY,EAAE,GAAG,CAAC,UAAU,CAAC,sBAAsB,EAAE,KAAK,CAAC;KAC5D;CACF,CAAC","sourcesContent":["import { Env } from \"./utils/env.utils\";\n\ntype LogLevel =\n | \"fatal\"\n | \"error\"\n | \"warn\"\n | \"info\"\n | \"debug\"\n | \"trace\"\n | \"silent\";\n\n/**\n * Application runtime configuration loaded from environment variables.\n */\nexport const Config = {\n Logger: {\n /**\n * Logging level (e.g., 'info', 'debug', 'warn', 'error').\n */\n level: Env.get(\"LOGGER_LEVEL\", \"info\") as LogLevel,\n\n /**\n * Name of the logger instance (defaults to npm package name).\n */\n name: Env.get(\"LOGGER_NAME\", Env.get(\"npm_package_name\", \"@catbee/utils\")),\n\n /**\n * Whether to use ISO 8601 timestamps in logs.\n */\n isoTimestamp: Env.getBoolean(\"LOGGER_ISO_TIMESTAMP\", false),\n },\n};\n"]}
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AAWxC;;GAEG;AACH,MAAM,CAAC,IAAM,MAAM,GAAG;IACpB,MAAM,EAAE;QACN;;WAEG;QACH,KAAK,EAAE,GAAG,CAAC,GAAG,CAAC,cAAc,EAAE,MAAM,CAAa;QAElD;;WAEG;QACH,IAAI,EAAE,GAAG,CAAC,GAAG,CAAC,aAAa,EAAE,GAAG,CAAC,GAAG,CAAC,kBAAkB,EAAE,eAAe,CAAC,CAAC;QAE1E;;WAEG;QACH,YAAY,EAAE,GAAG,CAAC,UAAU,CAAC,sBAAsB,EAAE,KAAK,CAAC;KAC5D;IAED,IAAI,EAAE;QACJ;;WAEG;QACH,OAAO,EAAE,GAAG,CAAC,SAAS,CAAC,cAAc,EAAE,KAAK,CAAC;KAC9C;IAED,KAAK,EAAE;QACL;;WAEG;QACH,UAAU,EAAE,GAAG,CAAC,SAAS,CAAC,mBAAmB,EAAE,GAAG,CAAC;KACpD;CACF,CAAC","sourcesContent":["import { Env } from \"./utils/env.utils\";\n\ntype LogLevel =\n | \"fatal\"\n | \"error\"\n | \"warn\"\n | \"info\"\n | \"debug\"\n | \"trace\"\n | \"silent\";\n\n/**\n * Application runtime configuration loaded from environment variables.\n */\nexport const Config = {\n Logger: {\n /**\n * Logging level (e.g., 'info', 'debug', 'warn', 'error').\n */\n level: Env.get(\"LOGGER_LEVEL\", \"info\") as LogLevel,\n\n /**\n * Name of the logger instance (defaults to npm package name).\n */\n name: Env.get(\"LOGGER_NAME\", Env.get(\"npm_package_name\", \"@catbee/utils\")),\n\n /**\n * Whether to use ISO 8601 timestamps in logs.\n */\n isoTimestamp: Env.getBoolean(\"LOGGER_ISO_TIMESTAMP\", false),\n },\n\n Http: {\n /**\n * Timeout for HTTP requests in milliseconds\n */\n timeout: Env.getNumber(\"HTTP_TIMEOUT\", 30000),\n },\n\n Cache: {\n /**\n * Default TTL (time to live) for cache entries in seconds\n */\n defaultTtl: Env.getNumber(\"CACHE_DEFAULT_TTL\", 300),\n },\n};\n"]}
|
package/build/esm/index.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ export * from "./utils/fs.utils";
|
|
|
10
10
|
export * from "./utils/http-status-codes";
|
|
11
11
|
export * from "./utils/id.utils";
|
|
12
12
|
export * from "./utils/logger.utils";
|
|
13
|
+
export * from "./utils/middleware.utils";
|
|
13
14
|
export * from "./utils/obj.utils";
|
|
14
15
|
export * from "./utils/response.utils";
|
|
15
16
|
export * from "./utils/string.utils";
|
package/build/esm/index.js
CHANGED
|
@@ -10,6 +10,7 @@ export * from "./utils/fs.utils";
|
|
|
10
10
|
export * from "./utils/http-status-codes";
|
|
11
11
|
export * from "./utils/id.utils";
|
|
12
12
|
export * from "./utils/logger.utils";
|
|
13
|
+
export * from "./utils/middleware.utils";
|
|
13
14
|
export * from "./utils/obj.utils";
|
|
14
15
|
export * from "./utils/response.utils";
|
|
15
16
|
export * from "./utils/string.utils";
|
package/build/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,yBAAyB,CAAC;AACxC,cAAc,kBAAkB,CAAC;AACjC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,wBAAwB,CAAC;AAEvC,cAAc,sBAAsB,CAAC","sourcesContent":["export * from \"./utils/array.utils\";\nexport * from \"./utils/async.utils\";\nexport * from \"./utils/cache.utils\";\nexport * from \"./utils/context-store.utils\";\nexport * from \"./utils/crypto.utils\";\nexport * from \"./utils/dir.utils\";\nexport * from \"./utils/env.utils\";\nexport * from \"./utils/exception.utils\";\nexport * from \"./utils/fs.utils\";\nexport * from \"./utils/http-status-codes\";\nexport * from \"./utils/id.utils\";\nexport * from \"./utils/logger.utils\";\nexport * from \"./utils/obj.utils\";\nexport * from \"./utils/response.utils\";\nexport * from \"./utils/string.utils\";\nexport * from \"./utils/url.utils\";\nexport * from \"./utils/validate.utils\";\n\nexport * from \"./types/api-response\";\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,yBAAyB,CAAC;AACxC,cAAc,kBAAkB,CAAC;AACjC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC;AACzC,cAAc,mBAAmB,CAAC;AAClC,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,wBAAwB,CAAC;AAEvC,cAAc,sBAAsB,CAAC","sourcesContent":["export * from \"./utils/array.utils\";\nexport * from \"./utils/async.utils\";\nexport * from \"./utils/cache.utils\";\nexport * from \"./utils/context-store.utils\";\nexport * from \"./utils/crypto.utils\";\nexport * from \"./utils/dir.utils\";\nexport * from \"./utils/env.utils\";\nexport * from \"./utils/exception.utils\";\nexport * from \"./utils/fs.utils\";\nexport * from \"./utils/http-status-codes\";\nexport * from \"./utils/id.utils\";\nexport * from \"./utils/logger.utils\";\nexport * from \"./utils/middleware.utils\";\nexport * from \"./utils/obj.utils\";\nexport * from \"./utils/response.utils\";\nexport * from \"./utils/string.utils\";\nexport * from \"./utils/url.utils\";\nexport * from \"./utils/validate.utils\";\n\nexport * from \"./types/api-response\";\n"]}
|