@webpieces/core-context 0.1.0

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 ADDED
@@ -0,0 +1,19 @@
1
+ # @webpieces/core-context
2
+
3
+ > AsyncLocalStorage-based context management for request-scoped data
4
+
5
+ Part of the [WebPieces TypeScript](https://github.com/deanhiller/webpieces-ts) framework.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install @webpieces/core-context
11
+ ```
12
+
13
+ ## Documentation
14
+
15
+ See the main [WebPieces README](https://github.com/deanhiller/webpieces-ts#readme) for complete documentation and examples.
16
+
17
+ ## License
18
+
19
+ Apache-2.0
package/package.json ADDED
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "@webpieces/core-context",
3
+ "version": "0.1.0",
4
+ "description": "AsyncLocalStorage-based context management for request-scoped data",
5
+ "type": "commonjs",
6
+ "main": "./src/index.js",
7
+ "types": "./src/index.d.ts",
8
+ "author": "Dean Hiller",
9
+ "license": "Apache-2.0",
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "https://github.com/deanhiller/webpieces-ts.git",
13
+ "directory": "packages/core/core-context"
14
+ },
15
+ "keywords": [
16
+ "webpieces",
17
+ "context",
18
+ "async",
19
+ "request-scoped"
20
+ ],
21
+ "publishConfig": {
22
+ "access": "public"
23
+ }
24
+ }
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Context management using AsyncLocalStorage.
3
+ * Similar to Java WebPieces Context class that uses ThreadLocal.
4
+ *
5
+ * This allows storing request-scoped data that is automatically available
6
+ * throughout the async call chain, similar to MDC (Mapped Diagnostic Context).
7
+ *
8
+ * Example usage:
9
+ * ```typescript
10
+ * Context.put('REQUEST_ID', '12345');
11
+ * await someAsyncOperation();
12
+ * const id = Context.get('REQUEST_ID'); // Still available!
13
+ * ```
14
+ */
15
+ declare class ContextManager {
16
+ private storage;
17
+ constructor();
18
+ /**
19
+ * Run a function with a new context.
20
+ * This is typically called at the beginning of a request.
21
+ */
22
+ run<T>(fn: () => T): T;
23
+ /**
24
+ * Run a function with a specific context.
25
+ */
26
+ runWithContext<T>(context: Map<string, any>, fn: () => T): T;
27
+ /**
28
+ * Store a value in the current context.
29
+ */
30
+ put(key: string, value: any): void;
31
+ /**
32
+ * Retrieve a value from the current context.
33
+ */
34
+ get<T = any>(key: string): T | undefined;
35
+ /**
36
+ * Remove a value from the current context.
37
+ */
38
+ remove(key: string): void;
39
+ /**
40
+ * Clear all values from the current context.
41
+ */
42
+ clear(): void;
43
+ /**
44
+ * Copy the current context to a new Map.
45
+ * Used by XPromise to preserve context across async boundaries.
46
+ */
47
+ copyContext(): Map<string, any>;
48
+ /**
49
+ * Set the entire context from a Map.
50
+ * Used by XPromise to restore context.
51
+ */
52
+ setContext(context: Map<string, any>): void;
53
+ /**
54
+ * Get all context entries.
55
+ */
56
+ getAll(): Map<string, any>;
57
+ /**
58
+ * Check if a key exists in the context.
59
+ */
60
+ has(key: string): boolean;
61
+ }
62
+ /**
63
+ * Global singleton instance of ContextManager.
64
+ * Use this throughout your application.
65
+ */
66
+ export declare const Context: ContextManager;
67
+ export {};
package/src/Context.js ADDED
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Context = void 0;
4
+ const async_hooks_1 = require("async_hooks");
5
+ /**
6
+ * Context management using AsyncLocalStorage.
7
+ * Similar to Java WebPieces Context class that uses ThreadLocal.
8
+ *
9
+ * This allows storing request-scoped data that is automatically available
10
+ * throughout the async call chain, similar to MDC (Mapped Diagnostic Context).
11
+ *
12
+ * Example usage:
13
+ * ```typescript
14
+ * Context.put('REQUEST_ID', '12345');
15
+ * await someAsyncOperation();
16
+ * const id = Context.get('REQUEST_ID'); // Still available!
17
+ * ```
18
+ */
19
+ class ContextManager {
20
+ constructor() {
21
+ this.storage = new async_hooks_1.AsyncLocalStorage();
22
+ }
23
+ /**
24
+ * Run a function with a new context.
25
+ * This is typically called at the beginning of a request.
26
+ */
27
+ run(fn) {
28
+ const store = new Map();
29
+ return this.storage.run(store, fn);
30
+ }
31
+ /**
32
+ * Run a function with a specific context.
33
+ */
34
+ runWithContext(context, fn) {
35
+ return this.storage.run(context, fn);
36
+ }
37
+ /**
38
+ * Store a value in the current context.
39
+ */
40
+ put(key, value) {
41
+ const store = this.storage.getStore();
42
+ if (!store) {
43
+ throw new Error('No context available. Did you call Context.run() first?');
44
+ }
45
+ store.set(key, value);
46
+ }
47
+ /**
48
+ * Retrieve a value from the current context.
49
+ */
50
+ get(key) {
51
+ const store = this.storage.getStore();
52
+ return store?.get(key);
53
+ }
54
+ /**
55
+ * Remove a value from the current context.
56
+ */
57
+ remove(key) {
58
+ const store = this.storage.getStore();
59
+ store?.delete(key);
60
+ }
61
+ /**
62
+ * Clear all values from the current context.
63
+ */
64
+ clear() {
65
+ const store = this.storage.getStore();
66
+ store?.clear();
67
+ }
68
+ /**
69
+ * Copy the current context to a new Map.
70
+ * Used by XPromise to preserve context across async boundaries.
71
+ */
72
+ copyContext() {
73
+ const store = this.storage.getStore();
74
+ if (!store) {
75
+ return new Map();
76
+ }
77
+ return new Map(store);
78
+ }
79
+ /**
80
+ * Set the entire context from a Map.
81
+ * Used by XPromise to restore context.
82
+ */
83
+ setContext(context) {
84
+ const store = this.storage.getStore();
85
+ if (!store) {
86
+ throw new Error('No context available. Did you call Context.run() first?');
87
+ }
88
+ store.clear();
89
+ context.forEach((value, key) => {
90
+ store.set(key, value);
91
+ });
92
+ }
93
+ /**
94
+ * Get all context entries.
95
+ */
96
+ getAll() {
97
+ const store = this.storage.getStore();
98
+ return store ? new Map(store) : new Map();
99
+ }
100
+ /**
101
+ * Check if a key exists in the context.
102
+ */
103
+ has(key) {
104
+ const store = this.storage.getStore();
105
+ return store?.has(key) ?? false;
106
+ }
107
+ }
108
+ /**
109
+ * Global singleton instance of ContextManager.
110
+ * Use this throughout your application.
111
+ */
112
+ exports.Context = new ContextManager();
113
+ //# sourceMappingURL=Context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Context.js","sourceRoot":"","sources":["../../../../../packages/core/core-context/src/Context.ts"],"names":[],"mappings":";;;AAAA,6CAAgD;AAEhD;;;;;;;;;;;;;GAaG;AACH,MAAM,cAAc;IAGlB;QACE,IAAI,CAAC,OAAO,GAAG,IAAI,+BAAiB,EAAoB,CAAC;IAC3D,CAAC;IAED;;;OAGG;IACH,GAAG,CAAI,EAAW;QAChB,MAAM,KAAK,GAAG,IAAI,GAAG,EAAe,CAAC;QACrC,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACrC,CAAC;IAED;;OAEG;IACH,cAAc,CAAI,OAAyB,EAAE,EAAW;QACtD,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IACvC,CAAC;IAED;;OAEG;IACH,GAAG,CAAC,GAAW,EAAE,KAAU;QACzB,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;QACtC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAC;QAC7E,CAAC;QACD,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACxB,CAAC;IAED;;OAEG;IACH,GAAG,CAAU,GAAW;QACtB,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;QACtC,OAAO,KAAK,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC;IACzB,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,GAAW;QAChB,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;QACtC,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;IACrB,CAAC;IAED;;OAEG;IACH,KAAK;QACH,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;QACtC,KAAK,EAAE,KAAK,EAAE,CAAC;IACjB,CAAC;IAED;;;OAGG;IACH,WAAW;QACT,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;QACtC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,IAAI,GAAG,EAAE,CAAC;QACnB,CAAC;QACD,OAAO,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;IACxB,CAAC;IAED;;;OAGG;IACH,UAAU,CAAC,OAAyB;QAClC,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;QACtC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAC;QAC7E,CAAC;QACD,KAAK,CAAC,KAAK,EAAE,CAAC;QACd,OAAO,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;YAC7B,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACxB,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,MAAM;QACJ,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;QACtC,OAAO,KAAK,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,EAAE,CAAC;IAC5C,CAAC;IAED;;OAEG;IACH,GAAG,CAAC,GAAW;QACb,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;QACtC,OAAO,KAAK,EAAE,GAAG,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC;IAClC,CAAC;CACF;AAED;;;GAGG;AACU,QAAA,OAAO,GAAG,IAAI,cAAc,EAAE,CAAC"}
package/src/index.d.ts ADDED
@@ -0,0 +1 @@
1
+ export { Context } from './Context';
package/src/index.js ADDED
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Context = void 0;
4
+ var Context_1 = require("./Context");
5
+ Object.defineProperty(exports, "Context", { enumerable: true, get: function () { return Context_1.Context; } });
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../packages/core/core-context/src/index.ts"],"names":[],"mappings":";;;AAAA,qCAAoC;AAA3B,kGAAA,OAAO,OAAA"}