@tahminator/sapling 2.1.0-beta.4344e0ca → 2.1.0-beta.845ac846
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 +59 -3
- package/dist/index.cjs +17 -17
- package/dist/index.d.cts +18 -19
- package/dist/index.d.mts +18 -19
- package/dist/index.mjs +17 -17
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -26,6 +26,10 @@ A lightweight Express.js dependency injection & route abstraction library.
|
|
|
26
26
|
+ [Automatic Spec Generation](#automatic-spec-generation)
|
|
27
27
|
+ [Adding Documentation with Decorators](#adding-documentation-with-decorators)
|
|
28
28
|
+ [Customizing Paths](#customizing-paths)
|
|
29
|
+
* [Health Checks](#health-checks)
|
|
30
|
+
+ [Liveness and Readiness Probes](#liveness-and-readiness-probes)
|
|
31
|
+
+ [Registering Custom Readiness Checks](#registering-custom-readiness-checks)
|
|
32
|
+
+ [Customizing Health Paths](#customizing-health-paths)
|
|
29
33
|
* [Custom Serialization](#custom-serialization)
|
|
30
34
|
- [Advanced Setup](#advanced-setup)
|
|
31
35
|
* [Automatically import controllers](#automatically-import-controllers)
|
|
@@ -97,9 +101,10 @@ class UserController {
|
|
|
97
101
|
}
|
|
98
102
|
}
|
|
99
103
|
|
|
100
|
-
//
|
|
101
|
-
|
|
102
|
-
|
|
104
|
+
// registerApp returns the app back to you - use the returned app instance
|
|
105
|
+
// so Sapling can inject some post-startup hooks into the app.
|
|
106
|
+
// BUT, you still have full access of app to do whatever you want!
|
|
107
|
+
const app = Sapling.registerApp(express());
|
|
103
108
|
|
|
104
109
|
// @MiddlewareClass should be registered first before @Controller and should be registered in order
|
|
105
110
|
// @Injectable classes will automatically be formed into singletons by Sapling behind the scenes!
|
|
@@ -581,6 +586,57 @@ Sapling.Extras.swaggerAndOpenApi.setOpenApiPath("/api-spec.json");
|
|
|
581
586
|
Sapling.Extras.swaggerAndOpenApi.setSwaggerPath("/api-docs");
|
|
582
587
|
```
|
|
583
588
|
|
|
589
|
+
### Health Checks
|
|
590
|
+
|
|
591
|
+
#### Liveness and Readiness Probes
|
|
592
|
+
|
|
593
|
+
Register `DefaultHealthMiddleware` to expose two health endpoints:
|
|
594
|
+
|
|
595
|
+
- `GET /live` — **liveness probe**: returns `{ up: true }` once the server has started listening. Use this to tell your orchestrator the process is alive.
|
|
596
|
+
- `GET /ready` — **readiness probe**: returns `{ up: true }` once the server is live *and* all registered readiness checks pass. Use this to gate traffic until your app is fully initialized.
|
|
597
|
+
|
|
598
|
+
```typescript
|
|
599
|
+
import { Sapling, DefaultHealthMiddleware } from "@tahminator/sapling";
|
|
600
|
+
|
|
601
|
+
const app = Sapling.registerApp(express());
|
|
602
|
+
|
|
603
|
+
app.use(Sapling.resolve(DefaultHealthMiddleware));
|
|
604
|
+
|
|
605
|
+
app.listen(3000); // _markLive() is called automatically once the server is listening
|
|
606
|
+
```
|
|
607
|
+
|
|
608
|
+
> [!IMPORTANT]
|
|
609
|
+
> `Sapling.registerApp` returns `express.App` - please use that as your `app` object inside of your server. There is a small post-startup hook applied via a proxy, in which the liveness probe is enabled from such.
|
|
610
|
+
|
|
611
|
+
#### Registering Custom Readiness Checks
|
|
612
|
+
|
|
613
|
+
Inject `HealthRegistrar` into any `@Injectable` or controller to add readiness checks. A check is any function returning `boolean | Promise<boolean>`. If any check returns `false` (or throws), `/ready` reports `{ up: false }`.
|
|
614
|
+
|
|
615
|
+
```typescript
|
|
616
|
+
import { Injectable, HealthRegistrar } from "@tahminator/sapling";
|
|
617
|
+
|
|
618
|
+
@Injectable([HealthRegistrar])
|
|
619
|
+
class DatabaseService {
|
|
620
|
+
constructor(
|
|
621
|
+
private readonly db: Database,
|
|
622
|
+
private readonly healthRegistrar: HealthRegistrar,
|
|
623
|
+
) {
|
|
624
|
+
healthRegistrar.add(async () => {
|
|
625
|
+
return this.db.isConnected();
|
|
626
|
+
});
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
```
|
|
630
|
+
|
|
631
|
+
#### Customizing Health Paths
|
|
632
|
+
|
|
633
|
+
The default paths are `/live` and `/ready`. Override them before registering `DefaultHealthMiddleware`:
|
|
634
|
+
|
|
635
|
+
```typescript
|
|
636
|
+
Sapling.Extras.health.setLivePath("/healthz/live");
|
|
637
|
+
Sapling.Extras.health.setReadyPath("/healthz/ready");
|
|
638
|
+
```
|
|
639
|
+
|
|
584
640
|
### Custom Serialization
|
|
585
641
|
|
|
586
642
|
By default, Sapling uses `JSON.stringify` and `JSON.parse` for serialization. You can override these with custom serializers like [superjson](https://github.com/flightcontrolhq/superjson#readme) to automatically handle Dates, BigInts, and more:
|
package/dist/index.cjs
CHANGED
|
@@ -401,15 +401,15 @@ function __decorate(decorators, target, key, desc) {
|
|
|
401
401
|
//#region src/middleware/health/registrar.ts
|
|
402
402
|
let HealthRegistrar = class HealthRegistrar {
|
|
403
403
|
_checks;
|
|
404
|
-
|
|
404
|
+
_live;
|
|
405
405
|
constructor() {
|
|
406
406
|
this._checks = [];
|
|
407
|
-
this.
|
|
407
|
+
this._live = false;
|
|
408
408
|
}
|
|
409
409
|
/**
|
|
410
410
|
* Add a health check.
|
|
411
411
|
*
|
|
412
|
-
* Health checks will be used to determine whether service can serve traffic or not (a.k.a `
|
|
412
|
+
* Health checks will be used to determine whether service can serve traffic or not (a.k.a `readiness`).
|
|
413
413
|
*/
|
|
414
414
|
add(healthCheck) {
|
|
415
415
|
this._checks.push(healthCheck);
|
|
@@ -418,21 +418,21 @@ let HealthRegistrar = class HealthRegistrar {
|
|
|
418
418
|
* @internal used by Sapling library, used to determine once all
|
|
419
419
|
* checks have been registered and server is, at the very least, alive.
|
|
420
420
|
*/
|
|
421
|
-
|
|
422
|
-
this.
|
|
421
|
+
_markLive() {
|
|
422
|
+
this._live = true;
|
|
423
423
|
}
|
|
424
424
|
/**
|
|
425
425
|
* @internal
|
|
426
426
|
*/
|
|
427
|
-
async
|
|
428
|
-
return this.
|
|
427
|
+
async _liveness() {
|
|
428
|
+
return this._live;
|
|
429
429
|
}
|
|
430
430
|
/**
|
|
431
431
|
* @internal
|
|
432
432
|
*/
|
|
433
|
-
async
|
|
434
|
-
if (!this.
|
|
435
|
-
return (await Promise.
|
|
433
|
+
async _readiness() {
|
|
434
|
+
if (!this._live) return false;
|
|
435
|
+
return (await Promise.allSettled(this._checks.map((c) => c()))).every((r) => r.status === "fulfilled" && r.value);
|
|
436
436
|
}
|
|
437
437
|
};
|
|
438
438
|
HealthRegistrar = __decorate([Injectable()], HealthRegistrar);
|
|
@@ -442,8 +442,8 @@ const _settings = {
|
|
|
442
442
|
serialize: JSON.stringify,
|
|
443
443
|
deserialize: JSON.parse,
|
|
444
444
|
health: {
|
|
445
|
-
ready: { path: "/
|
|
446
|
-
live: { path: "/
|
|
445
|
+
ready: { path: "/readyz" },
|
|
446
|
+
live: { path: "/livez" }
|
|
447
447
|
},
|
|
448
448
|
doc: {
|
|
449
449
|
openApiPath: "/openapi.json",
|
|
@@ -539,7 +539,7 @@ var Sapling = class Sapling {
|
|
|
539
539
|
* visible for testing
|
|
540
540
|
*/
|
|
541
541
|
static _onPostStartup() {
|
|
542
|
-
_InjectableRegistry.get(HealthRegistrar)?.
|
|
542
|
+
_InjectableRegistry.get(HealthRegistrar)?._markLive();
|
|
543
543
|
}
|
|
544
544
|
/**
|
|
545
545
|
* Serialize a value into a JSON string.
|
|
@@ -618,7 +618,7 @@ var Sapling = class Sapling {
|
|
|
618
618
|
/**
|
|
619
619
|
* change default endpoint that ready endpoint will be served on.
|
|
620
620
|
*
|
|
621
|
-
* @default `/
|
|
621
|
+
* @default `/readyz`
|
|
622
622
|
*/
|
|
623
623
|
setReadyPath(path) {
|
|
624
624
|
_settings.health.ready.path = path;
|
|
@@ -626,7 +626,7 @@ var Sapling = class Sapling {
|
|
|
626
626
|
/**
|
|
627
627
|
* change default endpoint that live endpoint will be served on.
|
|
628
628
|
*
|
|
629
|
-
* @default `/
|
|
629
|
+
* @default `/livez`
|
|
630
630
|
*/
|
|
631
631
|
setLivePath(path) {
|
|
632
632
|
_settings.health.live.path = path;
|
|
@@ -1226,11 +1226,11 @@ let DefaultHealthMiddleware = class DefaultHealthMiddleware {
|
|
|
1226
1226
|
this.healthRegistrar = healthRegistrar;
|
|
1227
1227
|
}
|
|
1228
1228
|
async readiness(_request, _response, _next) {
|
|
1229
|
-
const up = await this.healthRegistrar.
|
|
1229
|
+
const up = await this.healthRegistrar._readiness();
|
|
1230
1230
|
return ResponseEntity.ok().body({ up });
|
|
1231
1231
|
}
|
|
1232
1232
|
async liveness(_request, _response, _next) {
|
|
1233
|
-
const up = await this.healthRegistrar.
|
|
1233
|
+
const up = await this.healthRegistrar._liveness();
|
|
1234
1234
|
return ResponseEntity.ok().body({ up });
|
|
1235
1235
|
}
|
|
1236
1236
|
};
|
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import e, { ErrorRequestHandler, NextFunction, Request
|
|
1
|
+
import e, { ErrorRequestHandler, NextFunction, Request, RequestHandler, Response as Response$1, Router } from "express";
|
|
2
2
|
|
|
3
3
|
//#region src/html/404.d.ts
|
|
4
4
|
/**
|
|
@@ -26,7 +26,7 @@ type RouteDefinition = {
|
|
|
26
26
|
};
|
|
27
27
|
type Class<T> = new (...args: any[]) => T;
|
|
28
28
|
type HttpHeaders = Record<string, string>;
|
|
29
|
-
type ExpressMiddlewareFn = ($1: Request
|
|
29
|
+
type ExpressMiddlewareFn = ($1: Request, $2: Response$1, $3: NextFunction) => void;
|
|
30
30
|
//#endregion
|
|
31
31
|
//#region src/annotation/controller.d.ts
|
|
32
32
|
declare const _ControllerRegistry: WeakMap<Function, Router | ErrorRequestHandler>;
|
|
@@ -921,13 +921,13 @@ declare class Sapling {
|
|
|
921
921
|
/**
|
|
922
922
|
* change default endpoint that ready endpoint will be served on.
|
|
923
923
|
*
|
|
924
|
-
* @default `/
|
|
924
|
+
* @default `/readyz`
|
|
925
925
|
*/
|
|
926
926
|
setReadyPath(this: void, path: string): void;
|
|
927
927
|
/**
|
|
928
928
|
* change default endpoint that live endpoint will be served on.
|
|
929
929
|
*
|
|
930
|
-
* @default `/
|
|
930
|
+
* @default `/livez`
|
|
931
931
|
*/
|
|
932
932
|
setLivePath(this: void, path: string): void;
|
|
933
933
|
};
|
|
@@ -951,7 +951,7 @@ declare class Sapling {
|
|
|
951
951
|
* }
|
|
952
952
|
* ```
|
|
953
953
|
*/
|
|
954
|
-
static chainHandlers(this: void, handlers: RequestHandler[], request: Request
|
|
954
|
+
static chainHandlers(this: void, handlers: RequestHandler[], request: Request, response: Response$1, next: NextFunction, index?: number): void;
|
|
955
955
|
}
|
|
956
956
|
//#endregion
|
|
957
957
|
//#region src/annotation/validator.d.ts
|
|
@@ -1007,7 +1007,7 @@ declare function _getControllerSchema(ctor: Function): ControllerSchemaDefinitio
|
|
|
1007
1007
|
* If the default is not suitable, you may also easily write your own.
|
|
1008
1008
|
*/
|
|
1009
1009
|
declare class DefaultBaseErrorMiddleware {
|
|
1010
|
-
handle(err: unknown, _request: Request
|
|
1010
|
+
handle(err: unknown, _request: Request, _response: Response$1, _next: NextFunction): ResponseEntity<{
|
|
1011
1011
|
message: string;
|
|
1012
1012
|
}>;
|
|
1013
1013
|
}
|
|
@@ -1018,7 +1018,7 @@ declare class DefaultBaseErrorMiddleware {
|
|
|
1018
1018
|
* If the default is not suitable, you may also easily write your own.
|
|
1019
1019
|
*/
|
|
1020
1020
|
declare class DefaultParserErrorMiddleware {
|
|
1021
|
-
handle(err: unknown, _request: Request
|
|
1021
|
+
handle(err: unknown, _request: Request, _response: Response$1, next: NextFunction): ResponseEntity<{
|
|
1022
1022
|
message: string;
|
|
1023
1023
|
}> | undefined;
|
|
1024
1024
|
}
|
|
@@ -1029,7 +1029,7 @@ declare class DefaultParserErrorMiddleware {
|
|
|
1029
1029
|
* If the default is not suitable, you may also easily write your own.
|
|
1030
1030
|
*/
|
|
1031
1031
|
declare class DefaultResponseStatusErrorMiddleware {
|
|
1032
|
-
handle(err: unknown, _request: Request
|
|
1032
|
+
handle(err: unknown, _request: Request, _response: Response$1, next: NextFunction): ResponseEntity<{
|
|
1033
1033
|
message: string;
|
|
1034
1034
|
}> | undefined;
|
|
1035
1035
|
}
|
|
@@ -1052,7 +1052,7 @@ declare class DefaultResponseStatusErrorMiddleware {
|
|
|
1052
1052
|
* ```
|
|
1053
1053
|
*/
|
|
1054
1054
|
declare class DefaultOpenApiMiddleware {
|
|
1055
|
-
handle(_request: Request
|
|
1055
|
+
handle(_request: Request, _response: Response$1, _next: NextFunction): ResponseEntity<OpenAPIV3.Document<{}>>;
|
|
1056
1056
|
}
|
|
1057
1057
|
//#endregion
|
|
1058
1058
|
//#region src/middleware/default/swagger/index.d.ts
|
|
@@ -1074,7 +1074,7 @@ declare class DefaultOpenApiMiddleware {
|
|
|
1074
1074
|
*/
|
|
1075
1075
|
declare class Serve {
|
|
1076
1076
|
private readonly handlers;
|
|
1077
|
-
handle(request: Request
|
|
1077
|
+
handle(request: Request, response: Response$1, next: NextFunction): void;
|
|
1078
1078
|
}
|
|
1079
1079
|
/**
|
|
1080
1080
|
* Enable the serving of the Swagger endpoint used to serve the OpenAPI spec generated by Sapling.
|
|
@@ -1095,7 +1095,7 @@ declare class Serve {
|
|
|
1095
1095
|
declare class Setup {
|
|
1096
1096
|
private readonly handler;
|
|
1097
1097
|
constructor();
|
|
1098
|
-
handle(request: Request
|
|
1098
|
+
handle(request: Request, response: Response$1, next: NextFunction): unknown;
|
|
1099
1099
|
}
|
|
1100
1100
|
/**
|
|
1101
1101
|
* Enable the serving of the Swagger endpoint used to serve the OpenAPI spec generated by Sapling.
|
|
@@ -1122,27 +1122,27 @@ declare const DefaultSwaggerMiddleware: {
|
|
|
1122
1122
|
type HealthCheck = () => boolean | Promise<boolean>;
|
|
1123
1123
|
declare class HealthRegistrar {
|
|
1124
1124
|
private _checks;
|
|
1125
|
-
private
|
|
1125
|
+
private _live;
|
|
1126
1126
|
constructor();
|
|
1127
1127
|
/**
|
|
1128
1128
|
* Add a health check.
|
|
1129
1129
|
*
|
|
1130
|
-
* Health checks will be used to determine whether service can serve traffic or not (a.k.a `
|
|
1130
|
+
* Health checks will be used to determine whether service can serve traffic or not (a.k.a `readiness`).
|
|
1131
1131
|
*/
|
|
1132
1132
|
add(healthCheck: HealthCheck): void;
|
|
1133
1133
|
/**
|
|
1134
1134
|
* @internal used by Sapling library, used to determine once all
|
|
1135
1135
|
* checks have been registered and server is, at the very least, alive.
|
|
1136
1136
|
*/
|
|
1137
|
-
|
|
1137
|
+
_markLive(): void;
|
|
1138
1138
|
/**
|
|
1139
1139
|
* @internal
|
|
1140
1140
|
*/
|
|
1141
|
-
|
|
1141
|
+
_liveness(): Promise<boolean>;
|
|
1142
1142
|
/**
|
|
1143
1143
|
* @internal
|
|
1144
1144
|
*/
|
|
1145
|
-
|
|
1145
|
+
_readiness(): Promise<boolean>;
|
|
1146
1146
|
}
|
|
1147
1147
|
//#endregion
|
|
1148
1148
|
//#region src/middleware/default/health/index.d.ts
|
|
@@ -1150,15 +1150,14 @@ declare class HealthRegistrar {
|
|
|
1150
1150
|
* Enable the serving of `ready` and `live` endpoints.
|
|
1151
1151
|
*
|
|
1152
1152
|
* Configure any middleware-specific settings with `Sapling.Extras.health`
|
|
1153
|
-
* ```
|
|
1154
1153
|
*/
|
|
1155
1154
|
declare class DefaultHealthMiddleware {
|
|
1156
1155
|
private readonly healthRegistrar;
|
|
1157
1156
|
constructor(healthRegistrar: HealthRegistrar);
|
|
1158
|
-
readiness(_request: Request, _response: Response, _next: NextFunction): Promise<ResponseEntity<{
|
|
1157
|
+
readiness(_request: Request, _response: Response$1, _next: NextFunction): Promise<ResponseEntity<{
|
|
1159
1158
|
up: boolean;
|
|
1160
1159
|
}>>;
|
|
1161
|
-
liveness(_request: Request, _response: Response, _next: NextFunction): Promise<ResponseEntity<{
|
|
1160
|
+
liveness(_request: Request, _response: Response$1, _next: NextFunction): Promise<ResponseEntity<{
|
|
1162
1161
|
up: boolean;
|
|
1163
1162
|
}>>;
|
|
1164
1163
|
}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import e, { ErrorRequestHandler, NextFunction, Request
|
|
1
|
+
import e, { ErrorRequestHandler, NextFunction, Request, RequestHandler, Response as Response$1, Router } from "express";
|
|
2
2
|
|
|
3
3
|
//#region src/html/404.d.ts
|
|
4
4
|
/**
|
|
@@ -26,7 +26,7 @@ type RouteDefinition = {
|
|
|
26
26
|
};
|
|
27
27
|
type Class<T> = new (...args: any[]) => T;
|
|
28
28
|
type HttpHeaders = Record<string, string>;
|
|
29
|
-
type ExpressMiddlewareFn = ($1: Request
|
|
29
|
+
type ExpressMiddlewareFn = ($1: Request, $2: Response$1, $3: NextFunction) => void;
|
|
30
30
|
//#endregion
|
|
31
31
|
//#region src/annotation/controller.d.ts
|
|
32
32
|
declare const _ControllerRegistry: WeakMap<Function, Router | ErrorRequestHandler>;
|
|
@@ -921,13 +921,13 @@ declare class Sapling {
|
|
|
921
921
|
/**
|
|
922
922
|
* change default endpoint that ready endpoint will be served on.
|
|
923
923
|
*
|
|
924
|
-
* @default `/
|
|
924
|
+
* @default `/readyz`
|
|
925
925
|
*/
|
|
926
926
|
setReadyPath(this: void, path: string): void;
|
|
927
927
|
/**
|
|
928
928
|
* change default endpoint that live endpoint will be served on.
|
|
929
929
|
*
|
|
930
|
-
* @default `/
|
|
930
|
+
* @default `/livez`
|
|
931
931
|
*/
|
|
932
932
|
setLivePath(this: void, path: string): void;
|
|
933
933
|
};
|
|
@@ -951,7 +951,7 @@ declare class Sapling {
|
|
|
951
951
|
* }
|
|
952
952
|
* ```
|
|
953
953
|
*/
|
|
954
|
-
static chainHandlers(this: void, handlers: RequestHandler[], request: Request
|
|
954
|
+
static chainHandlers(this: void, handlers: RequestHandler[], request: Request, response: Response$1, next: NextFunction, index?: number): void;
|
|
955
955
|
}
|
|
956
956
|
//#endregion
|
|
957
957
|
//#region src/annotation/validator.d.ts
|
|
@@ -1007,7 +1007,7 @@ declare function _getControllerSchema(ctor: Function): ControllerSchemaDefinitio
|
|
|
1007
1007
|
* If the default is not suitable, you may also easily write your own.
|
|
1008
1008
|
*/
|
|
1009
1009
|
declare class DefaultBaseErrorMiddleware {
|
|
1010
|
-
handle(err: unknown, _request: Request
|
|
1010
|
+
handle(err: unknown, _request: Request, _response: Response$1, _next: NextFunction): ResponseEntity<{
|
|
1011
1011
|
message: string;
|
|
1012
1012
|
}>;
|
|
1013
1013
|
}
|
|
@@ -1018,7 +1018,7 @@ declare class DefaultBaseErrorMiddleware {
|
|
|
1018
1018
|
* If the default is not suitable, you may also easily write your own.
|
|
1019
1019
|
*/
|
|
1020
1020
|
declare class DefaultParserErrorMiddleware {
|
|
1021
|
-
handle(err: unknown, _request: Request
|
|
1021
|
+
handle(err: unknown, _request: Request, _response: Response$1, next: NextFunction): ResponseEntity<{
|
|
1022
1022
|
message: string;
|
|
1023
1023
|
}> | undefined;
|
|
1024
1024
|
}
|
|
@@ -1029,7 +1029,7 @@ declare class DefaultParserErrorMiddleware {
|
|
|
1029
1029
|
* If the default is not suitable, you may also easily write your own.
|
|
1030
1030
|
*/
|
|
1031
1031
|
declare class DefaultResponseStatusErrorMiddleware {
|
|
1032
|
-
handle(err: unknown, _request: Request
|
|
1032
|
+
handle(err: unknown, _request: Request, _response: Response$1, next: NextFunction): ResponseEntity<{
|
|
1033
1033
|
message: string;
|
|
1034
1034
|
}> | undefined;
|
|
1035
1035
|
}
|
|
@@ -1052,7 +1052,7 @@ declare class DefaultResponseStatusErrorMiddleware {
|
|
|
1052
1052
|
* ```
|
|
1053
1053
|
*/
|
|
1054
1054
|
declare class DefaultOpenApiMiddleware {
|
|
1055
|
-
handle(_request: Request
|
|
1055
|
+
handle(_request: Request, _response: Response$1, _next: NextFunction): ResponseEntity<OpenAPIV3.Document<{}>>;
|
|
1056
1056
|
}
|
|
1057
1057
|
//#endregion
|
|
1058
1058
|
//#region src/middleware/default/swagger/index.d.ts
|
|
@@ -1074,7 +1074,7 @@ declare class DefaultOpenApiMiddleware {
|
|
|
1074
1074
|
*/
|
|
1075
1075
|
declare class Serve {
|
|
1076
1076
|
private readonly handlers;
|
|
1077
|
-
handle(request: Request
|
|
1077
|
+
handle(request: Request, response: Response$1, next: NextFunction): void;
|
|
1078
1078
|
}
|
|
1079
1079
|
/**
|
|
1080
1080
|
* Enable the serving of the Swagger endpoint used to serve the OpenAPI spec generated by Sapling.
|
|
@@ -1095,7 +1095,7 @@ declare class Serve {
|
|
|
1095
1095
|
declare class Setup {
|
|
1096
1096
|
private readonly handler;
|
|
1097
1097
|
constructor();
|
|
1098
|
-
handle(request: Request
|
|
1098
|
+
handle(request: Request, response: Response$1, next: NextFunction): unknown;
|
|
1099
1099
|
}
|
|
1100
1100
|
/**
|
|
1101
1101
|
* Enable the serving of the Swagger endpoint used to serve the OpenAPI spec generated by Sapling.
|
|
@@ -1122,27 +1122,27 @@ declare const DefaultSwaggerMiddleware: {
|
|
|
1122
1122
|
type HealthCheck = () => boolean | Promise<boolean>;
|
|
1123
1123
|
declare class HealthRegistrar {
|
|
1124
1124
|
private _checks;
|
|
1125
|
-
private
|
|
1125
|
+
private _live;
|
|
1126
1126
|
constructor();
|
|
1127
1127
|
/**
|
|
1128
1128
|
* Add a health check.
|
|
1129
1129
|
*
|
|
1130
|
-
* Health checks will be used to determine whether service can serve traffic or not (a.k.a `
|
|
1130
|
+
* Health checks will be used to determine whether service can serve traffic or not (a.k.a `readiness`).
|
|
1131
1131
|
*/
|
|
1132
1132
|
add(healthCheck: HealthCheck): void;
|
|
1133
1133
|
/**
|
|
1134
1134
|
* @internal used by Sapling library, used to determine once all
|
|
1135
1135
|
* checks have been registered and server is, at the very least, alive.
|
|
1136
1136
|
*/
|
|
1137
|
-
|
|
1137
|
+
_markLive(): void;
|
|
1138
1138
|
/**
|
|
1139
1139
|
* @internal
|
|
1140
1140
|
*/
|
|
1141
|
-
|
|
1141
|
+
_liveness(): Promise<boolean>;
|
|
1142
1142
|
/**
|
|
1143
1143
|
* @internal
|
|
1144
1144
|
*/
|
|
1145
|
-
|
|
1145
|
+
_readiness(): Promise<boolean>;
|
|
1146
1146
|
}
|
|
1147
1147
|
//#endregion
|
|
1148
1148
|
//#region src/middleware/default/health/index.d.ts
|
|
@@ -1150,15 +1150,14 @@ declare class HealthRegistrar {
|
|
|
1150
1150
|
* Enable the serving of `ready` and `live` endpoints.
|
|
1151
1151
|
*
|
|
1152
1152
|
* Configure any middleware-specific settings with `Sapling.Extras.health`
|
|
1153
|
-
* ```
|
|
1154
1153
|
*/
|
|
1155
1154
|
declare class DefaultHealthMiddleware {
|
|
1156
1155
|
private readonly healthRegistrar;
|
|
1157
1156
|
constructor(healthRegistrar: HealthRegistrar);
|
|
1158
|
-
readiness(_request: Request, _response: Response, _next: NextFunction): Promise<ResponseEntity<{
|
|
1157
|
+
readiness(_request: Request, _response: Response$1, _next: NextFunction): Promise<ResponseEntity<{
|
|
1159
1158
|
up: boolean;
|
|
1160
1159
|
}>>;
|
|
1161
|
-
liveness(_request: Request, _response: Response, _next: NextFunction): Promise<ResponseEntity<{
|
|
1160
|
+
liveness(_request: Request, _response: Response$1, _next: NextFunction): Promise<ResponseEntity<{
|
|
1162
1161
|
up: boolean;
|
|
1163
1162
|
}>>;
|
|
1164
1163
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -376,15 +376,15 @@ function __decorate(decorators, target, key, desc) {
|
|
|
376
376
|
//#region src/middleware/health/registrar.ts
|
|
377
377
|
let HealthRegistrar = class HealthRegistrar {
|
|
378
378
|
_checks;
|
|
379
|
-
|
|
379
|
+
_live;
|
|
380
380
|
constructor() {
|
|
381
381
|
this._checks = [];
|
|
382
|
-
this.
|
|
382
|
+
this._live = false;
|
|
383
383
|
}
|
|
384
384
|
/**
|
|
385
385
|
* Add a health check.
|
|
386
386
|
*
|
|
387
|
-
* Health checks will be used to determine whether service can serve traffic or not (a.k.a `
|
|
387
|
+
* Health checks will be used to determine whether service can serve traffic or not (a.k.a `readiness`).
|
|
388
388
|
*/
|
|
389
389
|
add(healthCheck) {
|
|
390
390
|
this._checks.push(healthCheck);
|
|
@@ -393,21 +393,21 @@ let HealthRegistrar = class HealthRegistrar {
|
|
|
393
393
|
* @internal used by Sapling library, used to determine once all
|
|
394
394
|
* checks have been registered and server is, at the very least, alive.
|
|
395
395
|
*/
|
|
396
|
-
|
|
397
|
-
this.
|
|
396
|
+
_markLive() {
|
|
397
|
+
this._live = true;
|
|
398
398
|
}
|
|
399
399
|
/**
|
|
400
400
|
* @internal
|
|
401
401
|
*/
|
|
402
|
-
async
|
|
403
|
-
return this.
|
|
402
|
+
async _liveness() {
|
|
403
|
+
return this._live;
|
|
404
404
|
}
|
|
405
405
|
/**
|
|
406
406
|
* @internal
|
|
407
407
|
*/
|
|
408
|
-
async
|
|
409
|
-
if (!this.
|
|
410
|
-
return (await Promise.
|
|
408
|
+
async _readiness() {
|
|
409
|
+
if (!this._live) return false;
|
|
410
|
+
return (await Promise.allSettled(this._checks.map((c) => c()))).every((r) => r.status === "fulfilled" && r.value);
|
|
411
411
|
}
|
|
412
412
|
};
|
|
413
413
|
HealthRegistrar = __decorate([Injectable()], HealthRegistrar);
|
|
@@ -417,8 +417,8 @@ const _settings = {
|
|
|
417
417
|
serialize: JSON.stringify,
|
|
418
418
|
deserialize: JSON.parse,
|
|
419
419
|
health: {
|
|
420
|
-
ready: { path: "/
|
|
421
|
-
live: { path: "/
|
|
420
|
+
ready: { path: "/readyz" },
|
|
421
|
+
live: { path: "/livez" }
|
|
422
422
|
},
|
|
423
423
|
doc: {
|
|
424
424
|
openApiPath: "/openapi.json",
|
|
@@ -514,7 +514,7 @@ var Sapling = class Sapling {
|
|
|
514
514
|
* visible for testing
|
|
515
515
|
*/
|
|
516
516
|
static _onPostStartup() {
|
|
517
|
-
_InjectableRegistry.get(HealthRegistrar)?.
|
|
517
|
+
_InjectableRegistry.get(HealthRegistrar)?._markLive();
|
|
518
518
|
}
|
|
519
519
|
/**
|
|
520
520
|
* Serialize a value into a JSON string.
|
|
@@ -593,7 +593,7 @@ var Sapling = class Sapling {
|
|
|
593
593
|
/**
|
|
594
594
|
* change default endpoint that ready endpoint will be served on.
|
|
595
595
|
*
|
|
596
|
-
* @default `/
|
|
596
|
+
* @default `/readyz`
|
|
597
597
|
*/
|
|
598
598
|
setReadyPath(path) {
|
|
599
599
|
_settings.health.ready.path = path;
|
|
@@ -601,7 +601,7 @@ var Sapling = class Sapling {
|
|
|
601
601
|
/**
|
|
602
602
|
* change default endpoint that live endpoint will be served on.
|
|
603
603
|
*
|
|
604
|
-
* @default `/
|
|
604
|
+
* @default `/livez`
|
|
605
605
|
*/
|
|
606
606
|
setLivePath(path) {
|
|
607
607
|
_settings.health.live.path = path;
|
|
@@ -1201,11 +1201,11 @@ let DefaultHealthMiddleware = class DefaultHealthMiddleware {
|
|
|
1201
1201
|
this.healthRegistrar = healthRegistrar;
|
|
1202
1202
|
}
|
|
1203
1203
|
async readiness(_request, _response, _next) {
|
|
1204
|
-
const up = await this.healthRegistrar.
|
|
1204
|
+
const up = await this.healthRegistrar._readiness();
|
|
1205
1205
|
return ResponseEntity.ok().body({ up });
|
|
1206
1206
|
}
|
|
1207
1207
|
async liveness(_request, _response, _next) {
|
|
1208
|
-
const up = await this.healthRegistrar.
|
|
1208
|
+
const up = await this.healthRegistrar._liveness();
|
|
1209
1209
|
return ResponseEntity.ok().body({ up });
|
|
1210
1210
|
}
|
|
1211
1211
|
};
|