@tahminator/sapling 2.0.5-beta.0b3bd061 → 2.0.5-beta.1843d6fa

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
@@ -48,6 +48,7 @@ const Html404ErrorPage = (error) => `<!DOCTYPE html>
48
48
  * You can either return `new RedirectView(url)` or `RedirectView.redirect(url)` inside of a controller method.
49
49
  */
50
50
  var RedirectView = class RedirectView {
51
+ _url;
51
52
  constructor(url) {
52
53
  this._url = url;
53
54
  }
@@ -143,8 +144,10 @@ let HttpStatus = /* @__PURE__ */ function(HttpStatus) {
143
144
  * @typeParam T - the type of the response body
144
145
  */
145
146
  var ResponseEntity = class {
147
+ _statusCode;
148
+ _headers = {};
149
+ _body;
146
150
  constructor(body, headers = {}, statusCode = 200) {
147
- this._headers = {};
148
151
  this._body = body;
149
152
  this._headers = headers;
150
153
  this._statusCode = statusCode;
@@ -197,8 +200,9 @@ var ResponseEntity = class {
197
200
  * ensuring type safety when constructing the response.
198
201
  */
199
202
  var ResponseEntityBuilder = class {
203
+ _statusCode;
204
+ _headers = {};
200
205
  constructor(statusCode) {
201
- this._headers = {};
202
206
  this._statusCode = statusCode;
203
207
  }
204
208
  /**
@@ -230,6 +234,7 @@ var ResponseEntityBuilder = class {
230
234
  * @see {@link Sapling.loadResponseStatusErrorMiddleware}
231
235
  */
232
236
  var ResponseStatusError = class ResponseStatusError extends Error {
237
+ status;
233
238
  constructor(status, message) {
234
239
  super(message ?? "Something went wrong.");
235
240
  this.status = status;
@@ -241,26 +246,27 @@ var ResponseStatusError = class ResponseStatusError extends Error {
241
246
  //#endregion
242
247
  //#region src/helper/error/parse.ts
243
248
  /**
244
- * This error should be thrown when some data cannot be parsed by a given schema.
249
+ * This error should be thrown when some data cannot be parsed by a given Standard Schema compatible schema.
245
250
  */
246
251
  var ParserError = class ParserError extends ResponseStatusError {
247
- constructor(location, issues, vendor) {
248
- super(400, ParserError.formatMessage(location, issues, vendor));
252
+ constructor(location, issues, vendor, functionName) {
253
+ super(400, ParserError.formatMessage(location, issues, vendor, functionName));
249
254
  Object.setPrototypeOf(this, new.target.prototype);
250
255
  }
251
- static formatMessage(location, issues, vendor) {
256
+ static formatMessage(location, issues, vendor, functionName) {
252
257
  const formatted = issues.map((i) => {
253
258
  const path = Array.isArray(i.path) ? i.path.map((seg) => typeof seg === "object" && seg ? String(seg.key) : String(seg)).join(".") : "";
254
259
  return path ? `${path}: ${i.message}` : i.message;
255
260
  }).join("; ");
256
- return `${vendor} failed to parse ${(() => {
257
- switch (location) {
258
- case "reqbody": return "request body";
259
- case "reqparams": return "request params";
260
- case "reqquery": return "request query";
261
- case "resbody": return "response body";
262
- }
263
- })()}: ${formatted}`;
261
+ return `Failed to parse ${this.getPrettyLocationString(location)} with ${vendor} on ${functionName}: ${formatted}`;
262
+ }
263
+ static getPrettyLocationString(location) {
264
+ switch (location) {
265
+ case "reqbody": return "request body";
266
+ case "reqparams": return "request params";
267
+ case "reqquery": return "request query";
268
+ case "resbody": return "response body";
269
+ }
264
270
  }
265
271
  };
266
272
  //#endregion
@@ -270,7 +276,11 @@ const _settings = {
270
276
  deserialize: JSON.parse,
271
277
  doc: {
272
278
  openApiPath: "/openapi.json",
273
- swaggerPath: "/swagger.html"
279
+ swaggerPath: "/swagger.html",
280
+ metadata: {
281
+ title: "API",
282
+ version: "1.0.0"
283
+ }
274
284
  }
275
285
  };
276
286
  /**
@@ -376,12 +386,59 @@ var Sapling = class Sapling {
376
386
  static setDeserializeFn(fn) {
377
387
  _settings.deserialize = fn;
378
388
  }
379
- static setOpenApiPath(path) {
380
- _settings.doc.openApiPath = path;
381
- }
382
- static setSwaggerPath(path) {
383
- _settings.doc.swaggerPath = path;
384
- }
389
+ /**
390
+ * Modify extra settings
391
+ */
392
+ static Extras = {
393
+ /**
394
+ * Modify default settings applied to OpenAPI & Swagger
395
+ */
396
+ swaggerAndOpenApi: {
397
+ /**
398
+ * Set base OpenAPI metadata values.
399
+ *
400
+ * @default { title: "API", version: "1.0.0" }
401
+ */
402
+ setMetadata(metadata) {
403
+ _settings.doc.metadata = metadata;
404
+ },
405
+ /**
406
+ * change default endpoint that will serve OpenAPI spec.
407
+ * Swagger will also load this endpoint on load.
408
+ *
409
+ * @default `/openapi.json`
410
+ */
411
+ setOpenApiPath(path) {
412
+ _settings.doc.openApiPath = path;
413
+ },
414
+ /**
415
+ * change Swagger endpoint.
416
+ *
417
+ * @default `/swagger.html`
418
+ */
419
+ setSwaggerPath(path) {
420
+ _settings.doc.swaggerPath = path;
421
+ }
422
+ } };
423
+ /**
424
+ * This method can be used in a `@MiddlewareClass` to register any libraries
425
+ * that expect you to register multiple registers at once. An example is `swagger-ui-express`
426
+ *
427
+ * @example
428
+ * ```ts
429
+ * ⠀@MiddlewareClass()
430
+ * class Serve {
431
+ * // `swagger.serve` returns multiple Express handlers for all the assets and routes
432
+ * // that will be served
433
+ * private readonly handlers: RequestHandler[] = swagger.serve;
434
+ *
435
+ * ⠀@Middleware(_settings.doc.swaggerPath)
436
+ * handle(request: Request, response: Response, next: NextFunction) {
437
+ * return Sapling.chainHandlers(this.handlers, request, response, next);
438
+ * }
439
+ * }
440
+ * ```
441
+ */
385
442
  static chainHandlers(handlers, request, response, next, index = 0) {
386
443
  if (index >= handlers.length) {
387
444
  next();
@@ -478,18 +535,7 @@ function _getRoutes(ctor) {
478
535
  return _routeStore.get(ctor) ?? [];
479
536
  }
480
537
  //#endregion
481
- //#region src/utils.ts
482
- function _getOrCreateMap(store, ctor) {
483
- const existing = store.get(ctor);
484
- if (existing) return existing;
485
- const created = /* @__PURE__ */ new Map();
486
- store.set(ctor, created);
487
- return created;
488
- }
489
- //#endregion
490
538
  //#region src/annotation/schema.ts
491
- const _routeSchemaStore = /* @__PURE__ */ new WeakMap();
492
- const _controllerSchemaStore = /* @__PURE__ */ new WeakMap();
493
539
  function ControllerSchema(options) {
494
540
  return (target) => {
495
541
  _setControllerSchema(target, options);
@@ -501,8 +547,17 @@ function RouteSchema(options) {
501
547
  _setRouteSchema(ctor, String(propertyKey), options);
502
548
  };
503
549
  }
550
+ const _routeSchemaStore = /* @__PURE__ */ new WeakMap();
551
+ const _controllerSchemaStore = /* @__PURE__ */ new WeakMap();
552
+ function getOrCreateRouteSchemaStore(store, ctor) {
553
+ const existing = store.get(ctor);
554
+ if (existing) return existing;
555
+ const created = /* @__PURE__ */ new Map();
556
+ store.set(ctor, created);
557
+ return created;
558
+ }
504
559
  function _setRouteSchema(ctor, fnName, options) {
505
- _getOrCreateMap(_routeSchemaStore, ctor).set(fnName, options);
560
+ getOrCreateRouteSchemaStore(_routeSchemaStore, ctor).set(fnName, options);
506
561
  }
507
562
  function _setControllerSchema(ctor, options) {
508
563
  _controllerSchemaStore.set(ctor, options);
@@ -514,26 +569,85 @@ function _getControllerSchema(ctor) {
514
569
  return _controllerSchemaStore.get(ctor);
515
570
  }
516
571
  //#endregion
572
+ //#region src/annotation/validator.ts
573
+ const _validatorSchemaStore = /* @__PURE__ */ new WeakMap();
574
+ function ResponseBody(schema) {
575
+ return (target, propertyKey) => {
576
+ const ctor = target.constructor;
577
+ const fnName = String(propertyKey);
578
+ _saveValidatorSchema(_getOrCreateSchemaDefinition(ctor, fnName), "responseBody", schema, fnName);
579
+ };
580
+ }
581
+ function RequestBody(schema) {
582
+ return (target, propertyKey) => {
583
+ const ctor = target.constructor;
584
+ const fnName = String(propertyKey);
585
+ _saveValidatorSchema(_getOrCreateSchemaDefinition(ctor, fnName), "requestBody", schema, fnName);
586
+ };
587
+ }
588
+ function RequestParam(schema) {
589
+ return (target, propertyKey) => {
590
+ const ctor = target.constructor;
591
+ const fnName = String(propertyKey);
592
+ _saveValidatorSchema(_getOrCreateSchemaDefinition(ctor, fnName), "requestParam", schema, fnName);
593
+ };
594
+ }
595
+ function RequestQuery(schema) {
596
+ return (target, propertyKey) => {
597
+ const ctor = target.constructor;
598
+ const fnName = String(propertyKey);
599
+ _saveValidatorSchema(_getOrCreateSchemaDefinition(ctor, fnName), "requestQuery", schema, fnName);
600
+ };
601
+ }
602
+ function getOrCreateValidatorSchemaStore(store, ctor) {
603
+ const existing = store.get(ctor);
604
+ if (existing) return existing;
605
+ const created = /* @__PURE__ */ new Map();
606
+ store.set(ctor, created);
607
+ return created;
608
+ }
609
+ function _getOrCreateSchemaDefinition(ctor, fnName) {
610
+ const byFn = getOrCreateValidatorSchemaStore(_validatorSchemaStore, ctor);
611
+ const existing = byFn.get(fnName);
612
+ if (existing) return existing;
613
+ const created = {};
614
+ byFn.set(fnName, created);
615
+ return created;
616
+ }
617
+ async function _parseOrThrow(schema, input, location, fnName) {
618
+ const result = await schema["~standard"].validate(input);
619
+ if (result.issues) throw new ParserError(location, result.issues, schema["~standard"].vendor, fnName);
620
+ return result.value;
621
+ }
622
+ function _saveValidatorSchema(def, key, schema, fnName) {
623
+ if (def[key]) throw new Error(`Duplicate schema for "${String(key)}" on method "${fnName}"`);
624
+ def[key] = schema;
625
+ }
626
+ function _getValidatorSchema(ctor, fnName) {
627
+ return _validatorSchemaStore.get(ctor)?.get(fnName);
628
+ }
629
+ //#endregion
517
630
  //#region src/helper/openapi.ts
518
631
  var OpenAPIGenerator = class {
519
- constructor() {
520
- this.controllers = /* @__PURE__ */ new Set();
521
- this.config = {
522
- title: "API",
523
- version: "1.0.0"
524
- };
525
- }
526
- setConfig(config) {
527
- this.config = config;
528
- }
632
+ OPENAPI_VERSION = "3.0.0";
633
+ controllers = /* @__PURE__ */ new Set();
529
634
  registerController(controllerClass, prefix) {
530
635
  this.controllers.add({
531
636
  class: controllerClass,
532
637
  prefix
533
638
  });
534
639
  }
640
+ /**
641
+ * visible for testing
642
+ */
643
+ _clearControllers() {
644
+ this.controllers.clear();
645
+ }
646
+ get metadata() {
647
+ return _settings.doc.metadata;
648
+ }
535
649
  generateSpec() {
536
- const config = this.config;
650
+ const metadata = this.metadata;
537
651
  const paths = {};
538
652
  const tags = [];
539
653
  for (const { class: controllerClass, prefix } of this.controllers) {
@@ -617,11 +731,11 @@ var OpenAPIGenerator = class {
617
731
  }
618
732
  }
619
733
  return {
620
- openapi: "3.0.0",
734
+ openapi: this.OPENAPI_VERSION,
621
735
  info: {
622
- title: config.title,
623
- version: config.version,
624
- description: config.description
736
+ title: metadata.title,
737
+ version: metadata.version,
738
+ description: metadata.description
625
739
  },
626
740
  tags: tags.length > 0 ? tags : void 0,
627
741
  paths
@@ -630,24 +744,23 @@ var OpenAPIGenerator = class {
630
744
  toJsonSchema(schema, direction = "output") {
631
745
  try {
632
746
  const jsonSchema = schema["~standard"].jsonSchema;
633
- if (direction === "input" && jsonSchema.input) return jsonSchema.input({ target: "openapi-3.0" });
634
- return jsonSchema.output({ target: "openapi-3.0" });
747
+ return direction === "input" ? jsonSchema.input({ target: "openapi-3.0" }) : jsonSchema.output({ target: "openapi-3.0" });
635
748
  } catch (e) {
636
- if (e instanceof Error && e.message.includes("Transforms cannot be represented in JSON Schema")) throw new Error(`${e.message}.\nIt appears that you are using z.transform() - it is highly recommended that you use z.codec instead - https://zod.dev/codecs`);
749
+ if (e instanceof Error && e.message.includes("Transforms cannot be represented in JSON Schema")) throw new Error(`${e.message}.\nIt appears that you are using z.transform() - it is highly recommended that you use z.codec instead - https://zod.dev/codecs`, { cause: e });
637
750
  throw e;
638
751
  }
639
752
  }
640
753
  };
641
754
  const openApiGenerator = new OpenAPIGenerator();
642
- function _registerControllerClass(controllerClass, prefix) {
755
+ function _registerController(controllerClass, prefix) {
643
756
  openApiGenerator.registerController(controllerClass, prefix);
644
757
  }
645
- function setOpenApiConfig(config) {
646
- openApiGenerator.setConfig(config);
647
- }
648
758
  function generateOpenApiSpec() {
649
759
  return openApiGenerator.generateSpec();
650
760
  }
761
+ function _clearOpenApiRegistry() {
762
+ openApiGenerator._clearControllers();
763
+ }
651
764
  //#endregion
652
765
  //#region src/types.ts
653
766
  const methodResolve = {
@@ -781,60 +894,6 @@ function _resolve(ctor) {
781
894
  return _InjectableRegistry.get(ctor);
782
895
  }
783
896
  //#endregion
784
- //#region src/annotation/validator.ts
785
- const _validatorSchemaStore = /* @__PURE__ */ new WeakMap();
786
- function ResponseBody(schema) {
787
- return (target, propertyKey) => {
788
- const ctor = target.constructor;
789
- const fnName = String(propertyKey);
790
- _setOnce(_getOrCreateSchemaDefinition(ctor, fnName), "responseBody", schema, fnName);
791
- };
792
- }
793
- function RequestBody(schema) {
794
- return (target, propertyKey) => {
795
- const ctor = target.constructor;
796
- const fnName = String(propertyKey);
797
- _setOnce(_getOrCreateSchemaDefinition(ctor, fnName), "requestBody", schema, fnName);
798
- };
799
- }
800
- function RequestParam(schema) {
801
- return (target, propertyKey) => {
802
- const ctor = target.constructor;
803
- const fnName = String(propertyKey);
804
- _setOnce(_getOrCreateSchemaDefinition(ctor, fnName), "requestParam", schema, fnName);
805
- };
806
- }
807
- function RequestQuery(schema) {
808
- return (target, propertyKey) => {
809
- const ctor = target.constructor;
810
- const fnName = String(propertyKey);
811
- _setOnce(_getOrCreateSchemaDefinition(ctor, fnName), "requestQuery", schema, fnName);
812
- };
813
- }
814
- function _getOrCreateSchemaDefinition(ctor, fnName) {
815
- const byFn = _getOrCreateMap(_validatorSchemaStore, ctor);
816
- const existing = byFn.get(fnName);
817
- if (existing) return existing;
818
- const created = {};
819
- byFn.set(fnName, created);
820
- return created;
821
- }
822
- async function _parseOrThrow(schema, input, kind) {
823
- const result = await schema["~standard"].validate(input);
824
- if (result.issues) {
825
- console.debug(`Failed to parse ${schema["~standard"].vendor} schema\nissues: ${JSON.stringify(result.issues, null, 2)}`);
826
- throw new ParserError(kind, result.issues, schema["~standard"].vendor);
827
- }
828
- return result.value;
829
- }
830
- function _getValidatorSchema(ctor, fnName) {
831
- return _validatorSchemaStore.get(ctor)?.get(fnName);
832
- }
833
- function _setOnce(def, key, schema, fnName) {
834
- if (def[key]) throw new Error(`Duplicate schema for "${String(key)}" on method "${fnName}"`);
835
- def[key] = schema;
836
- }
837
- //#endregion
838
897
  //#region src/annotation/controller.ts
839
898
  const _ControllerRegistry = /* @__PURE__ */ new WeakMap();
840
899
  /**
@@ -846,7 +905,7 @@ const _ControllerRegistry = /* @__PURE__ */ new WeakMap();
846
905
  function Controller({ prefix = "", deps = [] } = {}) {
847
906
  return (target) => {
848
907
  const targetClass = target;
849
- _registerControllerClass(target, prefix);
908
+ _registerController(target, prefix);
850
909
  const router = (0, express.Router)();
851
910
  const routes = _getRoutes(target);
852
911
  const usedRoutes = /* @__PURE__ */ new Set();
@@ -871,15 +930,20 @@ Split these into separate @MiddlewareClass classes, or merge the logic into a si
871
930
  if (method === "USE" && fn.length >= 4) {
872
931
  const middlewareFn = async (err, request, response, next) => {
873
932
  try {
874
- const result = fn.bind(controllerInstance)(err, request, response, next);
875
- if (result instanceof ResponseEntity) {
876
- response.contentType("application/json").status(result.getStatusCode()).set(result.getHeaders()).send(Sapling.serialize(result.getBody()));
877
- return;
878
- }
879
- if (result instanceof RedirectView) {
880
- response.redirect(result.getUrl());
881
- return;
882
- }
933
+ await validate({
934
+ target,
935
+ fnName,
936
+ request
937
+ });
938
+ await handleResult({
939
+ result: fn.bind(controllerInstance)(err, request, response, next),
940
+ response,
941
+ target,
942
+ fnName,
943
+ method,
944
+ path: path instanceof RegExp ? path.source : fp,
945
+ isErrorMiddleware: true
946
+ });
883
947
  } catch (e) {
884
948
  console.error(e);
885
949
  next(e);
@@ -889,35 +953,52 @@ Split these into separate @MiddlewareClass classes, or merge the logic into a si
889
953
  return;
890
954
  }
891
955
  router[methodName](fp, async (request, response, next) => {
892
- const schemas = _getValidatorSchema(target, fnName);
893
- if (schemas) {
894
- if (schemas.requestBody) request.body = await _parseOrThrow(schemas.requestBody, request.body, "reqbody");
895
- if (schemas.requestParam) request.params = await _parseOrThrow(schemas.requestParam, request.params, "reqparams");
896
- if (schemas.requestQuery) {
897
- const parsedQuery = await _parseOrThrow(schemas.requestQuery, request.query, "reqquery");
898
- Object.defineProperty(request, "query", {
899
- value: parsedQuery,
900
- writable: true,
901
- configurable: true
902
- });
903
- }
904
- }
905
- const result = await fn.bind(controllerInstance)(request, response, next);
906
- if (result instanceof ResponseEntity) {
907
- const body = schemas && schemas.responseBody ? await _parseOrThrow(schemas.responseBody, result.getBody(), "resbody") : result.getBody();
908
- response.contentType("application/json").status(result.getStatusCode()).set(result.getHeaders()).send(Sapling.serialize(body));
909
- return;
910
- }
911
- if (result instanceof RedirectView) {
912
- response.redirect(result.getUrl());
913
- return;
914
- }
915
- if (method !== "USE" && !response.writableEnded) response.status(404).send(Html404ErrorPage(`Cannot ${methodName.toUpperCase()} ${path instanceof RegExp ? path.source : fp}`));
956
+ await validate({
957
+ target,
958
+ fnName,
959
+ request
960
+ });
961
+ await handleResult({
962
+ result: await fn.bind(controllerInstance)(request, response, next),
963
+ response,
964
+ target,
965
+ fnName,
966
+ method,
967
+ path: path instanceof RegExp ? path.source : fp
968
+ });
916
969
  });
917
970
  }
918
971
  _ControllerRegistry.set(targetClass, router);
919
972
  };
920
973
  }
974
+ async function handleResult({ result, target, fnName, response, method, path, isErrorMiddleware = false }) {
975
+ const schemas = _getValidatorSchema(target, fnName);
976
+ if (result instanceof ResponseEntity) {
977
+ const body = schemas && schemas.responseBody ? await _parseOrThrow(schemas.responseBody, result.getBody(), "resbody", fnName) : result.getBody();
978
+ response.contentType("application/json").status(result.getStatusCode()).set(result.getHeaders()).send(Sapling.serialize(body));
979
+ return;
980
+ }
981
+ if (result instanceof RedirectView) {
982
+ response.redirect(result.getUrl());
983
+ return;
984
+ }
985
+ if (!isErrorMiddleware && method !== "USE" && !response.writableEnded) response.status(404).send(Html404ErrorPage(`Cannot ${method} ${path}`));
986
+ }
987
+ async function validate({ target, fnName, request }) {
988
+ const schemas = _getValidatorSchema(target, fnName);
989
+ if (schemas) {
990
+ if (schemas.requestBody) request.body = await _parseOrThrow(schemas.requestBody, request.body, "reqbody", fnName);
991
+ if (schemas.requestParam) request.params = await _parseOrThrow(schemas.requestParam, request.params, "reqparams", fnName);
992
+ if (schemas.requestQuery) {
993
+ const parsedQuery = await _parseOrThrow(schemas.requestQuery, request.query, "reqquery", fnName);
994
+ Object.defineProperty(request, "query", {
995
+ value: parsedQuery,
996
+ writable: true,
997
+ configurable: true
998
+ });
999
+ }
1000
+ }
1001
+ }
921
1002
  //#endregion
922
1003
  //#region src/annotation/middleware.ts
923
1004
  /**
@@ -952,7 +1033,10 @@ DefaultBaseErrorMiddleware = __decorate([MiddlewareClass()], DefaultBaseErrorMid
952
1033
  //#region src/middleware/default/error/parse.ts
953
1034
  let DefaultParserErrorMiddleware = class DefaultParserErrorMiddleware {
954
1035
  handle(err, _request, _response, next) {
955
- if (err instanceof ParserError) return ResponseEntity.status(err.status).body({ message: err.message });
1036
+ if (err instanceof ParserError) {
1037
+ console.warn(err);
1038
+ return ResponseEntity.status(err.status).body({ message: err.message });
1039
+ }
956
1040
  next(err);
957
1041
  }
958
1042
  };
@@ -979,17 +1063,48 @@ __decorate([GET(_settings.doc.openApiPath)], DefaultOpenApiMiddleware.prototype,
979
1063
  DefaultOpenApiMiddleware = __decorate([MiddlewareClass()], DefaultOpenApiMiddleware);
980
1064
  //#endregion
981
1065
  //#region src/middleware/default/swagger/index.ts
1066
+ /**
1067
+ * Enable the serving of the Swagger endpoint used to serve the OpenAPI spec generated by Sapling.
1068
+ *
1069
+ * Configure any middleware-specific settings with `Sapling.Extras.swaggerAndOpenApi`
1070
+ *
1071
+ * You must register `DefaultSwaggerMiddleware.Serve` & `DefaultSwaggerMiddleware.Setup` after `DefaultOpenApiMiddleware`
1072
+ *
1073
+ * ```ts
1074
+ * const middlewares = [
1075
+ * DefaultOpenApiMiddleware,
1076
+ * DefaultSwaggerMiddleware.Serve,
1077
+ * DefaultSwaggerMiddleware.Setup,
1078
+ * ];
1079
+ * middlewares.map(Sapling.resolve).forEach((r) => app.use(r));
1080
+ * ```
1081
+ */
982
1082
  let Serve = class Serve {
983
- constructor() {
984
- this.handlers = swagger_ui_express.default.serve;
985
- }
1083
+ handlers = swagger_ui_express.default.serve;
986
1084
  handle(request, response, next) {
987
1085
  return Sapling.chainHandlers(this.handlers, request, response, next);
988
1086
  }
989
1087
  };
990
1088
  __decorate([Middleware(_settings.doc.swaggerPath)], Serve.prototype, "handle", null);
991
1089
  Serve = __decorate([MiddlewareClass()], Serve);
1090
+ /**
1091
+ * Enable the serving of the Swagger endpoint used to serve the OpenAPI spec generated by Sapling.
1092
+ *
1093
+ * Configure any middleware-specific settings with `Sapling.Extras.swaggerAndOpenApi`
1094
+ *
1095
+ * You must register `DefaultSwaggerMiddleware.Serve` & `DefaultSwaggerMiddleware.Setup` after `DefaultOpenApiMiddleware`
1096
+ *
1097
+ * ```ts
1098
+ * const middlewares = [
1099
+ * DefaultOpenApiMiddleware,
1100
+ * DefaultSwaggerMiddleware.Serve,
1101
+ * DefaultSwaggerMiddleware.Setup,
1102
+ * ];
1103
+ * middlewares.map(Sapling.resolve).forEach((r) => app.use(r));
1104
+ * ```
1105
+ */
992
1106
  let Setup = class Setup {
1107
+ handler;
993
1108
  constructor() {
994
1109
  this.handler = swagger_ui_express.default.setup(null, { swaggerOptions: { url: _settings.doc.openApiPath } });
995
1110
  }
@@ -999,6 +1114,22 @@ let Setup = class Setup {
999
1114
  };
1000
1115
  __decorate([Middleware(_settings.doc.swaggerPath)], Setup.prototype, "handle", null);
1001
1116
  Setup = __decorate([MiddlewareClass()], Setup);
1117
+ /**
1118
+ * Enable the serving of the Swagger endpoint used to serve the OpenAPI spec generated by Sapling.
1119
+ *
1120
+ * Configure any middleware-specific settings with `Sapling.Extras.swaggerAndOpenApi`
1121
+ *
1122
+ * You must register `DefaultSwaggerMiddleware.Serve` & `DefaultSwaggerMiddleware.Setup` after `DefaultOpenApiMiddleware`
1123
+ *
1124
+ * ```ts
1125
+ * const middlewares = [
1126
+ * DefaultOpenApiMiddleware,
1127
+ * DefaultSwaggerMiddleware.Serve,
1128
+ * DefaultSwaggerMiddleware.Setup,
1129
+ * ];
1130
+ * middlewares.map(Sapling.resolve).forEach((r) => app.use(r));
1131
+ * ```
1132
+ */
1002
1133
  const DefaultSwaggerMiddleware = {
1003
1134
  Serve,
1004
1135
  Setup
@@ -1058,19 +1189,19 @@ exports._ControllerRegistry = _ControllerRegistry;
1058
1189
  exports._InjectableDeps = _InjectableDeps;
1059
1190
  exports._InjectableRegistry = _InjectableRegistry;
1060
1191
  exports._Route = _Route;
1192
+ exports._clearOpenApiRegistry = _clearOpenApiRegistry;
1061
1193
  exports._getControllerSchema = _getControllerSchema;
1062
1194
  exports._getOrCreateSchemaDefinition = _getOrCreateSchemaDefinition;
1063
1195
  exports._getRouteSchema = _getRouteSchema;
1064
1196
  exports._getRoutes = _getRoutes;
1065
1197
  exports._getValidatorSchema = _getValidatorSchema;
1066
1198
  exports._parseOrThrow = _parseOrThrow;
1067
- exports._registerControllerClass = _registerControllerClass;
1199
+ exports._registerController = _registerController;
1068
1200
  exports._resolve = _resolve;
1201
+ exports._saveValidatorSchema = _saveValidatorSchema;
1069
1202
  exports._setControllerSchema = _setControllerSchema;
1070
- exports._setOnce = _setOnce;
1071
1203
  exports._setRouteSchema = _setRouteSchema;
1072
1204
  exports._settings = _settings;
1073
1205
  exports.generateOpenApiSpec = generateOpenApiSpec;
1074
1206
  exports.methodResolve = methodResolve;
1075
1207
  exports.openApiGenerator = openApiGenerator;
1076
- exports.setOpenApiConfig = setOpenApiConfig;