@catbee/utils 2.0.4 → 2.1.1

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.
@@ -23,6 +23,7 @@
23
23
  */
24
24
 
25
25
  import { AsyncLocalStorage } from 'node:async_hooks';
26
+ import { Logger } from 'pino';
26
27
 
27
28
  /**
28
29
  * Type representing the store object used in AsyncLocalStorage.
@@ -31,20 +32,76 @@ import { AsyncLocalStorage } from 'node:async_hooks';
31
32
  interface Store {
32
33
  [key: symbol]: unknown;
33
34
  }
35
+ /**
36
+ * Type-safe wrapper for accessing and modifying context values with specific types.
37
+ *
38
+ * @typeParam T - The value type.
39
+ */
40
+ declare class TypedContextKey<T> {
41
+ private readonly symbol;
42
+ private readonly defaultValue?;
43
+ /**
44
+ * Creates a new typed context key.
45
+ * @param symbol - The unique symbol for this key
46
+ * @param defaultValue - Optional default value if key is not found
47
+ */
48
+ constructor(symbol: symbol, defaultValue?: T | undefined);
49
+ /**
50
+ * Gets the current value for this key.
51
+ * @returns The value or defaultValue if not found
52
+ */
53
+ get(): T | undefined;
54
+ /**
55
+ * Sets the value for this key.
56
+ * @param value The value to set
57
+ */
58
+ set(value: T): void;
59
+ /**
60
+ * Checks if this key exists in the context.
61
+ * @returns True if the key exists
62
+ */
63
+ exists(): boolean;
64
+ /**
65
+ * Deletes this key from the context.
66
+ * @returns True if the key was deleted
67
+ */
68
+ delete(): boolean;
69
+ /**
70
+ * Gets the symbol for this key.
71
+ * @returns Symbol for this key
72
+ */
73
+ getSymbol(): symbol;
74
+ }
75
+ type ContextKey<T = unknown> = symbol | TypedContextKey<T>;
34
76
  /**
35
77
  * Predefined symbols used as keys in AsyncLocalStorage.
36
78
  * Add new symbols here to avoid duplication.
37
79
  */
38
80
  declare const StoreKeys: {
39
- LOGGER: symbol;
40
- REQUEST_ID: symbol;
41
- USER: symbol;
42
- SESSION: symbol;
43
- TRANSACTION_ID: symbol;
44
- USER_ID: symbol;
45
- TENANT_ID: symbol;
46
- TRACE_ID: symbol;
47
- CORRELATION_ID: symbol;
81
+ readonly LOGGER: symbol;
82
+ readonly REQUEST_ID: symbol;
83
+ readonly CORRELATION_ID: symbol;
84
+ readonly USER_ID: symbol;
85
+ readonly TRANSACTION_ID: symbol;
86
+ readonly TENANT_ID: symbol;
87
+ readonly TRACE_ID: symbol;
88
+ readonly SPAN_ID: symbol;
89
+ readonly MESSAGE_ID: symbol;
90
+ readonly MESSAGE_TYPE: symbol;
91
+ readonly QUEUE_NAME: symbol;
92
+ };
93
+ declare const TypedStoreKeys: {
94
+ readonly LOGGER: TypedContextKey<Logger>;
95
+ readonly REQUEST_ID: TypedContextKey<string>;
96
+ readonly CORRELATION_ID: TypedContextKey<string>;
97
+ readonly USER_ID: TypedContextKey<string>;
98
+ readonly TRANSACTION_ID: TypedContextKey<string>;
99
+ readonly TENANT_ID: TypedContextKey<string>;
100
+ readonly TRACE_ID: TypedContextKey<string>;
101
+ readonly SPAN_ID: TypedContextKey<string>;
102
+ readonly MESSAGE_ID: TypedContextKey<string>;
103
+ readonly MESSAGE_TYPE: TypedContextKey<string>;
104
+ readonly QUEUE_NAME: TypedContextKey<string>;
48
105
  };
49
106
  /**
50
107
  * Retrieves the current request ID from the async context, if available.
@@ -58,7 +115,7 @@ declare function getRequestId(): string | undefined;
58
115
  * @param key The store key symbol
59
116
  * @returns The typed value from the store
60
117
  */
61
- declare function getFromContext<T>(key: symbol): T | undefined;
118
+ declare function getFromContext<T>(key: ContextKey<T>): T | undefined;
62
119
  /**
63
120
  * ContextStore manages per-request scoped context using AsyncLocalStorage.
64
121
  * It allows storing and retrieving data across async calls (e.g., request ID, logger).
@@ -94,7 +151,7 @@ declare class ContextStore {
94
151
  * @param {symbol} key - Unique symbol used as the store key.
95
152
  * @returns {T | undefined} The value found (typed) or undefined if not present.
96
153
  */
97
- static get<T>(key: symbol): T | undefined;
154
+ static get<T>(key: ContextKey<T>): T | undefined;
98
155
  /**
99
156
  * Sets a value in the current context store by symbol key.
100
157
  *
@@ -103,7 +160,7 @@ declare class ContextStore {
103
160
  * @param {T} value - Value to set in context.
104
161
  * @throws {Error} If called outside an active context (not within a .run call or in the wrong async boundaries).
105
162
  */
106
- static set<T>(key: symbol, value: T): void;
163
+ static set<T>(key: ContextKey<T>, value: T): void;
107
164
  /**
108
165
  * Retrieves the entire context store object for the current async context.
109
166
  *
@@ -126,7 +183,7 @@ declare class ContextStore {
126
183
  * @param {symbol} key - The symbol key to check.
127
184
  * @returns {boolean} True if the key exists, false otherwise.
128
185
  */
129
- static has(key: symbol): boolean;
186
+ static has(key: ContextKey): boolean;
130
187
  /**
131
188
  * Removes a value from the current context store by symbol key.
132
189
  *
@@ -134,7 +191,7 @@ declare class ContextStore {
134
191
  * @returns {boolean} True if the key was deleted, false if the key wasn't found or no active context.
135
192
  * @throws {Error} If called outside an active context.
136
193
  */
137
- static delete(key: symbol): boolean;
194
+ static delete(key: ContextKey): boolean;
138
195
  /**
139
196
  * Updates multiple values in the current context store at once.
140
197
  *
@@ -153,7 +210,7 @@ declare class ContextStore {
153
210
  * @returns {T} The result of the callback function.
154
211
  * @throws {Error} If called outside an active context.
155
212
  */
156
- static withValue<T>(key: symbol, value: unknown, callback: () => T): T;
213
+ static withValue<T, V>(key: ContextKey<V>, value: V, callback: () => T): T;
157
214
  /**
158
215
  * Creates a new context that inherits values from the current context.
159
216
  *
@@ -171,46 +228,6 @@ declare class ContextStore {
171
228
  */
172
229
  static createExpressMiddleware(initialValuesFactory?: (req: any) => Partial<Record<symbol, unknown>>): (req: any, _res: any, next: any) => void;
173
230
  }
174
- /**
175
- * Type-safe wrapper for accessing and modifying context values with specific types.
176
- *
177
- * @typeParam T - The value type.
178
- */
179
- declare class TypedContextKey<T> {
180
- private readonly symbol;
181
- private readonly defaultValue?;
182
- /**
183
- * Creates a new typed context key.
184
- *
185
- * @param symbol - The unique symbol for this key
186
- * @param defaultValue - Optional default value if key is not found
187
- */
188
- constructor(symbol: symbol, defaultValue?: T | undefined);
189
- /**
190
- * Gets the current value for this key.
191
- *
192
- * @returns The value or defaultValue if not found
193
- */
194
- get(): T | undefined;
195
- /**
196
- * Sets the value for this key.
197
- *
198
- * @param value The value to set
199
- */
200
- set(value: T): void;
201
- /**
202
- * Checks if this key exists in the context.
203
- *
204
- * @returns True if the key exists
205
- */
206
- exists(): boolean;
207
- /**
208
- * Deletes this key from the context.
209
- *
210
- * @returns True if the key was deleted
211
- */
212
- delete(): boolean;
213
- }
214
231
 
215
- export { ContextStore, StoreKeys, TypedContextKey, getFromContext, getRequestId };
216
- export type { Store };
232
+ export { ContextStore, StoreKeys, TypedContextKey, TypedStoreKeys, getFromContext, getRequestId };
233
+ export type { ContextKey, Store };
@@ -26,23 +26,94 @@ import { AsyncLocalStorage } from 'async_hooks';
26
26
 
27
27
  var __defProp = Object.defineProperty;
28
28
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
29
+ var TypedContextKey = class {
30
+ static {
31
+ __name(this, "TypedContextKey");
32
+ }
33
+ symbol;
34
+ defaultValue;
35
+ /**
36
+ * Creates a new typed context key.
37
+ * @param symbol - The unique symbol for this key
38
+ * @param defaultValue - Optional default value if key is not found
39
+ */
40
+ constructor(symbol, defaultValue) {
41
+ this.symbol = symbol;
42
+ this.defaultValue = defaultValue;
43
+ }
44
+ /**
45
+ * Gets the current value for this key.
46
+ * @returns The value or defaultValue if not found
47
+ */
48
+ get() {
49
+ return ContextStore.get(this.symbol) ?? this.defaultValue;
50
+ }
51
+ /**
52
+ * Sets the value for this key.
53
+ * @param value The value to set
54
+ */
55
+ set(value) {
56
+ ContextStore.set(this.symbol, value);
57
+ }
58
+ /**
59
+ * Checks if this key exists in the context.
60
+ * @returns True if the key exists
61
+ */
62
+ exists() {
63
+ return ContextStore.has(this.symbol);
64
+ }
65
+ /**
66
+ * Deletes this key from the context.
67
+ * @returns True if the key was deleted
68
+ */
69
+ delete() {
70
+ return ContextStore.delete(this.symbol);
71
+ }
72
+ /**
73
+ * Gets the symbol for this key.
74
+ * @returns Symbol for this key
75
+ */
76
+ getSymbol() {
77
+ return this.symbol;
78
+ }
79
+ };
29
80
  var StoreKeys = {
30
81
  LOGGER: Symbol("LOGGER"),
31
82
  REQUEST_ID: Symbol("REQUEST_ID"),
32
- USER: Symbol("USER"),
33
- SESSION: Symbol("SESSION"),
34
- TRANSACTION_ID: Symbol("TRANSACTION_ID"),
83
+ CORRELATION_ID: Symbol("CORRELATION_ID"),
35
84
  USER_ID: Symbol("USER_ID"),
85
+ TRANSACTION_ID: Symbol("TRANSACTION_ID"),
36
86
  TENANT_ID: Symbol("TENANT_ID"),
37
87
  TRACE_ID: Symbol("TRACE_ID"),
38
- CORRELATION_ID: Symbol("CORRELATION_ID")
88
+ SPAN_ID: Symbol("SPAN_ID"),
89
+ MESSAGE_ID: Symbol("MESSAGE_ID"),
90
+ MESSAGE_TYPE: Symbol("MESSAGE_TYPE"),
91
+ QUEUE_NAME: Symbol("QUEUE_NAME")
92
+ };
93
+ var TypedStoreKeys = {
94
+ LOGGER: new TypedContextKey(StoreKeys.LOGGER),
95
+ REQUEST_ID: new TypedContextKey(StoreKeys.REQUEST_ID),
96
+ CORRELATION_ID: new TypedContextKey(StoreKeys.CORRELATION_ID),
97
+ USER_ID: new TypedContextKey(StoreKeys.USER_ID),
98
+ TRANSACTION_ID: new TypedContextKey(StoreKeys.TRANSACTION_ID),
99
+ TENANT_ID: new TypedContextKey(StoreKeys.TENANT_ID),
100
+ TRACE_ID: new TypedContextKey(StoreKeys.TRACE_ID),
101
+ SPAN_ID: new TypedContextKey(StoreKeys.SPAN_ID),
102
+ MESSAGE_ID: new TypedContextKey(StoreKeys.MESSAGE_ID),
103
+ MESSAGE_TYPE: new TypedContextKey(StoreKeys.MESSAGE_TYPE),
104
+ QUEUE_NAME: new TypedContextKey(StoreKeys.QUEUE_NAME)
39
105
  };
40
106
  function getRequestId() {
41
- return ContextStore.get(StoreKeys.REQUEST_ID);
107
+ return TypedStoreKeys.REQUEST_ID.get();
42
108
  }
43
109
  __name(getRequestId, "getRequestId");
110
+ function resolveKey(key) {
111
+ return key instanceof TypedContextKey ? key.getSymbol() : key;
112
+ }
113
+ __name(resolveKey, "resolveKey");
44
114
  function getFromContext(key) {
45
- return ContextStore.get(key);
115
+ const symbol = resolveKey(key);
116
+ return ContextStore.get(symbol);
46
117
  }
47
118
  __name(getFromContext, "getFromContext");
48
119
  var ContextStore = class _ContextStore {
@@ -70,8 +141,9 @@ var ContextStore = class _ContextStore {
70
141
  * @returns {T | undefined} The value found (typed) or undefined if not present.
71
142
  */
72
143
  static get(key) {
144
+ const symbol = resolveKey(key);
73
145
  const store = this.storage.getStore();
74
- return store?.[key];
146
+ return store?.[symbol];
75
147
  }
76
148
  /**
77
149
  * Sets a value in the current context store by symbol key.
@@ -82,11 +154,12 @@ var ContextStore = class _ContextStore {
82
154
  * @throws {Error} If called outside an active context (not within a .run call or in the wrong async boundaries).
83
155
  */
84
156
  static set(key, value) {
157
+ const symbol = resolveKey(key);
85
158
  const store = this.storage.getStore();
86
159
  if (!store) {
87
- throw new Error(`Failed to set ${String(key)}: AsyncLocalStorage store is not initialized.`);
160
+ throw new Error(`Failed to set ${String(symbol)}: AsyncLocalStorage store is not initialized.`);
88
161
  }
89
- store[key] = value;
162
+ store[symbol] = value;
90
163
  }
91
164
  /**
92
165
  * Retrieves the entire context store object for the current async context.
@@ -115,8 +188,9 @@ var ContextStore = class _ContextStore {
115
188
  * @returns {boolean} True if the key exists, false otherwise.
116
189
  */
117
190
  static has(key) {
191
+ const symbol = resolveKey(key);
118
192
  const store = this.storage.getStore();
119
- return store !== void 0 && key in store;
193
+ return store !== void 0 && symbol in store;
120
194
  }
121
195
  /**
122
196
  * Removes a value from the current context store by symbol key.
@@ -126,11 +200,12 @@ var ContextStore = class _ContextStore {
126
200
  * @throws {Error} If called outside an active context.
127
201
  */
128
202
  static delete(key) {
203
+ const symbol = resolveKey(key);
129
204
  const store = this.storage.getStore();
130
205
  if (!store) {
131
- throw new Error(`Failed to delete ${String(key)}: AsyncLocalStorage store is not initialized.`);
206
+ throw new Error(`Failed to delete ${String(symbol)}: AsyncLocalStorage store is not initialized.`);
132
207
  }
133
- return delete store[key];
208
+ return delete store[symbol];
134
209
  }
135
210
  /**
136
211
  * Updates multiple values in the current context store at once.
@@ -159,22 +234,16 @@ var ContextStore = class _ContextStore {
159
234
  * @throws {Error} If called outside an active context.
160
235
  */
161
236
  static withValue(key, value, callback) {
162
- const store = this.storage.getStore();
163
- if (!store) {
164
- throw new Error(`Failed to set temporary value: AsyncLocalStorage store is not initialized.`);
165
- }
166
- const hasOriginal = key in store;
167
- const originalValue = store[key];
168
- store[key] = value;
169
- try {
170
- return callback();
171
- } finally {
172
- if (hasOriginal) {
173
- store[key] = originalValue;
174
- } else {
175
- delete store[key];
176
- }
237
+ const symbol = resolveKey(key);
238
+ const currentStore = this.storage.getStore();
239
+ if (!currentStore) {
240
+ throw new Error("Failed to set temporary value: AsyncLocalStorage store is not initialized.");
177
241
  }
242
+ const newStore = {
243
+ ...currentStore,
244
+ [symbol]: value
245
+ };
246
+ return this.storage.run(newStore, callback);
178
247
  }
179
248
  /**
180
249
  * Creates a new context that inherits values from the current context.
@@ -207,54 +276,5 @@ var ContextStore = class _ContextStore {
207
276
  };
208
277
  }
209
278
  };
210
- var TypedContextKey = class {
211
- static {
212
- __name(this, "TypedContextKey");
213
- }
214
- symbol;
215
- defaultValue;
216
- /**
217
- * Creates a new typed context key.
218
- *
219
- * @param symbol - The unique symbol for this key
220
- * @param defaultValue - Optional default value if key is not found
221
- */
222
- constructor(symbol, defaultValue) {
223
- this.symbol = symbol;
224
- this.defaultValue = defaultValue;
225
- }
226
- /**
227
- * Gets the current value for this key.
228
- *
229
- * @returns The value or defaultValue if not found
230
- */
231
- get() {
232
- return ContextStore.get(this.symbol) ?? this.defaultValue;
233
- }
234
- /**
235
- * Sets the value for this key.
236
- *
237
- * @param value The value to set
238
- */
239
- set(value) {
240
- ContextStore.set(this.symbol, value);
241
- }
242
- /**
243
- * Checks if this key exists in the context.
244
- *
245
- * @returns True if the key exists
246
- */
247
- exists() {
248
- return ContextStore.has(this.symbol);
249
- }
250
- /**
251
- * Deletes this key from the context.
252
- *
253
- * @returns True if the key was deleted
254
- */
255
- delete() {
256
- return ContextStore.delete(this.symbol);
257
- }
258
- };
259
279
 
260
- export { ContextStore, StoreKeys, TypedContextKey, getFromContext, getRequestId };
280
+ export { ContextStore, StoreKeys, TypedContextKey, TypedStoreKeys, getFromContext, getRequestId };