@intuitionrobotics/thunderstorm 2.0.9 → 2.0.11

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.
@@ -0,0 +1,13 @@
1
+ import { ApiResponse, ServerApi } from "../../../../modules/server/server-api.js";
2
+ import { type ApiTypeBinder } from "../../../../../shared/types.js";
3
+ import { type ExpressRequest } from "../../../../utils/types.js";
4
+ import { type HealthReport } from "../../../../../shared/health.js";
5
+ export declare class ServerApi_Health_Class extends ServerApi<ApiTypeBinder<"health", HealthReport, void, {}>> {
6
+ private appVersion?;
7
+ constructor();
8
+ setVersion(version: string): this;
9
+ protected process(_request: ExpressRequest, response: ApiResponse): Promise<HealthReport>;
10
+ }
11
+ export declare const ServerApi_Health: ServerApi_Health_Class;
12
+ export default ServerApi_Health;
13
+ //# sourceMappingURL=get.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get.d.ts","sourceRoot":"","sources":["../../../../../../src/main/app-backend/api/v1/utils/health/get.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,WAAW,EAAE,SAAS,EAAC,MAAM,0CAA0C,CAAC;AAChF,OAAO,EAAC,KAAK,aAAa,EAAa,MAAM,gCAAgC,CAAC;AAC9E,OAAO,EAAC,KAAK,cAAc,EAAC,MAAM,4BAA4B,CAAC;AAG/D,OAAO,EAEH,KAAK,YAAY,EAIpB,MAAM,iCAAiC,CAAC;AAmBzC,qBAAa,sBACT,SAAQ,SAAS,CAAC,aAAa,CAAC,QAAQ,EAAE,YAAY,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;IAElE,OAAO,CAAC,UAAU,CAAC,CAAS;;IAO5B,UAAU,CAAC,OAAO,EAAE,MAAM;cAKV,OAAO,CAAC,QAAQ,EAAE,cAAc,EAAE,QAAQ,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;CAoClG;AAED,eAAO,MAAM,gBAAgB,wBAA+B,CAAC;AAC7D,eAAe,gBAAgB,CAAC"}
@@ -0,0 +1,67 @@
1
+ import { ApiResponse, ServerApi } from "../../../../modules/server/server-api.js";
2
+ import { HttpMethod } from "../../../../../shared/types.js";
3
+ import {} from "../../../../utils/types.js";
4
+ import { Storm } from "../../../../core/Storm.js";
5
+ import { currentTimeMillies } from "@intuitionrobotics/ts-common";
6
+ import { isHealthCheckContributor } from "../../../../../shared/health.js";
7
+ const statusRank = { pass: 0, warn: 1, fail: 2 };
8
+ const worse = (a, b) => (statusRank[a] >= statusRank[b] ? a : b);
9
+ // Smart, transparent health endpoint.
10
+ //
11
+ // TRANSPARENT — the framework never injects this for you. Mount it explicitly
12
+ // from your routes file (one visible line), choosing your own path:
13
+ //
14
+ // import {ServerApi_Health} from "@intuitionrobotics/thunderstorm/backend";
15
+ // v1.get("/health", ServerApi_Health.handler); // or
16
+ // v1.get("/health", ServerApi_Health.setVersion(version).handler);
17
+ //
18
+ // SMART — it enumerates every loaded Storm module and reports env / node /
19
+ // uptime. Any module implementing HealthCheckContributor (getHealth())
20
+ // contributes real subsystem health; the overall status is the worst of them,
21
+ // and a "fail" is reflected as HTTP 503 so load balancers / uptime probes can
22
+ // gate on it.
23
+ export class ServerApi_Health_Class extends ServerApi {
24
+ appVersion;
25
+ constructor() {
26
+ super(HttpMethod.GET, "health");
27
+ this.dontPrintResponse();
28
+ }
29
+ setVersion(version) {
30
+ this.appVersion = version;
31
+ return this;
32
+ }
33
+ async process(_request, response) {
34
+ const storm = Storm.getInstance();
35
+ const modules = storm ? storm.filterModules(() => true) : [];
36
+ const moduleHealth = await Promise.all(modules.map(async (module) => {
37
+ const name = module.getName();
38
+ if (!isHealthCheckContributor(module))
39
+ return { name, status: "pass" };
40
+ try {
41
+ const contribution = await module.getHealth();
42
+ return { name, status: contribution.status, detail: contribution.detail };
43
+ }
44
+ catch (e) {
45
+ return { name, status: "fail", detail: e?.message ?? "getHealth() threw" };
46
+ }
47
+ }));
48
+ const status = moduleHealth.reduce((worst, m) => worse(worst, m.status), "pass");
49
+ const report = {
50
+ status,
51
+ env: storm?.getEnvironment() ?? "unknown",
52
+ node: process.version,
53
+ uptimeSec: Math.floor(process.uptime()),
54
+ timestamp: currentTimeMillies(),
55
+ modules: moduleHealth,
56
+ version: this.appVersion
57
+ };
58
+ // Consuming the response here with 503 is safe: ServerApi.call() checks
59
+ // isConsumed() before it would otherwise send the 200 itself.
60
+ if (status === "fail")
61
+ response.json(503, report);
62
+ return report;
63
+ }
64
+ }
65
+ export const ServerApi_Health = new ServerApi_Health_Class();
66
+ export default ServerApi_Health;
67
+ //# sourceMappingURL=get.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get.js","sourceRoot":"","sources":["../../../../../../src/main/app-backend/api/v1/utils/health/get.ts"],"names":[],"mappings":"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"}
package/dist/backend.d.ts CHANGED
@@ -16,4 +16,6 @@ export * from "./app-backend/utils/LogClient_File.js";
16
16
  export * from "./app-backend/utils/file.js";
17
17
  export * from "./app-backend/exceptions.js";
18
18
  export * from "./app-backend/core/Storm.js";
19
+ export * from "./app-backend/api/v1/utils/health/get.js";
20
+ export * from "./shared/health.js";
19
21
  //# sourceMappingURL=backend.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../src/main/backend.ts"],"names":[],"mappings":"AAqBA,cAAc,kDAAkD,CAAC;AACjE,cAAc,4CAA4C,CAAC;AAC3D,cAAc,2CAA2C,CAAC;AAC1D,cAAc,mDAAmD,CAAC;AAClE,cAAc,+CAA+C,CAAC;AAC9D,cAAc,4CAA4C,CAAC;AAC3D,cAAc,4CAA4C,CAAC;AAI3D,OAAO,EAAC,UAAU,EAAC,MAAM,mBAAmB,CAAC;AAC7C,cAAc,+CAA+C,CAAC;AAC9D,cAAc,qCAAqC,CAAC;AACpD,cAAc,uCAAuC,CAAC;AACtD,cAAc,0CAA0C,CAAC;AACzD,cAAc,sCAAsC,CAAC;AACrD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,uCAAuC,CAAC;AACtD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,6BAA6B,CAAC"}
1
+ {"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../src/main/backend.ts"],"names":[],"mappings":"AAqBA,cAAc,kDAAkD,CAAC;AACjE,cAAc,4CAA4C,CAAC;AAC3D,cAAc,2CAA2C,CAAC;AAC1D,cAAc,mDAAmD,CAAC;AAClE,cAAc,+CAA+C,CAAC;AAC9D,cAAc,4CAA4C,CAAC;AAC3D,cAAc,4CAA4C,CAAC;AAI3D,OAAO,EAAC,UAAU,EAAC,MAAM,mBAAmB,CAAC;AAC7C,cAAc,+CAA+C,CAAC;AAC9D,cAAc,qCAAqC,CAAC;AACpD,cAAc,uCAAuC,CAAC;AACtD,cAAc,0CAA0C,CAAC;AACzD,cAAc,sCAAsC,CAAC;AACrD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,uCAAuC,CAAC;AACtD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,6BAA6B,CAAC;AAE5C,cAAc,0CAA0C,CAAC;AACzD,cAAc,oBAAoB,CAAC"}
package/dist/backend.js CHANGED
@@ -39,4 +39,7 @@ export * from "./app-backend/utils/LogClient_File.js";
39
39
  export * from "./app-backend/utils/file.js";
40
40
  export * from "./app-backend/exceptions.js";
41
41
  export * from "./app-backend/core/Storm.js";
42
+ // Smart, transparent health endpoint — mount explicitly: `v1.get("/health", ServerApi_Health.handler)`.
43
+ export * from "./app-backend/api/v1/utils/health/get.js";
44
+ export * from "./shared/health.js";
42
45
  //# sourceMappingURL=backend.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"backend.js","sourceRoot":"","sources":["../src/main/backend.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,cAAc,kDAAkD,CAAC;AACjE,cAAc,4CAA4C,CAAC;AAC3D,cAAc,2CAA2C,CAAC;AAC1D,cAAc,mDAAmD,CAAC;AAClE,cAAc,+CAA+C,CAAC;AAC9D,cAAc,4CAA4C,CAAC;AAC3D,cAAc,4CAA4C,CAAC;AAC3D,uDAAuD;AACvD,kFAAkF;AAClF,gCAAgC;AAChC,OAAO,EAAC,UAAU,EAAC,MAAM,mBAAmB,CAAC;AAC7C,cAAc,+CAA+C,CAAC;AAC9D,cAAc,qCAAqC,CAAC;AACpD,cAAc,uCAAuC,CAAC;AACtD,cAAc,0CAA0C,CAAC;AACzD,cAAc,sCAAsC,CAAC;AACrD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,uCAAuC,CAAC;AACtD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,6BAA6B,CAAC"}
1
+ {"version":3,"file":"backend.js","sourceRoot":"","sources":["../src/main/backend.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,cAAc,kDAAkD,CAAC;AACjE,cAAc,4CAA4C,CAAC;AAC3D,cAAc,2CAA2C,CAAC;AAC1D,cAAc,mDAAmD,CAAC;AAClE,cAAc,+CAA+C,CAAC;AAC9D,cAAc,4CAA4C,CAAC;AAC3D,cAAc,4CAA4C,CAAC;AAC3D,uDAAuD;AACvD,kFAAkF;AAClF,gCAAgC;AAChC,OAAO,EAAC,UAAU,EAAC,MAAM,mBAAmB,CAAC;AAC7C,cAAc,+CAA+C,CAAC;AAC9D,cAAc,qCAAqC,CAAC;AACpD,cAAc,uCAAuC,CAAC;AACtD,cAAc,0CAA0C,CAAC;AACzD,cAAc,sCAAsC,CAAC;AACrD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,uCAAuC,CAAC;AACtD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,6BAA6B,CAAC;AAC5C,wGAAwG;AACxG,cAAc,0CAA0C,CAAC;AACzD,cAAc,oBAAoB,CAAC"}
@@ -0,0 +1,22 @@
1
+ export type HealthStatus = "pass" | "warn" | "fail";
2
+ export type HealthContribution = {
3
+ status: HealthStatus;
4
+ detail?: string;
5
+ };
6
+ export type ModuleHealth = HealthContribution & {
7
+ name: string;
8
+ };
9
+ export type HealthReport = {
10
+ status: HealthStatus;
11
+ env: string;
12
+ node: string;
13
+ uptimeSec: number;
14
+ timestamp: number;
15
+ modules: ModuleHealth[];
16
+ version?: string;
17
+ };
18
+ export interface HealthCheckContributor {
19
+ getHealth(): HealthContribution | Promise<HealthContribution>;
20
+ }
21
+ export declare const isHealthCheckContributor: (module: any) => module is HealthCheckContributor;
22
+ //# sourceMappingURL=health.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.d.ts","sourceRoot":"","sources":["../../src/main/shared/health.ts"],"names":[],"mappings":"AAQA,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAIpD,MAAM,MAAM,kBAAkB,GAAG;IAC7B,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,kBAAkB,GAAG;IAC5C,IAAI,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACvB,MAAM,EAAE,YAAY,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,WAAW,sBAAsB;IACnC,SAAS,IAAI,kBAAkB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;CACjE;AAED,eAAO,MAAM,wBAAwB,GAAI,QAAQ,GAAG,KAAG,MAAM,IAAI,sBACX,CAAC"}
@@ -0,0 +1,9 @@
1
+ // Health-check contract shared by the backend `/health` endpoint.
2
+ //
3
+ // A backend Module opts INTO contributing real subsystem health by
4
+ // implementing HealthCheckContributor. There is no hidden registration — a
5
+ // module shows up as a health contributor only because its own code declares
6
+ // `getHealth()`. Modules that don't implement it are still listed (as a
7
+ // loaded "pass"), so the report always reflects exactly what is running.
8
+ export const isHealthCheckContributor = (module) => !!module && typeof module.getHealth === "function";
9
+ //# sourceMappingURL=health.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.js","sourceRoot":"","sources":["../../src/main/shared/health.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,EAAE;AACF,mEAAmE;AACnE,2EAA2E;AAC3E,6EAA6E;AAC7E,wEAAwE;AACxE,yEAAyE;AA6BzE,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,MAAW,EAAoC,EAAE,CACtF,CAAC,CAAC,MAAM,IAAI,OAAO,MAAM,CAAC,SAAS,KAAK,UAAU,CAAC"}