@webpieces/core-util 0.4.413 → 0.4.415
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
CHANGED
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
* DOES NOT THROW ON READ. {@link getName} / {@link getVersion} return `undefined` when unset, so a
|
|
34
34
|
* log line emitted before `setInfo` (early boot) still ships — it simply omits the version. Logging
|
|
35
35
|
* never blocks on identity. The "a deployed build MUST identify itself" guarantee is enforced ONCE,
|
|
36
|
-
* loudly, at startup by whoever
|
|
37
|
-
* of
|
|
36
|
+
* loudly, at startup by whoever calls {@link setInfo} — `setupRuntime` takes name+version as REQUIRED
|
|
37
|
+
* inputs and calls it, so a blank value throws and kills the deploy — instead of every reader throwing.
|
|
38
38
|
*/
|
|
39
39
|
export declare class ServiceInfo {
|
|
40
40
|
/** This service's name. Process-global; set once at startup. */
|
|
@@ -56,31 +56,15 @@ export declare class ServiceInfo {
|
|
|
56
56
|
/**
|
|
57
57
|
* This service's name, or `undefined` when {@link setInfo} has not been called. Does NOT throw:
|
|
58
58
|
* readers (logging backends, requestIdSource, outbound CLIENT_VERSION) simply omit the field when
|
|
59
|
-
* it is missing, so a pre-`setInfo` log line still emits.
|
|
60
|
-
* {@link
|
|
59
|
+
* it is missing, so a pre-`setInfo` log line still emits. Identity is REQUIRED where it matters —
|
|
60
|
+
* `setupRuntime` takes name+version and calls {@link setInfo} at startup, so a real server is
|
|
61
|
+
* always identified before it serves traffic.
|
|
61
62
|
*/
|
|
62
63
|
static getName(): string | undefined;
|
|
63
64
|
/**
|
|
64
65
|
* This build's version, or `undefined` when unset — same non-throwing contract as {@link getName}.
|
|
65
66
|
*/
|
|
66
67
|
static getVersion(): string | undefined;
|
|
67
|
-
/**
|
|
68
|
-
* FAIL FAST, AT STARTUP. Throws unless BOTH name and version are set. Whoever wants the "a
|
|
69
|
-
* deployed build must be able to say which build it is" guarantee calls this while booting
|
|
70
|
-
* (`setupRuntime` does) — so a forgotten `setInfo` kills the deploy (the revision never goes
|
|
71
|
-
* healthy) instead of quietly shipping logs that cannot say which build emitted them. Nothing on
|
|
72
|
-
* the REQUEST path calls this: a missing log field must never 500 live traffic.
|
|
73
|
-
*
|
|
74
|
-
* @throws Error if {@link setInfo} was never called.
|
|
75
|
-
*/
|
|
76
|
-
static assertIdentified(): void;
|
|
77
68
|
/** Reset — for tests, mirroring {@link ClientRegistry.clear}. */
|
|
78
69
|
static clear(): void;
|
|
79
|
-
/**
|
|
80
|
-
* The one actionable "you forgot to call setInfo" message, thrown by {@link assertIdentified}:
|
|
81
|
-
* setInfo sets BOTH, so either being missing has the identical cause and the identical fix —
|
|
82
|
-
* telling the caller only about the half they happened to read first would send them back for a
|
|
83
|
-
* second round.
|
|
84
|
-
*/
|
|
85
|
-
private static notSetMessage;
|
|
86
70
|
}
|
package/src/http/ServiceInfo.js
CHANGED
|
@@ -36,8 +36,8 @@ exports.ServiceInfo = void 0;
|
|
|
36
36
|
* DOES NOT THROW ON READ. {@link getName} / {@link getVersion} return `undefined` when unset, so a
|
|
37
37
|
* log line emitted before `setInfo` (early boot) still ships — it simply omits the version. Logging
|
|
38
38
|
* never blocks on identity. The "a deployed build MUST identify itself" guarantee is enforced ONCE,
|
|
39
|
-
* loudly, at startup by whoever
|
|
40
|
-
* of
|
|
39
|
+
* loudly, at startup by whoever calls {@link setInfo} — `setupRuntime` takes name+version as REQUIRED
|
|
40
|
+
* inputs and calls it, so a blank value throws and kills the deploy — instead of every reader throwing.
|
|
41
41
|
*/
|
|
42
42
|
class ServiceInfo {
|
|
43
43
|
/** This service's name. Process-global; set once at startup. */
|
|
@@ -71,8 +71,9 @@ class ServiceInfo {
|
|
|
71
71
|
/**
|
|
72
72
|
* This service's name, or `undefined` when {@link setInfo} has not been called. Does NOT throw:
|
|
73
73
|
* readers (logging backends, requestIdSource, outbound CLIENT_VERSION) simply omit the field when
|
|
74
|
-
* it is missing, so a pre-`setInfo` log line still emits.
|
|
75
|
-
* {@link
|
|
74
|
+
* it is missing, so a pre-`setInfo` log line still emits. Identity is REQUIRED where it matters —
|
|
75
|
+
* `setupRuntime` takes name+version and calls {@link setInfo} at startup, so a real server is
|
|
76
|
+
* always identified before it serves traffic.
|
|
76
77
|
*/
|
|
77
78
|
// webpieces-disable no-function-outside-class -- static global singleton (like HeaderRegistry/ClientRegistry); populated once at startup, never DI-injected
|
|
78
79
|
static getName() {
|
|
@@ -85,42 +86,12 @@ class ServiceInfo {
|
|
|
85
86
|
static getVersion() {
|
|
86
87
|
return ServiceInfo.svcVersion;
|
|
87
88
|
}
|
|
88
|
-
/**
|
|
89
|
-
* FAIL FAST, AT STARTUP. Throws unless BOTH name and version are set. Whoever wants the "a
|
|
90
|
-
* deployed build must be able to say which build it is" guarantee calls this while booting
|
|
91
|
-
* (`setupRuntime` does) — so a forgotten `setInfo` kills the deploy (the revision never goes
|
|
92
|
-
* healthy) instead of quietly shipping logs that cannot say which build emitted them. Nothing on
|
|
93
|
-
* the REQUEST path calls this: a missing log field must never 500 live traffic.
|
|
94
|
-
*
|
|
95
|
-
* @throws Error if {@link setInfo} was never called.
|
|
96
|
-
*/
|
|
97
|
-
// webpieces-disable no-function-outside-class -- static global singleton (like HeaderRegistry/ClientRegistry); populated once at startup, never DI-injected
|
|
98
|
-
static assertIdentified() {
|
|
99
|
-
if (!ServiceInfo.svcName || !ServiceInfo.svcVersion) {
|
|
100
|
-
throw new Error(ServiceInfo.notSetMessage());
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
89
|
/** Reset — for tests, mirroring {@link ClientRegistry.clear}. */
|
|
104
90
|
// webpieces-disable no-function-outside-class -- static global singleton (like HeaderRegistry/ClientRegistry); populated once at startup, never DI-injected
|
|
105
91
|
static clear() {
|
|
106
92
|
ServiceInfo.svcName = undefined;
|
|
107
93
|
ServiceInfo.svcVersion = undefined;
|
|
108
94
|
}
|
|
109
|
-
/**
|
|
110
|
-
* The one actionable "you forgot to call setInfo" message, thrown by {@link assertIdentified}:
|
|
111
|
-
* setInfo sets BOTH, so either being missing has the identical cause and the identical fix —
|
|
112
|
-
* telling the caller only about the half they happened to read first would send them back for a
|
|
113
|
-
* second round.
|
|
114
|
-
*/
|
|
115
|
-
// webpieces-disable no-function-outside-class -- static global singleton (like HeaderRegistry/ClientRegistry); populated once at startup, never DI-injected
|
|
116
|
-
static notSetMessage() {
|
|
117
|
-
return ('ServiceInfo.setInfo(...) has not been called. Identify this service at startup:\n' +
|
|
118
|
-
" ServiceInfo.setInfo('my-service', '2.1.0');\n" +
|
|
119
|
-
'The name+version stamp every log line (so you can tell WHICH BUILD emitted a line), ' +
|
|
120
|
-
'the name records which service minted a request id (requestIdSource), and the version ' +
|
|
121
|
-
'travels to downstream servers as clientVersion. The version is opaque — a git SHA, a ' +
|
|
122
|
-
'semver tag, a CI build number, whatever identifies your build.');
|
|
123
|
-
}
|
|
124
95
|
}
|
|
125
96
|
exports.ServiceInfo = ServiceInfo;
|
|
126
97
|
//# sourceMappingURL=ServiceInfo.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ServiceInfo.js","sourceRoot":"","sources":["../../../../../../packages/core/core-util/src/http/ServiceInfo.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,MAAa,WAAW;IACpB,gEAAgE;IACxD,MAAM,CAAC,OAAO,CAAqB;IAE3C,+FAA+F;IACvF,MAAM,CAAC,UAAU,CAAqB;IAE9C;;;;;;;;;;OAUG;IACH,4JAA4J;IAC5J,MAAM,CAAC,OAAO,CAAC,IAAY,EAAE,OAAe;QACxC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,6DAA6D,CAAC,CAAC;QACnF,CAAC;QACD,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CACX,qFAAqF;gBACrF,qFAAqF;gBACrF,2BAA2B,CAC9B,CAAC;QACN,CAAC;QACD,WAAW,CAAC,OAAO,GAAG,IAAI,CAAC;QAC3B,WAAW,CAAC,UAAU,GAAG,OAAO,CAAC;IACrC,CAAC;IAED
|
|
1
|
+
{"version":3,"file":"ServiceInfo.js","sourceRoot":"","sources":["../../../../../../packages/core/core-util/src/http/ServiceInfo.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,MAAa,WAAW;IACpB,gEAAgE;IACxD,MAAM,CAAC,OAAO,CAAqB;IAE3C,+FAA+F;IACvF,MAAM,CAAC,UAAU,CAAqB;IAE9C;;;;;;;;;;OAUG;IACH,4JAA4J;IAC5J,MAAM,CAAC,OAAO,CAAC,IAAY,EAAE,OAAe;QACxC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,6DAA6D,CAAC,CAAC;QACnF,CAAC;QACD,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CACX,qFAAqF;gBACrF,qFAAqF;gBACrF,2BAA2B,CAC9B,CAAC;QACN,CAAC;QACD,WAAW,CAAC,OAAO,GAAG,IAAI,CAAC;QAC3B,WAAW,CAAC,UAAU,GAAG,OAAO,CAAC;IACrC,CAAC;IAED;;;;;;OAMG;IACH,4JAA4J;IAC5J,MAAM,CAAC,OAAO;QACV,OAAO,WAAW,CAAC,OAAO,CAAC;IAC/B,CAAC;IAED;;OAEG;IACH,4JAA4J;IAC5J,MAAM,CAAC,UAAU;QACb,OAAO,WAAW,CAAC,UAAU,CAAC;IAClC,CAAC;IAED,iEAAiE;IACjE,4JAA4J;IAC5J,MAAM,CAAC,KAAK;QACR,WAAW,CAAC,OAAO,GAAG,SAAS,CAAC;QAChC,WAAW,CAAC,UAAU,GAAG,SAAS,CAAC;IACvC,CAAC;CACJ;AA5DD,kCA4DC","sourcesContent":["/**\n * ServiceInfo - the ONE answer to \"what service am I, and which build of it?\", for every part of\n * webpieces that needs it.\n *\n * Configured like {@link HeaderRegistry} / {@link ClientRegistry} / LogManager — populated once at\n * startup, then globally accessible with NO DI wiring. Browser-safe (no `process.env`, no node-only\n * deps), which is why it lives in core-util beside {@link ClientRegistry}.\n *\n * ```ts\n * // startup, FIRST:\n * ServiceInfo.setInfo('my-service', '2.1.0');\n * ```\n *\n * WHY THIS EXISTS. Both facts used to be artifacts of WHICH LOGGING LIBRARY YOU PICKED rather than\n * facts about the service:\n * - the name lived on `BunyanFactoryOptions`, because bunyan REQUIRES a root-logger name\n * (`options.name (string) is required` — bunyan's own TypeError). winston has no such concept, so\n * a winston app shipped its logs UNNAMED.\n * - the version lived on `WinstonFactoryOptions` as `svcGitHash`, so a bunyan app could not stamp a\n * version AT ALL — and the name presumed a git SHA, which not every project deploys from.\n *\n * Switching backends silently changed which fields your logs carried. Several unrelated readers\n * need these same two facts, so they belong to the framework, not to a backend:\n * - the winston backend, to stamp `svcName` + `version`;\n * - the bunyan backend, to stamp `version` (its root-logger `name` is a fixed constant now);\n * - {@link WebpiecesCoreHeaders.REQUEST_ID_SOURCE}, to record WHO minted a request id;\n * - {@link WebpiecesCoreHeaders.CLIENT_VERSION}, so a downstream server can log which build called it.\n *\n * VERSION IS OPAQUE. It is whatever string identifies THIS build — a git SHA, a semver tag, a CI\n * build number. webpieces neither parses nor derives it; the app decides where it comes from (a\n * generated file, an env var, a Docker build arg) and passes it here.\n *\n * DOES NOT THROW ON READ. {@link getName} / {@link getVersion} return `undefined` when unset, so a\n * log line emitted before `setInfo` (early boot) still ships — it simply omits the version. Logging\n * never blocks on identity. The \"a deployed build MUST identify itself\" guarantee is enforced ONCE,\n * loudly, at startup by whoever calls {@link setInfo} — `setupRuntime` takes name+version as REQUIRED\n * inputs and calls it, so a blank value throws and kills the deploy — instead of every reader throwing.\n */\nexport class ServiceInfo {\n /** This service's name. Process-global; set once at startup. */\n private static svcName: string | undefined;\n\n /** This build's version — an opaque app-chosen string. Process-global; set once at startup. */\n private static svcVersion: string | undefined;\n\n /**\n * Identify this service. Call it at startup.\n *\n * LAST CALL WINS, deliberately. A real deployment identifies itself once, but an in-process test\n * can legitimately boot TWO services back-to-back (see the app-example e2e two-server flow), so a\n * \"one process = one service\" rule would reject a case that genuinely exists.\n *\n * @param name - this service's name, e.g. 'my-service'.\n * @param version - the opaque identifier of THIS build (git SHA, semver, CI build number).\n * @throws Error on a blank name or version — that is always a bug, never a use case.\n */\n // webpieces-disable no-function-outside-class -- static global singleton (like HeaderRegistry/ClientRegistry); populated once at startup, never DI-injected\n static setInfo(name: string, version: string): void {\n if (!name || !name.trim()) {\n throw new Error('ServiceInfo.setInfo(...) requires a non-blank service name.');\n }\n if (!version || !version.trim()) {\n throw new Error(\n 'ServiceInfo.setInfo(...) requires a non-blank version. It is opaque to webpieces — ' +\n 'a git SHA, a semver tag, a CI build number — but every deployed build must be able ' +\n 'to say which build it is.',\n );\n }\n ServiceInfo.svcName = name;\n ServiceInfo.svcVersion = version;\n }\n\n /**\n * This service's name, or `undefined` when {@link setInfo} has not been called. Does NOT throw:\n * readers (logging backends, requestIdSource, outbound CLIENT_VERSION) simply omit the field when\n * it is missing, so a pre-`setInfo` log line still emits. Identity is REQUIRED where it matters —\n * `setupRuntime` takes name+version and calls {@link setInfo} at startup, so a real server is\n * always identified before it serves traffic.\n */\n // webpieces-disable no-function-outside-class -- static global singleton (like HeaderRegistry/ClientRegistry); populated once at startup, never DI-injected\n static getName(): string | undefined {\n return ServiceInfo.svcName;\n }\n\n /**\n * This build's version, or `undefined` when unset — same non-throwing contract as {@link getName}.\n */\n // webpieces-disable no-function-outside-class -- static global singleton (like HeaderRegistry/ClientRegistry); populated once at startup, never DI-injected\n static getVersion(): string | undefined {\n return ServiceInfo.svcVersion;\n }\n\n /** Reset — for tests, mirroring {@link ClientRegistry.clear}. */\n // webpieces-disable no-function-outside-class -- static global singleton (like HeaderRegistry/ClientRegistry); populated once at startup, never DI-injected\n static clear(): void {\n ServiceInfo.svcName = undefined;\n ServiceInfo.svcVersion = undefined;\n }\n}\n"]}
|