@tahminator/sapling 2.1.0-beta.a2de2fb9 → 2.1.0-beta.d7a333d9

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/dist/index.cjs CHANGED
@@ -401,22 +401,28 @@ function __decorate(decorators, target, key, desc) {
401
401
  //#region src/middleware/health/registrar.ts
402
402
  let HealthRegistrar = class HealthRegistrar {
403
403
  _checks;
404
- _sealed;
404
+ _ready;
405
405
  constructor() {
406
406
  this._checks = [];
407
- this._sealed = false;
407
+ this._ready = false;
408
408
  }
409
+ /**
410
+ * Add a health check.
411
+ *
412
+ * Health checks will be used to determine whether service can serve traffic or not (a.k.a `liveness`).
413
+ */
409
414
  add(healthCheck) {
410
415
  this._checks.push(healthCheck);
411
416
  }
412
417
  /**
413
- * @internal used by Sapling library
418
+ * @internal used by Sapling library, used to determine once all
419
+ * checks have been registered and server is, at the very least, alive.
414
420
  */
415
- _seal() {
416
- this._sealed = true;
421
+ _markReady() {
422
+ this._ready = true;
417
423
  }
418
424
  async check() {
419
- if (!this._sealed) return false;
425
+ if (!this._ready) return false;
420
426
  return (await Promise.all(this._checks.map((c) => c()))).every((c) => c === true);
421
427
  }
422
428
  };
@@ -426,7 +432,10 @@ HealthRegistrar = __decorate([Injectable()], HealthRegistrar);
426
432
  const _settings = {
427
433
  serialize: JSON.stringify,
428
434
  deserialize: JSON.parse,
429
- health: { path: "/up" },
435
+ health: {
436
+ ready: { path: "/ready" },
437
+ live: { path: "/live" }
438
+ },
430
439
  doc: {
431
440
  openApiPath: "/openapi.json",
432
441
  swaggerPath: "/swagger.html",
@@ -494,9 +503,8 @@ var Sapling = class Sapling {
494
503
  * import { Sapling } from "@tahminator/sapling";
495
504
  * import express from "express";
496
505
  *
497
- * const app = express();
498
- *
499
- * app.registerApp(app);
506
+ * // returns the exact same `express.App` type back to you!
507
+ * const app = Sapling.registerApp(express());
500
508
  * ```
501
509
  */
502
510
  static registerApp(app) {
@@ -508,7 +516,7 @@ var Sapling = class Sapling {
508
516
  return function(...args) {
509
517
  const server = originalListen.apply(target, args);
510
518
  server.once("listening", () => {
511
- Sapling.onStartup();
519
+ Sapling.onPostStartup();
512
520
  console.log("Sapling successfully initialized post-startup hooks on server start");
513
521
  });
514
522
  return server;
@@ -517,8 +525,8 @@ var Sapling = class Sapling {
517
525
  return Reflect.get(target, prop, receiver);
518
526
  } });
519
527
  }
520
- static onStartup() {
521
- _InjectableRegistry.get(HealthRegistrar)?.seal();
528
+ static onPostStartup() {
529
+ _InjectableRegistry.get(HealthRegistrar)?._markReady();
522
530
  }
523
531
  /**
524
532
  * Serialize a value into a JSON string.
@@ -559,37 +567,59 @@ var Sapling = class Sapling {
559
567
  /**
560
568
  * Modify extra settings
561
569
  */
562
- static Extras = {
563
- /**
564
- * Modify default settings applied to OpenAPI & Swagger
565
- */
566
- swaggerAndOpenApi: {
567
- /**
568
- * Set base OpenAPI metadata values.
569
- *
570
- * @default { title: "API", version: "1.0.0" }
571
- */
572
- setMetadata(metadata) {
573
- _settings.doc.metadata = metadata;
574
- },
570
+ static Extras = {
575
571
  /**
576
- * change default endpoint that will serve OpenAPI spec.
577
- * Swagger will also load this endpoint on load.
578
- *
579
- * @default `/openapi.json`
572
+ * Modify default settings applied to OpenAPI & Swagger
580
573
  */
581
- setOpenApiPath(path) {
582
- _settings.doc.openApiPath = path;
574
+ swaggerAndOpenApi: {
575
+ /**
576
+ * Set base OpenAPI metadata values.
577
+ *
578
+ * @default { title: "API", version: "1.0.0" }
579
+ */
580
+ setMetadata(metadata) {
581
+ _settings.doc.metadata = metadata;
582
+ },
583
+ /**
584
+ * change default endpoint that will serve OpenAPI spec.
585
+ * Swagger will also load this endpoint on load.
586
+ *
587
+ * @default `/openapi.json`
588
+ */
589
+ setOpenApiPath(path) {
590
+ _settings.doc.openApiPath = path;
591
+ },
592
+ /**
593
+ * change Swagger endpoint.
594
+ *
595
+ * @default `/swagger.html`
596
+ */
597
+ setSwaggerPath(path) {
598
+ _settings.doc.swaggerPath = path;
599
+ }
583
600
  },
584
601
  /**
585
- * change Swagger endpoint.
586
- *
587
- * @default `/swagger.html`
602
+ * Modify default settings applied to health / readiness / liveness.
588
603
  */
589
- setSwaggerPath(path) {
590
- _settings.doc.swaggerPath = path;
604
+ health: {
605
+ /**
606
+ * change default endpoint that ready endpoint will be served on.
607
+ *
608
+ * @default `/ready`
609
+ */
610
+ setReadyPath(path) {
611
+ _settings.health.ready.path = path;
612
+ },
613
+ /**
614
+ * change default endpoint that live endpoint will be served on.
615
+ *
616
+ * @default `/live`
617
+ */
618
+ setLivePath(path) {
619
+ _settings.health.live.path = path;
620
+ }
591
621
  }
592
- } };
622
+ };
593
623
  /**
594
624
  * This method can be used in a `@MiddlewareClass` to register any libraries
595
625
  * that expect you to register multiple registers at once. An example is `swagger-ui-express`
@@ -1182,12 +1212,17 @@ let DefaultHealthMiddleware = class DefaultHealthMiddleware {
1182
1212
  constructor(healthRegistrar) {
1183
1213
  this.healthRegistrar = healthRegistrar;
1184
1214
  }
1185
- async serve(_request, _response, _next) {
1215
+ async readiness(_request, _response, _next) {
1216
+ const up = await this.healthRegistrar.check();
1217
+ return ResponseEntity.ok().body({ up });
1218
+ }
1219
+ async liveness(_request, _response, _next) {
1186
1220
  const up = await this.healthRegistrar.check();
1187
1221
  return ResponseEntity.ok().body({ up });
1188
1222
  }
1189
1223
  };
1190
- __decorate([GET(_settings.health.path)], DefaultHealthMiddleware.prototype, "serve", null);
1224
+ __decorate([GET(_settings.health.ready.path)], DefaultHealthMiddleware.prototype, "readiness", null);
1225
+ __decorate([GET(_settings.health.live.path)], DefaultHealthMiddleware.prototype, "liveness", null);
1191
1226
  DefaultHealthMiddleware = __decorate([MiddlewareClass({ deps: [HealthRegistrar] })], DefaultHealthMiddleware);
1192
1227
  //#endregion
1193
1228
  exports.Controller = Controller;
package/dist/index.d.cts CHANGED
@@ -795,7 +795,12 @@ type Settings = {
795
795
  serialize: (value: any) => string;
796
796
  deserialize: (value: string) => any;
797
797
  health: {
798
- path: string;
798
+ ready: {
799
+ path: string;
800
+ };
801
+ live: {
802
+ path: string;
803
+ };
799
804
  };
800
805
  doc: {
801
806
  openApiPath: string;
@@ -843,13 +848,12 @@ declare class Sapling {
843
848
  * import { Sapling } from "@tahminator/sapling";
844
849
  * import express from "express";
845
850
  *
846
- * const app = express();
847
- *
848
- * app.registerApp(app);
851
+ * // returns the exact same `express.App` type back to you!
852
+ * const app = Sapling.registerApp(express());
849
853
  * ```
850
854
  */
851
855
  static registerApp(app: e.Express): e.Express;
852
- static onStartup(): void;
856
+ static onPostStartup(): void;
853
857
  /**
854
858
  * Serialize a value into a JSON string.
855
859
  *
@@ -906,6 +910,23 @@ declare class Sapling {
906
910
  */
907
911
  setSwaggerPath(this: void, path: string): void;
908
912
  };
913
+ /**
914
+ * Modify default settings applied to health / readiness / liveness.
915
+ */
916
+ health: {
917
+ /**
918
+ * change default endpoint that ready endpoint will be served on.
919
+ *
920
+ * @default `/ready`
921
+ */
922
+ setReadyPath(this: void, path: string): void;
923
+ /**
924
+ * change default endpoint that live endpoint will be served on.
925
+ *
926
+ * @default `/live`
927
+ */
928
+ setLivePath(this: void, path: string): void;
929
+ };
909
930
  };
910
931
  /**
911
932
  * This method can be used in a `@MiddlewareClass` to register any libraries
@@ -1097,21 +1118,36 @@ declare const DefaultSwaggerMiddleware: {
1097
1118
  type HealthCheck = () => boolean | Promise<boolean>;
1098
1119
  declare class HealthRegistrar {
1099
1120
  private _checks;
1100
- private _sealed;
1121
+ private _ready;
1101
1122
  constructor();
1123
+ /**
1124
+ * Add a health check.
1125
+ *
1126
+ * Health checks will be used to determine whether service can serve traffic or not (a.k.a `liveness`).
1127
+ */
1102
1128
  add(healthCheck: HealthCheck): void;
1103
1129
  /**
1104
- * @internal used by Sapling library
1130
+ * @internal used by Sapling library, used to determine once all
1131
+ * checks have been registered and server is, at the very least, alive.
1105
1132
  */
1106
- _seal(): void;
1133
+ _markReady(): void;
1107
1134
  check(): Promise<boolean>;
1108
1135
  }
1109
1136
  //#endregion
1110
1137
  //#region src/middleware/default/health/index.d.ts
1138
+ /**
1139
+ * Enable the serving of `ready` and `live` endpoints.
1140
+ *
1141
+ * Configure any middleware-specific settings with `Sapling.Extras.health`
1142
+ * ```
1143
+ */
1111
1144
  declare class DefaultHealthMiddleware {
1112
1145
  private readonly healthRegistrar;
1113
1146
  constructor(healthRegistrar: HealthRegistrar);
1114
- serve(_request: Request, _response: Response, _next: NextFunction): Promise<ResponseEntity<{
1147
+ readiness(_request: Request, _response: Response, _next: NextFunction): Promise<ResponseEntity<{
1148
+ up: boolean;
1149
+ }>>;
1150
+ liveness(_request: Request, _response: Response, _next: NextFunction): Promise<ResponseEntity<{
1115
1151
  up: boolean;
1116
1152
  }>>;
1117
1153
  }
package/dist/index.d.mts CHANGED
@@ -795,7 +795,12 @@ type Settings = {
795
795
  serialize: (value: any) => string;
796
796
  deserialize: (value: string) => any;
797
797
  health: {
798
- path: string;
798
+ ready: {
799
+ path: string;
800
+ };
801
+ live: {
802
+ path: string;
803
+ };
799
804
  };
800
805
  doc: {
801
806
  openApiPath: string;
@@ -843,13 +848,12 @@ declare class Sapling {
843
848
  * import { Sapling } from "@tahminator/sapling";
844
849
  * import express from "express";
845
850
  *
846
- * const app = express();
847
- *
848
- * app.registerApp(app);
851
+ * // returns the exact same `express.App` type back to you!
852
+ * const app = Sapling.registerApp(express());
849
853
  * ```
850
854
  */
851
855
  static registerApp(app: e.Express): e.Express;
852
- static onStartup(): void;
856
+ static onPostStartup(): void;
853
857
  /**
854
858
  * Serialize a value into a JSON string.
855
859
  *
@@ -906,6 +910,23 @@ declare class Sapling {
906
910
  */
907
911
  setSwaggerPath(this: void, path: string): void;
908
912
  };
913
+ /**
914
+ * Modify default settings applied to health / readiness / liveness.
915
+ */
916
+ health: {
917
+ /**
918
+ * change default endpoint that ready endpoint will be served on.
919
+ *
920
+ * @default `/ready`
921
+ */
922
+ setReadyPath(this: void, path: string): void;
923
+ /**
924
+ * change default endpoint that live endpoint will be served on.
925
+ *
926
+ * @default `/live`
927
+ */
928
+ setLivePath(this: void, path: string): void;
929
+ };
909
930
  };
910
931
  /**
911
932
  * This method can be used in a `@MiddlewareClass` to register any libraries
@@ -1097,21 +1118,36 @@ declare const DefaultSwaggerMiddleware: {
1097
1118
  type HealthCheck = () => boolean | Promise<boolean>;
1098
1119
  declare class HealthRegistrar {
1099
1120
  private _checks;
1100
- private _sealed;
1121
+ private _ready;
1101
1122
  constructor();
1123
+ /**
1124
+ * Add a health check.
1125
+ *
1126
+ * Health checks will be used to determine whether service can serve traffic or not (a.k.a `liveness`).
1127
+ */
1102
1128
  add(healthCheck: HealthCheck): void;
1103
1129
  /**
1104
- * @internal used by Sapling library
1130
+ * @internal used by Sapling library, used to determine once all
1131
+ * checks have been registered and server is, at the very least, alive.
1105
1132
  */
1106
- _seal(): void;
1133
+ _markReady(): void;
1107
1134
  check(): Promise<boolean>;
1108
1135
  }
1109
1136
  //#endregion
1110
1137
  //#region src/middleware/default/health/index.d.ts
1138
+ /**
1139
+ * Enable the serving of `ready` and `live` endpoints.
1140
+ *
1141
+ * Configure any middleware-specific settings with `Sapling.Extras.health`
1142
+ * ```
1143
+ */
1111
1144
  declare class DefaultHealthMiddleware {
1112
1145
  private readonly healthRegistrar;
1113
1146
  constructor(healthRegistrar: HealthRegistrar);
1114
- serve(_request: Request, _response: Response, _next: NextFunction): Promise<ResponseEntity<{
1147
+ readiness(_request: Request, _response: Response, _next: NextFunction): Promise<ResponseEntity<{
1148
+ up: boolean;
1149
+ }>>;
1150
+ liveness(_request: Request, _response: Response, _next: NextFunction): Promise<ResponseEntity<{
1115
1151
  up: boolean;
1116
1152
  }>>;
1117
1153
  }
package/dist/index.mjs CHANGED
@@ -376,22 +376,28 @@ function __decorate(decorators, target, key, desc) {
376
376
  //#region src/middleware/health/registrar.ts
377
377
  let HealthRegistrar = class HealthRegistrar {
378
378
  _checks;
379
- _sealed;
379
+ _ready;
380
380
  constructor() {
381
381
  this._checks = [];
382
- this._sealed = false;
382
+ this._ready = false;
383
383
  }
384
+ /**
385
+ * Add a health check.
386
+ *
387
+ * Health checks will be used to determine whether service can serve traffic or not (a.k.a `liveness`).
388
+ */
384
389
  add(healthCheck) {
385
390
  this._checks.push(healthCheck);
386
391
  }
387
392
  /**
388
- * @internal used by Sapling library
393
+ * @internal used by Sapling library, used to determine once all
394
+ * checks have been registered and server is, at the very least, alive.
389
395
  */
390
- _seal() {
391
- this._sealed = true;
396
+ _markReady() {
397
+ this._ready = true;
392
398
  }
393
399
  async check() {
394
- if (!this._sealed) return false;
400
+ if (!this._ready) return false;
395
401
  return (await Promise.all(this._checks.map((c) => c()))).every((c) => c === true);
396
402
  }
397
403
  };
@@ -401,7 +407,10 @@ HealthRegistrar = __decorate([Injectable()], HealthRegistrar);
401
407
  const _settings = {
402
408
  serialize: JSON.stringify,
403
409
  deserialize: JSON.parse,
404
- health: { path: "/up" },
410
+ health: {
411
+ ready: { path: "/ready" },
412
+ live: { path: "/live" }
413
+ },
405
414
  doc: {
406
415
  openApiPath: "/openapi.json",
407
416
  swaggerPath: "/swagger.html",
@@ -469,9 +478,8 @@ var Sapling = class Sapling {
469
478
  * import { Sapling } from "@tahminator/sapling";
470
479
  * import express from "express";
471
480
  *
472
- * const app = express();
473
- *
474
- * app.registerApp(app);
481
+ * // returns the exact same `express.App` type back to you!
482
+ * const app = Sapling.registerApp(express());
475
483
  * ```
476
484
  */
477
485
  static registerApp(app) {
@@ -483,7 +491,7 @@ var Sapling = class Sapling {
483
491
  return function(...args) {
484
492
  const server = originalListen.apply(target, args);
485
493
  server.once("listening", () => {
486
- Sapling.onStartup();
494
+ Sapling.onPostStartup();
487
495
  console.log("Sapling successfully initialized post-startup hooks on server start");
488
496
  });
489
497
  return server;
@@ -492,8 +500,8 @@ var Sapling = class Sapling {
492
500
  return Reflect.get(target, prop, receiver);
493
501
  } });
494
502
  }
495
- static onStartup() {
496
- _InjectableRegistry.get(HealthRegistrar)?.seal();
503
+ static onPostStartup() {
504
+ _InjectableRegistry.get(HealthRegistrar)?._markReady();
497
505
  }
498
506
  /**
499
507
  * Serialize a value into a JSON string.
@@ -534,37 +542,59 @@ var Sapling = class Sapling {
534
542
  /**
535
543
  * Modify extra settings
536
544
  */
537
- static Extras = {
538
- /**
539
- * Modify default settings applied to OpenAPI & Swagger
540
- */
541
- swaggerAndOpenApi: {
542
- /**
543
- * Set base OpenAPI metadata values.
544
- *
545
- * @default { title: "API", version: "1.0.0" }
546
- */
547
- setMetadata(metadata) {
548
- _settings.doc.metadata = metadata;
549
- },
545
+ static Extras = {
550
546
  /**
551
- * change default endpoint that will serve OpenAPI spec.
552
- * Swagger will also load this endpoint on load.
553
- *
554
- * @default `/openapi.json`
547
+ * Modify default settings applied to OpenAPI & Swagger
555
548
  */
556
- setOpenApiPath(path) {
557
- _settings.doc.openApiPath = path;
549
+ swaggerAndOpenApi: {
550
+ /**
551
+ * Set base OpenAPI metadata values.
552
+ *
553
+ * @default { title: "API", version: "1.0.0" }
554
+ */
555
+ setMetadata(metadata) {
556
+ _settings.doc.metadata = metadata;
557
+ },
558
+ /**
559
+ * change default endpoint that will serve OpenAPI spec.
560
+ * Swagger will also load this endpoint on load.
561
+ *
562
+ * @default `/openapi.json`
563
+ */
564
+ setOpenApiPath(path) {
565
+ _settings.doc.openApiPath = path;
566
+ },
567
+ /**
568
+ * change Swagger endpoint.
569
+ *
570
+ * @default `/swagger.html`
571
+ */
572
+ setSwaggerPath(path) {
573
+ _settings.doc.swaggerPath = path;
574
+ }
558
575
  },
559
576
  /**
560
- * change Swagger endpoint.
561
- *
562
- * @default `/swagger.html`
577
+ * Modify default settings applied to health / readiness / liveness.
563
578
  */
564
- setSwaggerPath(path) {
565
- _settings.doc.swaggerPath = path;
579
+ health: {
580
+ /**
581
+ * change default endpoint that ready endpoint will be served on.
582
+ *
583
+ * @default `/ready`
584
+ */
585
+ setReadyPath(path) {
586
+ _settings.health.ready.path = path;
587
+ },
588
+ /**
589
+ * change default endpoint that live endpoint will be served on.
590
+ *
591
+ * @default `/live`
592
+ */
593
+ setLivePath(path) {
594
+ _settings.health.live.path = path;
595
+ }
566
596
  }
567
- } };
597
+ };
568
598
  /**
569
599
  * This method can be used in a `@MiddlewareClass` to register any libraries
570
600
  * that expect you to register multiple registers at once. An example is `swagger-ui-express`
@@ -1157,12 +1187,17 @@ let DefaultHealthMiddleware = class DefaultHealthMiddleware {
1157
1187
  constructor(healthRegistrar) {
1158
1188
  this.healthRegistrar = healthRegistrar;
1159
1189
  }
1160
- async serve(_request, _response, _next) {
1190
+ async readiness(_request, _response, _next) {
1191
+ const up = await this.healthRegistrar.check();
1192
+ return ResponseEntity.ok().body({ up });
1193
+ }
1194
+ async liveness(_request, _response, _next) {
1161
1195
  const up = await this.healthRegistrar.check();
1162
1196
  return ResponseEntity.ok().body({ up });
1163
1197
  }
1164
1198
  };
1165
- __decorate([GET(_settings.health.path)], DefaultHealthMiddleware.prototype, "serve", null);
1199
+ __decorate([GET(_settings.health.ready.path)], DefaultHealthMiddleware.prototype, "readiness", null);
1200
+ __decorate([GET(_settings.health.live.path)], DefaultHealthMiddleware.prototype, "liveness", null);
1166
1201
  DefaultHealthMiddleware = __decorate([MiddlewareClass({ deps: [HealthRegistrar] })], DefaultHealthMiddleware);
1167
1202
  //#endregion
1168
1203
  export { Controller, ControllerSchema, DELETE, DefaultBaseErrorMiddleware, DefaultHealthMiddleware, DefaultOpenApiMiddleware, DefaultParserErrorMiddleware, DefaultResponseStatusErrorMiddleware, DefaultSwaggerMiddleware, GET, HEAD, HealthRegistrar, Html404ErrorPage, HttpStatus, Injectable, Middleware, MiddlewareClass, OPTIONS, PATCH, POST, PUT, ParserError, RedirectView, RequestBody, RequestParam, RequestQuery, ResponseBody, ResponseEntity, ResponseEntityBuilder, ResponseStatusError, RouteSchema, Sapling, _ControllerRegistry, _InjectableDeps, _InjectableRegistry, _Route, _clearOpenApiRegistry, _getControllerSchema, _getOrCreateSchemaDefinition, _getRouteSchema, _getRoutes, _getValidatorSchema, _parseOrThrow, _registerController, _resolve, _saveValidatorSchema, _setControllerSchema, _setRouteSchema, _settings, generateOpenApiSpec, methodResolve, openApiGenerator };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tahminator/sapling",
3
- "version": "2.1.0-beta.a2de2fb9",
3
+ "version": "2.1.0-beta.d7a333d9",
4
4
  "author": "Tahmid Ahmed",
5
5
  "description": "A library to help you write cleaner Express.js code",
6
6
  "repository": {