@warlock.js/context 4.0.48 → 4.0.57
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/cjs/base-context.d.ts +96 -0
- package/cjs/base-context.d.ts.map +1 -0
- package/cjs/base-context.js +105 -0
- package/cjs/base-context.js.map +1 -0
- package/cjs/context-manager.d.ts +102 -0
- package/cjs/context-manager.d.ts.map +1 -0
- package/cjs/context-manager.js +132 -0
- package/cjs/context-manager.js.map +1 -0
- package/cjs/index.d.ts +3 -0
- package/cjs/index.d.ts.map +1 -0
- package/cjs/index.js +1 -21
- package/cjs/index.js.map +1 -1
- package/esm/base-context.d.ts +96 -0
- package/esm/base-context.d.ts.map +1 -0
- package/esm/base-context.js +105 -0
- package/esm/base-context.js.map +1 -0
- package/esm/context-manager.d.ts +102 -0
- package/esm/context-manager.d.ts.map +1 -0
- package/esm/context-manager.js +132 -0
- package/esm/context-manager.js.map +1 -0
- package/esm/index.d.ts +3 -0
- package/esm/index.d.ts.map +1 -0
- package/esm/index.js +1 -4
- package/esm/index.js.map +1 -1
- package/package.json +30 -43
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { AsyncLocalStorage } from "async_hooks";
|
|
3
|
+
/**
|
|
4
|
+
* Base class for all AsyncLocalStorage-based contexts
|
|
5
|
+
*
|
|
6
|
+
* Provides a consistent API for managing context across async operations.
|
|
7
|
+
* All framework contexts (request, storage, database) extend this class.
|
|
8
|
+
*
|
|
9
|
+
* @template TStore - The type of data stored in context
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* interface MyContextStore {
|
|
14
|
+
* userId: string;
|
|
15
|
+
* tenant: string;
|
|
16
|
+
* }
|
|
17
|
+
*
|
|
18
|
+
* class MyContext extends Context<MyContextStore> {}
|
|
19
|
+
* const myContext = new MyContext();
|
|
20
|
+
*
|
|
21
|
+
* // Use it
|
|
22
|
+
* await myContext.run({ userId: '123', tenant: 'acme' }, async () => {
|
|
23
|
+
* const userId = myContext.get('userId'); // '123'
|
|
24
|
+
* });
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export declare abstract class Context<TStore extends Record<string, any>> {
|
|
28
|
+
protected readonly storage: AsyncLocalStorage<TStore>;
|
|
29
|
+
/**
|
|
30
|
+
* Run a callback within a new context
|
|
31
|
+
*
|
|
32
|
+
* Creates a new async context with the provided store data.
|
|
33
|
+
* All operations within the callback will have access to this context.
|
|
34
|
+
*
|
|
35
|
+
* @param store - Initial context data
|
|
36
|
+
* @param callback - Async function to execute
|
|
37
|
+
* @returns Result of the callback
|
|
38
|
+
*/
|
|
39
|
+
run<T>(store: TStore, callback: () => Promise<T>): Promise<T>;
|
|
40
|
+
/**
|
|
41
|
+
* Enter a new context without a callback
|
|
42
|
+
*
|
|
43
|
+
* Useful for middleware where you want to set context for the rest of the request.
|
|
44
|
+
* Unlike `run()`, this doesn't require a callback.
|
|
45
|
+
*
|
|
46
|
+
* @param store - Context data to set
|
|
47
|
+
*/
|
|
48
|
+
enter(store: TStore): void;
|
|
49
|
+
/**
|
|
50
|
+
* Update the current context
|
|
51
|
+
*
|
|
52
|
+
* Merges new data into existing context, or enters new context if none exists.
|
|
53
|
+
*
|
|
54
|
+
* @param updates - Partial context data to merge
|
|
55
|
+
*/
|
|
56
|
+
update(updates: Partial<TStore>): void;
|
|
57
|
+
/**
|
|
58
|
+
* Get the current context store
|
|
59
|
+
*
|
|
60
|
+
* @returns Current context or undefined if not in context
|
|
61
|
+
*/
|
|
62
|
+
getStore(): TStore | undefined;
|
|
63
|
+
/**
|
|
64
|
+
* Get a specific value from context
|
|
65
|
+
*
|
|
66
|
+
* @param key - Key to retrieve
|
|
67
|
+
* @returns Value or undefined
|
|
68
|
+
*/
|
|
69
|
+
get<K extends keyof TStore>(key: K): TStore[K] | undefined;
|
|
70
|
+
/**
|
|
71
|
+
* Set a specific value in context
|
|
72
|
+
*
|
|
73
|
+
* @param key - Key to set
|
|
74
|
+
* @param value - Value to store
|
|
75
|
+
*/
|
|
76
|
+
set<K extends keyof TStore>(key: K, value: TStore[K]): void;
|
|
77
|
+
/**
|
|
78
|
+
* Clear the context
|
|
79
|
+
*/
|
|
80
|
+
clear(): void;
|
|
81
|
+
/**
|
|
82
|
+
* Check if currently in a context
|
|
83
|
+
*/
|
|
84
|
+
hasContext(): boolean;
|
|
85
|
+
/**
|
|
86
|
+
* Build the initial store for this context
|
|
87
|
+
*
|
|
88
|
+
* Override this method to provide custom initialization logic.
|
|
89
|
+
* Called by ContextManager.buildStores() for each registered context.
|
|
90
|
+
*
|
|
91
|
+
* @param payload - Generic payload (e.g., { request, response } for HTTP contexts)
|
|
92
|
+
* @returns Initial store data
|
|
93
|
+
*/
|
|
94
|
+
abstract buildStore(payload?: Record<string, any>): TStore;
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=base-context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base-context.d.ts","sourceRoot":"","sources":["../src/base-context.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEhD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,8BAAsB,OAAO,CAAC,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IAC9D,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAmC;IAExF;;;;;;;;;OASG;IACI,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAIpE;;;;;;;OAOG;IACI,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAIjC;;;;;;OAMG;IACI,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,GAAG,IAAI;IAU7C;;;;OAIG;IACI,QAAQ,IAAI,MAAM,GAAG,SAAS;IAIrC;;;;;OAKG;IACI,GAAG,CAAC,CAAC,SAAS,MAAM,MAAM,EAAE,GAAG,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,SAAS;IAIjE;;;;;OAKG;IACI,GAAG,CAAC,CAAC,SAAS,MAAM,MAAM,EAAE,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI;IAIlE;;OAEG;IACI,KAAK,IAAI,IAAI;IAIpB;;OAEG;IACI,UAAU,IAAI,OAAO;IAI5B;;;;;;;;OAQG;aACa,UAAU,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM;CAClE"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
'use strict';var async_hooks=require('async_hooks');/**
|
|
2
|
+
* Base class for all AsyncLocalStorage-based contexts
|
|
3
|
+
*
|
|
4
|
+
* Provides a consistent API for managing context across async operations.
|
|
5
|
+
* All framework contexts (request, storage, database) extend this class.
|
|
6
|
+
*
|
|
7
|
+
* @template TStore - The type of data stored in context
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* interface MyContextStore {
|
|
12
|
+
* userId: string;
|
|
13
|
+
* tenant: string;
|
|
14
|
+
* }
|
|
15
|
+
*
|
|
16
|
+
* class MyContext extends Context<MyContextStore> {}
|
|
17
|
+
* const myContext = new MyContext();
|
|
18
|
+
*
|
|
19
|
+
* // Use it
|
|
20
|
+
* await myContext.run({ userId: '123', tenant: 'acme' }, async () => {
|
|
21
|
+
* const userId = myContext.get('userId'); // '123'
|
|
22
|
+
* });
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
class Context {
|
|
26
|
+
storage = new async_hooks.AsyncLocalStorage();
|
|
27
|
+
/**
|
|
28
|
+
* Run a callback within a new context
|
|
29
|
+
*
|
|
30
|
+
* Creates a new async context with the provided store data.
|
|
31
|
+
* All operations within the callback will have access to this context.
|
|
32
|
+
*
|
|
33
|
+
* @param store - Initial context data
|
|
34
|
+
* @param callback - Async function to execute
|
|
35
|
+
* @returns Result of the callback
|
|
36
|
+
*/
|
|
37
|
+
run(store, callback) {
|
|
38
|
+
return this.storage.run(store, callback);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Enter a new context without a callback
|
|
42
|
+
*
|
|
43
|
+
* Useful for middleware where you want to set context for the rest of the request.
|
|
44
|
+
* Unlike `run()`, this doesn't require a callback.
|
|
45
|
+
*
|
|
46
|
+
* @param store - Context data to set
|
|
47
|
+
*/
|
|
48
|
+
enter(store) {
|
|
49
|
+
this.storage.enterWith(store);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Update the current context
|
|
53
|
+
*
|
|
54
|
+
* Merges new data into existing context, or enters new context if none exists.
|
|
55
|
+
*
|
|
56
|
+
* @param updates - Partial context data to merge
|
|
57
|
+
*/
|
|
58
|
+
update(updates) {
|
|
59
|
+
const current = this.storage.getStore();
|
|
60
|
+
if (current) {
|
|
61
|
+
Object.assign(current, updates);
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
this.enter(updates);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Get the current context store
|
|
69
|
+
*
|
|
70
|
+
* @returns Current context or undefined if not in context
|
|
71
|
+
*/
|
|
72
|
+
getStore() {
|
|
73
|
+
return this.storage.getStore();
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Get a specific value from context
|
|
77
|
+
*
|
|
78
|
+
* @param key - Key to retrieve
|
|
79
|
+
* @returns Value or undefined
|
|
80
|
+
*/
|
|
81
|
+
get(key) {
|
|
82
|
+
return this.storage.getStore()?.[key];
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Set a specific value in context
|
|
86
|
+
*
|
|
87
|
+
* @param key - Key to set
|
|
88
|
+
* @param value - Value to store
|
|
89
|
+
*/
|
|
90
|
+
set(key, value) {
|
|
91
|
+
this.update({ [key]: value });
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Clear the context
|
|
95
|
+
*/
|
|
96
|
+
clear() {
|
|
97
|
+
this.storage.enterWith({});
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Check if currently in a context
|
|
101
|
+
*/
|
|
102
|
+
hasContext() {
|
|
103
|
+
return this.storage.getStore() !== undefined;
|
|
104
|
+
}
|
|
105
|
+
}exports.Context=Context;//# sourceMappingURL=base-context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base-context.js","sources":["../src/base-context.ts"],"sourcesContent":[null],"names":["AsyncLocalStorage"],"mappings":"oDAEA;;;;;;;;;;;;;;;;;;;;;;;AAuBG;MACmB,OAAO,CAAA;AACR,IAAA,OAAO,GAA8B,IAAIA,6BAAiB,EAAU,CAAC;AAExF;;;;;;;;;AASG;IACI,GAAG,CAAI,KAAa,EAAE,QAA0B,EAAA;QACrD,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;KAC1C;AAED;;;;;;;AAOG;AACI,IAAA,KAAK,CAAC,KAAa,EAAA;AACxB,QAAA,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;KAC/B;AAED;;;;;;AAMG;AACI,IAAA,MAAM,CAAC,OAAwB,EAAA;QACpC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;AAExC,QAAA,IAAI,OAAO,EAAE;AACX,YAAA,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;AACjC,SAAA;AAAM,aAAA;AACL,YAAA,IAAI,CAAC,KAAK,CAAC,OAAiB,CAAC,CAAC;AAC/B,SAAA;KACF;AAED;;;;AAIG;IACI,QAAQ,GAAA;AACb,QAAA,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;KAChC;AAED;;;;;AAKG;AACI,IAAA,GAAG,CAAyB,GAAM,EAAA;QACvC,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,GAAG,GAAG,CAAC,CAAC;KACvC;AAED;;;;;AAKG;IACI,GAAG,CAAyB,GAAM,EAAE,KAAgB,EAAA;QACzD,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,GAAG,KAAK,EAAS,CAAC,CAAC;KACtC;AAED;;AAEG;IACI,KAAK,GAAA;AACV,QAAA,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,EAAY,CAAC,CAAC;KACtC;AAED;;AAEG;IACI,UAAU,GAAA;QACf,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,KAAK,SAAS,CAAC;KAC9C;AAYF"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import type { Context } from "./base-context";
|
|
2
|
+
/**
|
|
3
|
+
* Context Manager - Orchestrates multiple contexts together
|
|
4
|
+
*
|
|
5
|
+
* Allows running multiple AsyncLocalStorage contexts in a single operation,
|
|
6
|
+
* making it easy to link request, storage, database, and other contexts.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* // Register contexts
|
|
11
|
+
* contextManager
|
|
12
|
+
* .register('request', requestContext)
|
|
13
|
+
* .register('storage', storageDriverContext)
|
|
14
|
+
* .register('database', databaseDataSourceContext);
|
|
15
|
+
*
|
|
16
|
+
* // Run all contexts together
|
|
17
|
+
* await contextManager.runAll({
|
|
18
|
+
* request: { request, response, user },
|
|
19
|
+
* storage: { driver, metadata: { tenantId: '123' } },
|
|
20
|
+
* database: { dataSource: 'primary' },
|
|
21
|
+
* }, async () => {
|
|
22
|
+
* // All contexts active!
|
|
23
|
+
* await handleRequest();
|
|
24
|
+
* });
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export declare class ContextManager {
|
|
28
|
+
private contexts;
|
|
29
|
+
/**
|
|
30
|
+
* Register a context
|
|
31
|
+
*
|
|
32
|
+
* @param name - Unique context name
|
|
33
|
+
* @param context - Context instance
|
|
34
|
+
* @returns This instance for chaining
|
|
35
|
+
*/
|
|
36
|
+
register(name: string, context: Context<any>): this;
|
|
37
|
+
/**
|
|
38
|
+
* Run all registered contexts together
|
|
39
|
+
*
|
|
40
|
+
* Nests all context.run() calls, ensuring all contexts are active
|
|
41
|
+
* for the duration of the callback.
|
|
42
|
+
*
|
|
43
|
+
* @param stores - Context stores keyed by context name
|
|
44
|
+
* @param callback - Async function to execute
|
|
45
|
+
* @returns Result of the callback
|
|
46
|
+
*/
|
|
47
|
+
runAll<T>(stores: Record<string, any>, callback: () => Promise<T>): Promise<T>;
|
|
48
|
+
/**
|
|
49
|
+
* Enter all contexts at once (for middleware)
|
|
50
|
+
*
|
|
51
|
+
* @param stores - Context stores keyed by context name
|
|
52
|
+
*/
|
|
53
|
+
enterAll(stores: Record<string, any>): void;
|
|
54
|
+
/**
|
|
55
|
+
* Clear all contexts
|
|
56
|
+
*/
|
|
57
|
+
clearAll(): void;
|
|
58
|
+
/**
|
|
59
|
+
* Get a specific registered context
|
|
60
|
+
*
|
|
61
|
+
* @param name - Context name
|
|
62
|
+
* @returns Context instance or undefined
|
|
63
|
+
*/
|
|
64
|
+
getContext<T extends Context<any>>(name: string): T | undefined;
|
|
65
|
+
/**
|
|
66
|
+
* Check if a context is registered
|
|
67
|
+
*
|
|
68
|
+
* @param name - Context name
|
|
69
|
+
* @returns True if context is registered
|
|
70
|
+
*/
|
|
71
|
+
hasContext(name: string): boolean;
|
|
72
|
+
/**
|
|
73
|
+
* Build all context stores by calling each context's buildStore() method
|
|
74
|
+
*
|
|
75
|
+
* This is the immutable pattern - returns a new record of stores.
|
|
76
|
+
* Each context defines its own initialization logic.
|
|
77
|
+
*
|
|
78
|
+
* @param payload - Payload passed to each buildStore() (e.g., { request, response })
|
|
79
|
+
* @returns Record of context name -> store data
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```typescript
|
|
83
|
+
* const httpContextStore = contextManager.buildStores({ request, response });
|
|
84
|
+
* await contextManager.runAll(httpContextStore, async () => { ... });
|
|
85
|
+
* ```
|
|
86
|
+
*/
|
|
87
|
+
buildStores(payload?: Record<string, any>): Record<string, any>;
|
|
88
|
+
/**
|
|
89
|
+
* Unregister a context
|
|
90
|
+
*
|
|
91
|
+
* @param name - Context name to remove
|
|
92
|
+
* @returns True if context was removed
|
|
93
|
+
*/
|
|
94
|
+
unregister(name: string): boolean;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Global context manager instance
|
|
98
|
+
*
|
|
99
|
+
* Use this singleton to register and manage all framework contexts.
|
|
100
|
+
*/
|
|
101
|
+
export declare const contextManager: ContextManager;
|
|
102
|
+
//# sourceMappingURL=context-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-manager.d.ts","sourceRoot":"","sources":["../src/context-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAE9C;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAmC;IAEnD;;;;;;OAMG;IACI,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI;IAK1D;;;;;;;;;OASG;IACU,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAW3F;;;;OAIG;IACI,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IAQlD;;OAEG;IACI,QAAQ,IAAI,IAAI;IAMvB;;;;;OAKG;IACI,UAAU,CAAC,CAAC,SAAS,OAAO,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS;IAItE;;;;;OAKG;IACI,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAIxC;;;;;;;;;;;;;;OAcG;IACI,WAAW,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IAUtE;;;;;OAKG;IACI,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;CAGzC;AAED;;;;GAIG;AACH,eAAO,MAAM,cAAc,gBAAuB,CAAC"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
'use strict';/**
|
|
2
|
+
* Context Manager - Orchestrates multiple contexts together
|
|
3
|
+
*
|
|
4
|
+
* Allows running multiple AsyncLocalStorage contexts in a single operation,
|
|
5
|
+
* making it easy to link request, storage, database, and other contexts.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* // Register contexts
|
|
10
|
+
* contextManager
|
|
11
|
+
* .register('request', requestContext)
|
|
12
|
+
* .register('storage', storageDriverContext)
|
|
13
|
+
* .register('database', databaseDataSourceContext);
|
|
14
|
+
*
|
|
15
|
+
* // Run all contexts together
|
|
16
|
+
* await contextManager.runAll({
|
|
17
|
+
* request: { request, response, user },
|
|
18
|
+
* storage: { driver, metadata: { tenantId: '123' } },
|
|
19
|
+
* database: { dataSource: 'primary' },
|
|
20
|
+
* }, async () => {
|
|
21
|
+
* // All contexts active!
|
|
22
|
+
* await handleRequest();
|
|
23
|
+
* });
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
class ContextManager {
|
|
27
|
+
contexts = new Map();
|
|
28
|
+
/**
|
|
29
|
+
* Register a context
|
|
30
|
+
*
|
|
31
|
+
* @param name - Unique context name
|
|
32
|
+
* @param context - Context instance
|
|
33
|
+
* @returns This instance for chaining
|
|
34
|
+
*/
|
|
35
|
+
register(name, context) {
|
|
36
|
+
this.contexts.set(name, context);
|
|
37
|
+
return this;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Run all registered contexts together
|
|
41
|
+
*
|
|
42
|
+
* Nests all context.run() calls, ensuring all contexts are active
|
|
43
|
+
* for the duration of the callback.
|
|
44
|
+
*
|
|
45
|
+
* @param stores - Context stores keyed by context name
|
|
46
|
+
* @param callback - Async function to execute
|
|
47
|
+
* @returns Result of the callback
|
|
48
|
+
*/
|
|
49
|
+
async runAll(stores, callback) {
|
|
50
|
+
const entries = Array.from(this.contexts.entries());
|
|
51
|
+
// Build nested context runners
|
|
52
|
+
const runner = entries.reduceRight((next, [name, context]) => {
|
|
53
|
+
return () => context.run(stores[name] || {}, next);
|
|
54
|
+
}, callback);
|
|
55
|
+
return runner();
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Enter all contexts at once (for middleware)
|
|
59
|
+
*
|
|
60
|
+
* @param stores - Context stores keyed by context name
|
|
61
|
+
*/
|
|
62
|
+
enterAll(stores) {
|
|
63
|
+
for (const [name, context] of this.contexts.entries()) {
|
|
64
|
+
if (stores[name]) {
|
|
65
|
+
context.enter(stores[name]);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Clear all contexts
|
|
71
|
+
*/
|
|
72
|
+
clearAll() {
|
|
73
|
+
for (const context of this.contexts.values()) {
|
|
74
|
+
context.clear();
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Get a specific registered context
|
|
79
|
+
*
|
|
80
|
+
* @param name - Context name
|
|
81
|
+
* @returns Context instance or undefined
|
|
82
|
+
*/
|
|
83
|
+
getContext(name) {
|
|
84
|
+
return this.contexts.get(name);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Check if a context is registered
|
|
88
|
+
*
|
|
89
|
+
* @param name - Context name
|
|
90
|
+
* @returns True if context is registered
|
|
91
|
+
*/
|
|
92
|
+
hasContext(name) {
|
|
93
|
+
return this.contexts.has(name);
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Build all context stores by calling each context's buildStore() method
|
|
97
|
+
*
|
|
98
|
+
* This is the immutable pattern - returns a new record of stores.
|
|
99
|
+
* Each context defines its own initialization logic.
|
|
100
|
+
*
|
|
101
|
+
* @param payload - Payload passed to each buildStore() (e.g., { request, response })
|
|
102
|
+
* @returns Record of context name -> store data
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* ```typescript
|
|
106
|
+
* const httpContextStore = contextManager.buildStores({ request, response });
|
|
107
|
+
* await contextManager.runAll(httpContextStore, async () => { ... });
|
|
108
|
+
* ```
|
|
109
|
+
*/
|
|
110
|
+
buildStores(payload) {
|
|
111
|
+
const stores = {};
|
|
112
|
+
for (const [name, context] of this.contexts.entries()) {
|
|
113
|
+
stores[name] = context.buildStore(payload) ?? {};
|
|
114
|
+
}
|
|
115
|
+
return stores;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Unregister a context
|
|
119
|
+
*
|
|
120
|
+
* @param name - Context name to remove
|
|
121
|
+
* @returns True if context was removed
|
|
122
|
+
*/
|
|
123
|
+
unregister(name) {
|
|
124
|
+
return this.contexts.delete(name);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Global context manager instance
|
|
129
|
+
*
|
|
130
|
+
* Use this singleton to register and manage all framework contexts.
|
|
131
|
+
*/
|
|
132
|
+
const contextManager = new ContextManager();exports.ContextManager=ContextManager;exports.contextManager=contextManager;//# sourceMappingURL=context-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-manager.js","sources":["../src/context-manager.ts"],"sourcesContent":[null],"names":[],"mappings":"aAEA;;;;;;;;;;;;;;;;;;;;;;;;AAwBG;MACU,cAAc,CAAA;AACjB,IAAA,QAAQ,GAAG,IAAI,GAAG,EAAwB,CAAC;AAEnD;;;;;;AAMG;IACI,QAAQ,CAAC,IAAY,EAAE,OAAqB,EAAA;QACjD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AACjC,QAAA,OAAO,IAAI,CAAC;KACb;AAED;;;;;;;;;AASG;AACI,IAAA,MAAM,MAAM,CAAI,MAA2B,EAAE,QAA0B,EAAA;AAC5E,QAAA,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;;AAGpD,QAAA,MAAM,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,KAAI;AAC3D,YAAA,OAAO,MAAM,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,IAAI,CAAC,CAAC;SACpD,EAAE,QAAQ,CAAC,CAAC;QAEb,OAAO,MAAM,EAAE,CAAC;KACjB;AAED;;;;AAIG;AACI,IAAA,QAAQ,CAAC,MAA2B,EAAA;AACzC,QAAA,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE;AACrD,YAAA,IAAI,MAAM,CAAC,IAAI,CAAC,EAAE;gBAChB,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;AAC7B,aAAA;AACF,SAAA;KACF;AAED;;AAEG;IACI,QAAQ,GAAA;QACb,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE;YAC5C,OAAO,CAAC,KAAK,EAAE,CAAC;AACjB,SAAA;KACF;AAED;;;;;AAKG;AACI,IAAA,UAAU,CAAyB,IAAY,EAAA;QACpD,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAkB,CAAC;KACjD;AAED;;;;;AAKG;AACI,IAAA,UAAU,CAAC,IAAY,EAAA;QAC5B,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;KAChC;AAED;;;;;;;;;;;;;;AAcG;AACI,IAAA,WAAW,CAAC,OAA6B,EAAA;QAC9C,MAAM,MAAM,GAAwB,EAAE,CAAC;AAEvC,QAAA,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE;AACrD,YAAA,MAAM,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;AAClD,SAAA;AAED,QAAA,OAAO,MAAM,CAAC;KACf;AAED;;;;;AAKG;AACI,IAAA,UAAU,CAAC,IAAY,EAAA;QAC5B,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;KACnC;AACF,CAAA;AAED;;;;AAIG;AACU,MAAA,cAAc,GAAG,IAAI,cAAc"}
|
package/cjs/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC"}
|
package/cjs/index.js
CHANGED
|
@@ -1,21 +1 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var baseContext = require('./base-context');
|
|
4
|
-
var contextManager = require('./context-manager');
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
Object.keys(baseContext).forEach(function (k) {
|
|
9
|
-
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
|
10
|
-
enumerable: true,
|
|
11
|
-
get: function () { return baseContext[k]; }
|
|
12
|
-
});
|
|
13
|
-
});
|
|
14
|
-
Object.keys(contextManager).forEach(function (k) {
|
|
15
|
-
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
|
16
|
-
enumerable: true,
|
|
17
|
-
get: function () { return contextManager[k]; }
|
|
18
|
-
});
|
|
19
|
-
});
|
|
20
|
-
//# sourceMappingURL=index.js.map
|
|
21
|
-
//# sourceMappingURL=index.js.map
|
|
1
|
+
'use strict';var baseContext=require('./base-context.js'),contextManager=require('./context-manager.js');exports.Context=baseContext.Context;exports.ContextManager=contextManager.ContextManager;exports.contextManager=contextManager.contextManager;//# sourceMappingURL=index.js.map
|
package/cjs/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { AsyncLocalStorage } from "async_hooks";
|
|
3
|
+
/**
|
|
4
|
+
* Base class for all AsyncLocalStorage-based contexts
|
|
5
|
+
*
|
|
6
|
+
* Provides a consistent API for managing context across async operations.
|
|
7
|
+
* All framework contexts (request, storage, database) extend this class.
|
|
8
|
+
*
|
|
9
|
+
* @template TStore - The type of data stored in context
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* interface MyContextStore {
|
|
14
|
+
* userId: string;
|
|
15
|
+
* tenant: string;
|
|
16
|
+
* }
|
|
17
|
+
*
|
|
18
|
+
* class MyContext extends Context<MyContextStore> {}
|
|
19
|
+
* const myContext = new MyContext();
|
|
20
|
+
*
|
|
21
|
+
* // Use it
|
|
22
|
+
* await myContext.run({ userId: '123', tenant: 'acme' }, async () => {
|
|
23
|
+
* const userId = myContext.get('userId'); // '123'
|
|
24
|
+
* });
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export declare abstract class Context<TStore extends Record<string, any>> {
|
|
28
|
+
protected readonly storage: AsyncLocalStorage<TStore>;
|
|
29
|
+
/**
|
|
30
|
+
* Run a callback within a new context
|
|
31
|
+
*
|
|
32
|
+
* Creates a new async context with the provided store data.
|
|
33
|
+
* All operations within the callback will have access to this context.
|
|
34
|
+
*
|
|
35
|
+
* @param store - Initial context data
|
|
36
|
+
* @param callback - Async function to execute
|
|
37
|
+
* @returns Result of the callback
|
|
38
|
+
*/
|
|
39
|
+
run<T>(store: TStore, callback: () => Promise<T>): Promise<T>;
|
|
40
|
+
/**
|
|
41
|
+
* Enter a new context without a callback
|
|
42
|
+
*
|
|
43
|
+
* Useful for middleware where you want to set context for the rest of the request.
|
|
44
|
+
* Unlike `run()`, this doesn't require a callback.
|
|
45
|
+
*
|
|
46
|
+
* @param store - Context data to set
|
|
47
|
+
*/
|
|
48
|
+
enter(store: TStore): void;
|
|
49
|
+
/**
|
|
50
|
+
* Update the current context
|
|
51
|
+
*
|
|
52
|
+
* Merges new data into existing context, or enters new context if none exists.
|
|
53
|
+
*
|
|
54
|
+
* @param updates - Partial context data to merge
|
|
55
|
+
*/
|
|
56
|
+
update(updates: Partial<TStore>): void;
|
|
57
|
+
/**
|
|
58
|
+
* Get the current context store
|
|
59
|
+
*
|
|
60
|
+
* @returns Current context or undefined if not in context
|
|
61
|
+
*/
|
|
62
|
+
getStore(): TStore | undefined;
|
|
63
|
+
/**
|
|
64
|
+
* Get a specific value from context
|
|
65
|
+
*
|
|
66
|
+
* @param key - Key to retrieve
|
|
67
|
+
* @returns Value or undefined
|
|
68
|
+
*/
|
|
69
|
+
get<K extends keyof TStore>(key: K): TStore[K] | undefined;
|
|
70
|
+
/**
|
|
71
|
+
* Set a specific value in context
|
|
72
|
+
*
|
|
73
|
+
* @param key - Key to set
|
|
74
|
+
* @param value - Value to store
|
|
75
|
+
*/
|
|
76
|
+
set<K extends keyof TStore>(key: K, value: TStore[K]): void;
|
|
77
|
+
/**
|
|
78
|
+
* Clear the context
|
|
79
|
+
*/
|
|
80
|
+
clear(): void;
|
|
81
|
+
/**
|
|
82
|
+
* Check if currently in a context
|
|
83
|
+
*/
|
|
84
|
+
hasContext(): boolean;
|
|
85
|
+
/**
|
|
86
|
+
* Build the initial store for this context
|
|
87
|
+
*
|
|
88
|
+
* Override this method to provide custom initialization logic.
|
|
89
|
+
* Called by ContextManager.buildStores() for each registered context.
|
|
90
|
+
*
|
|
91
|
+
* @param payload - Generic payload (e.g., { request, response } for HTTP contexts)
|
|
92
|
+
* @returns Initial store data
|
|
93
|
+
*/
|
|
94
|
+
abstract buildStore(payload?: Record<string, any>): TStore;
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=base-context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base-context.d.ts","sourceRoot":"","sources":["../src/base-context.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEhD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,8BAAsB,OAAO,CAAC,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IAC9D,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAmC;IAExF;;;;;;;;;OASG;IACI,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAIpE;;;;;;;OAOG;IACI,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAIjC;;;;;;OAMG;IACI,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,GAAG,IAAI;IAU7C;;;;OAIG;IACI,QAAQ,IAAI,MAAM,GAAG,SAAS;IAIrC;;;;;OAKG;IACI,GAAG,CAAC,CAAC,SAAS,MAAM,MAAM,EAAE,GAAG,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,SAAS;IAIjE;;;;;OAKG;IACI,GAAG,CAAC,CAAC,SAAS,MAAM,MAAM,EAAE,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI;IAIlE;;OAEG;IACI,KAAK,IAAI,IAAI;IAIpB;;OAEG;IACI,UAAU,IAAI,OAAO;IAI5B;;;;;;;;OAQG;aACa,UAAU,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM;CAClE"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import {AsyncLocalStorage}from'async_hooks';/**
|
|
2
|
+
* Base class for all AsyncLocalStorage-based contexts
|
|
3
|
+
*
|
|
4
|
+
* Provides a consistent API for managing context across async operations.
|
|
5
|
+
* All framework contexts (request, storage, database) extend this class.
|
|
6
|
+
*
|
|
7
|
+
* @template TStore - The type of data stored in context
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* interface MyContextStore {
|
|
12
|
+
* userId: string;
|
|
13
|
+
* tenant: string;
|
|
14
|
+
* }
|
|
15
|
+
*
|
|
16
|
+
* class MyContext extends Context<MyContextStore> {}
|
|
17
|
+
* const myContext = new MyContext();
|
|
18
|
+
*
|
|
19
|
+
* // Use it
|
|
20
|
+
* await myContext.run({ userId: '123', tenant: 'acme' }, async () => {
|
|
21
|
+
* const userId = myContext.get('userId'); // '123'
|
|
22
|
+
* });
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
class Context {
|
|
26
|
+
storage = new AsyncLocalStorage();
|
|
27
|
+
/**
|
|
28
|
+
* Run a callback within a new context
|
|
29
|
+
*
|
|
30
|
+
* Creates a new async context with the provided store data.
|
|
31
|
+
* All operations within the callback will have access to this context.
|
|
32
|
+
*
|
|
33
|
+
* @param store - Initial context data
|
|
34
|
+
* @param callback - Async function to execute
|
|
35
|
+
* @returns Result of the callback
|
|
36
|
+
*/
|
|
37
|
+
run(store, callback) {
|
|
38
|
+
return this.storage.run(store, callback);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Enter a new context without a callback
|
|
42
|
+
*
|
|
43
|
+
* Useful for middleware where you want to set context for the rest of the request.
|
|
44
|
+
* Unlike `run()`, this doesn't require a callback.
|
|
45
|
+
*
|
|
46
|
+
* @param store - Context data to set
|
|
47
|
+
*/
|
|
48
|
+
enter(store) {
|
|
49
|
+
this.storage.enterWith(store);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Update the current context
|
|
53
|
+
*
|
|
54
|
+
* Merges new data into existing context, or enters new context if none exists.
|
|
55
|
+
*
|
|
56
|
+
* @param updates - Partial context data to merge
|
|
57
|
+
*/
|
|
58
|
+
update(updates) {
|
|
59
|
+
const current = this.storage.getStore();
|
|
60
|
+
if (current) {
|
|
61
|
+
Object.assign(current, updates);
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
this.enter(updates);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Get the current context store
|
|
69
|
+
*
|
|
70
|
+
* @returns Current context or undefined if not in context
|
|
71
|
+
*/
|
|
72
|
+
getStore() {
|
|
73
|
+
return this.storage.getStore();
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Get a specific value from context
|
|
77
|
+
*
|
|
78
|
+
* @param key - Key to retrieve
|
|
79
|
+
* @returns Value or undefined
|
|
80
|
+
*/
|
|
81
|
+
get(key) {
|
|
82
|
+
return this.storage.getStore()?.[key];
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Set a specific value in context
|
|
86
|
+
*
|
|
87
|
+
* @param key - Key to set
|
|
88
|
+
* @param value - Value to store
|
|
89
|
+
*/
|
|
90
|
+
set(key, value) {
|
|
91
|
+
this.update({ [key]: value });
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Clear the context
|
|
95
|
+
*/
|
|
96
|
+
clear() {
|
|
97
|
+
this.storage.enterWith({});
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Check if currently in a context
|
|
101
|
+
*/
|
|
102
|
+
hasContext() {
|
|
103
|
+
return this.storage.getStore() !== undefined;
|
|
104
|
+
}
|
|
105
|
+
}export{Context};//# sourceMappingURL=base-context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base-context.js","sources":["../src/base-context.ts"],"sourcesContent":[null],"names":[],"mappings":"4CAEA;;;;;;;;;;;;;;;;;;;;;;;AAuBG;MACmB,OAAO,CAAA;AACR,IAAA,OAAO,GAA8B,IAAI,iBAAiB,EAAU,CAAC;AAExF;;;;;;;;;AASG;IACI,GAAG,CAAI,KAAa,EAAE,QAA0B,EAAA;QACrD,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;KAC1C;AAED;;;;;;;AAOG;AACI,IAAA,KAAK,CAAC,KAAa,EAAA;AACxB,QAAA,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;KAC/B;AAED;;;;;;AAMG;AACI,IAAA,MAAM,CAAC,OAAwB,EAAA;QACpC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;AAExC,QAAA,IAAI,OAAO,EAAE;AACX,YAAA,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;AACjC,SAAA;AAAM,aAAA;AACL,YAAA,IAAI,CAAC,KAAK,CAAC,OAAiB,CAAC,CAAC;AAC/B,SAAA;KACF;AAED;;;;AAIG;IACI,QAAQ,GAAA;AACb,QAAA,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;KAChC;AAED;;;;;AAKG;AACI,IAAA,GAAG,CAAyB,GAAM,EAAA;QACvC,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,GAAG,GAAG,CAAC,CAAC;KACvC;AAED;;;;;AAKG;IACI,GAAG,CAAyB,GAAM,EAAE,KAAgB,EAAA;QACzD,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,GAAG,KAAK,EAAS,CAAC,CAAC;KACtC;AAED;;AAEG;IACI,KAAK,GAAA;AACV,QAAA,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,EAAY,CAAC,CAAC;KACtC;AAED;;AAEG;IACI,UAAU,GAAA;QACf,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,KAAK,SAAS,CAAC;KAC9C;AAYF"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import type { Context } from "./base-context";
|
|
2
|
+
/**
|
|
3
|
+
* Context Manager - Orchestrates multiple contexts together
|
|
4
|
+
*
|
|
5
|
+
* Allows running multiple AsyncLocalStorage contexts in a single operation,
|
|
6
|
+
* making it easy to link request, storage, database, and other contexts.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* // Register contexts
|
|
11
|
+
* contextManager
|
|
12
|
+
* .register('request', requestContext)
|
|
13
|
+
* .register('storage', storageDriverContext)
|
|
14
|
+
* .register('database', databaseDataSourceContext);
|
|
15
|
+
*
|
|
16
|
+
* // Run all contexts together
|
|
17
|
+
* await contextManager.runAll({
|
|
18
|
+
* request: { request, response, user },
|
|
19
|
+
* storage: { driver, metadata: { tenantId: '123' } },
|
|
20
|
+
* database: { dataSource: 'primary' },
|
|
21
|
+
* }, async () => {
|
|
22
|
+
* // All contexts active!
|
|
23
|
+
* await handleRequest();
|
|
24
|
+
* });
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export declare class ContextManager {
|
|
28
|
+
private contexts;
|
|
29
|
+
/**
|
|
30
|
+
* Register a context
|
|
31
|
+
*
|
|
32
|
+
* @param name - Unique context name
|
|
33
|
+
* @param context - Context instance
|
|
34
|
+
* @returns This instance for chaining
|
|
35
|
+
*/
|
|
36
|
+
register(name: string, context: Context<any>): this;
|
|
37
|
+
/**
|
|
38
|
+
* Run all registered contexts together
|
|
39
|
+
*
|
|
40
|
+
* Nests all context.run() calls, ensuring all contexts are active
|
|
41
|
+
* for the duration of the callback.
|
|
42
|
+
*
|
|
43
|
+
* @param stores - Context stores keyed by context name
|
|
44
|
+
* @param callback - Async function to execute
|
|
45
|
+
* @returns Result of the callback
|
|
46
|
+
*/
|
|
47
|
+
runAll<T>(stores: Record<string, any>, callback: () => Promise<T>): Promise<T>;
|
|
48
|
+
/**
|
|
49
|
+
* Enter all contexts at once (for middleware)
|
|
50
|
+
*
|
|
51
|
+
* @param stores - Context stores keyed by context name
|
|
52
|
+
*/
|
|
53
|
+
enterAll(stores: Record<string, any>): void;
|
|
54
|
+
/**
|
|
55
|
+
* Clear all contexts
|
|
56
|
+
*/
|
|
57
|
+
clearAll(): void;
|
|
58
|
+
/**
|
|
59
|
+
* Get a specific registered context
|
|
60
|
+
*
|
|
61
|
+
* @param name - Context name
|
|
62
|
+
* @returns Context instance or undefined
|
|
63
|
+
*/
|
|
64
|
+
getContext<T extends Context<any>>(name: string): T | undefined;
|
|
65
|
+
/**
|
|
66
|
+
* Check if a context is registered
|
|
67
|
+
*
|
|
68
|
+
* @param name - Context name
|
|
69
|
+
* @returns True if context is registered
|
|
70
|
+
*/
|
|
71
|
+
hasContext(name: string): boolean;
|
|
72
|
+
/**
|
|
73
|
+
* Build all context stores by calling each context's buildStore() method
|
|
74
|
+
*
|
|
75
|
+
* This is the immutable pattern - returns a new record of stores.
|
|
76
|
+
* Each context defines its own initialization logic.
|
|
77
|
+
*
|
|
78
|
+
* @param payload - Payload passed to each buildStore() (e.g., { request, response })
|
|
79
|
+
* @returns Record of context name -> store data
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```typescript
|
|
83
|
+
* const httpContextStore = contextManager.buildStores({ request, response });
|
|
84
|
+
* await contextManager.runAll(httpContextStore, async () => { ... });
|
|
85
|
+
* ```
|
|
86
|
+
*/
|
|
87
|
+
buildStores(payload?: Record<string, any>): Record<string, any>;
|
|
88
|
+
/**
|
|
89
|
+
* Unregister a context
|
|
90
|
+
*
|
|
91
|
+
* @param name - Context name to remove
|
|
92
|
+
* @returns True if context was removed
|
|
93
|
+
*/
|
|
94
|
+
unregister(name: string): boolean;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Global context manager instance
|
|
98
|
+
*
|
|
99
|
+
* Use this singleton to register and manage all framework contexts.
|
|
100
|
+
*/
|
|
101
|
+
export declare const contextManager: ContextManager;
|
|
102
|
+
//# sourceMappingURL=context-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-manager.d.ts","sourceRoot":"","sources":["../src/context-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAE9C;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAmC;IAEnD;;;;;;OAMG;IACI,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI;IAK1D;;;;;;;;;OASG;IACU,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAW3F;;;;OAIG;IACI,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IAQlD;;OAEG;IACI,QAAQ,IAAI,IAAI;IAMvB;;;;;OAKG;IACI,UAAU,CAAC,CAAC,SAAS,OAAO,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS;IAItE;;;;;OAKG;IACI,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAIxC;;;;;;;;;;;;;;OAcG;IACI,WAAW,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IAUtE;;;;;OAKG;IACI,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;CAGzC;AAED;;;;GAIG;AACH,eAAO,MAAM,cAAc,gBAAuB,CAAC"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Context Manager - Orchestrates multiple contexts together
|
|
3
|
+
*
|
|
4
|
+
* Allows running multiple AsyncLocalStorage contexts in a single operation,
|
|
5
|
+
* making it easy to link request, storage, database, and other contexts.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* // Register contexts
|
|
10
|
+
* contextManager
|
|
11
|
+
* .register('request', requestContext)
|
|
12
|
+
* .register('storage', storageDriverContext)
|
|
13
|
+
* .register('database', databaseDataSourceContext);
|
|
14
|
+
*
|
|
15
|
+
* // Run all contexts together
|
|
16
|
+
* await contextManager.runAll({
|
|
17
|
+
* request: { request, response, user },
|
|
18
|
+
* storage: { driver, metadata: { tenantId: '123' } },
|
|
19
|
+
* database: { dataSource: 'primary' },
|
|
20
|
+
* }, async () => {
|
|
21
|
+
* // All contexts active!
|
|
22
|
+
* await handleRequest();
|
|
23
|
+
* });
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
class ContextManager {
|
|
27
|
+
contexts = new Map();
|
|
28
|
+
/**
|
|
29
|
+
* Register a context
|
|
30
|
+
*
|
|
31
|
+
* @param name - Unique context name
|
|
32
|
+
* @param context - Context instance
|
|
33
|
+
* @returns This instance for chaining
|
|
34
|
+
*/
|
|
35
|
+
register(name, context) {
|
|
36
|
+
this.contexts.set(name, context);
|
|
37
|
+
return this;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Run all registered contexts together
|
|
41
|
+
*
|
|
42
|
+
* Nests all context.run() calls, ensuring all contexts are active
|
|
43
|
+
* for the duration of the callback.
|
|
44
|
+
*
|
|
45
|
+
* @param stores - Context stores keyed by context name
|
|
46
|
+
* @param callback - Async function to execute
|
|
47
|
+
* @returns Result of the callback
|
|
48
|
+
*/
|
|
49
|
+
async runAll(stores, callback) {
|
|
50
|
+
const entries = Array.from(this.contexts.entries());
|
|
51
|
+
// Build nested context runners
|
|
52
|
+
const runner = entries.reduceRight((next, [name, context]) => {
|
|
53
|
+
return () => context.run(stores[name] || {}, next);
|
|
54
|
+
}, callback);
|
|
55
|
+
return runner();
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Enter all contexts at once (for middleware)
|
|
59
|
+
*
|
|
60
|
+
* @param stores - Context stores keyed by context name
|
|
61
|
+
*/
|
|
62
|
+
enterAll(stores) {
|
|
63
|
+
for (const [name, context] of this.contexts.entries()) {
|
|
64
|
+
if (stores[name]) {
|
|
65
|
+
context.enter(stores[name]);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Clear all contexts
|
|
71
|
+
*/
|
|
72
|
+
clearAll() {
|
|
73
|
+
for (const context of this.contexts.values()) {
|
|
74
|
+
context.clear();
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Get a specific registered context
|
|
79
|
+
*
|
|
80
|
+
* @param name - Context name
|
|
81
|
+
* @returns Context instance or undefined
|
|
82
|
+
*/
|
|
83
|
+
getContext(name) {
|
|
84
|
+
return this.contexts.get(name);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Check if a context is registered
|
|
88
|
+
*
|
|
89
|
+
* @param name - Context name
|
|
90
|
+
* @returns True if context is registered
|
|
91
|
+
*/
|
|
92
|
+
hasContext(name) {
|
|
93
|
+
return this.contexts.has(name);
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Build all context stores by calling each context's buildStore() method
|
|
97
|
+
*
|
|
98
|
+
* This is the immutable pattern - returns a new record of stores.
|
|
99
|
+
* Each context defines its own initialization logic.
|
|
100
|
+
*
|
|
101
|
+
* @param payload - Payload passed to each buildStore() (e.g., { request, response })
|
|
102
|
+
* @returns Record of context name -> store data
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* ```typescript
|
|
106
|
+
* const httpContextStore = contextManager.buildStores({ request, response });
|
|
107
|
+
* await contextManager.runAll(httpContextStore, async () => { ... });
|
|
108
|
+
* ```
|
|
109
|
+
*/
|
|
110
|
+
buildStores(payload) {
|
|
111
|
+
const stores = {};
|
|
112
|
+
for (const [name, context] of this.contexts.entries()) {
|
|
113
|
+
stores[name] = context.buildStore(payload) ?? {};
|
|
114
|
+
}
|
|
115
|
+
return stores;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Unregister a context
|
|
119
|
+
*
|
|
120
|
+
* @param name - Context name to remove
|
|
121
|
+
* @returns True if context was removed
|
|
122
|
+
*/
|
|
123
|
+
unregister(name) {
|
|
124
|
+
return this.contexts.delete(name);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Global context manager instance
|
|
129
|
+
*
|
|
130
|
+
* Use this singleton to register and manage all framework contexts.
|
|
131
|
+
*/
|
|
132
|
+
const contextManager = new ContextManager();export{ContextManager,contextManager};//# sourceMappingURL=context-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-manager.js","sources":["../src/context-manager.ts"],"sourcesContent":[null],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;AAwBG;MACU,cAAc,CAAA;AACjB,IAAA,QAAQ,GAAG,IAAI,GAAG,EAAwB,CAAC;AAEnD;;;;;;AAMG;IACI,QAAQ,CAAC,IAAY,EAAE,OAAqB,EAAA;QACjD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AACjC,QAAA,OAAO,IAAI,CAAC;KACb;AAED;;;;;;;;;AASG;AACI,IAAA,MAAM,MAAM,CAAI,MAA2B,EAAE,QAA0B,EAAA;AAC5E,QAAA,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;;AAGpD,QAAA,MAAM,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,KAAI;AAC3D,YAAA,OAAO,MAAM,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,IAAI,CAAC,CAAC;SACpD,EAAE,QAAQ,CAAC,CAAC;QAEb,OAAO,MAAM,EAAE,CAAC;KACjB;AAED;;;;AAIG;AACI,IAAA,QAAQ,CAAC,MAA2B,EAAA;AACzC,QAAA,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE;AACrD,YAAA,IAAI,MAAM,CAAC,IAAI,CAAC,EAAE;gBAChB,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;AAC7B,aAAA;AACF,SAAA;KACF;AAED;;AAEG;IACI,QAAQ,GAAA;QACb,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE;YAC5C,OAAO,CAAC,KAAK,EAAE,CAAC;AACjB,SAAA;KACF;AAED;;;;;AAKG;AACI,IAAA,UAAU,CAAyB,IAAY,EAAA;QACpD,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAkB,CAAC;KACjD;AAED;;;;;AAKG;AACI,IAAA,UAAU,CAAC,IAAY,EAAA;QAC5B,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;KAChC;AAED;;;;;;;;;;;;;;AAcG;AACI,IAAA,WAAW,CAAC,OAA6B,EAAA;QAC9C,MAAM,MAAM,GAAwB,EAAE,CAAC;AAEvC,QAAA,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE;AACrD,YAAA,MAAM,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;AAClD,SAAA;AAED,QAAA,OAAO,MAAM,CAAC;KACf;AAED;;;;;AAKG;AACI,IAAA,UAAU,CAAC,IAAY,EAAA;QAC5B,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;KACnC;AACF,CAAA;AAED;;;;AAIG;AACU,MAAA,cAAc,GAAG,IAAI,cAAc"}
|
package/esm/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC"}
|
package/esm/index.js
CHANGED
|
@@ -1,4 +1 @@
|
|
|
1
|
-
export
|
|
2
|
-
export * from './context-manager';
|
|
3
|
-
//# sourceMappingURL=index.js.map
|
|
4
|
-
//# sourceMappingURL=index.js.map
|
|
1
|
+
export{Context}from'./base-context.js';export{ContextManager,contextManager}from'./context-manager.js';//# sourceMappingURL=index.js.map
|
package/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
package/package.json
CHANGED
|
@@ -1,45 +1,32 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
"
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
"default": "./esm/index.js"
|
|
33
|
-
},
|
|
34
|
-
"require": {
|
|
35
|
-
"types": "./cjs/index.d.ts",
|
|
36
|
-
"default": "./cjs/index.js"
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
},
|
|
40
|
-
"type": "module",
|
|
41
|
-
"sideEffects": false,
|
|
42
|
-
"engines": {
|
|
43
|
-
"node": ">=18.0.0"
|
|
44
|
-
}
|
|
2
|
+
"name": "@warlock.js/context",
|
|
3
|
+
"version": "4.0.57",
|
|
4
|
+
"description": "A simple and unified way to share context using AsyncLocalStorage for the Warlock.js framework",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"warlock",
|
|
7
|
+
"warlockjs",
|
|
8
|
+
"context",
|
|
9
|
+
"async-local-storage",
|
|
10
|
+
"asynclocalstorage",
|
|
11
|
+
"async-context",
|
|
12
|
+
"request-context",
|
|
13
|
+
"nodejs"
|
|
14
|
+
],
|
|
15
|
+
"author": "hassanzohdy",
|
|
16
|
+
"license": "MIT",
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "git+https://github.com/warlockjs/context.git"
|
|
20
|
+
},
|
|
21
|
+
"bugs": {
|
|
22
|
+
"url": "https://github.com/warlockjs/context/issues"
|
|
23
|
+
},
|
|
24
|
+
"homepage": "https://github.com/warlockjs/context#readme",
|
|
25
|
+
"engines": {
|
|
26
|
+
"node": ">=18.0.0"
|
|
27
|
+
},
|
|
28
|
+
"type": "module",
|
|
29
|
+
"module": "./esm/index.js",
|
|
30
|
+
"main": "./esm/index.js",
|
|
31
|
+
"typings": "./esm/index.d.ts"
|
|
45
32
|
}
|