@webpieces/core-util 0.4.437 → 0.4.439
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 +1 -1
- package/src/ContextKey.d.ts +16 -1
- package/src/ContextKey.js +9 -0
- package/src/ContextKey.js.map +1 -1
- package/src/http/WebpiecesCoreHeaders.d.ts +14 -13
- package/src/http/WebpiecesCoreHeaders.js.map +1 -1
- package/src/http/recorder/TestCaseRecorder.d.ts +1 -1
- package/src/http/recorder/TestCaseRecorder.js.map +1 -1
package/package.json
CHANGED
package/src/ContextKey.d.ts
CHANGED
|
@@ -20,8 +20,23 @@
|
|
|
20
20
|
* must not be serialized into log lines).
|
|
21
21
|
*
|
|
22
22
|
* Per CLAUDE.md: data-only structures are classes, not interfaces.
|
|
23
|
+
*
|
|
24
|
+
* The type parameter `V` is the TYPE OF THE VALUE stored under this key — `string` for the wire/log
|
|
25
|
+
* keys (requestId, tenantId, ...), `ApiCallInfo` for the structured api tag, `TestCaseRecorder` for
|
|
26
|
+
* the recorder. It defaults to `unknown` so an untyped `ContextKey` still works. A heterogeneous
|
|
27
|
+
* store CANNOT be a `Record<string, string>` — the recorder and the api payload are not strings —
|
|
28
|
+
* so instead each KEY carries its own value type, and `RequestContext.getHeader/putHeader` INFER it
|
|
29
|
+
* from the key. That keeps the backing Map honestly type-erased while the public surface stays fully
|
|
30
|
+
* typed: a caller never asserts a value type, the key already declares it.
|
|
23
31
|
*/
|
|
24
|
-
export declare class ContextKey {
|
|
32
|
+
export declare class ContextKey<V = unknown> {
|
|
33
|
+
/**
|
|
34
|
+
* Phantom marker carrying the value type {@link V}. It has no runtime existence (`declare`, never
|
|
35
|
+
* assigned) — it exists ONLY so `getHeader(key)` returns `V` and `putHeader(key, value)` checks
|
|
36
|
+
* `value` against `V`, both inferred straight from the key. Optional, so `ContextKey<A>` stays
|
|
37
|
+
* assignable to `ContextKey` (i.e. `ContextKey<unknown>`) — arrays of mixed keys keep working.
|
|
38
|
+
*/
|
|
39
|
+
readonly __valueType?: V;
|
|
25
40
|
/** Context storage key + log/MDC key + recorder name. Always set. */
|
|
26
41
|
readonly name: string;
|
|
27
42
|
/**
|
package/src/ContextKey.js
CHANGED
|
@@ -23,7 +23,16 @@ exports.ContextKey = void 0;
|
|
|
23
23
|
* must not be serialized into log lines).
|
|
24
24
|
*
|
|
25
25
|
* Per CLAUDE.md: data-only structures are classes, not interfaces.
|
|
26
|
+
*
|
|
27
|
+
* The type parameter `V` is the TYPE OF THE VALUE stored under this key — `string` for the wire/log
|
|
28
|
+
* keys (requestId, tenantId, ...), `ApiCallInfo` for the structured api tag, `TestCaseRecorder` for
|
|
29
|
+
* the recorder. It defaults to `unknown` so an untyped `ContextKey` still works. A heterogeneous
|
|
30
|
+
* store CANNOT be a `Record<string, string>` — the recorder and the api payload are not strings —
|
|
31
|
+
* so instead each KEY carries its own value type, and `RequestContext.getHeader/putHeader` INFER it
|
|
32
|
+
* from the key. That keeps the backing Map honestly type-erased while the public surface stays fully
|
|
33
|
+
* typed: a caller never asserts a value type, the key already declares it.
|
|
26
34
|
*/
|
|
35
|
+
// webpieces-disable no-any-unknown -- `unknown` is the deliberate default value type for an untyped ContextKey (a heterogeneous store cannot be narrowed further); typed keys override it with string/ApiCallInfo/TestCaseRecorder
|
|
27
36
|
class ContextKey {
|
|
28
37
|
/** Context storage key + log/MDC key + recorder name. Always set. */
|
|
29
38
|
name;
|
package/src/ContextKey.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ContextKey.js","sourceRoot":"","sources":["../../../../../packages/core/core-util/src/ContextKey.ts"],"names":[],"mappings":";;;AAAA
|
|
1
|
+
{"version":3,"file":"ContextKey.js","sourceRoot":"","sources":["../../../../../packages/core/core-util/src/ContextKey.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,mOAAmO;AACnO,MAAa,UAAU;IASnB,qEAAqE;IAC5D,IAAI,CAAS;IAEtB;;;OAGG;IACM,UAAU,CAAU;IAE7B,2CAA2C;IAClC,SAAS,CAAU;IAE5B,6EAA6E;IACpE,QAAQ,CAAU;IAE3B,YACI,IAAY,EACZ,UAAmB,EACnB,SAAS,GAAG,KAAK,EACjB,QAAQ,GAAG,IAAI;QAEf,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC7B,CAAC;IAED,uEAAuE;IACvE,aAAa;QACT,OAAO,IAAI,CAAC,UAAU,KAAK,SAAS,CAAC;IACzC,CAAC;IAED;;;;;;OAMG;IACH,aAAa,CAAC,KAAa;QACvB,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YAClB,OAAO,KAAK,CAAC;QACjB,CAAC;QACD,MAAM,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC;QACzB,IAAI,GAAG,GAAG,CAAC,EAAE,CAAC;YACV,OAAO,+BAA+B,CAAC;QAC3C,CAAC;aAAM,IAAI,GAAG,IAAI,EAAE,EAAE,CAAC;YACnB,OAAO,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC;QACzC,CAAC;aAAM,CAAC;YACJ,OAAO,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,KAAK,CAAC,SAAS,CAAC,GAAG,GAAG,CAAC,CAAC,EAAE,CAAC;QACpE,CAAC;IACL,CAAC;CACJ;AA7DD,gCA6DC","sourcesContent":["/**\n * ContextKey - a single key that travels in the request's \"magic context\"\n * (RequestContext on the server, MutableContextStore in the browser).\n *\n * This ONE class replaces the old split of `Header` (interface) + `PlatformHeader`\n * (class) + `ContextKey` (class). Every context value — whether it rides over HTTP\n * (request-id, tenant, authorization) or stays in-process (method-meta, the\n * TestCaseRecorder) — is a `ContextKey`.\n *\n * The fields are named for what they DO (flipped from the old model):\n * - `name` ALWAYS set. The context storage key, the log/MDC key, and the\n * recorder name. e.g. 'requestId', 'tenantId', 'authorization'.\n * - `httpHeader` OPTIONAL. When set, this key is transferred over the wire under\n * this HTTP header name (inbound request -> context, and context ->\n * outbound request). e.g. 'x-request-id'. When UNSET, the key is\n * context-only and never leaves the process (method-meta, recorder).\n * - `isSecured` When true, the value is masked (partially) in logs.\n * - `isLogged` Defaults to true. When false, the value is NEVER logged (used for\n * object-valued/internal keys like the recorder or method-meta that\n * must not be serialized into log lines).\n *\n * Per CLAUDE.md: data-only structures are classes, not interfaces.\n *\n * The type parameter `V` is the TYPE OF THE VALUE stored under this key — `string` for the wire/log\n * keys (requestId, tenantId, ...), `ApiCallInfo` for the structured api tag, `TestCaseRecorder` for\n * the recorder. It defaults to `unknown` so an untyped `ContextKey` still works. A heterogeneous\n * store CANNOT be a `Record<string, string>` — the recorder and the api payload are not strings —\n * so instead each KEY carries its own value type, and `RequestContext.getHeader/putHeader` INFER it\n * from the key. That keeps the backing Map honestly type-erased while the public surface stays fully\n * typed: a caller never asserts a value type, the key already declares it.\n */\n// webpieces-disable no-any-unknown -- `unknown` is the deliberate default value type for an untyped ContextKey (a heterogeneous store cannot be narrowed further); typed keys override it with string/ApiCallInfo/TestCaseRecorder\nexport class ContextKey<V = unknown> {\n /**\n * Phantom marker carrying the value type {@link V}. It has no runtime existence (`declare`, never\n * assigned) — it exists ONLY so `getHeader(key)` returns `V` and `putHeader(key, value)` checks\n * `value` against `V`, both inferred straight from the key. Optional, so `ContextKey<A>` stays\n * assignable to `ContextKey` (i.e. `ContextKey<unknown>`) — arrays of mixed keys keep working.\n */\n declare readonly __valueType?: V;\n\n /** Context storage key + log/MDC key + recorder name. Always set. */\n readonly name: string;\n\n /**\n * HTTP header name when this key is transferred over the wire (e.g.\n * 'x-request-id'). Undefined = context-only, never transferred.\n */\n readonly httpHeader?: string;\n\n /** Mask this value (partially) in logs. */\n readonly isSecured: boolean;\n\n /** Whether this key is logged at all. Default true; false = never logged. */\n readonly isLogged: boolean;\n\n constructor(\n name: string,\n httpHeader?: string,\n isSecured = false,\n isLogged = true,\n ) {\n this.name = name;\n this.httpHeader = httpHeader;\n this.isSecured = isSecured;\n this.isLogged = isLogged;\n }\n\n /** True when this key is transferred over HTTP (has an httpHeader). */\n isTransferred(): boolean {\n return this.httpHeader !== undefined;\n }\n\n /**\n * The value as it should appear in a log line: returned as-is for a normal\n * key, partially masked when this key is secured. Masking is length-based:\n * - Length > 15: first 3 + \"...\" + last 3\n * - Length 8-15: first 2 + \"...\"\n * - Length < 8: \"<secure key too short to log>\"\n */\n maskIfSecured(value: string): string {\n if (!this.isSecured) {\n return value;\n }\n const len = value.length;\n if (len < 8) {\n return '<secure key too short to log>';\n } else if (len <= 15) {\n return `${value.substring(0, 2)}...`;\n } else {\n return `${value.substring(0, 3)}...${value.substring(len - 3)}`;\n }\n }\n}\n"]}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ContextKey } from '../ContextKey';
|
|
2
|
+
import { ApiCallInfo } from './ApiCallInfo';
|
|
2
3
|
/**
|
|
3
4
|
* Core framework context keys — the minimum the WebPieces framework needs to correlate one
|
|
4
5
|
* request across every service it touches, and across every log line each of them writes.
|
|
@@ -20,7 +21,7 @@ export declare class WebpiecesCoreHeaders {
|
|
|
20
21
|
* The id that correlates every hop of one request, and every log line of every hop.
|
|
21
22
|
* Generated by the first service to see a request without one; propagated unchanged after that.
|
|
22
23
|
*/
|
|
23
|
-
static readonly REQUEST_ID: ContextKey
|
|
24
|
+
static readonly REQUEST_ID: ContextKey<string>;
|
|
24
25
|
/**
|
|
25
26
|
* WHICH SERVICE MINTED {@link REQUEST_ID} — the name from {@link ServiceInfo}, stamped by
|
|
26
27
|
* `RequestContextHeaders.fillFromRequest` ONLY on the branch that generates a new id (i.e. when
|
|
@@ -35,7 +36,7 @@ export declare class WebpiecesCoreHeaders {
|
|
|
35
36
|
* the signal: present == I am the origin.
|
|
36
37
|
* - `isLogged` TRUE → emitted as a plain string at `jsonPayload.requestIdSource`.
|
|
37
38
|
*/
|
|
38
|
-
static readonly REQUEST_ID_SOURCE: ContextKey
|
|
39
|
+
static readonly REQUEST_ID_SOURCE: ContextKey<string>;
|
|
39
40
|
/**
|
|
40
41
|
* The CALLER's build version — so a downstream server's logs record which build of the client
|
|
41
42
|
* called it (surfaces as `jsonPayload.clientVersion`). Distinct from the log line's own `version`
|
|
@@ -49,7 +50,7 @@ export declare class WebpiecesCoreHeaders {
|
|
|
49
50
|
* - `isLogged` TRUE → the inbound value lands in the context and flows through the normal log
|
|
50
51
|
* field map; no backend change needed.
|
|
51
52
|
*/
|
|
52
|
-
static readonly CLIENT_VERSION: ContextKey
|
|
53
|
+
static readonly CLIENT_VERSION: ContextKey<string>;
|
|
53
54
|
/**
|
|
54
55
|
* A frontend/app-minted correlation id that groups every request triggered by ONE user ACTION.
|
|
55
56
|
*
|
|
@@ -73,15 +74,15 @@ export declare class WebpiecesCoreHeaders {
|
|
|
73
74
|
* outbound hops, so the id follows the action across services.
|
|
74
75
|
* - `isLogged` TRUE → emitted as a plain string on every log line of the request.
|
|
75
76
|
*/
|
|
76
|
-
static readonly ACTION_ID: ContextKey
|
|
77
|
-
static readonly ORG_ID: ContextKey
|
|
78
|
-
static readonly USER_ID: ContextKey
|
|
79
|
-
static readonly USER_ROLES: ContextKey
|
|
77
|
+
static readonly ACTION_ID: ContextKey<string>;
|
|
78
|
+
static readonly ORG_ID: ContextKey<string>;
|
|
79
|
+
static readonly USER_ID: ContextKey<string>;
|
|
80
|
+
static readonly USER_ROLES: ContextKey<string>;
|
|
80
81
|
/**
|
|
81
82
|
* Turns on test-case recording for this request (Java: x-webpieces-recording).
|
|
82
83
|
* Transferred so recording follows the request across service hops.
|
|
83
84
|
*/
|
|
84
|
-
static readonly RECORDING: ContextKey
|
|
85
|
+
static readonly RECORDING: ContextKey<string>;
|
|
85
86
|
/**
|
|
86
87
|
* The structured API-call tag ({@link ApiCallInfo}) stamped by {@link LogApiCall} around every
|
|
87
88
|
* outbound (client) / inbound (server) call. It rides the magic context so EVERY log line emitted
|
|
@@ -94,7 +95,7 @@ export declare class WebpiecesCoreHeaders {
|
|
|
94
95
|
* read it via {@link HeaderRegistry.buildStructuredLogFields} (object-aware); the flat
|
|
95
96
|
* `buildLogFields()` string map deliberately skips it (typeof-string guard).
|
|
96
97
|
*/
|
|
97
|
-
static readonly API_CALL_INFO: ContextKey
|
|
98
|
+
static readonly API_CALL_INFO: ContextKey<ApiCallInfo>;
|
|
98
99
|
/**
|
|
99
100
|
* The inbound request's HTTP method and path, stamped ONCE from the {@link HttpRequest} by
|
|
100
101
|
* `RequestContextHeaders.fillFromRequest` (the atomic inbound choke point every transport funnels
|
|
@@ -106,8 +107,8 @@ export declare class WebpiecesCoreHeaders {
|
|
|
106
107
|
* method/path, never the caller's. Outbound client calls never set these (no inbound path).
|
|
107
108
|
* - `isLogged` TRUE → emitted by the logging backends as plain strings.
|
|
108
109
|
*/
|
|
109
|
-
static readonly HTTP_METHOD: ContextKey
|
|
110
|
-
static readonly REQUEST_PATH: ContextKey
|
|
110
|
+
static readonly HTTP_METHOD: ContextKey<string>;
|
|
111
|
+
static readonly REQUEST_PATH: ContextKey<string>;
|
|
111
112
|
/**
|
|
112
113
|
* The routed endpoint's IMPLEMENTATION identity: the concrete controller class name
|
|
113
114
|
* ({@link RouteMetadata.controllerClassName}, e.g. `LoginController`) and the handler method NAME
|
|
@@ -126,8 +127,8 @@ export declare class WebpiecesCoreHeaders {
|
|
|
126
127
|
* - `httpHeader` UNDEFINED → NOT transferred: each hop stamps its OWN routed controller/method.
|
|
127
128
|
* - `isLogged` TRUE → emitted by the logging backends as plain strings.
|
|
128
129
|
*/
|
|
129
|
-
static readonly CONTROLLER: ContextKey
|
|
130
|
-
static readonly METHOD: ContextKey
|
|
130
|
+
static readonly CONTROLLER: ContextKey<string>;
|
|
131
|
+
static readonly METHOD: ContextKey<string>;
|
|
131
132
|
/**
|
|
132
133
|
* NO CREDENTIAL KEYS LIVE HERE.
|
|
133
134
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WebpiecesCoreHeaders.js","sourceRoot":"","sources":["../../../../../../packages/core/core-util/src/http/WebpiecesCoreHeaders.ts"],"names":[],"mappings":";;;AAAA,8CAA2C;AAE3C;;;;;;;;;;;;;;;GAeG;AACH,MAAa,oBAAoB;IAC7B;;;OAGG;IACH,MAAM,CAAU,UAAU,GAAG,IAAI,uBAAU,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;IAEzE;;;;;;;;;;;;;OAaG;IACH,MAAM,CAAU,iBAAiB,GAAG,IAAI,uBAAU,CAC9C,iBAAiB;IACjB,cAAc,CAAC,SAAS,CAC3B,CAAC;IAEF;;;;;;;;;;;;OAYG;IACH,MAAM,CAAU,cAAc,GAAG,IAAI,uBAAU,CAAC,eAAe,EAAE,4BAA4B,CAAC,CAAC;IAE/F;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,MAAM,CAAU,SAAS,GAAG,IAAI,uBAAU,CAAC,UAAU,EAAE,sBAAsB,CAAC,CAAC;IAE/E,MAAM,CAAU,MAAM,GAAG,IAAI,uBAAU,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IAE7D,MAAM,CAAU,OAAO,GAAG,IAAI,uBAAU,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;IAEhE,MAAM,CAAU,UAAU,GAAG,IAAI,uBAAU,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;IAE1E;;;OAGG;IACH,MAAM,CAAU,SAAS,GAAG,IAAI,uBAAU,CAAC,WAAW,EAAE,uBAAuB,CAAC,CAAC;IAEjF;;;;;;;;;;;OAWG;IACH,MAAM,CAAU,aAAa,GAAG,IAAI,uBAAU,CAAC,KAAK,EAAE,cAAc,CAAC,SAAS,EAAE,aAAa,CAAC,KAAK,EAAE,YAAY,CAAC,IAAI,CAAC,CAAC;IAExH;;;;;;;;;;OAUG;IACH,MAAM,CAAU,WAAW,GAAG,IAAI,uBAAU,CAAC,YAAY,EAAE,cAAc,CAAC,SAAS,EAAE,aAAa,CAAC,KAAK,EAAE,YAAY,CAAC,IAAI,CAAC,CAAC;IAE7H,MAAM,CAAU,YAAY,GAAG,IAAI,uBAAU,CAAC,aAAa,EAAE,cAAc,CAAC,SAAS,EAAE,aAAa,CAAC,KAAK,EAAE,YAAY,CAAC,IAAI,CAAC,CAAC;IAE/H;;;;;;;;;;;;;;;;;OAiBG;IACH,MAAM,CAAU,UAAU,GAAG,IAAI,uBAAU,CAAC,YAAY,EAAE,cAAc,CAAC,SAAS,EAAE,aAAa,CAAC,KAAK,EAAE,YAAY,CAAC,IAAI,CAAC,CAAC;IAE5H,MAAM,CAAU,MAAM,GAAG,IAAI,uBAAU,CAAC,QAAQ,EAAE,cAAc,CAAC,SAAS,EAAE,aAAa,CAAC,KAAK,EAAE,YAAY,CAAC,IAAI,CAAC,CAAC;IAEpH;;;;;;;;;;;;;;;OAeG;IAEH;;OAEG;IACH,MAAM,CAAC,aAAa;QAChB,OAAO;YACH,oBAAoB,CAAC,UAAU;YAC/B,oBAAoB,CAAC,iBAAiB;YACtC,oBAAoB,CAAC,cAAc;YACnC,oBAAoB,CAAC,SAAS;YAC9B,oBAAoB,CAAC,OAAO;YAC5B,oBAAoB,CAAC,MAAM;YAC3B,oBAAoB,CAAC,UAAU;YAC/B,oBAAoB,CAAC,SAAS;YAC9B,oBAAoB,CAAC,aAAa;YAClC,oBAAoB,CAAC,WAAW;YAChC,oBAAoB,CAAC,YAAY;YACjC,oBAAoB,CAAC,UAAU;YAC/B,oBAAoB,CAAC,MAAM;SAC9B,CAAC;IACN,CAAC;;AArKL,oDAsKC","sourcesContent":["import { ContextKey } from '../ContextKey';\n\n/**\n * Core framework context keys — the minimum the WebPieces framework needs to correlate one\n * request across every service it touches, and across every log line each of them writes.\n *\n * ONE id, propagated unchanged. The first service to see a request without an `x-request-id`\n * generates one (RequestContextHeaders.fillFromRequest); every hop copies it onward verbatim. Grep that id and you\n * have the whole call tree. There is no per-hop id and no parent pointer: a chain of ids you must\n * stitch back together buys nothing a single shared id does not already give you.\n *\n * Lives in core-util (browser-safe) so both the http clients and http-server can reference it.\n *\n * Exposed as {@link HeaderRegistry.DEFAULT_HEADERS} — a service opts into these by\n * passing `platformHeaders=true` to `HeaderRegistry.configure(...)`.\n *\n * Each key's `name` is the logical/log name; `httpHeader` is the wire name.\n */\nexport class WebpiecesCoreHeaders {\n /**\n * The id that correlates every hop of one request, and every log line of every hop.\n * Generated by the first service to see a request without one; propagated unchanged after that.\n */\n static readonly REQUEST_ID = new ContextKey('requestId', 'x-request-id');\n\n /**\n * WHICH SERVICE MINTED {@link REQUEST_ID} — the name from {@link ServiceInfo}, stamped by\n * `RequestContextHeaders.fillFromRequest` ONLY on the branch that generates a new id (i.e. when\n * the inbound request carried no `x-request-id`). It answers the question the id alone cannot:\n * \"this trace starts here — is that right?\" An id appearing with no source means it came from\n * outside; an id sourced by a service that should never be an entry point is a routing bug.\n *\n * - `httpHeader` UNDEFINED → NOT transferred over the wire, and that is the WHOLE POINT. If it\n * travelled, hop 2 would inherit it, hop 3 would inherit it, and \"who started this trace\"\n * would be indistinguishable from \"who passed it along\" — the origin, the one fact this key\n * carries, would be lost. It is absent on every hop that did NOT mint the id, which is exactly\n * the signal: present == I am the origin.\n * - `isLogged` TRUE → emitted as a plain string at `jsonPayload.requestIdSource`.\n */\n static readonly REQUEST_ID_SOURCE = new ContextKey(\n 'requestIdSource',\n /*httpHeader*/ undefined\n );\n\n /**\n * The CALLER's build version — so a downstream server's logs record which build of the client\n * called it (surfaces as `jsonPayload.clientVersion`). Distinct from the log line's own `version`\n * (this service's build): `version` answers \"which build wrote this line?\", `clientVersion`\n * answers \"which build asked us to?\".\n *\n * - `httpHeader` SET → transferred over the wire, BUT unlike a normal transferred key it is NOT\n * copied from the context onward. Each hop OVERWRITES it with its OWN `ServiceInfo.getVersion()`\n * as it becomes the client to the next hop (see `buildOutboundHeaders`), so on any given server\n * `clientVersion` is always the IMMEDIATE caller's version, never a stale grand-caller's.\n * - `isLogged` TRUE → the inbound value lands in the context and flows through the normal log\n * field map; no backend change needed.\n */\n static readonly CLIENT_VERSION = new ContextKey('clientVersion', 'x-webpieces-client-version');\n\n /**\n * A frontend/app-minted correlation id that groups every request triggered by ONE user ACTION.\n *\n * An \"action\" is a single thing the user did in the GUI — a CLICK on a button/link, or TYPING in a\n * field — or a background poller tick: anything that may fan out into MULTIPLE remote calls. That one\n * action fires 1..N browser HTTP calls, each of which gets its own framework-minted {@link REQUEST_ID}\n * (one per HTTP call, shared within that call's server→server subtree). `actionId` sits ABOVE\n * `requestId` and is what stitches those N requests back to the single action that caused them:\n *\n * actionId (app-minted, ONE per user action, rides EVERY call of that action)\n * └── 1..N requestId (framework-minted, ONE per HTTP call)\n *\n * Grep one `actionId` in the logs → every `requestId` it spawned, and every log line of the whole\n * action. Minted and refreshed by the app (a UI concern), carried under `x-webpieces-actionid`.\n *\n * Browser/app-minted ONLY: unlike {@link REQUEST_ID}, the framework transfers and logs it but must\n * NOT auto-mint one server-side. Absent `actionId` ⇒ a non-action flow (system / cron / task), which\n * is the correct signal.\n *\n * - `httpHeader` SET → transferred: copied off the inbound request into context and re-emitted on\n * outbound hops, so the id follows the action across services.\n * - `isLogged` TRUE → emitted as a plain string on every log line of the request.\n */\n static readonly ACTION_ID = new ContextKey('actionId', 'x-webpieces-actionid');\n\n static readonly ORG_ID = new ContextKey('orgId', 'x-org-id');\n\n static readonly USER_ID = new ContextKey('userId', 'x-user-id');\n\n static readonly USER_ROLES = new ContextKey('roles', 'x-webpieces-roles');\n\n /**\n * Turns on test-case recording for this request (Java: x-webpieces-recording).\n * Transferred so recording follows the request across service hops.\n */\n static readonly RECORDING = new ContextKey('recording', 'x-webpieces-recording');\n\n /**\n * The structured API-call tag ({@link ApiCallInfo}) stamped by {@link LogApiCall} around every\n * outbound (client) / inbound (server) call. It rides the magic context so EVERY log line emitted\n * during the call inherits a filterable `api` object, surfacing in GCP as nested\n * `jsonPayload.api.{side,type,result,path,method}`.\n *\n * - `httpHeader` UNDEFINED → NOT transferred over the wire. Per-hop only: each server/client hop\n * stamps its own tag, so a downstream server records `side:'server'`, never the caller's `side:'client'`.\n * - `isLogged` TRUE → emitted by the logging backends. It carries an OBJECT value, so the backends\n * read it via {@link HeaderRegistry.buildStructuredLogFields} (object-aware); the flat\n * `buildLogFields()` string map deliberately skips it (typeof-string guard).\n */\n static readonly API_CALL_INFO = new ContextKey('api', /*httpHeader*/ undefined, /*isSecured*/ false, /*isLogged*/ true);\n\n /**\n * The inbound request's HTTP method and path, stamped ONCE from the {@link HttpRequest} by\n * `RequestContextHeaders.fillFromRequest` (the atomic inbound choke point every transport funnels\n * through). They surface as top-level `jsonPayload.httpMethod` / `jsonPayload.requestPath` so every\n * log line of the request carries them — they used to ride inside {@link ApiCallInfo} (`api.path` /\n * `api.method`) but that coupled a per-CALL logger to the per-REQUEST transport shape.\n *\n * - `httpHeader` UNDEFINED → NOT transferred over the wire: a downstream hop stamps its OWN inbound\n * method/path, never the caller's. Outbound client calls never set these (no inbound path).\n * - `isLogged` TRUE → emitted by the logging backends as plain strings.\n */\n static readonly HTTP_METHOD = new ContextKey('httpMethod', /*httpHeader*/ undefined, /*isSecured*/ false, /*isLogged*/ true);\n\n static readonly REQUEST_PATH = new ContextKey('requestPath', /*httpHeader*/ undefined, /*isSecured*/ false, /*isLogged*/ true);\n\n /**\n * The routed endpoint's IMPLEMENTATION identity: the concrete controller class name\n * ({@link RouteMetadata.controllerClassName}, e.g. `LoginController`) and the handler method NAME\n * ({@link RouteMetadata.methodName}, e.g. `login`), stamped once per request by {@link LogApiFilter}\n * after route matching so every subsequent log line of the request carries them.\n *\n * These say WHICH CODE ran, which is what you actually grep for — far more useful than the raw\n * `requestPath`. They are the top-level, filterable twin of what previously only lived nested in\n * {@link ApiCallInfo} (`api.method.controllerName` / `api.method.methodName`). The local console\n * formatters render them together as a compact `[Controller.method]` bracket; GCP keeps them as two\n * separate `jsonPayload.controller` / `jsonPayload.method` fields.\n *\n * NOTE: `method` here is the CODE method name (e.g. `login`), NOT the HTTP verb — that is\n * {@link HTTP_METHOD} (`httpMethod`).\n *\n * - `httpHeader` UNDEFINED → NOT transferred: each hop stamps its OWN routed controller/method.\n * - `isLogged` TRUE → emitted by the logging backends as plain strings.\n */\n static readonly CONTROLLER = new ContextKey('controller', /*httpHeader*/ undefined, /*isSecured*/ false, /*isLogged*/ true);\n\n static readonly METHOD = new ContextKey('method', /*httpHeader*/ undefined, /*isSecured*/ false, /*isLogged*/ true);\n\n /**\n * NO CREDENTIAL KEYS LIVE HERE.\n *\n * `authorization` and `x-webpieces-shared-secret` used to be ContextKeys. That made them\n * TRANSFERRED keys, so the inbound transfer copied them off the request into the\n * RequestContext, and every outbound RPC call and enqueued Cloud Task then carried the\n * caller's credential onward — to services that had no business seeing it.\n *\n * A credential belongs to ONE request hop. It is read straight off the {@link HttpRequest}\n * by the framework AuthFilter, and written straight onto the outbound request by the client\n * that mints it (NodeProxyClient, GcpTaskInvoker, InMemoryTaskInvoker). It never enters the\n * magic context, so nothing can propagate it by accident.\n *\n * An app that genuinely wants a credential to travel can still register its own ContextKey for\n * it — but that is now an explicit, visible decision rather than the default.\n */\n\n /**\n * Get all core context keys as an array (the platform DEFAULT_HEADERS set).\n */\n static getAllHeaders(): ContextKey[] {\n return [\n WebpiecesCoreHeaders.REQUEST_ID,\n WebpiecesCoreHeaders.REQUEST_ID_SOURCE,\n WebpiecesCoreHeaders.CLIENT_VERSION,\n WebpiecesCoreHeaders.ACTION_ID,\n WebpiecesCoreHeaders.USER_ID,\n WebpiecesCoreHeaders.ORG_ID,\n WebpiecesCoreHeaders.USER_ROLES,\n WebpiecesCoreHeaders.RECORDING,\n WebpiecesCoreHeaders.API_CALL_INFO,\n WebpiecesCoreHeaders.HTTP_METHOD,\n WebpiecesCoreHeaders.REQUEST_PATH,\n WebpiecesCoreHeaders.CONTROLLER,\n WebpiecesCoreHeaders.METHOD,\n ];\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"WebpiecesCoreHeaders.js","sourceRoot":"","sources":["../../../../../../packages/core/core-util/src/http/WebpiecesCoreHeaders.ts"],"names":[],"mappings":";;;AAAA,8CAA2C;AAG3C;;;;;;;;;;;;;;;GAeG;AACH,MAAa,oBAAoB;IAC7B;;;OAGG;IACH,MAAM,CAAU,UAAU,GAAG,IAAI,uBAAU,CAAS,WAAW,EAAE,cAAc,CAAC,CAAC;IAEjF;;;;;;;;;;;;;OAaG;IACH,MAAM,CAAU,iBAAiB,GAAG,IAAI,uBAAU,CAC9C,iBAAiB;IACjB,cAAc,CAAC,SAAS,CAC3B,CAAC;IAEF;;;;;;;;;;;;OAYG;IACH,MAAM,CAAU,cAAc,GAAG,IAAI,uBAAU,CAAS,eAAe,EAAE,4BAA4B,CAAC,CAAC;IAEvG;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,MAAM,CAAU,SAAS,GAAG,IAAI,uBAAU,CAAS,UAAU,EAAE,sBAAsB,CAAC,CAAC;IAEvF,MAAM,CAAU,MAAM,GAAG,IAAI,uBAAU,CAAS,OAAO,EAAE,UAAU,CAAC,CAAC;IAErE,MAAM,CAAU,OAAO,GAAG,IAAI,uBAAU,CAAS,QAAQ,EAAE,WAAW,CAAC,CAAC;IAExE,MAAM,CAAU,UAAU,GAAG,IAAI,uBAAU,CAAS,OAAO,EAAE,mBAAmB,CAAC,CAAC;IAElF;;;OAGG;IACH,MAAM,CAAU,SAAS,GAAG,IAAI,uBAAU,CAAS,WAAW,EAAE,uBAAuB,CAAC,CAAC;IAEzF;;;;;;;;;;;OAWG;IACH,MAAM,CAAU,aAAa,GAAG,IAAI,uBAAU,CAAc,KAAK,EAAE,cAAc,CAAC,SAAS,EAAE,aAAa,CAAC,KAAK,EAAE,YAAY,CAAC,IAAI,CAAC,CAAC;IAErI;;;;;;;;;;OAUG;IACH,MAAM,CAAU,WAAW,GAAG,IAAI,uBAAU,CAAS,YAAY,EAAE,cAAc,CAAC,SAAS,EAAE,aAAa,CAAC,KAAK,EAAE,YAAY,CAAC,IAAI,CAAC,CAAC;IAErI,MAAM,CAAU,YAAY,GAAG,IAAI,uBAAU,CAAS,aAAa,EAAE,cAAc,CAAC,SAAS,EAAE,aAAa,CAAC,KAAK,EAAE,YAAY,CAAC,IAAI,CAAC,CAAC;IAEvI;;;;;;;;;;;;;;;;;OAiBG;IACH,MAAM,CAAU,UAAU,GAAG,IAAI,uBAAU,CAAS,YAAY,EAAE,cAAc,CAAC,SAAS,EAAE,aAAa,CAAC,KAAK,EAAE,YAAY,CAAC,IAAI,CAAC,CAAC;IAEpI,MAAM,CAAU,MAAM,GAAG,IAAI,uBAAU,CAAS,QAAQ,EAAE,cAAc,CAAC,SAAS,EAAE,aAAa,CAAC,KAAK,EAAE,YAAY,CAAC,IAAI,CAAC,CAAC;IAE5H;;;;;;;;;;;;;;;OAeG;IAEH;;OAEG;IACH,MAAM,CAAC,aAAa;QAChB,OAAO;YACH,oBAAoB,CAAC,UAAU;YAC/B,oBAAoB,CAAC,iBAAiB;YACtC,oBAAoB,CAAC,cAAc;YACnC,oBAAoB,CAAC,SAAS;YAC9B,oBAAoB,CAAC,OAAO;YAC5B,oBAAoB,CAAC,MAAM;YAC3B,oBAAoB,CAAC,UAAU;YAC/B,oBAAoB,CAAC,SAAS;YAC9B,oBAAoB,CAAC,aAAa;YAClC,oBAAoB,CAAC,WAAW;YAChC,oBAAoB,CAAC,YAAY;YACjC,oBAAoB,CAAC,UAAU;YAC/B,oBAAoB,CAAC,MAAM;SAC9B,CAAC;IACN,CAAC;;AArKL,oDAsKC","sourcesContent":["import { ContextKey } from '../ContextKey';\nimport { ApiCallInfo } from './ApiCallInfo';\n\n/**\n * Core framework context keys — the minimum the WebPieces framework needs to correlate one\n * request across every service it touches, and across every log line each of them writes.\n *\n * ONE id, propagated unchanged. The first service to see a request without an `x-request-id`\n * generates one (RequestContextHeaders.fillFromRequest); every hop copies it onward verbatim. Grep that id and you\n * have the whole call tree. There is no per-hop id and no parent pointer: a chain of ids you must\n * stitch back together buys nothing a single shared id does not already give you.\n *\n * Lives in core-util (browser-safe) so both the http clients and http-server can reference it.\n *\n * Exposed as {@link HeaderRegistry.DEFAULT_HEADERS} — a service opts into these by\n * passing `platformHeaders=true` to `HeaderRegistry.configure(...)`.\n *\n * Each key's `name` is the logical/log name; `httpHeader` is the wire name.\n */\nexport class WebpiecesCoreHeaders {\n /**\n * The id that correlates every hop of one request, and every log line of every hop.\n * Generated by the first service to see a request without one; propagated unchanged after that.\n */\n static readonly REQUEST_ID = new ContextKey<string>('requestId', 'x-request-id');\n\n /**\n * WHICH SERVICE MINTED {@link REQUEST_ID} — the name from {@link ServiceInfo}, stamped by\n * `RequestContextHeaders.fillFromRequest` ONLY on the branch that generates a new id (i.e. when\n * the inbound request carried no `x-request-id`). It answers the question the id alone cannot:\n * \"this trace starts here — is that right?\" An id appearing with no source means it came from\n * outside; an id sourced by a service that should never be an entry point is a routing bug.\n *\n * - `httpHeader` UNDEFINED → NOT transferred over the wire, and that is the WHOLE POINT. If it\n * travelled, hop 2 would inherit it, hop 3 would inherit it, and \"who started this trace\"\n * would be indistinguishable from \"who passed it along\" — the origin, the one fact this key\n * carries, would be lost. It is absent on every hop that did NOT mint the id, which is exactly\n * the signal: present == I am the origin.\n * - `isLogged` TRUE → emitted as a plain string at `jsonPayload.requestIdSource`.\n */\n static readonly REQUEST_ID_SOURCE = new ContextKey<string>(\n 'requestIdSource',\n /*httpHeader*/ undefined\n );\n\n /**\n * The CALLER's build version — so a downstream server's logs record which build of the client\n * called it (surfaces as `jsonPayload.clientVersion`). Distinct from the log line's own `version`\n * (this service's build): `version` answers \"which build wrote this line?\", `clientVersion`\n * answers \"which build asked us to?\".\n *\n * - `httpHeader` SET → transferred over the wire, BUT unlike a normal transferred key it is NOT\n * copied from the context onward. Each hop OVERWRITES it with its OWN `ServiceInfo.getVersion()`\n * as it becomes the client to the next hop (see `buildOutboundHeaders`), so on any given server\n * `clientVersion` is always the IMMEDIATE caller's version, never a stale grand-caller's.\n * - `isLogged` TRUE → the inbound value lands in the context and flows through the normal log\n * field map; no backend change needed.\n */\n static readonly CLIENT_VERSION = new ContextKey<string>('clientVersion', 'x-webpieces-client-version');\n\n /**\n * A frontend/app-minted correlation id that groups every request triggered by ONE user ACTION.\n *\n * An \"action\" is a single thing the user did in the GUI — a CLICK on a button/link, or TYPING in a\n * field — or a background poller tick: anything that may fan out into MULTIPLE remote calls. That one\n * action fires 1..N browser HTTP calls, each of which gets its own framework-minted {@link REQUEST_ID}\n * (one per HTTP call, shared within that call's server→server subtree). `actionId` sits ABOVE\n * `requestId` and is what stitches those N requests back to the single action that caused them:\n *\n * actionId (app-minted, ONE per user action, rides EVERY call of that action)\n * └── 1..N requestId (framework-minted, ONE per HTTP call)\n *\n * Grep one `actionId` in the logs → every `requestId` it spawned, and every log line of the whole\n * action. Minted and refreshed by the app (a UI concern), carried under `x-webpieces-actionid`.\n *\n * Browser/app-minted ONLY: unlike {@link REQUEST_ID}, the framework transfers and logs it but must\n * NOT auto-mint one server-side. Absent `actionId` ⇒ a non-action flow (system / cron / task), which\n * is the correct signal.\n *\n * - `httpHeader` SET → transferred: copied off the inbound request into context and re-emitted on\n * outbound hops, so the id follows the action across services.\n * - `isLogged` TRUE → emitted as a plain string on every log line of the request.\n */\n static readonly ACTION_ID = new ContextKey<string>('actionId', 'x-webpieces-actionid');\n\n static readonly ORG_ID = new ContextKey<string>('orgId', 'x-org-id');\n\n static readonly USER_ID = new ContextKey<string>('userId', 'x-user-id');\n\n static readonly USER_ROLES = new ContextKey<string>('roles', 'x-webpieces-roles');\n\n /**\n * Turns on test-case recording for this request (Java: x-webpieces-recording).\n * Transferred so recording follows the request across service hops.\n */\n static readonly RECORDING = new ContextKey<string>('recording', 'x-webpieces-recording');\n\n /**\n * The structured API-call tag ({@link ApiCallInfo}) stamped by {@link LogApiCall} around every\n * outbound (client) / inbound (server) call. It rides the magic context so EVERY log line emitted\n * during the call inherits a filterable `api` object, surfacing in GCP as nested\n * `jsonPayload.api.{side,type,result,path,method}`.\n *\n * - `httpHeader` UNDEFINED → NOT transferred over the wire. Per-hop only: each server/client hop\n * stamps its own tag, so a downstream server records `side:'server'`, never the caller's `side:'client'`.\n * - `isLogged` TRUE → emitted by the logging backends. It carries an OBJECT value, so the backends\n * read it via {@link HeaderRegistry.buildStructuredLogFields} (object-aware); the flat\n * `buildLogFields()` string map deliberately skips it (typeof-string guard).\n */\n static readonly API_CALL_INFO = new ContextKey<ApiCallInfo>('api', /*httpHeader*/ undefined, /*isSecured*/ false, /*isLogged*/ true);\n\n /**\n * The inbound request's HTTP method and path, stamped ONCE from the {@link HttpRequest} by\n * `RequestContextHeaders.fillFromRequest` (the atomic inbound choke point every transport funnels\n * through). They surface as top-level `jsonPayload.httpMethod` / `jsonPayload.requestPath` so every\n * log line of the request carries them — they used to ride inside {@link ApiCallInfo} (`api.path` /\n * `api.method`) but that coupled a per-CALL logger to the per-REQUEST transport shape.\n *\n * - `httpHeader` UNDEFINED → NOT transferred over the wire: a downstream hop stamps its OWN inbound\n * method/path, never the caller's. Outbound client calls never set these (no inbound path).\n * - `isLogged` TRUE → emitted by the logging backends as plain strings.\n */\n static readonly HTTP_METHOD = new ContextKey<string>('httpMethod', /*httpHeader*/ undefined, /*isSecured*/ false, /*isLogged*/ true);\n\n static readonly REQUEST_PATH = new ContextKey<string>('requestPath', /*httpHeader*/ undefined, /*isSecured*/ false, /*isLogged*/ true);\n\n /**\n * The routed endpoint's IMPLEMENTATION identity: the concrete controller class name\n * ({@link RouteMetadata.controllerClassName}, e.g. `LoginController`) and the handler method NAME\n * ({@link RouteMetadata.methodName}, e.g. `login`), stamped once per request by {@link LogApiFilter}\n * after route matching so every subsequent log line of the request carries them.\n *\n * These say WHICH CODE ran, which is what you actually grep for — far more useful than the raw\n * `requestPath`. They are the top-level, filterable twin of what previously only lived nested in\n * {@link ApiCallInfo} (`api.method.controllerName` / `api.method.methodName`). The local console\n * formatters render them together as a compact `[Controller.method]` bracket; GCP keeps them as two\n * separate `jsonPayload.controller` / `jsonPayload.method` fields.\n *\n * NOTE: `method` here is the CODE method name (e.g. `login`), NOT the HTTP verb — that is\n * {@link HTTP_METHOD} (`httpMethod`).\n *\n * - `httpHeader` UNDEFINED → NOT transferred: each hop stamps its OWN routed controller/method.\n * - `isLogged` TRUE → emitted by the logging backends as plain strings.\n */\n static readonly CONTROLLER = new ContextKey<string>('controller', /*httpHeader*/ undefined, /*isSecured*/ false, /*isLogged*/ true);\n\n static readonly METHOD = new ContextKey<string>('method', /*httpHeader*/ undefined, /*isSecured*/ false, /*isLogged*/ true);\n\n /**\n * NO CREDENTIAL KEYS LIVE HERE.\n *\n * `authorization` and `x-webpieces-shared-secret` used to be ContextKeys. That made them\n * TRANSFERRED keys, so the inbound transfer copied them off the request into the\n * RequestContext, and every outbound RPC call and enqueued Cloud Task then carried the\n * caller's credential onward — to services that had no business seeing it.\n *\n * A credential belongs to ONE request hop. It is read straight off the {@link HttpRequest}\n * by the framework AuthFilter, and written straight onto the outbound request by the client\n * that mints it (NodeProxyClient, GcpTaskInvoker, InMemoryTaskInvoker). It never enters the\n * magic context, so nothing can propagate it by accident.\n *\n * An app that genuinely wants a credential to travel can still register its own ContextKey for\n * it — but that is now an explicit, visible decision rather than the default.\n */\n\n /**\n * Get all core context keys as an array (the platform DEFAULT_HEADERS set).\n */\n static getAllHeaders(): ContextKey[] {\n return [\n WebpiecesCoreHeaders.REQUEST_ID,\n WebpiecesCoreHeaders.REQUEST_ID_SOURCE,\n WebpiecesCoreHeaders.CLIENT_VERSION,\n WebpiecesCoreHeaders.ACTION_ID,\n WebpiecesCoreHeaders.USER_ID,\n WebpiecesCoreHeaders.ORG_ID,\n WebpiecesCoreHeaders.USER_ROLES,\n WebpiecesCoreHeaders.RECORDING,\n WebpiecesCoreHeaders.API_CALL_INFO,\n WebpiecesCoreHeaders.HTTP_METHOD,\n WebpiecesCoreHeaders.REQUEST_PATH,\n WebpiecesCoreHeaders.CONTROLLER,\n WebpiecesCoreHeaders.METHOD,\n ];\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TestCaseRecorder.js","sourceRoot":"","sources":["../../../../../../../packages/core/core-util/src/http/recorder/TestCaseRecorder.ts"],"names":[],"mappings":";;;AAAA,iDAA8C;AA6B9C;;GAEG;AACH,MAAa,YAAY;IACrB;;;OAGG;IACH,MAAM,CAAU,QAAQ,GAAG,IAAI,uBAAU,
|
|
1
|
+
{"version":3,"file":"TestCaseRecorder.js","sourceRoot":"","sources":["../../../../../../../packages/core/core-util/src/http/recorder/TestCaseRecorder.ts"],"names":[],"mappings":";;;AAAA,iDAA8C;AA6B9C;;GAEG;AACH,MAAa,YAAY;IACrB;;;OAGG;IACH,MAAM,CAAU,QAAQ,GAAG,IAAI,uBAAU,CAAmB,oBAAoB,EAAE,SAAS,EAAE,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,CAAC;;AAL5H,oCAMC","sourcesContent":["import { ContextKey } from '../../ContextKey';\nimport { RecordedEndpoint } from './RecordedEndpoint';\n\n/**\n * TestCaseRecorder - Records every api call made while serving one inbound\n * request (port of Java TestCaseRecorder).\n *\n * The recorder travels in the request's magic context under\n * RecorderKeys.RECORDER (Java: Context RECORDER_KEY). Downstream hooks -\n * the HTTP client proxy and recordable() in-process wrappers - check the\n * context and record into it when present.\n *\n * The contract lives in http-api (browser-safe, no Node imports) so the\n * http-client can reference it; the implementation (TestCaseRecorderImpl)\n * lives in http-server.\n */\nexport interface TestCaseRecorder {\n /**\n * Record one downstream api call (outbound HTTP or in-process recordable).\n */\n addEndpointInfo(info: RecordedEndpoint): void;\n\n /**\n * The most recently recorded downstream call (for hooks that fill in the\n * response after the call completes).\n */\n getLastEndpointInfo(): RecordedEndpoint | undefined;\n}\n\n/**\n * Context keys for the recording subsystem.\n */\nexport class RecorderKeys {\n /**\n * Key under which the active TestCaseRecorder travels in the request\n * context. Absent = not recording.\n */\n static readonly RECORDER = new ContextKey<TestCaseRecorder>('webpieces-recorder', undefined, false, /*isLogged*/ false);\n}\n"]}
|