@webpieces/core-context 0.3.263 → 0.3.265
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/package.json +5 -2
- package/src/ContextMgr.d.ts +76 -0
- package/src/ContextMgr.js +87 -0
- package/src/ContextMgr.js.map +1 -0
- package/src/RequestContextReader.d.ts +29 -0
- package/src/RequestContextReader.js +39 -0
- package/src/RequestContextReader.js.map +1 -0
- package/src/RequestIdChainProcessor.d.ts +20 -0
- package/src/RequestIdChainProcessor.js +35 -0
- package/src/RequestIdChainProcessor.js.map +1 -0
- package/src/index.d.ts +4 -0
- package/src/index.js +13 -1
- package/src/index.js.map +1 -1
- package/src/provide.d.ts +49 -0
- package/src/provide.js +67 -0
- package/src/provide.js.map +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webpieces/core-context",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.265",
|
|
4
4
|
"description": "AsyncLocalStorage-based context management for request-scoped data",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "./src/index.js",
|
|
@@ -22,6 +22,9 @@
|
|
|
22
22
|
"access": "public"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@webpieces/core-util": "0.3.
|
|
25
|
+
"@webpieces/core-util": "0.3.265",
|
|
26
|
+
"@inversifyjs/binding-decorators": "1.1.5",
|
|
27
|
+
"inversify": "7.10.4",
|
|
28
|
+
"reflect-metadata": "0.2.2"
|
|
26
29
|
}
|
|
27
30
|
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { ContextReader, HeaderMethods, HeaderRegistry } from '@webpieces/core-util';
|
|
2
|
+
/**
|
|
3
|
+
* ContextMgr - Manages context reader + header registry for HTTP clients.
|
|
4
|
+
*
|
|
5
|
+
* Passed to createApiClient() via ClientConfig.contextMgr to enable automatic
|
|
6
|
+
* header propagation: every header in the registry with isWantTransferred=true
|
|
7
|
+
* is read from the ContextReader and added to outbound requests.
|
|
8
|
+
*
|
|
9
|
+
* BREAKING (migration from the PlatformHeader[] constructor):
|
|
10
|
+
* new ContextMgr(reader, headerArray)
|
|
11
|
+
* becomes
|
|
12
|
+
* new ContextMgr(reader, new HeaderRegistry([new PlatformHeadersExtension(headerArray)]))
|
|
13
|
+
*
|
|
14
|
+
* Example usage:
|
|
15
|
+
* ```typescript
|
|
16
|
+
* // Node.js server-side (reads the magic context from RequestContext):
|
|
17
|
+
* const contextMgr = new ContextMgr(new RequestContextReader(), registry);
|
|
18
|
+
*
|
|
19
|
+
* // Browser client-side (app-managed store, no AsyncLocalStorage):
|
|
20
|
+
* const store = new MutableContextStore();
|
|
21
|
+
* const contextMgr = new ContextMgr(store, registry);
|
|
22
|
+
*
|
|
23
|
+
* // Both cases:
|
|
24
|
+
* const config = new ClientConfig('http://api.example.com', contextMgr);
|
|
25
|
+
* const client = createApiClient(SaveApi, config);
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export declare class ContextMgr {
|
|
29
|
+
/**
|
|
30
|
+
* The context reader that provides header values.
|
|
31
|
+
* Different implementations for Node.js vs browser.
|
|
32
|
+
*/
|
|
33
|
+
readonly contextReader: ContextReader;
|
|
34
|
+
/**
|
|
35
|
+
* The single source of truth for which headers exist and how they behave
|
|
36
|
+
* (transferred/secured/MDC). Shared with the server-side filters.
|
|
37
|
+
*/
|
|
38
|
+
readonly registry: HeaderRegistry;
|
|
39
|
+
/**
|
|
40
|
+
* When true (default), outbound calls send the current x-request-id as
|
|
41
|
+
* x-previous-request-id (and drop x-request-id) so each hop in a
|
|
42
|
+
* distributed trace gets its own id chained to its caller's.
|
|
43
|
+
*/
|
|
44
|
+
readonly chainRequestIds: boolean;
|
|
45
|
+
private chainProcessor;
|
|
46
|
+
constructor(
|
|
47
|
+
/**
|
|
48
|
+
* The context reader that provides header values.
|
|
49
|
+
* Different implementations for Node.js vs browser.
|
|
50
|
+
*/
|
|
51
|
+
contextReader: ContextReader,
|
|
52
|
+
/**
|
|
53
|
+
* The single source of truth for which headers exist and how they behave
|
|
54
|
+
* (transferred/secured/MDC). Shared with the server-side filters.
|
|
55
|
+
*/
|
|
56
|
+
registry: HeaderRegistry,
|
|
57
|
+
/**
|
|
58
|
+
* When true (default), outbound calls send the current x-request-id as
|
|
59
|
+
* x-previous-request-id (and drop x-request-id) so each hop in a
|
|
60
|
+
* distributed trace gets its own id chained to its caller's.
|
|
61
|
+
*/
|
|
62
|
+
chainRequestIds?: boolean);
|
|
63
|
+
/**
|
|
64
|
+
* Build the headers to send on an outbound request: every transferred
|
|
65
|
+
* header (isWantTransferred=true) with a non-empty value in the context,
|
|
66
|
+
* then request-id chaining applied (unless opted out).
|
|
67
|
+
*
|
|
68
|
+
* Values are RAW (unmasked) - this map goes on the wire, not in logs.
|
|
69
|
+
*/
|
|
70
|
+
buildOutboundHeaders(): Map<string, string>;
|
|
71
|
+
/**
|
|
72
|
+
* Build the header map for LOGGING: secured header values are masked,
|
|
73
|
+
* and headers are keyed by loggerMdcKey when defined.
|
|
74
|
+
*/
|
|
75
|
+
buildHeadersForLogging(headerMethods: HeaderMethods): Map<string, string>;
|
|
76
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ContextMgr = void 0;
|
|
4
|
+
const RequestIdChainProcessor_1 = require("./RequestIdChainProcessor");
|
|
5
|
+
/**
|
|
6
|
+
* ContextMgr - Manages context reader + header registry for HTTP clients.
|
|
7
|
+
*
|
|
8
|
+
* Passed to createApiClient() via ClientConfig.contextMgr to enable automatic
|
|
9
|
+
* header propagation: every header in the registry with isWantTransferred=true
|
|
10
|
+
* is read from the ContextReader and added to outbound requests.
|
|
11
|
+
*
|
|
12
|
+
* BREAKING (migration from the PlatformHeader[] constructor):
|
|
13
|
+
* new ContextMgr(reader, headerArray)
|
|
14
|
+
* becomes
|
|
15
|
+
* new ContextMgr(reader, new HeaderRegistry([new PlatformHeadersExtension(headerArray)]))
|
|
16
|
+
*
|
|
17
|
+
* Example usage:
|
|
18
|
+
* ```typescript
|
|
19
|
+
* // Node.js server-side (reads the magic context from RequestContext):
|
|
20
|
+
* const contextMgr = new ContextMgr(new RequestContextReader(), registry);
|
|
21
|
+
*
|
|
22
|
+
* // Browser client-side (app-managed store, no AsyncLocalStorage):
|
|
23
|
+
* const store = new MutableContextStore();
|
|
24
|
+
* const contextMgr = new ContextMgr(store, registry);
|
|
25
|
+
*
|
|
26
|
+
* // Both cases:
|
|
27
|
+
* const config = new ClientConfig('http://api.example.com', contextMgr);
|
|
28
|
+
* const client = createApiClient(SaveApi, config);
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
class ContextMgr {
|
|
32
|
+
contextReader;
|
|
33
|
+
registry;
|
|
34
|
+
chainRequestIds;
|
|
35
|
+
chainProcessor;
|
|
36
|
+
constructor(
|
|
37
|
+
/**
|
|
38
|
+
* The context reader that provides header values.
|
|
39
|
+
* Different implementations for Node.js vs browser.
|
|
40
|
+
*/
|
|
41
|
+
contextReader,
|
|
42
|
+
/**
|
|
43
|
+
* The single source of truth for which headers exist and how they behave
|
|
44
|
+
* (transferred/secured/MDC). Shared with the server-side filters.
|
|
45
|
+
*/
|
|
46
|
+
registry,
|
|
47
|
+
/**
|
|
48
|
+
* When true (default), outbound calls send the current x-request-id as
|
|
49
|
+
* x-previous-request-id (and drop x-request-id) so each hop in a
|
|
50
|
+
* distributed trace gets its own id chained to its caller's.
|
|
51
|
+
*/
|
|
52
|
+
chainRequestIds = true) {
|
|
53
|
+
this.contextReader = contextReader;
|
|
54
|
+
this.registry = registry;
|
|
55
|
+
this.chainRequestIds = chainRequestIds;
|
|
56
|
+
this.chainProcessor = new RequestIdChainProcessor_1.RequestIdChainProcessor();
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Build the headers to send on an outbound request: every transferred
|
|
60
|
+
* header (isWantTransferred=true) with a non-empty value in the context,
|
|
61
|
+
* then request-id chaining applied (unless opted out).
|
|
62
|
+
*
|
|
63
|
+
* Values are RAW (unmasked) - this map goes on the wire, not in logs.
|
|
64
|
+
*/
|
|
65
|
+
buildOutboundHeaders() {
|
|
66
|
+
const outbound = new Map();
|
|
67
|
+
for (const header of this.registry.getTransferredHeaders()) {
|
|
68
|
+
const value = this.contextReader.read(header);
|
|
69
|
+
if (value !== undefined && value !== null && value !== '') {
|
|
70
|
+
outbound.set(header.headerName, value);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (this.chainRequestIds) {
|
|
74
|
+
this.chainProcessor.process(outbound);
|
|
75
|
+
}
|
|
76
|
+
return outbound;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Build the header map for LOGGING: secured header values are masked,
|
|
80
|
+
* and headers are keyed by loggerMdcKey when defined.
|
|
81
|
+
*/
|
|
82
|
+
buildHeadersForLogging(headerMethods) {
|
|
83
|
+
return headerMethods.buildSecureMapForLogs(this.registry.getHeaders(), this.contextReader);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
exports.ContextMgr = ContextMgr;
|
|
87
|
+
//# sourceMappingURL=ContextMgr.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ContextMgr.js","sourceRoot":"","sources":["../../../../../packages/core/core-context/src/ContextMgr.ts"],"names":[],"mappings":";;;AACA,uEAAoE;AAEpE;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAa,UAAU;IAQC;IAMA;IAOA;IApBZ,cAAc,CAA0B;IAEhD;IACI;;;OAGG;IACa,aAA4B;IAE5C;;;OAGG;IACa,QAAwB;IAExC;;;;OAIG;IACa,kBAA2B,IAAI;QAb/B,kBAAa,GAAb,aAAa,CAAe;QAM5B,aAAQ,GAAR,QAAQ,CAAgB;QAOxB,oBAAe,GAAf,eAAe,CAAgB;QAE/C,IAAI,CAAC,cAAc,GAAG,IAAI,iDAAuB,EAAE,CAAC;IACxD,CAAC;IAED;;;;;;OAMG;IACH,oBAAoB;QAChB,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAkB,CAAC;QAE3C,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,QAAQ,CAAC,qBAAqB,EAAE,EAAE,CAAC;YACzD,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC9C,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,EAAE,EAAE,CAAC;gBACxD,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;YAC3C,CAAC;QACL,CAAC;QAED,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;YACvB,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC1C,CAAC;QAED,OAAO,QAAQ,CAAC;IACpB,CAAC;IAED;;;OAGG;IACH,sBAAsB,CAAC,aAA4B;QAC/C,OAAO,aAAa,CAAC,qBAAqB,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;IAC/F,CAAC;CACJ;AAzDD,gCAyDC","sourcesContent":["import { ContextReader, HeaderMethods, HeaderRegistry } from '@webpieces/core-util';\nimport { RequestIdChainProcessor } from './RequestIdChainProcessor';\n\n/**\n * ContextMgr - Manages context reader + header registry for HTTP clients.\n *\n * Passed to createApiClient() via ClientConfig.contextMgr to enable automatic\n * header propagation: every header in the registry with isWantTransferred=true\n * is read from the ContextReader and added to outbound requests.\n *\n * BREAKING (migration from the PlatformHeader[] constructor):\n * new ContextMgr(reader, headerArray)\n * becomes\n * new ContextMgr(reader, new HeaderRegistry([new PlatformHeadersExtension(headerArray)]))\n *\n * Example usage:\n * ```typescript\n * // Node.js server-side (reads the magic context from RequestContext):\n * const contextMgr = new ContextMgr(new RequestContextReader(), registry);\n *\n * // Browser client-side (app-managed store, no AsyncLocalStorage):\n * const store = new MutableContextStore();\n * const contextMgr = new ContextMgr(store, registry);\n *\n * // Both cases:\n * const config = new ClientConfig('http://api.example.com', contextMgr);\n * const client = createApiClient(SaveApi, config);\n * ```\n */\nexport class ContextMgr {\n private chainProcessor: RequestIdChainProcessor;\n\n constructor(\n /**\n * The context reader that provides header values.\n * Different implementations for Node.js vs browser.\n */\n public readonly contextReader: ContextReader,\n\n /**\n * The single source of truth for which headers exist and how they behave\n * (transferred/secured/MDC). Shared with the server-side filters.\n */\n public readonly registry: HeaderRegistry,\n\n /**\n * When true (default), outbound calls send the current x-request-id as\n * x-previous-request-id (and drop x-request-id) so each hop in a\n * distributed trace gets its own id chained to its caller's.\n */\n public readonly chainRequestIds: boolean = true,\n ) {\n this.chainProcessor = new RequestIdChainProcessor();\n }\n\n /**\n * Build the headers to send on an outbound request: every transferred\n * header (isWantTransferred=true) with a non-empty value in the context,\n * then request-id chaining applied (unless opted out).\n *\n * Values are RAW (unmasked) - this map goes on the wire, not in logs.\n */\n buildOutboundHeaders(): Map<string, string> {\n const outbound = new Map<string, string>();\n\n for (const header of this.registry.getTransferredHeaders()) {\n const value = this.contextReader.read(header);\n if (value !== undefined && value !== null && value !== '') {\n outbound.set(header.headerName, value);\n }\n }\n\n if (this.chainRequestIds) {\n this.chainProcessor.process(outbound);\n }\n\n return outbound;\n }\n\n /**\n * Build the header map for LOGGING: secured header values are masked,\n * and headers are keyed by loggerMdcKey when defined.\n */\n buildHeadersForLogging(headerMethods: HeaderMethods): Map<string, string> {\n return headerMethods.buildSecureMapForLogs(this.registry.getHeaders(), this.contextReader);\n }\n}\n"]}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { PlatformHeader, ContextReader } from '@webpieces/core-util';
|
|
2
|
+
import { ContextKey } from '@webpieces/core-util';
|
|
3
|
+
/**
|
|
4
|
+
* RequestContextReader - Reads headers from Node.js RequestContext.
|
|
5
|
+
*
|
|
6
|
+
* Only works in Node.js with active AsyncLocalStorage context.
|
|
7
|
+
* This is a server-side only implementation.
|
|
8
|
+
*
|
|
9
|
+
* Lives in @webpieces/core-context (Node.js only) alongside the RequestContext
|
|
10
|
+
* (AsyncLocalStorage) it reads from, so libraries can build a context-propagating
|
|
11
|
+
* ContextMgr without pulling in @webpieces/http-routing.
|
|
12
|
+
*
|
|
13
|
+
* For browser environments, use StaticContextReader from @webpieces/http-client.
|
|
14
|
+
*/
|
|
15
|
+
export declare class RequestContextReader implements ContextReader {
|
|
16
|
+
/**
|
|
17
|
+
* Read a header value from the active RequestContext.
|
|
18
|
+
*
|
|
19
|
+
* @param header - The platform header to read
|
|
20
|
+
* @returns The header value, or undefined if not in context
|
|
21
|
+
*/
|
|
22
|
+
read(header: PlatformHeader): string | undefined;
|
|
23
|
+
/**
|
|
24
|
+
* Read a non-header context value (e.g. the active TestCaseRecorder under
|
|
25
|
+
* RecorderKeys.RECORDER). Lets the isomorphic http-client find server-side
|
|
26
|
+
* context without importing core-context itself.
|
|
27
|
+
*/
|
|
28
|
+
readValue(key: ContextKey): unknown;
|
|
29
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RequestContextReader = void 0;
|
|
4
|
+
const RequestContext_1 = require("./RequestContext");
|
|
5
|
+
/**
|
|
6
|
+
* RequestContextReader - Reads headers from Node.js RequestContext.
|
|
7
|
+
*
|
|
8
|
+
* Only works in Node.js with active AsyncLocalStorage context.
|
|
9
|
+
* This is a server-side only implementation.
|
|
10
|
+
*
|
|
11
|
+
* Lives in @webpieces/core-context (Node.js only) alongside the RequestContext
|
|
12
|
+
* (AsyncLocalStorage) it reads from, so libraries can build a context-propagating
|
|
13
|
+
* ContextMgr without pulling in @webpieces/http-routing.
|
|
14
|
+
*
|
|
15
|
+
* For browser environments, use StaticContextReader from @webpieces/http-client.
|
|
16
|
+
*/
|
|
17
|
+
class RequestContextReader {
|
|
18
|
+
/**
|
|
19
|
+
* Read a header value from the active RequestContext.
|
|
20
|
+
*
|
|
21
|
+
* @param header - The platform header to read
|
|
22
|
+
* @returns The header value, or undefined if not in context
|
|
23
|
+
*/
|
|
24
|
+
read(header) {
|
|
25
|
+
// Use RequestContext.getHeader() which calls header.getHeaderName()
|
|
26
|
+
return RequestContext_1.RequestContext.getHeader(header);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Read a non-header context value (e.g. the active TestCaseRecorder under
|
|
30
|
+
* RecorderKeys.RECORDER). Lets the isomorphic http-client find server-side
|
|
31
|
+
* context without importing core-context itself.
|
|
32
|
+
*/
|
|
33
|
+
// webpieces-disable no-any-unknown -- context values are heterogeneous (recorder, meta objects)
|
|
34
|
+
readValue(key) {
|
|
35
|
+
return RequestContext_1.RequestContext.getHeader(key);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
exports.RequestContextReader = RequestContextReader;
|
|
39
|
+
//# sourceMappingURL=RequestContextReader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RequestContextReader.js","sourceRoot":"","sources":["../../../../../packages/core/core-context/src/RequestContextReader.ts"],"names":[],"mappings":";;;AAEA,qDAAkD;AAElD;;;;;;;;;;;GAWG;AACH,MAAa,oBAAoB;IAC7B;;;;;OAKG;IACH,IAAI,CAAC,MAAsB;QACvB,oEAAoE;QACpE,OAAO,+BAAc,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IAC5C,CAAC;IAED;;;;OAIG;IACH,gGAAgG;IAChG,SAAS,CAAC,GAAe;QACrB,OAAO,+BAAc,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IACzC,CAAC;CACJ;AArBD,oDAqBC","sourcesContent":["import { PlatformHeader, ContextReader } from '@webpieces/core-util';\nimport { ContextKey } from '@webpieces/core-util';\nimport { RequestContext } from './RequestContext';\n\n/**\n * RequestContextReader - Reads headers from Node.js RequestContext.\n *\n * Only works in Node.js with active AsyncLocalStorage context.\n * This is a server-side only implementation.\n *\n * Lives in @webpieces/core-context (Node.js only) alongside the RequestContext\n * (AsyncLocalStorage) it reads from, so libraries can build a context-propagating\n * ContextMgr without pulling in @webpieces/http-routing.\n *\n * For browser environments, use StaticContextReader from @webpieces/http-client.\n */\nexport class RequestContextReader implements ContextReader {\n /**\n * Read a header value from the active RequestContext.\n *\n * @param header - The platform header to read\n * @returns The header value, or undefined if not in context\n */\n read(header: PlatformHeader): string | undefined {\n // Use RequestContext.getHeader() which calls header.getHeaderName()\n return RequestContext.getHeader(header);\n }\n\n /**\n * Read a non-header context value (e.g. the active TestCaseRecorder under\n * RecorderKeys.RECORDER). Lets the isomorphic http-client find server-side\n * context without importing core-context itself.\n */\n // webpieces-disable no-any-unknown -- context values are heterogeneous (recorder, meta objects)\n readValue(key: ContextKey): unknown {\n return RequestContext.getHeader(key);\n }\n}\n"]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RequestIdChainProcessor - Builds the per-hop distributed-trace chain.
|
|
3
|
+
*
|
|
4
|
+
* TS equivalent of the Java MicroSvcHeader REQUEST_ID/PREVIOUS_REQUEST_ID flow:
|
|
5
|
+
* when a server makes an outbound call, its CURRENT request id is sent to the
|
|
6
|
+
* downstream service as x-previous-request-id, and x-request-id is NOT sent -
|
|
7
|
+
* the downstream ContextFilter then generates a fresh id for its own hop.
|
|
8
|
+
* Result: every hop has its own id plus a pointer to its caller's id, forming
|
|
9
|
+
* a trace tree.
|
|
10
|
+
*
|
|
11
|
+
* Invoked by ContextMgr.buildOutboundHeaders() after the transferred headers
|
|
12
|
+
* are collected. Opt out via `new ContextMgr(reader, registry, false)` if you
|
|
13
|
+
* want raw pass-through of x-request-id instead.
|
|
14
|
+
*/
|
|
15
|
+
export declare class RequestIdChainProcessor {
|
|
16
|
+
/**
|
|
17
|
+
* Rewrite the outbound header map in place: x-request-id -> x-previous-request-id.
|
|
18
|
+
*/
|
|
19
|
+
process(outboundHeaders: Map<string, string>): void;
|
|
20
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RequestIdChainProcessor = void 0;
|
|
4
|
+
const core_util_1 = require("@webpieces/core-util");
|
|
5
|
+
/**
|
|
6
|
+
* RequestIdChainProcessor - Builds the per-hop distributed-trace chain.
|
|
7
|
+
*
|
|
8
|
+
* TS equivalent of the Java MicroSvcHeader REQUEST_ID/PREVIOUS_REQUEST_ID flow:
|
|
9
|
+
* when a server makes an outbound call, its CURRENT request id is sent to the
|
|
10
|
+
* downstream service as x-previous-request-id, and x-request-id is NOT sent -
|
|
11
|
+
* the downstream ContextFilter then generates a fresh id for its own hop.
|
|
12
|
+
* Result: every hop has its own id plus a pointer to its caller's id, forming
|
|
13
|
+
* a trace tree.
|
|
14
|
+
*
|
|
15
|
+
* Invoked by ContextMgr.buildOutboundHeaders() after the transferred headers
|
|
16
|
+
* are collected. Opt out via `new ContextMgr(reader, registry, false)` if you
|
|
17
|
+
* want raw pass-through of x-request-id instead.
|
|
18
|
+
*/
|
|
19
|
+
class RequestIdChainProcessor {
|
|
20
|
+
/**
|
|
21
|
+
* Rewrite the outbound header map in place: x-request-id -> x-previous-request-id.
|
|
22
|
+
*/
|
|
23
|
+
process(outboundHeaders) {
|
|
24
|
+
const requestIdName = core_util_1.WebpiecesCoreHeaders.REQUEST_ID.headerName;
|
|
25
|
+
const previousIdName = core_util_1.WebpiecesCoreHeaders.PREVIOUS_REQUEST_ID.headerName;
|
|
26
|
+
const currentRequestId = outboundHeaders.get(requestIdName);
|
|
27
|
+
if (currentRequestId === undefined) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
outboundHeaders.set(previousIdName, currentRequestId);
|
|
31
|
+
outboundHeaders.delete(requestIdName);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
exports.RequestIdChainProcessor = RequestIdChainProcessor;
|
|
35
|
+
//# sourceMappingURL=RequestIdChainProcessor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RequestIdChainProcessor.js","sourceRoot":"","sources":["../../../../../packages/core/core-context/src/RequestIdChainProcessor.ts"],"names":[],"mappings":";;;AAAA,oDAA4D;AAE5D;;;;;;;;;;;;;GAaG;AACH,MAAa,uBAAuB;IAChC;;OAEG;IACH,OAAO,CAAC,eAAoC;QACxC,MAAM,aAAa,GAAG,gCAAoB,CAAC,UAAU,CAAC,UAAU,CAAC;QACjE,MAAM,cAAc,GAAG,gCAAoB,CAAC,mBAAmB,CAAC,UAAU,CAAC;QAE3E,MAAM,gBAAgB,GAAG,eAAe,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;QAC5D,IAAI,gBAAgB,KAAK,SAAS,EAAE,CAAC;YACjC,OAAO;QACX,CAAC;QAED,eAAe,CAAC,GAAG,CAAC,cAAc,EAAE,gBAAgB,CAAC,CAAC;QACtD,eAAe,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;IAC1C,CAAC;CACJ;AAhBD,0DAgBC","sourcesContent":["import { WebpiecesCoreHeaders } from '@webpieces/core-util';\n\n/**\n * RequestIdChainProcessor - Builds the per-hop distributed-trace chain.\n *\n * TS equivalent of the Java MicroSvcHeader REQUEST_ID/PREVIOUS_REQUEST_ID flow:\n * when a server makes an outbound call, its CURRENT request id is sent to the\n * downstream service as x-previous-request-id, and x-request-id is NOT sent -\n * the downstream ContextFilter then generates a fresh id for its own hop.\n * Result: every hop has its own id plus a pointer to its caller's id, forming\n * a trace tree.\n *\n * Invoked by ContextMgr.buildOutboundHeaders() after the transferred headers\n * are collected. Opt out via `new ContextMgr(reader, registry, false)` if you\n * want raw pass-through of x-request-id instead.\n */\nexport class RequestIdChainProcessor {\n /**\n * Rewrite the outbound header map in place: x-request-id -> x-previous-request-id.\n */\n process(outboundHeaders: Map<string, string>): void {\n const requestIdName = WebpiecesCoreHeaders.REQUEST_ID.headerName;\n const previousIdName = WebpiecesCoreHeaders.PREVIOUS_REQUEST_ID.headerName;\n\n const currentRequestId = outboundHeaders.get(requestIdName);\n if (currentRequestId === undefined) {\n return;\n }\n\n outboundHeaders.set(previousIdName, currentRequestId);\n outboundHeaders.delete(requestIdName);\n }\n}\n"]}
|
package/src/index.d.ts
CHANGED
|
@@ -1 +1,5 @@
|
|
|
1
1
|
export { RequestContext } from './RequestContext';
|
|
2
|
+
export { provideSingleton, provideSingletonAs, provideTransient } from './provide';
|
|
3
|
+
export { ContextMgr } from './ContextMgr';
|
|
4
|
+
export { RequestIdChainProcessor } from './RequestIdChainProcessor';
|
|
5
|
+
export { RequestContextReader } from './RequestContextReader';
|
package/src/index.js
CHANGED
|
@@ -1,7 +1,19 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.RequestContext = void 0;
|
|
3
|
+
exports.RequestContextReader = exports.RequestIdChainProcessor = exports.ContextMgr = exports.provideTransient = exports.provideSingletonAs = exports.provideSingleton = exports.RequestContext = void 0;
|
|
4
4
|
// Context management with AsyncLocalStorage
|
|
5
5
|
var RequestContext_1 = require("./RequestContext");
|
|
6
6
|
Object.defineProperty(exports, "RequestContext", { enumerable: true, get: function () { return RequestContext_1.RequestContext; } });
|
|
7
|
+
// DI provider decorators (shared DI seam; http-routing re-exports for back-compat)
|
|
8
|
+
var provide_1 = require("./provide");
|
|
9
|
+
Object.defineProperty(exports, "provideSingleton", { enumerable: true, get: function () { return provide_1.provideSingleton; } });
|
|
10
|
+
Object.defineProperty(exports, "provideSingletonAs", { enumerable: true, get: function () { return provide_1.provideSingletonAs; } });
|
|
11
|
+
Object.defineProperty(exports, "provideTransient", { enumerable: true, get: function () { return provide_1.provideTransient; } });
|
|
12
|
+
// Outbound-header machinery (request-context -> outbound HTTP headers)
|
|
13
|
+
var ContextMgr_1 = require("./ContextMgr");
|
|
14
|
+
Object.defineProperty(exports, "ContextMgr", { enumerable: true, get: function () { return ContextMgr_1.ContextMgr; } });
|
|
15
|
+
var RequestIdChainProcessor_1 = require("./RequestIdChainProcessor");
|
|
16
|
+
Object.defineProperty(exports, "RequestIdChainProcessor", { enumerable: true, get: function () { return RequestIdChainProcessor_1.RequestIdChainProcessor; } });
|
|
17
|
+
var RequestContextReader_1 = require("./RequestContextReader");
|
|
18
|
+
Object.defineProperty(exports, "RequestContextReader", { enumerable: true, get: function () { return RequestContextReader_1.RequestContextReader; } });
|
|
7
19
|
//# sourceMappingURL=index.js.map
|
package/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../packages/core/core-context/src/index.ts"],"names":[],"mappings":";;;AAAA,4CAA4C;AAC5C,mDAAkD;AAAzC,gHAAA,cAAc,OAAA","sourcesContent":["// Context management with AsyncLocalStorage\nexport { RequestContext } from './RequestContext';\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../packages/core/core-context/src/index.ts"],"names":[],"mappings":";;;AAAA,4CAA4C;AAC5C,mDAAkD;AAAzC,gHAAA,cAAc,OAAA;AAEvB,mFAAmF;AACnF,qCAAmF;AAA1E,2GAAA,gBAAgB,OAAA;AAAE,6GAAA,kBAAkB,OAAA;AAAE,2GAAA,gBAAgB,OAAA;AAE/D,uEAAuE;AACvE,2CAA0C;AAAjC,wGAAA,UAAU,OAAA;AACnB,qEAAoE;AAA3D,kIAAA,uBAAuB,OAAA;AAChC,+DAA8D;AAArD,4HAAA,oBAAoB,OAAA","sourcesContent":["// Context management with AsyncLocalStorage\nexport { RequestContext } from './RequestContext';\n\n// DI provider decorators (shared DI seam; http-routing re-exports for back-compat)\nexport { provideSingleton, provideSingletonAs, provideTransient } from './provide';\n\n// Outbound-header machinery (request-context -> outbound HTTP headers)\nexport { ContextMgr } from './ContextMgr';\nexport { RequestIdChainProcessor } from './RequestIdChainProcessor';\nexport { RequestContextReader } from './RequestContextReader';\n"]}
|
package/src/provide.d.ts
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import 'reflect-metadata';
|
|
2
|
+
import type { ServiceIdentifier } from 'inversify';
|
|
3
|
+
/**
|
|
4
|
+
* DI provider decorators (the lightweight DI seam shared across webpieces).
|
|
5
|
+
*
|
|
6
|
+
* These live in @webpieces/core-context — the lowest package that already owns
|
|
7
|
+
* request-scoped context — so libraries (cloudtasks-client, http-client, …) can
|
|
8
|
+
* register singletons WITHOUT depending on the server-side @webpieces/http-routing
|
|
9
|
+
* package. http-routing re-exports them for back-compat.
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Provides a singleton-scoped dependency.
|
|
13
|
+
* When called without arguments, the decorated class binds to itself.
|
|
14
|
+
*
|
|
15
|
+
* Usage:
|
|
16
|
+
* ```typescript
|
|
17
|
+
* @provideSingleton()
|
|
18
|
+
* export class SaveController {
|
|
19
|
+
* // ...
|
|
20
|
+
* }
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export declare function provideSingleton(): ClassDecorator;
|
|
24
|
+
/**
|
|
25
|
+
* Provides a singleton-scoped dependency bound to a specific token (Symbol or abstract class).
|
|
26
|
+
* Use this in libraries/apis-external/** to bind an impl to the Symbol defined in libraries/apis/**.
|
|
27
|
+
*
|
|
28
|
+
* Usage:
|
|
29
|
+
* ```typescript
|
|
30
|
+
* import { SOME_API_TOKEN } from '@myorg/some-api';
|
|
31
|
+
*
|
|
32
|
+
* @provideSingletonAs(SOME_API_TOKEN)
|
|
33
|
+
* export class SomeApiImpl { ... }
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export declare function provideSingletonAs<T>(serviceIdentifier: ServiceIdentifier<T>): ClassDecorator;
|
|
37
|
+
/**
|
|
38
|
+
* Provides a transient-scoped dependency (new instance every time).
|
|
39
|
+
* When called without arguments, the decorated class binds to itself.
|
|
40
|
+
*
|
|
41
|
+
* Usage:
|
|
42
|
+
* ```typescript
|
|
43
|
+
* @provideTransient()
|
|
44
|
+
* export class TransientController {
|
|
45
|
+
* // ...
|
|
46
|
+
* }
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
export declare function provideTransient(): ClassDecorator;
|
package/src/provide.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.provideSingleton = provideSingleton;
|
|
4
|
+
exports.provideSingletonAs = provideSingletonAs;
|
|
5
|
+
exports.provideTransient = provideTransient;
|
|
6
|
+
require("reflect-metadata");
|
|
7
|
+
const binding_decorators_1 = require("@inversifyjs/binding-decorators");
|
|
8
|
+
/**
|
|
9
|
+
* DI provider decorators (the lightweight DI seam shared across webpieces).
|
|
10
|
+
*
|
|
11
|
+
* These live in @webpieces/core-context — the lowest package that already owns
|
|
12
|
+
* request-scoped context — so libraries (cloudtasks-client, http-client, …) can
|
|
13
|
+
* register singletons WITHOUT depending on the server-side @webpieces/http-routing
|
|
14
|
+
* package. http-routing re-exports them for back-compat.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* Provides a singleton-scoped dependency.
|
|
18
|
+
* When called without arguments, the decorated class binds to itself.
|
|
19
|
+
*
|
|
20
|
+
* Usage:
|
|
21
|
+
* ```typescript
|
|
22
|
+
* @provideSingleton()
|
|
23
|
+
* export class SaveController {
|
|
24
|
+
* // ...
|
|
25
|
+
* }
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
function provideSingleton() {
|
|
29
|
+
// webpieces-disable no-any-unknown -- decorator target is any class constructor
|
|
30
|
+
return (target) => {
|
|
31
|
+
return (0, binding_decorators_1.provide)(target, (bind) => bind.inSingletonScope())(target);
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Provides a singleton-scoped dependency bound to a specific token (Symbol or abstract class).
|
|
36
|
+
* Use this in libraries/apis-external/** to bind an impl to the Symbol defined in libraries/apis/**.
|
|
37
|
+
*
|
|
38
|
+
* Usage:
|
|
39
|
+
* ```typescript
|
|
40
|
+
* import { SOME_API_TOKEN } from '@myorg/some-api';
|
|
41
|
+
*
|
|
42
|
+
* @provideSingletonAs(SOME_API_TOKEN)
|
|
43
|
+
* export class SomeApiImpl { ... }
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
function provideSingletonAs(serviceIdentifier) {
|
|
47
|
+
return (0, binding_decorators_1.provide)(serviceIdentifier, (bind) => bind.inSingletonScope());
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Provides a transient-scoped dependency (new instance every time).
|
|
51
|
+
* When called without arguments, the decorated class binds to itself.
|
|
52
|
+
*
|
|
53
|
+
* Usage:
|
|
54
|
+
* ```typescript
|
|
55
|
+
* @provideTransient()
|
|
56
|
+
* export class TransientController {
|
|
57
|
+
* // ...
|
|
58
|
+
* }
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
function provideTransient() {
|
|
62
|
+
// webpieces-disable no-any-unknown -- decorator target is any class constructor
|
|
63
|
+
return (target) => {
|
|
64
|
+
return (0, binding_decorators_1.provide)(target)(target);
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=provide.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provide.js","sourceRoot":"","sources":["../../../../../packages/core/core-context/src/provide.ts"],"names":[],"mappings":";;AAyBA,4CAKC;AAcD,gDAEC;AAcD,4CAKC;AAjED,4BAA0B;AAC1B,wEAA0D;AAG1D;;;;;;;GAOG;AAEH;;;;;;;;;;;GAWG;AACH,SAAgB,gBAAgB;IAC5B,gFAAgF;IAChF,OAAO,CAAC,MAAW,EAAE,EAAE;QACnB,OAAO,IAAA,4BAAO,EAAC,MAAM,EAAE,CAAC,IAAuC,EAAE,EAAE,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;IACzG,CAAC,CAAC;AACN,CAAC;AAED;;;;;;;;;;;GAWG;AACH,SAAgB,kBAAkB,CAAI,iBAAuC;IACzE,OAAO,IAAA,4BAAO,EAAC,iBAAiB,EAAE,CAAC,IAAiC,EAAE,EAAE,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC,CAAC;AACtG,CAAC;AAED;;;;;;;;;;;GAWG;AACH,SAAgB,gBAAgB;IAC5B,gFAAgF;IAChF,OAAO,CAAC,MAAW,EAAE,EAAE;QACnB,OAAO,IAAA,4BAAO,EAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC;IACnC,CAAC,CAAC;AACN,CAAC","sourcesContent":["import 'reflect-metadata';\nimport { provide } from '@inversifyjs/binding-decorators';\nimport type { BindInWhenOnFluentSyntax, ServiceIdentifier } from 'inversify';\n\n/**\n * DI provider decorators (the lightweight DI seam shared across webpieces).\n *\n * These live in @webpieces/core-context — the lowest package that already owns\n * request-scoped context — so libraries (cloudtasks-client, http-client, …) can\n * register singletons WITHOUT depending on the server-side @webpieces/http-routing\n * package. http-routing re-exports them for back-compat.\n */\n\n/**\n * Provides a singleton-scoped dependency.\n * When called without arguments, the decorated class binds to itself.\n *\n * Usage:\n * ```typescript\n * @provideSingleton()\n * export class SaveController {\n * // ...\n * }\n * ```\n */\nexport function provideSingleton(): ClassDecorator {\n // webpieces-disable no-any-unknown -- decorator target is any class constructor\n return (target: any) => {\n return provide(target, (bind: BindInWhenOnFluentSyntax<unknown>) => bind.inSingletonScope())(target);\n };\n}\n\n/**\n * Provides a singleton-scoped dependency bound to a specific token (Symbol or abstract class).\n * Use this in libraries/apis-external/** to bind an impl to the Symbol defined in libraries/apis/**.\n *\n * Usage:\n * ```typescript\n * import { SOME_API_TOKEN } from '@myorg/some-api';\n *\n * @provideSingletonAs(SOME_API_TOKEN)\n * export class SomeApiImpl { ... }\n * ```\n */\nexport function provideSingletonAs<T>(serviceIdentifier: ServiceIdentifier<T>): ClassDecorator {\n return provide(serviceIdentifier, (bind: BindInWhenOnFluentSyntax<T>) => bind.inSingletonScope());\n}\n\n/**\n * Provides a transient-scoped dependency (new instance every time).\n * When called without arguments, the decorated class binds to itself.\n *\n * Usage:\n * ```typescript\n * @provideTransient()\n * export class TransientController {\n * // ...\n * }\n * ```\n */\nexport function provideTransient(): ClassDecorator {\n // webpieces-disable no-any-unknown -- decorator target is any class constructor\n return (target: any) => {\n return provide(target)(target);\n };\n}\n"]}
|