@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.mjs CHANGED
@@ -23,6 +23,7 @@ const Html404ErrorPage = (error) => `<!DOCTYPE html>
23
23
  * You can either return `new RedirectView(url)` or `RedirectView.redirect(url)` inside of a controller method.
24
24
  */
25
25
  var RedirectView = class RedirectView {
26
+ _url;
26
27
  constructor(url) {
27
28
  this._url = url;
28
29
  }
@@ -118,8 +119,10 @@ let HttpStatus = /* @__PURE__ */ function(HttpStatus) {
118
119
  * @typeParam T - the type of the response body
119
120
  */
120
121
  var ResponseEntity = class {
122
+ _statusCode;
123
+ _headers = {};
124
+ _body;
121
125
  constructor(body, headers = {}, statusCode = 200) {
122
- this._headers = {};
123
126
  this._body = body;
124
127
  this._headers = headers;
125
128
  this._statusCode = statusCode;
@@ -172,8 +175,9 @@ var ResponseEntity = class {
172
175
  * ensuring type safety when constructing the response.
173
176
  */
174
177
  var ResponseEntityBuilder = class {
178
+ _statusCode;
179
+ _headers = {};
175
180
  constructor(statusCode) {
176
- this._headers = {};
177
181
  this._statusCode = statusCode;
178
182
  }
179
183
  /**
@@ -205,6 +209,7 @@ var ResponseEntityBuilder = class {
205
209
  * @see {@link Sapling.loadResponseStatusErrorMiddleware}
206
210
  */
207
211
  var ResponseStatusError = class ResponseStatusError extends Error {
212
+ status;
208
213
  constructor(status, message) {
209
214
  super(message ?? "Something went wrong.");
210
215
  this.status = status;
@@ -216,26 +221,27 @@ var ResponseStatusError = class ResponseStatusError extends Error {
216
221
  //#endregion
217
222
  //#region src/helper/error/parse.ts
218
223
  /**
219
- * This error should be thrown when some data cannot be parsed by a given schema.
224
+ * This error should be thrown when some data cannot be parsed by a given Standard Schema compatible schema.
220
225
  */
221
226
  var ParserError = class ParserError extends ResponseStatusError {
222
- constructor(location, issues, vendor) {
223
- super(400, ParserError.formatMessage(location, issues, vendor));
227
+ constructor(location, issues, vendor, functionName) {
228
+ super(400, ParserError.formatMessage(location, issues, vendor, functionName));
224
229
  Object.setPrototypeOf(this, new.target.prototype);
225
230
  }
226
- static formatMessage(location, issues, vendor) {
231
+ static formatMessage(location, issues, vendor, functionName) {
227
232
  const formatted = issues.map((i) => {
228
233
  const path = Array.isArray(i.path) ? i.path.map((seg) => typeof seg === "object" && seg ? String(seg.key) : String(seg)).join(".") : "";
229
234
  return path ? `${path}: ${i.message}` : i.message;
230
235
  }).join("; ");
231
- return `${vendor} failed to parse ${(() => {
232
- switch (location) {
233
- case "reqbody": return "request body";
234
- case "reqparams": return "request params";
235
- case "reqquery": return "request query";
236
- case "resbody": return "response body";
237
- }
238
- })()}: ${formatted}`;
236
+ return `Failed to parse ${this.getPrettyLocationString(location)} with ${vendor} on ${functionName}: ${formatted}`;
237
+ }
238
+ static getPrettyLocationString(location) {
239
+ switch (location) {
240
+ case "reqbody": return "request body";
241
+ case "reqparams": return "request params";
242
+ case "reqquery": return "request query";
243
+ case "resbody": return "response body";
244
+ }
239
245
  }
240
246
  };
241
247
  //#endregion
@@ -245,7 +251,11 @@ const _settings = {
245
251
  deserialize: JSON.parse,
246
252
  doc: {
247
253
  openApiPath: "/openapi.json",
248
- swaggerPath: "/swagger.html"
254
+ swaggerPath: "/swagger.html",
255
+ metadata: {
256
+ title: "API",
257
+ version: "1.0.0"
258
+ }
249
259
  }
250
260
  };
251
261
  /**
@@ -351,12 +361,59 @@ var Sapling = class Sapling {
351
361
  static setDeserializeFn(fn) {
352
362
  _settings.deserialize = fn;
353
363
  }
354
- static setOpenApiPath(path) {
355
- _settings.doc.openApiPath = path;
356
- }
357
- static setSwaggerPath(path) {
358
- _settings.doc.swaggerPath = path;
359
- }
364
+ /**
365
+ * Modify extra settings
366
+ */
367
+ static Extras = {
368
+ /**
369
+ * Modify default settings applied to OpenAPI & Swagger
370
+ */
371
+ swaggerAndOpenApi: {
372
+ /**
373
+ * Set base OpenAPI metadata values.
374
+ *
375
+ * @default { title: "API", version: "1.0.0" }
376
+ */
377
+ setMetadata(metadata) {
378
+ _settings.doc.metadata = metadata;
379
+ },
380
+ /**
381
+ * change default endpoint that will serve OpenAPI spec.
382
+ * Swagger will also load this endpoint on load.
383
+ *
384
+ * @default `/openapi.json`
385
+ */
386
+ setOpenApiPath(path) {
387
+ _settings.doc.openApiPath = path;
388
+ },
389
+ /**
390
+ * change Swagger endpoint.
391
+ *
392
+ * @default `/swagger.html`
393
+ */
394
+ setSwaggerPath(path) {
395
+ _settings.doc.swaggerPath = path;
396
+ }
397
+ } };
398
+ /**
399
+ * This method can be used in a `@MiddlewareClass` to register any libraries
400
+ * that expect you to register multiple registers at once. An example is `swagger-ui-express`
401
+ *
402
+ * @example
403
+ * ```ts
404
+ * ⠀@MiddlewareClass()
405
+ * class Serve {
406
+ * // `swagger.serve` returns multiple Express handlers for all the assets and routes
407
+ * // that will be served
408
+ * private readonly handlers: RequestHandler[] = swagger.serve;
409
+ *
410
+ * ⠀@Middleware(_settings.doc.swaggerPath)
411
+ * handle(request: Request, response: Response, next: NextFunction) {
412
+ * return Sapling.chainHandlers(this.handlers, request, response, next);
413
+ * }
414
+ * }
415
+ * ```
416
+ */
360
417
  static chainHandlers(handlers, request, response, next, index = 0) {
361
418
  if (index >= handlers.length) {
362
419
  next();
@@ -453,18 +510,7 @@ function _getRoutes(ctor) {
453
510
  return _routeStore.get(ctor) ?? [];
454
511
  }
455
512
  //#endregion
456
- //#region src/utils.ts
457
- function _getOrCreateMap(store, ctor) {
458
- const existing = store.get(ctor);
459
- if (existing) return existing;
460
- const created = /* @__PURE__ */ new Map();
461
- store.set(ctor, created);
462
- return created;
463
- }
464
- //#endregion
465
513
  //#region src/annotation/schema.ts
466
- const _routeSchemaStore = /* @__PURE__ */ new WeakMap();
467
- const _controllerSchemaStore = /* @__PURE__ */ new WeakMap();
468
514
  function ControllerSchema(options) {
469
515
  return (target) => {
470
516
  _setControllerSchema(target, options);
@@ -476,8 +522,17 @@ function RouteSchema(options) {
476
522
  _setRouteSchema(ctor, String(propertyKey), options);
477
523
  };
478
524
  }
525
+ const _routeSchemaStore = /* @__PURE__ */ new WeakMap();
526
+ const _controllerSchemaStore = /* @__PURE__ */ new WeakMap();
527
+ function getOrCreateRouteSchemaStore(store, ctor) {
528
+ const existing = store.get(ctor);
529
+ if (existing) return existing;
530
+ const created = /* @__PURE__ */ new Map();
531
+ store.set(ctor, created);
532
+ return created;
533
+ }
479
534
  function _setRouteSchema(ctor, fnName, options) {
480
- _getOrCreateMap(_routeSchemaStore, ctor).set(fnName, options);
535
+ getOrCreateRouteSchemaStore(_routeSchemaStore, ctor).set(fnName, options);
481
536
  }
482
537
  function _setControllerSchema(ctor, options) {
483
538
  _controllerSchemaStore.set(ctor, options);
@@ -489,26 +544,85 @@ function _getControllerSchema(ctor) {
489
544
  return _controllerSchemaStore.get(ctor);
490
545
  }
491
546
  //#endregion
547
+ //#region src/annotation/validator.ts
548
+ const _validatorSchemaStore = /* @__PURE__ */ new WeakMap();
549
+ function ResponseBody(schema) {
550
+ return (target, propertyKey) => {
551
+ const ctor = target.constructor;
552
+ const fnName = String(propertyKey);
553
+ _saveValidatorSchema(_getOrCreateSchemaDefinition(ctor, fnName), "responseBody", schema, fnName);
554
+ };
555
+ }
556
+ function RequestBody(schema) {
557
+ return (target, propertyKey) => {
558
+ const ctor = target.constructor;
559
+ const fnName = String(propertyKey);
560
+ _saveValidatorSchema(_getOrCreateSchemaDefinition(ctor, fnName), "requestBody", schema, fnName);
561
+ };
562
+ }
563
+ function RequestParam(schema) {
564
+ return (target, propertyKey) => {
565
+ const ctor = target.constructor;
566
+ const fnName = String(propertyKey);
567
+ _saveValidatorSchema(_getOrCreateSchemaDefinition(ctor, fnName), "requestParam", schema, fnName);
568
+ };
569
+ }
570
+ function RequestQuery(schema) {
571
+ return (target, propertyKey) => {
572
+ const ctor = target.constructor;
573
+ const fnName = String(propertyKey);
574
+ _saveValidatorSchema(_getOrCreateSchemaDefinition(ctor, fnName), "requestQuery", schema, fnName);
575
+ };
576
+ }
577
+ function getOrCreateValidatorSchemaStore(store, ctor) {
578
+ const existing = store.get(ctor);
579
+ if (existing) return existing;
580
+ const created = /* @__PURE__ */ new Map();
581
+ store.set(ctor, created);
582
+ return created;
583
+ }
584
+ function _getOrCreateSchemaDefinition(ctor, fnName) {
585
+ const byFn = getOrCreateValidatorSchemaStore(_validatorSchemaStore, ctor);
586
+ const existing = byFn.get(fnName);
587
+ if (existing) return existing;
588
+ const created = {};
589
+ byFn.set(fnName, created);
590
+ return created;
591
+ }
592
+ async function _parseOrThrow(schema, input, location, fnName) {
593
+ const result = await schema["~standard"].validate(input);
594
+ if (result.issues) throw new ParserError(location, result.issues, schema["~standard"].vendor, fnName);
595
+ return result.value;
596
+ }
597
+ function _saveValidatorSchema(def, key, schema, fnName) {
598
+ if (def[key]) throw new Error(`Duplicate schema for "${String(key)}" on method "${fnName}"`);
599
+ def[key] = schema;
600
+ }
601
+ function _getValidatorSchema(ctor, fnName) {
602
+ return _validatorSchemaStore.get(ctor)?.get(fnName);
603
+ }
604
+ //#endregion
492
605
  //#region src/helper/openapi.ts
493
606
  var OpenAPIGenerator = class {
494
- constructor() {
495
- this.controllers = /* @__PURE__ */ new Set();
496
- this.config = {
497
- title: "API",
498
- version: "1.0.0"
499
- };
500
- }
501
- setConfig(config) {
502
- this.config = config;
503
- }
607
+ OPENAPI_VERSION = "3.0.0";
608
+ controllers = /* @__PURE__ */ new Set();
504
609
  registerController(controllerClass, prefix) {
505
610
  this.controllers.add({
506
611
  class: controllerClass,
507
612
  prefix
508
613
  });
509
614
  }
615
+ /**
616
+ * visible for testing
617
+ */
618
+ _clearControllers() {
619
+ this.controllers.clear();
620
+ }
621
+ get metadata() {
622
+ return _settings.doc.metadata;
623
+ }
510
624
  generateSpec() {
511
- const config = this.config;
625
+ const metadata = this.metadata;
512
626
  const paths = {};
513
627
  const tags = [];
514
628
  for (const { class: controllerClass, prefix } of this.controllers) {
@@ -592,11 +706,11 @@ var OpenAPIGenerator = class {
592
706
  }
593
707
  }
594
708
  return {
595
- openapi: "3.0.0",
709
+ openapi: this.OPENAPI_VERSION,
596
710
  info: {
597
- title: config.title,
598
- version: config.version,
599
- description: config.description
711
+ title: metadata.title,
712
+ version: metadata.version,
713
+ description: metadata.description
600
714
  },
601
715
  tags: tags.length > 0 ? tags : void 0,
602
716
  paths
@@ -605,24 +719,23 @@ var OpenAPIGenerator = class {
605
719
  toJsonSchema(schema, direction = "output") {
606
720
  try {
607
721
  const jsonSchema = schema["~standard"].jsonSchema;
608
- if (direction === "input" && jsonSchema.input) return jsonSchema.input({ target: "openapi-3.0" });
609
- return jsonSchema.output({ target: "openapi-3.0" });
722
+ return direction === "input" ? jsonSchema.input({ target: "openapi-3.0" }) : jsonSchema.output({ target: "openapi-3.0" });
610
723
  } catch (e) {
611
- 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`);
724
+ 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 });
612
725
  throw e;
613
726
  }
614
727
  }
615
728
  };
616
729
  const openApiGenerator = new OpenAPIGenerator();
617
- function _registerControllerClass(controllerClass, prefix) {
730
+ function _registerController(controllerClass, prefix) {
618
731
  openApiGenerator.registerController(controllerClass, prefix);
619
732
  }
620
- function setOpenApiConfig(config) {
621
- openApiGenerator.setConfig(config);
622
- }
623
733
  function generateOpenApiSpec() {
624
734
  return openApiGenerator.generateSpec();
625
735
  }
736
+ function _clearOpenApiRegistry() {
737
+ openApiGenerator._clearControllers();
738
+ }
626
739
  //#endregion
627
740
  //#region src/types.ts
628
741
  const methodResolve = {
@@ -756,60 +869,6 @@ function _resolve(ctor) {
756
869
  return _InjectableRegistry.get(ctor);
757
870
  }
758
871
  //#endregion
759
- //#region src/annotation/validator.ts
760
- const _validatorSchemaStore = /* @__PURE__ */ new WeakMap();
761
- function ResponseBody(schema) {
762
- return (target, propertyKey) => {
763
- const ctor = target.constructor;
764
- const fnName = String(propertyKey);
765
- _setOnce(_getOrCreateSchemaDefinition(ctor, fnName), "responseBody", schema, fnName);
766
- };
767
- }
768
- function RequestBody(schema) {
769
- return (target, propertyKey) => {
770
- const ctor = target.constructor;
771
- const fnName = String(propertyKey);
772
- _setOnce(_getOrCreateSchemaDefinition(ctor, fnName), "requestBody", schema, fnName);
773
- };
774
- }
775
- function RequestParam(schema) {
776
- return (target, propertyKey) => {
777
- const ctor = target.constructor;
778
- const fnName = String(propertyKey);
779
- _setOnce(_getOrCreateSchemaDefinition(ctor, fnName), "requestParam", schema, fnName);
780
- };
781
- }
782
- function RequestQuery(schema) {
783
- return (target, propertyKey) => {
784
- const ctor = target.constructor;
785
- const fnName = String(propertyKey);
786
- _setOnce(_getOrCreateSchemaDefinition(ctor, fnName), "requestQuery", schema, fnName);
787
- };
788
- }
789
- function _getOrCreateSchemaDefinition(ctor, fnName) {
790
- const byFn = _getOrCreateMap(_validatorSchemaStore, ctor);
791
- const existing = byFn.get(fnName);
792
- if (existing) return existing;
793
- const created = {};
794
- byFn.set(fnName, created);
795
- return created;
796
- }
797
- async function _parseOrThrow(schema, input, kind) {
798
- const result = await schema["~standard"].validate(input);
799
- if (result.issues) {
800
- console.debug(`Failed to parse ${schema["~standard"].vendor} schema\nissues: ${JSON.stringify(result.issues, null, 2)}`);
801
- throw new ParserError(kind, result.issues, schema["~standard"].vendor);
802
- }
803
- return result.value;
804
- }
805
- function _getValidatorSchema(ctor, fnName) {
806
- return _validatorSchemaStore.get(ctor)?.get(fnName);
807
- }
808
- function _setOnce(def, key, schema, fnName) {
809
- if (def[key]) throw new Error(`Duplicate schema for "${String(key)}" on method "${fnName}"`);
810
- def[key] = schema;
811
- }
812
- //#endregion
813
872
  //#region src/annotation/controller.ts
814
873
  const _ControllerRegistry = /* @__PURE__ */ new WeakMap();
815
874
  /**
@@ -821,7 +880,7 @@ const _ControllerRegistry = /* @__PURE__ */ new WeakMap();
821
880
  function Controller({ prefix = "", deps = [] } = {}) {
822
881
  return (target) => {
823
882
  const targetClass = target;
824
- _registerControllerClass(target, prefix);
883
+ _registerController(target, prefix);
825
884
  const router = Router();
826
885
  const routes = _getRoutes(target);
827
886
  const usedRoutes = /* @__PURE__ */ new Set();
@@ -846,15 +905,20 @@ Split these into separate @MiddlewareClass classes, or merge the logic into a si
846
905
  if (method === "USE" && fn.length >= 4) {
847
906
  const middlewareFn = async (err, request, response, next) => {
848
907
  try {
849
- const result = fn.bind(controllerInstance)(err, request, response, next);
850
- if (result instanceof ResponseEntity) {
851
- response.contentType("application/json").status(result.getStatusCode()).set(result.getHeaders()).send(Sapling.serialize(result.getBody()));
852
- return;
853
- }
854
- if (result instanceof RedirectView) {
855
- response.redirect(result.getUrl());
856
- return;
857
- }
908
+ await validate({
909
+ target,
910
+ fnName,
911
+ request
912
+ });
913
+ await handleResult({
914
+ result: fn.bind(controllerInstance)(err, request, response, next),
915
+ response,
916
+ target,
917
+ fnName,
918
+ method,
919
+ path: path instanceof RegExp ? path.source : fp,
920
+ isErrorMiddleware: true
921
+ });
858
922
  } catch (e) {
859
923
  console.error(e);
860
924
  next(e);
@@ -864,35 +928,52 @@ Split these into separate @MiddlewareClass classes, or merge the logic into a si
864
928
  return;
865
929
  }
866
930
  router[methodName](fp, async (request, response, next) => {
867
- const schemas = _getValidatorSchema(target, fnName);
868
- if (schemas) {
869
- if (schemas.requestBody) request.body = await _parseOrThrow(schemas.requestBody, request.body, "reqbody");
870
- if (schemas.requestParam) request.params = await _parseOrThrow(schemas.requestParam, request.params, "reqparams");
871
- if (schemas.requestQuery) {
872
- const parsedQuery = await _parseOrThrow(schemas.requestQuery, request.query, "reqquery");
873
- Object.defineProperty(request, "query", {
874
- value: parsedQuery,
875
- writable: true,
876
- configurable: true
877
- });
878
- }
879
- }
880
- const result = await fn.bind(controllerInstance)(request, response, next);
881
- if (result instanceof ResponseEntity) {
882
- const body = schemas && schemas.responseBody ? await _parseOrThrow(schemas.responseBody, result.getBody(), "resbody") : result.getBody();
883
- response.contentType("application/json").status(result.getStatusCode()).set(result.getHeaders()).send(Sapling.serialize(body));
884
- return;
885
- }
886
- if (result instanceof RedirectView) {
887
- response.redirect(result.getUrl());
888
- return;
889
- }
890
- if (method !== "USE" && !response.writableEnded) response.status(404).send(Html404ErrorPage(`Cannot ${methodName.toUpperCase()} ${path instanceof RegExp ? path.source : fp}`));
931
+ await validate({
932
+ target,
933
+ fnName,
934
+ request
935
+ });
936
+ await handleResult({
937
+ result: await fn.bind(controllerInstance)(request, response, next),
938
+ response,
939
+ target,
940
+ fnName,
941
+ method,
942
+ path: path instanceof RegExp ? path.source : fp
943
+ });
891
944
  });
892
945
  }
893
946
  _ControllerRegistry.set(targetClass, router);
894
947
  };
895
948
  }
949
+ async function handleResult({ result, target, fnName, response, method, path, isErrorMiddleware = false }) {
950
+ const schemas = _getValidatorSchema(target, fnName);
951
+ if (result instanceof ResponseEntity) {
952
+ const body = schemas && schemas.responseBody ? await _parseOrThrow(schemas.responseBody, result.getBody(), "resbody", fnName) : result.getBody();
953
+ response.contentType("application/json").status(result.getStatusCode()).set(result.getHeaders()).send(Sapling.serialize(body));
954
+ return;
955
+ }
956
+ if (result instanceof RedirectView) {
957
+ response.redirect(result.getUrl());
958
+ return;
959
+ }
960
+ if (!isErrorMiddleware && method !== "USE" && !response.writableEnded) response.status(404).send(Html404ErrorPage(`Cannot ${method} ${path}`));
961
+ }
962
+ async function validate({ target, fnName, request }) {
963
+ const schemas = _getValidatorSchema(target, fnName);
964
+ if (schemas) {
965
+ if (schemas.requestBody) request.body = await _parseOrThrow(schemas.requestBody, request.body, "reqbody", fnName);
966
+ if (schemas.requestParam) request.params = await _parseOrThrow(schemas.requestParam, request.params, "reqparams", fnName);
967
+ if (schemas.requestQuery) {
968
+ const parsedQuery = await _parseOrThrow(schemas.requestQuery, request.query, "reqquery", fnName);
969
+ Object.defineProperty(request, "query", {
970
+ value: parsedQuery,
971
+ writable: true,
972
+ configurable: true
973
+ });
974
+ }
975
+ }
976
+ }
896
977
  //#endregion
897
978
  //#region src/annotation/middleware.ts
898
979
  /**
@@ -927,7 +1008,10 @@ DefaultBaseErrorMiddleware = __decorate([MiddlewareClass()], DefaultBaseErrorMid
927
1008
  //#region src/middleware/default/error/parse.ts
928
1009
  let DefaultParserErrorMiddleware = class DefaultParserErrorMiddleware {
929
1010
  handle(err, _request, _response, next) {
930
- if (err instanceof ParserError) return ResponseEntity.status(err.status).body({ message: err.message });
1011
+ if (err instanceof ParserError) {
1012
+ console.warn(err);
1013
+ return ResponseEntity.status(err.status).body({ message: err.message });
1014
+ }
931
1015
  next(err);
932
1016
  }
933
1017
  };
@@ -954,17 +1038,48 @@ __decorate([GET(_settings.doc.openApiPath)], DefaultOpenApiMiddleware.prototype,
954
1038
  DefaultOpenApiMiddleware = __decorate([MiddlewareClass()], DefaultOpenApiMiddleware);
955
1039
  //#endregion
956
1040
  //#region src/middleware/default/swagger/index.ts
1041
+ /**
1042
+ * Enable the serving of the Swagger endpoint used to serve the OpenAPI spec generated by Sapling.
1043
+ *
1044
+ * Configure any middleware-specific settings with `Sapling.Extras.swaggerAndOpenApi`
1045
+ *
1046
+ * You must register `DefaultSwaggerMiddleware.Serve` & `DefaultSwaggerMiddleware.Setup` after `DefaultOpenApiMiddleware`
1047
+ *
1048
+ * ```ts
1049
+ * const middlewares = [
1050
+ * DefaultOpenApiMiddleware,
1051
+ * DefaultSwaggerMiddleware.Serve,
1052
+ * DefaultSwaggerMiddleware.Setup,
1053
+ * ];
1054
+ * middlewares.map(Sapling.resolve).forEach((r) => app.use(r));
1055
+ * ```
1056
+ */
957
1057
  let Serve = class Serve {
958
- constructor() {
959
- this.handlers = swagger.serve;
960
- }
1058
+ handlers = swagger.serve;
961
1059
  handle(request, response, next) {
962
1060
  return Sapling.chainHandlers(this.handlers, request, response, next);
963
1061
  }
964
1062
  };
965
1063
  __decorate([Middleware(_settings.doc.swaggerPath)], Serve.prototype, "handle", null);
966
1064
  Serve = __decorate([MiddlewareClass()], Serve);
1065
+ /**
1066
+ * Enable the serving of the Swagger endpoint used to serve the OpenAPI spec generated by Sapling.
1067
+ *
1068
+ * Configure any middleware-specific settings with `Sapling.Extras.swaggerAndOpenApi`
1069
+ *
1070
+ * You must register `DefaultSwaggerMiddleware.Serve` & `DefaultSwaggerMiddleware.Setup` after `DefaultOpenApiMiddleware`
1071
+ *
1072
+ * ```ts
1073
+ * const middlewares = [
1074
+ * DefaultOpenApiMiddleware,
1075
+ * DefaultSwaggerMiddleware.Serve,
1076
+ * DefaultSwaggerMiddleware.Setup,
1077
+ * ];
1078
+ * middlewares.map(Sapling.resolve).forEach((r) => app.use(r));
1079
+ * ```
1080
+ */
967
1081
  let Setup = class Setup {
1082
+ handler;
968
1083
  constructor() {
969
1084
  this.handler = swagger.setup(null, { swaggerOptions: { url: _settings.doc.openApiPath } });
970
1085
  }
@@ -974,9 +1089,25 @@ let Setup = class Setup {
974
1089
  };
975
1090
  __decorate([Middleware(_settings.doc.swaggerPath)], Setup.prototype, "handle", null);
976
1091
  Setup = __decorate([MiddlewareClass()], Setup);
1092
+ /**
1093
+ * Enable the serving of the Swagger endpoint used to serve the OpenAPI spec generated by Sapling.
1094
+ *
1095
+ * Configure any middleware-specific settings with `Sapling.Extras.swaggerAndOpenApi`
1096
+ *
1097
+ * You must register `DefaultSwaggerMiddleware.Serve` & `DefaultSwaggerMiddleware.Setup` after `DefaultOpenApiMiddleware`
1098
+ *
1099
+ * ```ts
1100
+ * const middlewares = [
1101
+ * DefaultOpenApiMiddleware,
1102
+ * DefaultSwaggerMiddleware.Serve,
1103
+ * DefaultSwaggerMiddleware.Setup,
1104
+ * ];
1105
+ * middlewares.map(Sapling.resolve).forEach((r) => app.use(r));
1106
+ * ```
1107
+ */
977
1108
  const DefaultSwaggerMiddleware = {
978
1109
  Serve,
979
1110
  Setup
980
1111
  };
981
1112
  //#endregion
982
- export { Controller, ControllerSchema, DELETE, DefaultBaseErrorMiddleware, DefaultOpenApiMiddleware, DefaultParserErrorMiddleware, DefaultResponseStatusErrorMiddleware, DefaultSwaggerMiddleware, GET, HEAD, Html404ErrorPage, HttpStatus, Injectable, Middleware, MiddlewareClass, OPTIONS, PATCH, POST, PUT, ParserError, RedirectView, RequestBody, RequestParam, RequestQuery, ResponseBody, ResponseEntity, ResponseEntityBuilder, ResponseStatusError, RouteSchema, Sapling, _ControllerRegistry, _InjectableDeps, _InjectableRegistry, _Route, _getControllerSchema, _getOrCreateSchemaDefinition, _getRouteSchema, _getRoutes, _getValidatorSchema, _parseOrThrow, _registerControllerClass, _resolve, _setControllerSchema, _setOnce, _setRouteSchema, _settings, generateOpenApiSpec, methodResolve, openApiGenerator, setOpenApiConfig };
1113
+ export { Controller, ControllerSchema, DELETE, DefaultBaseErrorMiddleware, DefaultOpenApiMiddleware, DefaultParserErrorMiddleware, DefaultResponseStatusErrorMiddleware, DefaultSwaggerMiddleware, GET, HEAD, 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.0.5-beta.0b3bd061",
3
+ "version": "2.0.5-beta.1843d6fa",
4
4
  "author": "Tahmid Ahmed",
5
5
  "description": "A library to help you write cleaner Express.js code",
6
6
  "repository": {