@twin.org/api-service 0.0.3-next.8 → 0.9.0-next.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/es/healthRoutes.js +107 -0
- package/dist/es/healthRoutes.js.map +1 -0
- package/dist/es/healthService.js +155 -0
- package/dist/es/healthService.js.map +1 -0
- package/dist/es/index.js +7 -0
- package/dist/es/index.js.map +1 -1
- package/dist/es/informationRoutes.js +92 -62
- package/dist/es/informationRoutes.js.map +1 -1
- package/dist/es/informationService.js +13 -59
- package/dist/es/informationService.js.map +1 -1
- package/dist/es/models/IHealthServiceConfig.js +4 -0
- package/dist/es/models/IHealthServiceConfig.js.map +1 -0
- package/dist/es/models/IHealthServiceConstructorOptions.js +2 -0
- package/dist/es/models/IHealthServiceConstructorOptions.js.map +1 -0
- package/dist/es/models/IPlatformServiceConfig.js +4 -0
- package/dist/es/models/IPlatformServiceConfig.js.map +1 -0
- package/dist/es/models/IPlatformServiceConstructorOptions.js +2 -0
- package/dist/es/models/IPlatformServiceConstructorOptions.js.map +1 -0
- package/dist/es/platformService.js +155 -0
- package/dist/es/platformService.js.map +1 -0
- package/dist/es/restEntryPoints.js +10 -0
- package/dist/es/restEntryPoints.js.map +1 -1
- package/dist/types/healthRoutes.d.ts +20 -0
- package/dist/types/healthService.d.ts +42 -0
- package/dist/types/index.d.ts +7 -0
- package/dist/types/informationRoutes.d.ts +11 -3
- package/dist/types/informationService.d.ts +12 -17
- package/dist/types/models/IHealthServiceConfig.d.ts +16 -0
- package/dist/types/models/IHealthServiceConstructorOptions.d.ts +10 -0
- package/dist/types/models/IPlatformServiceConfig.d.ts +10 -0
- package/dist/types/models/IPlatformServiceConstructorOptions.d.ts +15 -0
- package/dist/types/platformService.d.ts +39 -0
- package/dist/types/restEntryPoints.d.ts +3 -0
- package/docs/changelog.md +752 -59
- package/docs/examples.md +74 -1
- package/docs/reference/classes/HealthService.md +123 -0
- package/docs/reference/classes/InformationService.md +20 -66
- package/docs/reference/classes/PlatformService.md +123 -0
- package/docs/reference/functions/generateRestRoutesHealth.md +25 -0
- package/docs/reference/functions/serverLivez.md +31 -0
- package/docs/reference/functions/serverReadyz.md +31 -0
- package/docs/reference/index.md +11 -1
- package/docs/reference/interfaces/IHealthServiceConfig.md +32 -0
- package/docs/reference/interfaces/IHealthServiceConstructorOptions.md +11 -0
- package/docs/reference/interfaces/IInformationServiceConfig.md +5 -5
- package/docs/reference/interfaces/IInformationServiceConstructorOptions.md +1 -1
- package/docs/reference/interfaces/IPlatformServiceConfig.md +17 -0
- package/docs/reference/interfaces/IPlatformServiceConstructorOptions.md +25 -0
- package/docs/reference/variables/restEntryPoints.md +2 -0
- package/docs/reference/variables/tagsHealth.md +5 -0
- package/locales/en.json +7 -1
- package/package.json +13 -8
package/README.md
CHANGED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { ComponentFactory, HealthStatus } from "@twin.org/core";
|
|
2
|
+
/**
|
|
3
|
+
* The tag to associate with the routes.
|
|
4
|
+
*/
|
|
5
|
+
export const tagsHealth = [
|
|
6
|
+
{
|
|
7
|
+
name: "Health",
|
|
8
|
+
description: "Health endpoints for the REST server."
|
|
9
|
+
}
|
|
10
|
+
];
|
|
11
|
+
/**
|
|
12
|
+
* The REST routes for server health.
|
|
13
|
+
* @param baseRouteName Prefix to prepend to the paths.
|
|
14
|
+
* @param componentName The name of the component to use in the routes stored in the ComponentFactory.
|
|
15
|
+
* @returns The generated routes.
|
|
16
|
+
*/
|
|
17
|
+
export function generateRestRoutesHealth(baseRouteName, componentName) {
|
|
18
|
+
const healthRoute = {
|
|
19
|
+
operationId: "serverHealth",
|
|
20
|
+
summary: "Get the health for the server",
|
|
21
|
+
tag: tagsHealth[0].name,
|
|
22
|
+
method: "GET",
|
|
23
|
+
path: `${baseRouteName}/`,
|
|
24
|
+
handler: async (httpRequestContext, request) => serverHealth(httpRequestContext, componentName, request),
|
|
25
|
+
responseType: [
|
|
26
|
+
{
|
|
27
|
+
type: "IServerHealthResponse",
|
|
28
|
+
examples: [
|
|
29
|
+
{
|
|
30
|
+
id: "healthResponseOK",
|
|
31
|
+
description: "The response for the health request.",
|
|
32
|
+
response: {
|
|
33
|
+
body: {
|
|
34
|
+
status: HealthStatus.Ok,
|
|
35
|
+
components: [
|
|
36
|
+
{
|
|
37
|
+
source: "Database",
|
|
38
|
+
status: HealthStatus.Ok
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
source: "Storage",
|
|
42
|
+
status: HealthStatus.Ok
|
|
43
|
+
}
|
|
44
|
+
]
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
id: "healthResponseWarning",
|
|
50
|
+
description: "The response for the health request with warnings.",
|
|
51
|
+
response: {
|
|
52
|
+
body: {
|
|
53
|
+
status: HealthStatus.Warning,
|
|
54
|
+
components: [
|
|
55
|
+
{
|
|
56
|
+
source: "Database",
|
|
57
|
+
status: HealthStatus.Warning,
|
|
58
|
+
description: "slowRunning"
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
source: "Storage",
|
|
62
|
+
status: HealthStatus.Ok
|
|
63
|
+
}
|
|
64
|
+
]
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
id: "healthResponseError",
|
|
70
|
+
description: "The response for the health request with errors.",
|
|
71
|
+
response: {
|
|
72
|
+
body: {
|
|
73
|
+
status: "error",
|
|
74
|
+
components: [
|
|
75
|
+
{
|
|
76
|
+
source: "Database",
|
|
77
|
+
status: "ok"
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
source: "Storage",
|
|
81
|
+
status: "error",
|
|
82
|
+
description: "storageFull"
|
|
83
|
+
}
|
|
84
|
+
]
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
]
|
|
89
|
+
}
|
|
90
|
+
]
|
|
91
|
+
};
|
|
92
|
+
return [healthRoute];
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Get the health for the server.
|
|
96
|
+
* @param httpRequestContext The request context for the API.
|
|
97
|
+
* @param componentName The name of the component to use in the routes.
|
|
98
|
+
* @param request The request.
|
|
99
|
+
* @returns The response object with additional http response properties.
|
|
100
|
+
*/
|
|
101
|
+
export async function serverHealth(httpRequestContext, componentName, request) {
|
|
102
|
+
const component = ComponentFactory.get(componentName);
|
|
103
|
+
return {
|
|
104
|
+
body: await component.healthStatus()
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=healthRoutes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"healthRoutes.js","sourceRoot":"","sources":["../../src/healthRoutes.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAGhE;;GAEG;AACH,MAAM,CAAC,MAAM,UAAU,GAAW;IACjC;QACC,IAAI,EAAE,QAAQ;QACd,WAAW,EAAE,uCAAuC;KACpD;CACD,CAAC;AAEF;;;;;GAKG;AACH,MAAM,UAAU,wBAAwB,CACvC,aAAqB,EACrB,aAAqB;IAErB,MAAM,WAAW,GAAyD;QACzE,WAAW,EAAE,cAAc;QAC3B,OAAO,EAAE,+BAA+B;QACxC,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI;QACvB,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,GAAG,aAAa,GAAG;QACzB,OAAO,EAAE,KAAK,EAAE,kBAAkB,EAAE,OAAO,EAAE,EAAE,CAC9C,YAAY,CAAC,kBAAkB,EAAE,aAAa,EAAE,OAAO,CAAC;QACzD,YAAY,EAAE;YACb;gBACC,IAAI,yBAAiC;gBACrC,QAAQ,EAAE;oBACT;wBACC,EAAE,EAAE,kBAAkB;wBACtB,WAAW,EAAE,sCAAsC;wBACnD,QAAQ,EAAE;4BACT,IAAI,EAAE;gCACL,MAAM,EAAE,YAAY,CAAC,EAAE;gCACvB,UAAU,EAAE;oCACX;wCACC,MAAM,EAAE,UAAU;wCAClB,MAAM,EAAE,YAAY,CAAC,EAAE;qCACvB;oCACD;wCACC,MAAM,EAAE,SAAS;wCACjB,MAAM,EAAE,YAAY,CAAC,EAAE;qCACvB;iCACD;6BACD;yBACD;qBACD;oBACD;wBACC,EAAE,EAAE,uBAAuB;wBAC3B,WAAW,EAAE,oDAAoD;wBACjE,QAAQ,EAAE;4BACT,IAAI,EAAE;gCACL,MAAM,EAAE,YAAY,CAAC,OAAO;gCAC5B,UAAU,EAAE;oCACX;wCACC,MAAM,EAAE,UAAU;wCAClB,MAAM,EAAE,YAAY,CAAC,OAAO;wCAC5B,WAAW,EAAE,aAAa;qCAC1B;oCACD;wCACC,MAAM,EAAE,SAAS;wCACjB,MAAM,EAAE,YAAY,CAAC,EAAE;qCACvB;iCACD;6BACD;yBACD;qBACD;oBACD;wBACC,EAAE,EAAE,qBAAqB;wBACzB,WAAW,EAAE,kDAAkD;wBAC/D,QAAQ,EAAE;4BACT,IAAI,EAAE;gCACL,MAAM,EAAE,OAAO;gCACf,UAAU,EAAE;oCACX;wCACC,MAAM,EAAE,UAAU;wCAClB,MAAM,EAAE,IAAI;qCACZ;oCACD;wCACC,MAAM,EAAE,SAAS;wCACjB,MAAM,EAAE,OAAO;wCACf,WAAW,EAAE,aAAa;qCAC1B;iCACD;6BACD;yBACD;qBACD;iBACD;aACD;SACD;KACD,CAAC;IAEF,OAAO,CAAC,WAAW,CAAC,CAAC;AACtB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CACjC,kBAAuC,EACvC,aAAqB,EACrB,OAA0B;IAE1B,MAAM,SAAS,GAAG,gBAAgB,CAAC,GAAG,CAAmB,aAAa,CAAC,CAAC;IACxE,OAAO;QACN,IAAI,EAAE,MAAM,SAAS,CAAC,YAAY,EAAE;KACpC,CAAC;AACH,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type {\n\tIHealthComponent,\n\tIHttpRequestContext,\n\tINoContentRequest,\n\tIRestRoute,\n\tIServerHealthResponse,\n\tITag\n} from \"@twin.org/api-models\";\nimport { ComponentFactory, HealthStatus } from \"@twin.org/core\";\nimport { nameof } from \"@twin.org/nameof\";\n\n/**\n * The tag to associate with the routes.\n */\nexport const tagsHealth: ITag[] = [\n\t{\n\t\tname: \"Health\",\n\t\tdescription: \"Health endpoints for the REST server.\"\n\t}\n];\n\n/**\n * The REST routes for server health.\n * @param baseRouteName Prefix to prepend to the paths.\n * @param componentName The name of the component to use in the routes stored in the ComponentFactory.\n * @returns The generated routes.\n */\nexport function generateRestRoutesHealth(\n\tbaseRouteName: string,\n\tcomponentName: string\n): IRestRoute[] {\n\tconst healthRoute: IRestRoute<INoContentRequest, IServerHealthResponse> = {\n\t\toperationId: \"serverHealth\",\n\t\tsummary: \"Get the health for the server\",\n\t\ttag: tagsHealth[0].name,\n\t\tmethod: \"GET\",\n\t\tpath: `${baseRouteName}/`,\n\t\thandler: async (httpRequestContext, request) =>\n\t\t\tserverHealth(httpRequestContext, componentName, request),\n\t\tresponseType: [\n\t\t\t{\n\t\t\t\ttype: nameof<IServerHealthResponse>(),\n\t\t\t\texamples: [\n\t\t\t\t\t{\n\t\t\t\t\t\tid: \"healthResponseOK\",\n\t\t\t\t\t\tdescription: \"The response for the health request.\",\n\t\t\t\t\t\tresponse: {\n\t\t\t\t\t\t\tbody: {\n\t\t\t\t\t\t\t\tstatus: HealthStatus.Ok,\n\t\t\t\t\t\t\t\tcomponents: [\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tsource: \"Database\",\n\t\t\t\t\t\t\t\t\t\tstatus: HealthStatus.Ok\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tsource: \"Storage\",\n\t\t\t\t\t\t\t\t\t\tstatus: HealthStatus.Ok\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tid: \"healthResponseWarning\",\n\t\t\t\t\t\tdescription: \"The response for the health request with warnings.\",\n\t\t\t\t\t\tresponse: {\n\t\t\t\t\t\t\tbody: {\n\t\t\t\t\t\t\t\tstatus: HealthStatus.Warning,\n\t\t\t\t\t\t\t\tcomponents: [\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tsource: \"Database\",\n\t\t\t\t\t\t\t\t\t\tstatus: HealthStatus.Warning,\n\t\t\t\t\t\t\t\t\t\tdescription: \"slowRunning\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tsource: \"Storage\",\n\t\t\t\t\t\t\t\t\t\tstatus: HealthStatus.Ok\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tid: \"healthResponseError\",\n\t\t\t\t\t\tdescription: \"The response for the health request with errors.\",\n\t\t\t\t\t\tresponse: {\n\t\t\t\t\t\t\tbody: {\n\t\t\t\t\t\t\t\tstatus: \"error\",\n\t\t\t\t\t\t\t\tcomponents: [\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tsource: \"Database\",\n\t\t\t\t\t\t\t\t\t\tstatus: \"ok\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tsource: \"Storage\",\n\t\t\t\t\t\t\t\t\t\tstatus: \"error\",\n\t\t\t\t\t\t\t\t\t\tdescription: \"storageFull\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t}\n\t\t]\n\t};\n\n\treturn [healthRoute];\n}\n\n/**\n * Get the health for the server.\n * @param httpRequestContext The request context for the API.\n * @param componentName The name of the component to use in the routes.\n * @param request The request.\n * @returns The response object with additional http response properties.\n */\nexport async function serverHealth(\n\thttpRequestContext: IHttpRequestContext,\n\tcomponentName: string,\n\trequest: INoContentRequest\n): Promise<IServerHealthResponse> {\n\tconst component = ComponentFactory.get<IHealthComponent>(componentName);\n\treturn {\n\t\tbody: await component.healthStatus()\n\t};\n}\n"]}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { ContextIdStore } from "@twin.org/context";
|
|
2
|
+
import { BaseError, ComponentFactory, HealthStatus, Is } from "@twin.org/core";
|
|
3
|
+
import { EngineCoreFactory } from "@twin.org/engine-models";
|
|
4
|
+
/**
|
|
5
|
+
* The health service for the server.
|
|
6
|
+
*/
|
|
7
|
+
export class HealthService {
|
|
8
|
+
/**
|
|
9
|
+
* Runtime name for the class.
|
|
10
|
+
*/
|
|
11
|
+
static CLASS_NAME = "HealthService";
|
|
12
|
+
/**
|
|
13
|
+
* The server health.
|
|
14
|
+
* @internal
|
|
15
|
+
*/
|
|
16
|
+
_healthInfo;
|
|
17
|
+
/**
|
|
18
|
+
* The interval for checking the health of the components and setting it in the health service.
|
|
19
|
+
* @internal
|
|
20
|
+
*/
|
|
21
|
+
_healthCheckInterval;
|
|
22
|
+
/**
|
|
23
|
+
* The initial interval for checking the health of the components and setting it in the health service.
|
|
24
|
+
* This is used to check the health of the components immediately after the service is started.
|
|
25
|
+
* @internal
|
|
26
|
+
*/
|
|
27
|
+
_initialInterval;
|
|
28
|
+
/**
|
|
29
|
+
* Interval for checking the health of the components and setting it in the health service.
|
|
30
|
+
* @internal
|
|
31
|
+
*/
|
|
32
|
+
_healthTimer;
|
|
33
|
+
/**
|
|
34
|
+
* Create a new instance of HealthService.
|
|
35
|
+
* @param options The constructor options.
|
|
36
|
+
*/
|
|
37
|
+
constructor(options) {
|
|
38
|
+
this._healthInfo = { status: HealthStatus.Ok, components: [] };
|
|
39
|
+
this._healthCheckInterval = options?.config?.healthCheckInterval ?? 60000;
|
|
40
|
+
this._initialInterval = options?.config?.initialInterval ?? 2000;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Returns the class name of the component.
|
|
44
|
+
* @returns The class name of the component.
|
|
45
|
+
*/
|
|
46
|
+
className() {
|
|
47
|
+
return HealthService.CLASS_NAME;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* The component needs to be started when the node is initialized.
|
|
51
|
+
* @param nodeLoggingComponentType The node logging component type.
|
|
52
|
+
* @returns A promise that resolves when the initial health check timer has been scheduled.
|
|
53
|
+
*/
|
|
54
|
+
async start(nodeLoggingComponentType) {
|
|
55
|
+
const engineCore = EngineCoreFactory.getIfExists("engine");
|
|
56
|
+
if (!Is.empty(engineCore) && Is.empty(this._healthTimer)) {
|
|
57
|
+
// Immediately check health after a startup settling period
|
|
58
|
+
// the interval for the next checks are trigger on success of the current
|
|
59
|
+
// check to prevent overlapping checks in case of long running health checks
|
|
60
|
+
this._healthTimer = globalThis.setTimeout(async () => this.checkHealth(engineCore, nodeLoggingComponentType), this._initialInterval);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* The component needs to be stopped when the node is closed.
|
|
65
|
+
* @param nodeLoggingComponentType The node logging component type.
|
|
66
|
+
* @returns A promise that resolves when the health check timer has been cancelled.
|
|
67
|
+
*/
|
|
68
|
+
async stop(nodeLoggingComponentType) {
|
|
69
|
+
if (this._healthTimer) {
|
|
70
|
+
clearTimeout(this._healthTimer);
|
|
71
|
+
this._healthTimer = undefined;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Get the server health.
|
|
76
|
+
* @returns The service health.
|
|
77
|
+
*/
|
|
78
|
+
async healthStatus() {
|
|
79
|
+
return this._healthInfo;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Check the health of all registered components and set the health info in the service.
|
|
83
|
+
* @param engineCore The engine core to get the registered components from.
|
|
84
|
+
* @param nodeLoggingComponentType The node logging component type to log any errors that occur during health checks.
|
|
85
|
+
* @returns A promise that resolves when all component health checks are complete and the next check is scheduled.
|
|
86
|
+
* @internal
|
|
87
|
+
*/
|
|
88
|
+
async checkHealth(engineCore, nodeLoggingComponentType) {
|
|
89
|
+
await ContextIdStore.run(engineCore.getContextIds() ?? {}, async () => {
|
|
90
|
+
const allHealth = [];
|
|
91
|
+
const registeredInstances = await engineCore.getRegisteredComponents();
|
|
92
|
+
for (const registeredInstance of registeredInstances) {
|
|
93
|
+
const healthMethod = registeredInstance.component.health?.bind(registeredInstance.component);
|
|
94
|
+
if (Is.function(healthMethod)) {
|
|
95
|
+
try {
|
|
96
|
+
allHealth.push(...(await healthMethod()));
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
const nodeLogging = ComponentFactory.getIfExists(nodeLoggingComponentType);
|
|
100
|
+
await nodeLogging?.log({
|
|
101
|
+
level: "error",
|
|
102
|
+
source: HealthService.CLASS_NAME,
|
|
103
|
+
message: "componentHealthCheckFailed",
|
|
104
|
+
data: {
|
|
105
|
+
className: registeredInstance.component.className()
|
|
106
|
+
},
|
|
107
|
+
error: BaseError.fromError(error)
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
this.groupHealthByName(allHealth);
|
|
113
|
+
});
|
|
114
|
+
// Queue the next health check.
|
|
115
|
+
this._healthTimer = globalThis.setTimeout(async () => this.checkHealth(engineCore, nodeLoggingComponentType), this._healthCheckInterval);
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Group raw health entries by name, collapsing duplicates into a parent with a grouped array.
|
|
119
|
+
* @param entries The flat list of health entries from all components.
|
|
120
|
+
* @internal
|
|
121
|
+
*/
|
|
122
|
+
groupHealthByName(entries) {
|
|
123
|
+
const bySource = new Map();
|
|
124
|
+
for (const entry of entries) {
|
|
125
|
+
const existing = bySource.get(entry.source) ?? [];
|
|
126
|
+
existing.push(entry);
|
|
127
|
+
bySource.set(entry.source, existing);
|
|
128
|
+
}
|
|
129
|
+
const result = [];
|
|
130
|
+
for (const [source, group] of bySource) {
|
|
131
|
+
if (group.length > 1) {
|
|
132
|
+
let parentStatus = HealthStatus.Ok;
|
|
133
|
+
if (group.some(e => e.status === HealthStatus.Error)) {
|
|
134
|
+
parentStatus = HealthStatus.Error;
|
|
135
|
+
}
|
|
136
|
+
else if (group.some(e => e.status === HealthStatus.Warning)) {
|
|
137
|
+
parentStatus = HealthStatus.Warning;
|
|
138
|
+
}
|
|
139
|
+
result.push({ source, status: parentStatus, grouped: group });
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
result.push(group[0]);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
let finalStatus = HealthStatus.Ok;
|
|
146
|
+
if (result.some(e => e.status === HealthStatus.Error)) {
|
|
147
|
+
finalStatus = HealthStatus.Error;
|
|
148
|
+
}
|
|
149
|
+
else if (result.some(e => e.status === HealthStatus.Warning)) {
|
|
150
|
+
finalStatus = HealthStatus.Warning;
|
|
151
|
+
}
|
|
152
|
+
this._healthInfo = { status: finalStatus, components: result };
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=healthService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"healthService.js","sourceRoot":"","sources":["../../src/healthService.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { IHealthComponent } from \"@twin.org/api-models\";\nimport { ContextIdStore } from \"@twin.org/context\";\nimport { BaseError, ComponentFactory, HealthStatus, type IHealth, Is } from \"@twin.org/core\";\nimport { EngineCoreFactory, type IEngineCore } from \"@twin.org/engine-models\";\nimport type { ILoggingComponent } from \"@twin.org/logging-models\";\nimport { nameof } from \"@twin.org/nameof\";\nimport type { IHealthServiceConstructorOptions } from \"./models/IHealthServiceConstructorOptions.js\";\n\n/**\n * The health service for the server.\n */\nexport class HealthService implements IHealthComponent {\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<HealthService>();\n\n\t/**\n\t * The server health.\n\t * @internal\n\t */\n\tprivate _healthInfo: {\n\t\tstatus: HealthStatus;\n\t\tcomponents: IHealth[];\n\t};\n\n\t/**\n\t * The interval for checking the health of the components and setting it in the health service.\n\t * @internal\n\t */\n\tprivate readonly _healthCheckInterval: number;\n\n\t/**\n\t * The initial interval for checking the health of the components and setting it in the health service.\n\t * This is used to check the health of the components immediately after the service is started.\n\t * @internal\n\t */\n\tprivate readonly _initialInterval: number;\n\n\t/**\n\t * Interval for checking the health of the components and setting it in the health service.\n\t * @internal\n\t */\n\tprivate _healthTimer: NodeJS.Timeout | undefined;\n\n\t/**\n\t * Create a new instance of HealthService.\n\t * @param options The constructor options.\n\t */\n\tconstructor(options?: IHealthServiceConstructorOptions) {\n\t\tthis._healthInfo = { status: HealthStatus.Ok, components: [] };\n\t\tthis._healthCheckInterval = options?.config?.healthCheckInterval ?? 60000;\n\t\tthis._initialInterval = options?.config?.initialInterval ?? 2000;\n\t}\n\n\t/**\n\t * Returns the class name of the component.\n\t * @returns The class name of the component.\n\t */\n\tpublic className(): string {\n\t\treturn HealthService.CLASS_NAME;\n\t}\n\n\t/**\n\t * The component needs to be started when the node is initialized.\n\t * @param nodeLoggingComponentType The node logging component type.\n\t * @returns A promise that resolves when the initial health check timer has been scheduled.\n\t */\n\tpublic async start(nodeLoggingComponentType?: string): Promise<void> {\n\t\tconst engineCore = EngineCoreFactory.getIfExists(\"engine\");\n\n\t\tif (!Is.empty(engineCore) && Is.empty(this._healthTimer)) {\n\t\t\t// Immediately check health after a startup settling period\n\t\t\t// the interval for the next checks are trigger on success of the current\n\t\t\t// check to prevent overlapping checks in case of long running health checks\n\t\t\tthis._healthTimer = globalThis.setTimeout(\n\t\t\t\tasync () => this.checkHealth(engineCore, nodeLoggingComponentType),\n\t\t\t\tthis._initialInterval\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * The component needs to be stopped when the node is closed.\n\t * @param nodeLoggingComponentType The node logging component type.\n\t * @returns A promise that resolves when the health check timer has been cancelled.\n\t */\n\tpublic async stop(nodeLoggingComponentType?: string): Promise<void> {\n\t\tif (this._healthTimer) {\n\t\t\tclearTimeout(this._healthTimer);\n\t\t\tthis._healthTimer = undefined;\n\t\t}\n\t}\n\n\t/**\n\t * Get the server health.\n\t * @returns The service health.\n\t */\n\tpublic async healthStatus(): Promise<{ status: HealthStatus; components: IHealth[] }> {\n\t\treturn this._healthInfo;\n\t}\n\n\t/**\n\t * Check the health of all registered components and set the health info in the service.\n\t * @param engineCore The engine core to get the registered components from.\n\t * @param nodeLoggingComponentType The node logging component type to log any errors that occur during health checks.\n\t * @returns A promise that resolves when all component health checks are complete and the next check is scheduled.\n\t * @internal\n\t */\n\tprivate async checkHealth(\n\t\tengineCore: IEngineCore,\n\t\tnodeLoggingComponentType?: string\n\t): Promise<void> {\n\t\tawait ContextIdStore.run(engineCore.getContextIds() ?? {}, async () => {\n\t\t\tconst allHealth: IHealth[] = [];\n\n\t\t\tconst registeredInstances = await engineCore.getRegisteredComponents();\n\t\t\tfor (const registeredInstance of registeredInstances) {\n\t\t\t\tconst healthMethod = registeredInstance.component.health?.bind(\n\t\t\t\t\tregisteredInstance.component\n\t\t\t\t);\n\t\t\t\tif (Is.function(healthMethod)) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tallHealth.push(...(await healthMethod()));\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tconst nodeLogging =\n\t\t\t\t\t\t\tComponentFactory.getIfExists<ILoggingComponent>(nodeLoggingComponentType);\n\t\t\t\t\t\tawait nodeLogging?.log({\n\t\t\t\t\t\t\tlevel: \"error\",\n\t\t\t\t\t\t\tsource: HealthService.CLASS_NAME,\n\t\t\t\t\t\t\tmessage: \"componentHealthCheckFailed\",\n\t\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t\tclassName: registeredInstance.component.className()\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\terror: BaseError.fromError(error)\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.groupHealthByName(allHealth);\n\t\t});\n\n\t\t// Queue the next health check.\n\t\tthis._healthTimer = globalThis.setTimeout(\n\t\t\tasync () => this.checkHealth(engineCore, nodeLoggingComponentType),\n\t\t\tthis._healthCheckInterval\n\t\t);\n\t}\n\n\t/**\n\t * Group raw health entries by name, collapsing duplicates into a parent with a grouped array.\n\t * @param entries The flat list of health entries from all components.\n\t * @internal\n\t */\n\tprivate groupHealthByName(entries: IHealth[]): void {\n\t\tconst bySource = new Map<string, IHealth[]>();\n\t\tfor (const entry of entries) {\n\t\t\tconst existing = bySource.get(entry.source) ?? [];\n\t\t\texisting.push(entry);\n\t\t\tbySource.set(entry.source, existing);\n\t\t}\n\n\t\tconst result: IHealth[] = [];\n\t\tfor (const [source, group] of bySource) {\n\t\t\tif (group.length > 1) {\n\t\t\t\tlet parentStatus: HealthStatus = HealthStatus.Ok;\n\n\t\t\t\tif (group.some(e => e.status === HealthStatus.Error)) {\n\t\t\t\t\tparentStatus = HealthStatus.Error;\n\t\t\t\t} else if (group.some(e => e.status === HealthStatus.Warning)) {\n\t\t\t\t\tparentStatus = HealthStatus.Warning;\n\t\t\t\t}\n\n\t\t\t\tresult.push({ source, status: parentStatus, grouped: group });\n\t\t\t} else {\n\t\t\t\tresult.push(group[0]);\n\t\t\t}\n\t\t}\n\n\t\tlet finalStatus: HealthStatus = HealthStatus.Ok;\n\t\tif (result.some(e => e.status === HealthStatus.Error)) {\n\t\t\tfinalStatus = HealthStatus.Error;\n\t\t} else if (result.some(e => e.status === HealthStatus.Warning)) {\n\t\t\tfinalStatus = HealthStatus.Warning;\n\t\t}\n\n\t\tthis._healthInfo = { status: finalStatus, components: result };\n\t}\n}\n"]}
|
package/dist/es/index.js
CHANGED
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
// Copyright 2024 IOTA Stiftung.
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0.
|
|
3
|
+
export * from "./healthRoutes.js";
|
|
4
|
+
export * from "./healthService.js";
|
|
3
5
|
export * from "./informationRoutes.js";
|
|
4
6
|
export * from "./informationService.js";
|
|
7
|
+
export * from "./models/IHealthServiceConfig.js";
|
|
8
|
+
export * from "./models/IHealthServiceConstructorOptions.js";
|
|
5
9
|
export * from "./models/IInformationServiceConfig.js";
|
|
6
10
|
export * from "./models/IInformationServiceConstructorOptions.js";
|
|
11
|
+
export * from "./models/IPlatformServiceConfig.js";
|
|
12
|
+
export * from "./models/IPlatformServiceConstructorOptions.js";
|
|
13
|
+
export * from "./platformService.js";
|
|
7
14
|
export * from "./restEntryPoints.js";
|
|
8
15
|
//# sourceMappingURL=index.js.map
|
package/dist/es/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,uCAAuC,CAAC;AACtD,cAAc,mDAAmD,CAAC;AAClE,cAAc,sBAAsB,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nexport * from \"./informationRoutes.js\";\nexport * from \"./informationService.js\";\nexport * from \"./models/IInformationServiceConfig.js\";\nexport * from \"./models/IInformationServiceConstructorOptions.js\";\nexport * from \"./restEntryPoints.js\";\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,kCAAkC,CAAC;AACjD,cAAc,8CAA8C,CAAC;AAC7D,cAAc,uCAAuC,CAAC;AACtD,cAAc,mDAAmD,CAAC;AAClE,cAAc,oCAAoC,CAAC;AACnD,cAAc,gDAAgD,CAAC;AAC/D,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nexport * from \"./healthRoutes.js\";\nexport * from \"./healthService.js\";\nexport * from \"./informationRoutes.js\";\nexport * from \"./informationService.js\";\nexport * from \"./models/IHealthServiceConfig.js\";\nexport * from \"./models/IHealthServiceConstructorOptions.js\";\nexport * from \"./models/IInformationServiceConfig.js\";\nexport * from \"./models/IInformationServiceConstructorOptions.js\";\nexport * from \"./models/IPlatformServiceConfig.js\";\nexport * from \"./models/IPlatformServiceConstructorOptions.js\";\nexport * from \"./platformService.js\";\nexport * from \"./restEntryPoints.js\";\n"]}
|
|
@@ -32,13 +32,17 @@ export function generateRestRoutesInformation(baseRouteName, componentName) {
|
|
|
32
32
|
id: "serverRootResponse",
|
|
33
33
|
description: "The response for the root request.",
|
|
34
34
|
response: {
|
|
35
|
+
headers: {
|
|
36
|
+
[HeaderTypes.ContentType]: MimeTypes.PlainText
|
|
37
|
+
},
|
|
35
38
|
body: "API Server - 1.0.0"
|
|
36
39
|
}
|
|
37
40
|
}
|
|
38
41
|
]
|
|
39
42
|
}
|
|
40
43
|
],
|
|
41
|
-
skipAuth: true
|
|
44
|
+
skipAuth: true,
|
|
45
|
+
skipTenant: true
|
|
42
46
|
};
|
|
43
47
|
const informationRoute = {
|
|
44
48
|
operationId: "serverInformation",
|
|
@@ -64,7 +68,8 @@ export function generateRestRoutesInformation(baseRouteName, componentName) {
|
|
|
64
68
|
]
|
|
65
69
|
}
|
|
66
70
|
],
|
|
67
|
-
skipAuth: true
|
|
71
|
+
skipAuth: true,
|
|
72
|
+
skipTenant: true
|
|
68
73
|
};
|
|
69
74
|
const favIconRoute = {
|
|
70
75
|
operationId: "serverFavIcon",
|
|
@@ -79,82 +84,84 @@ export function generateRestRoutesInformation(baseRouteName, componentName) {
|
|
|
79
84
|
mimeType: "image/x-icon"
|
|
80
85
|
}
|
|
81
86
|
],
|
|
82
|
-
skipAuth: true
|
|
87
|
+
skipAuth: true,
|
|
88
|
+
skipTenant: true
|
|
83
89
|
};
|
|
84
|
-
const
|
|
85
|
-
operationId: "
|
|
86
|
-
summary: "Get the
|
|
90
|
+
const livezRoute = {
|
|
91
|
+
operationId: "serverLivez",
|
|
92
|
+
summary: "Get the livez status for the server",
|
|
87
93
|
tag: tagsInformation[0].name,
|
|
88
94
|
method: "GET",
|
|
89
|
-
path: `${baseRouteName}/
|
|
90
|
-
handler: async (httpRequestContext, request) =>
|
|
95
|
+
path: `${baseRouteName}/livez`,
|
|
96
|
+
handler: async (httpRequestContext, request) => serverLivez(httpRequestContext, componentName, request),
|
|
91
97
|
responseType: [
|
|
92
98
|
{
|
|
93
|
-
type: "
|
|
99
|
+
type: "IServerLivezResponse",
|
|
100
|
+
mimeType: MimeTypes.PlainText,
|
|
94
101
|
examples: [
|
|
95
102
|
{
|
|
96
|
-
id: "
|
|
97
|
-
description: "The response for the
|
|
103
|
+
id: "livezResponseOK",
|
|
104
|
+
description: "The response for the liveness request.",
|
|
98
105
|
response: {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
name: "Database",
|
|
104
|
-
status: "ok"
|
|
105
|
-
},
|
|
106
|
-
{
|
|
107
|
-
name: "Storage",
|
|
108
|
-
status: "ok"
|
|
109
|
-
}
|
|
110
|
-
]
|
|
111
|
-
}
|
|
106
|
+
headers: {
|
|
107
|
+
[HeaderTypes.ContentType]: MimeTypes.PlainText
|
|
108
|
+
},
|
|
109
|
+
body: "alive"
|
|
112
110
|
}
|
|
113
111
|
},
|
|
114
112
|
{
|
|
115
|
-
id: "
|
|
116
|
-
description: "The response for the
|
|
113
|
+
id: "livezResponseFailure",
|
|
114
|
+
description: "The response for the liveness request with errors.",
|
|
117
115
|
response: {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
116
|
+
headers: {
|
|
117
|
+
[HeaderTypes.ContentType]: MimeTypes.PlainText
|
|
118
|
+
},
|
|
119
|
+
body: "dead"
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
]
|
|
123
|
+
}
|
|
124
|
+
],
|
|
125
|
+
skipAuth: true,
|
|
126
|
+
skipTenant: true
|
|
127
|
+
};
|
|
128
|
+
const readyzRoute = {
|
|
129
|
+
operationId: "serverReadyz",
|
|
130
|
+
summary: "Get the readyz status for the server",
|
|
131
|
+
tag: tagsInformation[0].name,
|
|
132
|
+
method: "GET",
|
|
133
|
+
path: `${baseRouteName}/readyz`,
|
|
134
|
+
handler: async (httpRequestContext, request) => serverReadyz(httpRequestContext, componentName, request),
|
|
135
|
+
responseType: [
|
|
136
|
+
{
|
|
137
|
+
type: "IServerReadyzResponse",
|
|
138
|
+
mimeType: MimeTypes.PlainText,
|
|
139
|
+
examples: [
|
|
140
|
+
{
|
|
141
|
+
id: "readyzResponseOK",
|
|
142
|
+
description: "The response for the readiness request.",
|
|
143
|
+
response: {
|
|
144
|
+
headers: {
|
|
145
|
+
[HeaderTypes.ContentType]: MimeTypes.PlainText
|
|
146
|
+
},
|
|
147
|
+
body: "ready"
|
|
132
148
|
}
|
|
133
149
|
},
|
|
134
150
|
{
|
|
135
|
-
id: "
|
|
136
|
-
description: "The response for the
|
|
151
|
+
id: "readyzResponseFailure",
|
|
152
|
+
description: "The response for the readiness request with errors.",
|
|
137
153
|
response: {
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
name: "Database",
|
|
143
|
-
status: "ok"
|
|
144
|
-
},
|
|
145
|
-
{
|
|
146
|
-
name: "Storage",
|
|
147
|
-
status: "error",
|
|
148
|
-
details: "The storage is full."
|
|
149
|
-
}
|
|
150
|
-
]
|
|
151
|
-
}
|
|
154
|
+
headers: {
|
|
155
|
+
[HeaderTypes.ContentType]: MimeTypes.PlainText
|
|
156
|
+
},
|
|
157
|
+
body: "not ready"
|
|
152
158
|
}
|
|
153
159
|
}
|
|
154
160
|
]
|
|
155
161
|
}
|
|
156
162
|
],
|
|
157
|
-
skipAuth: true
|
|
163
|
+
skipAuth: true,
|
|
164
|
+
skipTenant: true
|
|
158
165
|
};
|
|
159
166
|
const specRoute = {
|
|
160
167
|
operationId: "serverSpec",
|
|
@@ -181,9 +188,10 @@ export function generateRestRoutesInformation(baseRouteName, componentName) {
|
|
|
181
188
|
]
|
|
182
189
|
}
|
|
183
190
|
],
|
|
184
|
-
skipAuth: true
|
|
191
|
+
skipAuth: true,
|
|
192
|
+
skipTenant: true
|
|
185
193
|
};
|
|
186
|
-
return [rootRoute, favIconRoute, informationRoute,
|
|
194
|
+
return [rootRoute, favIconRoute, informationRoute, livezRoute, readyzRoute, specRoute];
|
|
187
195
|
}
|
|
188
196
|
/**
|
|
189
197
|
* Get the root for the server.
|
|
@@ -195,6 +203,9 @@ export function generateRestRoutesInformation(baseRouteName, componentName) {
|
|
|
195
203
|
export async function serverRoot(httpRequestContext, componentName, request) {
|
|
196
204
|
const component = ComponentFactory.get(componentName);
|
|
197
205
|
return {
|
|
206
|
+
headers: {
|
|
207
|
+
[HeaderTypes.ContentType]: MimeTypes.PlainText
|
|
208
|
+
},
|
|
198
209
|
body: await component.root()
|
|
199
210
|
};
|
|
200
211
|
}
|
|
@@ -212,16 +223,35 @@ export async function serverInfo(httpRequestContext, componentName, request) {
|
|
|
212
223
|
};
|
|
213
224
|
}
|
|
214
225
|
/**
|
|
215
|
-
* Get the
|
|
226
|
+
* Get the livez for the server.
|
|
227
|
+
* @param httpRequestContext The request context for the API.
|
|
228
|
+
* @param componentName The name of the component to use in the routes.
|
|
229
|
+
* @param request The request.
|
|
230
|
+
* @returns The response object with additional http response properties.
|
|
231
|
+
*/
|
|
232
|
+
export async function serverLivez(httpRequestContext, componentName, request) {
|
|
233
|
+
const component = ComponentFactory.get(componentName);
|
|
234
|
+
return {
|
|
235
|
+
headers: {
|
|
236
|
+
[HeaderTypes.ContentType]: MimeTypes.PlainText
|
|
237
|
+
},
|
|
238
|
+
body: (await component.livez()).status
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Get the readyz for the server.
|
|
216
243
|
* @param httpRequestContext The request context for the API.
|
|
217
244
|
* @param componentName The name of the component to use in the routes.
|
|
218
245
|
* @param request The request.
|
|
219
246
|
* @returns The response object with additional http response properties.
|
|
220
247
|
*/
|
|
221
|
-
export async function
|
|
248
|
+
export async function serverReadyz(httpRequestContext, componentName, request) {
|
|
222
249
|
const component = ComponentFactory.get(componentName);
|
|
223
250
|
return {
|
|
224
|
-
|
|
251
|
+
headers: {
|
|
252
|
+
[HeaderTypes.ContentType]: MimeTypes.PlainText
|
|
253
|
+
},
|
|
254
|
+
body: (await component.readyz()).status
|
|
225
255
|
};
|
|
226
256
|
}
|
|
227
257
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"informationRoutes.js","sourceRoot":"","sources":["../../src/informationRoutes.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type {\n\tIHttpRequestContext,\n\tIInformationComponent,\n\tINoContentRequest,\n\tIRestRoute,\n\tIServerFavIconResponse,\n\tIServerHealthResponse,\n\tIServerInfoResponse,\n\tIServerRootResponse,\n\tIServerSpecResponse,\n\tITag\n} from \"@twin.org/api-models\";\nimport { ComponentFactory, Is } from \"@twin.org/core\";\nimport { nameof } from \"@twin.org/nameof\";\nimport { HeaderTypes, HttpStatusCode, MimeTypes } from \"@twin.org/web\";\n\n/**\n * The tag to associate with the routes.\n */\nexport const tagsInformation: ITag[] = [\n\t{\n\t\tname: \"Info\",\n\t\tdescription: \"Information endpoints for the REST server.\"\n\t}\n];\n\n/**\n * The REST routes for server information.\n * @param baseRouteName Prefix to prepend to the paths.\n * @param componentName The name of the component to use in the routes stored in the ComponentFactory.\n * @returns The generated routes.\n */\nexport function generateRestRoutesInformation(\n\tbaseRouteName: string,\n\tcomponentName: string\n): IRestRoute[] {\n\tconst rootRoute: IRestRoute = {\n\t\toperationId: \"serverRoot\",\n\t\tsummary: \"Get the root text page\",\n\t\ttag: tagsInformation[0].name,\n\t\tmethod: \"GET\",\n\t\tpath: `${baseRouteName}/`,\n\t\thandler: async (httpRequestContext, request) =>\n\t\t\tserverRoot(httpRequestContext, componentName, request),\n\t\tresponseType: [\n\t\t\t{\n\t\t\t\ttype: nameof<IServerRootResponse>(),\n\t\t\t\tmimeType: MimeTypes.PlainText,\n\t\t\t\texamples: [\n\t\t\t\t\t{\n\t\t\t\t\t\tid: \"serverRootResponse\",\n\t\t\t\t\t\tdescription: \"The response for the root request.\",\n\t\t\t\t\t\tresponse: {\n\t\t\t\t\t\t\tbody: \"API Server - 1.0.0\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t}\n\t\t],\n\t\tskipAuth: true\n\t};\n\n\tconst informationRoute: IRestRoute<INoContentRequest, IServerInfoResponse> = {\n\t\toperationId: \"serverInformation\",\n\t\tsummary: \"Get the information for the server\",\n\t\ttag: tagsInformation[0].name,\n\t\tmethod: \"GET\",\n\t\tpath: `${baseRouteName}/info`,\n\t\thandler: async (httpRequestContext, request) =>\n\t\t\tserverInfo(httpRequestContext, componentName, request),\n\t\tresponseType: [\n\t\t\t{\n\t\t\t\ttype: nameof<IServerInfoResponse>(),\n\t\t\t\texamples: [\n\t\t\t\t\t{\n\t\t\t\t\t\tid: \"informationResponse\",\n\t\t\t\t\t\tdescription: \"The response for the information request.\",\n\t\t\t\t\t\tresponse: {\n\t\t\t\t\t\t\tbody: {\n\t\t\t\t\t\t\t\tname: \"API Server\",\n\t\t\t\t\t\t\t\tversion: \"1.0.0\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t}\n\t\t],\n\t\tskipAuth: true\n\t};\n\n\tconst favIconRoute: IRestRoute<INoContentRequest, IServerFavIconResponse> = {\n\t\toperationId: \"serverFavIcon\",\n\t\tsummary: \"Get the favicon for the server\",\n\t\ttag: tagsInformation[0].name,\n\t\tmethod: \"GET\",\n\t\tpath: `${baseRouteName}/favicon.ico`,\n\t\thandler: async (httpRequestContext, request) =>\n\t\t\tserverFavIcon(httpRequestContext, componentName, request),\n\t\tresponseType: [\n\t\t\t{\n\t\t\t\ttype: nameof<IServerFavIconResponse>(),\n\t\t\t\tmimeType: \"image/x-icon\"\n\t\t\t}\n\t\t],\n\t\tskipAuth: true\n\t};\n\n\tconst healthRoute: IRestRoute<INoContentRequest, IServerHealthResponse> = {\n\t\toperationId: \"serverHealth\",\n\t\tsummary: \"Get the health for the server\",\n\t\ttag: tagsInformation[0].name,\n\t\tmethod: \"GET\",\n\t\tpath: `${baseRouteName}/health`,\n\t\thandler: async (httpRequestContext, request) =>\n\t\t\tserverHealth(httpRequestContext, componentName, request),\n\t\tresponseType: [\n\t\t\t{\n\t\t\t\ttype: nameof<IServerHealthResponse>(),\n\t\t\t\texamples: [\n\t\t\t\t\t{\n\t\t\t\t\t\tid: \"healthResponseOK\",\n\t\t\t\t\t\tdescription: \"The response for the health request.\",\n\t\t\t\t\t\tresponse: {\n\t\t\t\t\t\t\tbody: {\n\t\t\t\t\t\t\t\tstatus: \"ok\",\n\t\t\t\t\t\t\t\tcomponents: [\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tname: \"Database\",\n\t\t\t\t\t\t\t\t\t\tstatus: \"ok\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tname: \"Storage\",\n\t\t\t\t\t\t\t\t\t\tstatus: \"ok\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tid: \"healthResponseWarning\",\n\t\t\t\t\t\tdescription: \"The response for the health request with warnings.\",\n\t\t\t\t\t\tresponse: {\n\t\t\t\t\t\t\tbody: {\n\t\t\t\t\t\t\t\tstatus: \"warning\",\n\t\t\t\t\t\t\t\tcomponents: [\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tname: \"Database\",\n\t\t\t\t\t\t\t\t\t\tstatus: \"warning\",\n\t\t\t\t\t\t\t\t\t\tdetails: \"The database is running slow.\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tname: \"Storage\",\n\t\t\t\t\t\t\t\t\t\tstatus: \"ok\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tid: \"healthResponseError\",\n\t\t\t\t\t\tdescription: \"The response for the health request with errors.\",\n\t\t\t\t\t\tresponse: {\n\t\t\t\t\t\t\tbody: {\n\t\t\t\t\t\t\t\tstatus: \"error\",\n\t\t\t\t\t\t\t\tcomponents: [\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tname: \"Database\",\n\t\t\t\t\t\t\t\t\t\tstatus: \"ok\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tname: \"Storage\",\n\t\t\t\t\t\t\t\t\t\tstatus: \"error\",\n\t\t\t\t\t\t\t\t\t\tdetails: \"The storage is full.\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t}\n\t\t],\n\t\tskipAuth: true\n\t};\n\n\tconst specRoute: IRestRoute<INoContentRequest, IServerSpecResponse> = {\n\t\toperationId: \"serverSpec\",\n\t\tsummary: \"Get the OpenAPI specification for the endpoints\",\n\t\ttag: tagsInformation[0].name,\n\t\tmethod: \"GET\",\n\t\tpath: `${baseRouteName}/spec`,\n\t\thandler: async (httpRequestContext, request) =>\n\t\t\tserverSpec(httpRequestContext, componentName, request),\n\t\tresponseType: [\n\t\t\t{\n\t\t\t\ttype: nameof<IServerSpecResponse>(),\n\t\t\t\texamples: [\n\t\t\t\t\t{\n\t\t\t\t\t\tid: \"specResponse\",\n\t\t\t\t\t\tdescription: \"The response for the spec request.\",\n\t\t\t\t\t\tresponse: {\n\t\t\t\t\t\t\tbody: {\n\t\t\t\t\t\t\t\topenapi: \"3.1.0\",\n\t\t\t\t\t\t\t\tinfo: {},\n\t\t\t\t\t\t\t\tpaths: {}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t}\n\t\t],\n\t\tskipAuth: true\n\t};\n\n\treturn [rootRoute, favIconRoute, informationRoute, healthRoute, specRoute];\n}\n\n/**\n * Get the root for the server.\n * @param httpRequestContext The request context for the API.\n * @param componentName The name of the component to use in the routes.\n * @param request The request.\n * @returns The response object with additional http response properties.\n */\nexport async function serverRoot(\n\thttpRequestContext: IHttpRequestContext,\n\tcomponentName: string,\n\trequest: INoContentRequest\n): Promise<IServerRootResponse> {\n\tconst component = ComponentFactory.get<IInformationComponent>(componentName);\n\treturn {\n\t\tbody: await component.root()\n\t};\n}\n\n/**\n * Get the information for the server.\n * @param httpRequestContext The request context for the API.\n * @param componentName The name of the component to use in the routes.\n * @param request The request.\n * @returns The response object with additional http response properties.\n */\nexport async function serverInfo(\n\thttpRequestContext: IHttpRequestContext,\n\tcomponentName: string,\n\trequest: INoContentRequest\n): Promise<IServerInfoResponse> {\n\tconst component = ComponentFactory.get<IInformationComponent>(componentName);\n\treturn {\n\t\tbody: await component.info()\n\t};\n}\n\n/**\n * Get the health for the server.\n * @param httpRequestContext The request context for the API.\n * @param componentName The name of the component to use in the routes.\n * @param request The request.\n * @returns The response object with additional http response properties.\n */\nexport async function serverHealth(\n\thttpRequestContext: IHttpRequestContext,\n\tcomponentName: string,\n\trequest: INoContentRequest\n): Promise<IServerHealthResponse> {\n\tconst component = ComponentFactory.get<IInformationComponent>(componentName);\n\treturn {\n\t\tbody: await component.health()\n\t};\n}\n\n/**\n * Get the favicon for the server.\n * @param httpRequestContext The request context for the API.\n * @param componentName The name of the component to use in the routes.\n * @param request The request.\n * @returns The response object with additional http response properties.\n */\nexport async function serverFavIcon(\n\thttpRequestContext: IHttpRequestContext,\n\tcomponentName: string,\n\trequest: INoContentRequest\n): Promise<IServerFavIconResponse> {\n\tconst component = ComponentFactory.get<IInformationComponent>(componentName);\n\tconst favIcon = await component.favicon();\n\n\tif (Is.uint8Array(favIcon)) {\n\t\treturn {\n\t\t\theaders: {\n\t\t\t\t[HeaderTypes.ContentType]: \"image/x-icon\"\n\t\t\t},\n\t\t\tbody: favIcon\n\t\t};\n\t}\n\treturn {\n\t\tstatusCode: HttpStatusCode.notFound\n\t};\n}\n\n/**\n * Get the spec for the server.\n * @param httpRequestContext The request context for the API.\n * @param componentName The name of the component to use in the routes.\n * @param request The request.\n * @returns The response object with additional http response properties.\n */\nexport async function serverSpec(\n\thttpRequestContext: IHttpRequestContext,\n\tcomponentName: string,\n\trequest: INoContentRequest\n): Promise<IServerSpecResponse> {\n\tconst component = ComponentFactory.get<IInformationComponent>(componentName);\n\tconst spec = await component.spec();\n\n\tif (Is.objectValue(spec)) {\n\t\treturn {\n\t\t\tbody: spec\n\t\t};\n\t}\n\treturn {\n\t\tstatusCode: HttpStatusCode.notFound\n\t};\n}\n"]}
|
|
1
|
+
{"version":3,"file":"informationRoutes.js","sourceRoot":"","sources":["../../src/informationRoutes.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type {\n\tIHttpRequestContext,\n\tIInformationComponent,\n\tINoContentRequest,\n\tIRestRoute,\n\tIServerFavIconResponse,\n\tIServerInfoResponse,\n\tIServerLivezResponse,\n\tIServerReadyzResponse,\n\tIServerRootResponse,\n\tIServerSpecResponse,\n\tITag\n} from \"@twin.org/api-models\";\nimport { ComponentFactory, Is } from \"@twin.org/core\";\nimport { nameof } from \"@twin.org/nameof\";\nimport { HeaderTypes, HttpStatusCode, MimeTypes } from \"@twin.org/web\";\n\n/**\n * The tag to associate with the routes.\n */\nexport const tagsInformation: ITag[] = [\n\t{\n\t\tname: \"Info\",\n\t\tdescription: \"Information endpoints for the REST server.\"\n\t}\n];\n\n/**\n * The REST routes for server information.\n * @param baseRouteName Prefix to prepend to the paths.\n * @param componentName The name of the component to use in the routes stored in the ComponentFactory.\n * @returns The generated routes.\n */\nexport function generateRestRoutesInformation(\n\tbaseRouteName: string,\n\tcomponentName: string\n): IRestRoute[] {\n\tconst rootRoute: IRestRoute = {\n\t\toperationId: \"serverRoot\",\n\t\tsummary: \"Get the root text page\",\n\t\ttag: tagsInformation[0].name,\n\t\tmethod: \"GET\",\n\t\tpath: `${baseRouteName}/`,\n\t\thandler: async (httpRequestContext, request) =>\n\t\t\tserverRoot(httpRequestContext, componentName, request),\n\t\tresponseType: [\n\t\t\t{\n\t\t\t\ttype: nameof<IServerRootResponse>(),\n\t\t\t\tmimeType: MimeTypes.PlainText,\n\t\t\t\texamples: [\n\t\t\t\t\t{\n\t\t\t\t\t\tid: \"serverRootResponse\",\n\t\t\t\t\t\tdescription: \"The response for the root request.\",\n\t\t\t\t\t\tresponse: {\n\t\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\t\t[HeaderTypes.ContentType]: MimeTypes.PlainText\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbody: \"API Server - 1.0.0\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t}\n\t\t],\n\t\tskipAuth: true,\n\t\tskipTenant: true\n\t};\n\n\tconst informationRoute: IRestRoute<INoContentRequest, IServerInfoResponse> = {\n\t\toperationId: \"serverInformation\",\n\t\tsummary: \"Get the information for the server\",\n\t\ttag: tagsInformation[0].name,\n\t\tmethod: \"GET\",\n\t\tpath: `${baseRouteName}/info`,\n\t\thandler: async (httpRequestContext, request) =>\n\t\t\tserverInfo(httpRequestContext, componentName, request),\n\t\tresponseType: [\n\t\t\t{\n\t\t\t\ttype: nameof<IServerInfoResponse>(),\n\t\t\t\texamples: [\n\t\t\t\t\t{\n\t\t\t\t\t\tid: \"informationResponse\",\n\t\t\t\t\t\tdescription: \"The response for the information request.\",\n\t\t\t\t\t\tresponse: {\n\t\t\t\t\t\t\tbody: {\n\t\t\t\t\t\t\t\tname: \"API Server\",\n\t\t\t\t\t\t\t\tversion: \"1.0.0\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t}\n\t\t],\n\t\tskipAuth: true,\n\t\tskipTenant: true\n\t};\n\n\tconst favIconRoute: IRestRoute<INoContentRequest, IServerFavIconResponse> = {\n\t\toperationId: \"serverFavIcon\",\n\t\tsummary: \"Get the favicon for the server\",\n\t\ttag: tagsInformation[0].name,\n\t\tmethod: \"GET\",\n\t\tpath: `${baseRouteName}/favicon.ico`,\n\t\thandler: async (httpRequestContext, request) =>\n\t\t\tserverFavIcon(httpRequestContext, componentName, request),\n\t\tresponseType: [\n\t\t\t{\n\t\t\t\ttype: nameof<IServerFavIconResponse>(),\n\t\t\t\tmimeType: \"image/x-icon\"\n\t\t\t}\n\t\t],\n\t\tskipAuth: true,\n\t\tskipTenant: true\n\t};\n\n\tconst livezRoute: IRestRoute<INoContentRequest, IServerLivezResponse> = {\n\t\toperationId: \"serverLivez\",\n\t\tsummary: \"Get the livez status for the server\",\n\t\ttag: tagsInformation[0].name,\n\t\tmethod: \"GET\",\n\t\tpath: `${baseRouteName}/livez`,\n\t\thandler: async (httpRequestContext, request) =>\n\t\t\tserverLivez(httpRequestContext, componentName, request),\n\t\tresponseType: [\n\t\t\t{\n\t\t\t\ttype: nameof<IServerLivezResponse>(),\n\t\t\t\tmimeType: MimeTypes.PlainText,\n\t\t\t\texamples: [\n\t\t\t\t\t{\n\t\t\t\t\t\tid: \"livezResponseOK\",\n\t\t\t\t\t\tdescription: \"The response for the liveness request.\",\n\t\t\t\t\t\tresponse: {\n\t\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\t\t[HeaderTypes.ContentType]: MimeTypes.PlainText\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbody: \"alive\"\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tid: \"livezResponseFailure\",\n\t\t\t\t\t\tdescription: \"The response for the liveness request with errors.\",\n\t\t\t\t\t\tresponse: {\n\t\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\t\t[HeaderTypes.ContentType]: MimeTypes.PlainText\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbody: \"dead\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t}\n\t\t],\n\t\tskipAuth: true,\n\t\tskipTenant: true\n\t};\n\n\tconst readyzRoute: IRestRoute<INoContentRequest, IServerReadyzResponse> = {\n\t\toperationId: \"serverReadyz\",\n\t\tsummary: \"Get the readyz status for the server\",\n\t\ttag: tagsInformation[0].name,\n\t\tmethod: \"GET\",\n\t\tpath: `${baseRouteName}/readyz`,\n\t\thandler: async (httpRequestContext, request) =>\n\t\t\tserverReadyz(httpRequestContext, componentName, request),\n\t\tresponseType: [\n\t\t\t{\n\t\t\t\ttype: nameof<IServerReadyzResponse>(),\n\t\t\t\tmimeType: MimeTypes.PlainText,\n\t\t\t\texamples: [\n\t\t\t\t\t{\n\t\t\t\t\t\tid: \"readyzResponseOK\",\n\t\t\t\t\t\tdescription: \"The response for the readiness request.\",\n\t\t\t\t\t\tresponse: {\n\t\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\t\t[HeaderTypes.ContentType]: MimeTypes.PlainText\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbody: \"ready\"\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tid: \"readyzResponseFailure\",\n\t\t\t\t\t\tdescription: \"The response for the readiness request with errors.\",\n\t\t\t\t\t\tresponse: {\n\t\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\t\t[HeaderTypes.ContentType]: MimeTypes.PlainText\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbody: \"not ready\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t}\n\t\t],\n\t\tskipAuth: true,\n\t\tskipTenant: true\n\t};\n\n\tconst specRoute: IRestRoute<INoContentRequest, IServerSpecResponse> = {\n\t\toperationId: \"serverSpec\",\n\t\tsummary: \"Get the OpenAPI specification for the endpoints\",\n\t\ttag: tagsInformation[0].name,\n\t\tmethod: \"GET\",\n\t\tpath: `${baseRouteName}/spec`,\n\t\thandler: async (httpRequestContext, request) =>\n\t\t\tserverSpec(httpRequestContext, componentName, request),\n\t\tresponseType: [\n\t\t\t{\n\t\t\t\ttype: nameof<IServerSpecResponse>(),\n\t\t\t\texamples: [\n\t\t\t\t\t{\n\t\t\t\t\t\tid: \"specResponse\",\n\t\t\t\t\t\tdescription: \"The response for the spec request.\",\n\t\t\t\t\t\tresponse: {\n\t\t\t\t\t\t\tbody: {\n\t\t\t\t\t\t\t\topenapi: \"3.1.0\",\n\t\t\t\t\t\t\t\tinfo: {},\n\t\t\t\t\t\t\t\tpaths: {}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t}\n\t\t],\n\t\tskipAuth: true,\n\t\tskipTenant: true\n\t};\n\n\treturn [rootRoute, favIconRoute, informationRoute, livezRoute, readyzRoute, specRoute];\n}\n\n/**\n * Get the root for the server.\n * @param httpRequestContext The request context for the API.\n * @param componentName The name of the component to use in the routes.\n * @param request The request.\n * @returns The response object with additional http response properties.\n */\nexport async function serverRoot(\n\thttpRequestContext: IHttpRequestContext,\n\tcomponentName: string,\n\trequest: INoContentRequest\n): Promise<IServerRootResponse> {\n\tconst component = ComponentFactory.get<IInformationComponent>(componentName);\n\treturn {\n\t\theaders: {\n\t\t\t[HeaderTypes.ContentType]: MimeTypes.PlainText\n\t\t},\n\t\tbody: await component.root()\n\t};\n}\n\n/**\n * Get the information for the server.\n * @param httpRequestContext The request context for the API.\n * @param componentName The name of the component to use in the routes.\n * @param request The request.\n * @returns The response object with additional http response properties.\n */\nexport async function serverInfo(\n\thttpRequestContext: IHttpRequestContext,\n\tcomponentName: string,\n\trequest: INoContentRequest\n): Promise<IServerInfoResponse> {\n\tconst component = ComponentFactory.get<IInformationComponent>(componentName);\n\treturn {\n\t\tbody: await component.info()\n\t};\n}\n\n/**\n * Get the livez for the server.\n * @param httpRequestContext The request context for the API.\n * @param componentName The name of the component to use in the routes.\n * @param request The request.\n * @returns The response object with additional http response properties.\n */\nexport async function serverLivez(\n\thttpRequestContext: IHttpRequestContext,\n\tcomponentName: string,\n\trequest: INoContentRequest\n): Promise<IServerLivezResponse> {\n\tconst component = ComponentFactory.get<IInformationComponent>(componentName);\n\treturn {\n\t\theaders: {\n\t\t\t[HeaderTypes.ContentType]: MimeTypes.PlainText\n\t\t},\n\t\tbody: (await component.livez()).status\n\t};\n}\n\n/**\n * Get the readyz for the server.\n * @param httpRequestContext The request context for the API.\n * @param componentName The name of the component to use in the routes.\n * @param request The request.\n * @returns The response object with additional http response properties.\n */\nexport async function serverReadyz(\n\thttpRequestContext: IHttpRequestContext,\n\tcomponentName: string,\n\trequest: INoContentRequest\n): Promise<IServerReadyzResponse> {\n\tconst component = ComponentFactory.get<IInformationComponent>(componentName);\n\treturn {\n\t\theaders: {\n\t\t\t[HeaderTypes.ContentType]: MimeTypes.PlainText\n\t\t},\n\t\tbody: (await component.readyz()).status\n\t};\n}\n\n/**\n * Get the favicon for the server.\n * @param httpRequestContext The request context for the API.\n * @param componentName The name of the component to use in the routes.\n * @param request The request.\n * @returns The response object with additional http response properties.\n */\nexport async function serverFavIcon(\n\thttpRequestContext: IHttpRequestContext,\n\tcomponentName: string,\n\trequest: INoContentRequest\n): Promise<IServerFavIconResponse> {\n\tconst component = ComponentFactory.get<IInformationComponent>(componentName);\n\tconst favIcon = await component.favicon();\n\n\tif (Is.uint8Array(favIcon)) {\n\t\treturn {\n\t\t\theaders: {\n\t\t\t\t[HeaderTypes.ContentType]: \"image/x-icon\"\n\t\t\t},\n\t\t\tbody: favIcon\n\t\t};\n\t}\n\treturn {\n\t\tstatusCode: HttpStatusCode.notFound\n\t};\n}\n\n/**\n * Get the spec for the server.\n * @param httpRequestContext The request context for the API.\n * @param componentName The name of the component to use in the routes.\n * @param request The request.\n * @returns The response object with additional http response properties.\n */\nexport async function serverSpec(\n\thttpRequestContext: IHttpRequestContext,\n\tcomponentName: string,\n\trequest: INoContentRequest\n): Promise<IServerSpecResponse> {\n\tconst component = ComponentFactory.get<IInformationComponent>(componentName);\n\tconst spec = await component.spec();\n\n\tif (Is.objectValue(spec)) {\n\t\treturn {\n\t\t\tbody: spec\n\t\t};\n\t}\n\treturn {\n\t\tstatusCode: HttpStatusCode.notFound\n\t};\n}\n"]}
|