@tahminator/sapling 2.0.5-beta.ac279593 → 2.0.5-beta.e0403942

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,78 @@ 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
+ controllers = /* @__PURE__ */ new Set();
504
608
  registerController(controllerClass, prefix) {
505
609
  this.controllers.add({
506
610
  class: controllerClass,
507
611
  prefix
508
612
  });
509
613
  }
614
+ get metadata() {
615
+ return _settings.doc.metadata;
616
+ }
510
617
  generateSpec() {
511
- const config = this.config;
618
+ const metadata = this.metadata;
512
619
  const paths = {};
513
620
  const tags = [];
514
621
  for (const { class: controllerClass, prefix } of this.controllers) {
@@ -534,14 +641,19 @@ var OpenAPIGenerator = class {
534
641
  };
535
642
  } else responses["200"] = { description: "Successful response" };
536
643
  if (routeSchema?.responses) for (const resp of routeSchema.responses) {
537
- const responseSchema = this.toJsonSchema(resp.schema, "output");
538
- responses[String(resp.statusCode)] = {
539
- description: resp.description ?? responseSchema.description ?? `Response ${resp.statusCode}`,
540
- content: { "application/json": { schema: responseSchema } }
644
+ const statusCode = String(resp.statusCode);
645
+ const existingResponse = responses[statusCode];
646
+ const existingSchema = existingResponse && "content" in existingResponse ? existingResponse.content?.["application/json"]?.schema : void 0;
647
+ const responseSchema = resp.schema ? this.toJsonSchema(resp.schema, "output") : statusCode === "200" ? existingSchema : void 0;
648
+ responses[statusCode] = {
649
+ ...existingResponse,
650
+ description: resp.description ?? responseSchema?.description ?? existingResponse?.description ?? `Response ${resp.statusCode}`,
651
+ ...responseSchema ? { content: { "application/json": { schema: responseSchema } } } : {}
541
652
  };
542
653
  }
543
654
  const operation = {
544
655
  responses,
656
+ summary: routeSchema?.summary,
545
657
  description: routeSchema?.description,
546
658
  tags: controllerSchema?.title ? [controllerSchema.title] : void 0
547
659
  };
@@ -589,9 +701,9 @@ var OpenAPIGenerator = class {
589
701
  return {
590
702
  openapi: "3.0.0",
591
703
  info: {
592
- title: config.title,
593
- version: config.version,
594
- description: config.description
704
+ title: metadata.title,
705
+ version: metadata.version,
706
+ description: metadata.description
595
707
  },
596
708
  tags: tags.length > 0 ? tags : void 0,
597
709
  paths
@@ -600,21 +712,17 @@ var OpenAPIGenerator = class {
600
712
  toJsonSchema(schema, direction = "output") {
601
713
  try {
602
714
  const jsonSchema = schema["~standard"].jsonSchema;
603
- if (direction === "input" && jsonSchema.input) return jsonSchema.input({ target: "openapi-3.0" });
604
- return jsonSchema.output({ target: "openapi-3.0" });
715
+ return direction === "input" ? jsonSchema.input({ target: "openapi-3.0" }) : jsonSchema.output({ target: "openapi-3.0" });
605
716
  } catch (e) {
606
- 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`);
717
+ 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 });
607
718
  throw e;
608
719
  }
609
720
  }
610
721
  };
611
722
  const openApiGenerator = new OpenAPIGenerator();
612
- function _registerControllerClass(controllerClass, prefix) {
723
+ function _registerController(controllerClass, prefix) {
613
724
  openApiGenerator.registerController(controllerClass, prefix);
614
725
  }
615
- function setOpenApiConfig(config) {
616
- openApiGenerator.setConfig(config);
617
- }
618
726
  function generateOpenApiSpec() {
619
727
  return openApiGenerator.generateSpec();
620
728
  }
@@ -751,60 +859,6 @@ function _resolve(ctor) {
751
859
  return _InjectableRegistry.get(ctor);
752
860
  }
753
861
  //#endregion
754
- //#region src/annotation/validator.ts
755
- const _validatorSchemaStore = /* @__PURE__ */ new WeakMap();
756
- function ResponseBody(schema) {
757
- return (target, propertyKey) => {
758
- const ctor = target.constructor;
759
- const fnName = String(propertyKey);
760
- _setOnce(_getOrCreateSchemaDefinition(ctor, fnName), "responseBody", schema, fnName);
761
- };
762
- }
763
- function RequestBody(schema) {
764
- return (target, propertyKey) => {
765
- const ctor = target.constructor;
766
- const fnName = String(propertyKey);
767
- _setOnce(_getOrCreateSchemaDefinition(ctor, fnName), "requestBody", schema, fnName);
768
- };
769
- }
770
- function RequestParam(schema) {
771
- return (target, propertyKey) => {
772
- const ctor = target.constructor;
773
- const fnName = String(propertyKey);
774
- _setOnce(_getOrCreateSchemaDefinition(ctor, fnName), "requestParam", schema, fnName);
775
- };
776
- }
777
- function RequestQuery(schema) {
778
- return (target, propertyKey) => {
779
- const ctor = target.constructor;
780
- const fnName = String(propertyKey);
781
- _setOnce(_getOrCreateSchemaDefinition(ctor, fnName), "requestQuery", schema, fnName);
782
- };
783
- }
784
- function _getOrCreateSchemaDefinition(ctor, fnName) {
785
- const byFn = _getOrCreateMap(_validatorSchemaStore, ctor);
786
- const existing = byFn.get(fnName);
787
- if (existing) return existing;
788
- const created = {};
789
- byFn.set(fnName, created);
790
- return created;
791
- }
792
- async function _parseOrThrow(schema, input, kind) {
793
- const result = await schema["~standard"].validate(input);
794
- if (result.issues) {
795
- console.debug(`Failed to parse a schema`);
796
- throw new ParserError(kind, result.issues, schema["~standard"].vendor);
797
- }
798
- return result.value;
799
- }
800
- function _getValidatorSchema(ctor, fnName) {
801
- return _validatorSchemaStore.get(ctor)?.get(fnName);
802
- }
803
- function _setOnce(def, key, schema, fnName) {
804
- if (def[key]) throw new Error(`Duplicate schema for "${String(key)}" on method "${fnName}"`);
805
- def[key] = schema;
806
- }
807
- //#endregion
808
862
  //#region src/annotation/controller.ts
809
863
  const _ControllerRegistry = /* @__PURE__ */ new WeakMap();
810
864
  /**
@@ -816,7 +870,7 @@ const _ControllerRegistry = /* @__PURE__ */ new WeakMap();
816
870
  function Controller({ prefix = "", deps = [] } = {}) {
817
871
  return (target) => {
818
872
  const targetClass = target;
819
- _registerControllerClass(target, prefix);
873
+ _registerController(target, prefix);
820
874
  const router = Router();
821
875
  const routes = _getRoutes(target);
822
876
  const usedRoutes = /* @__PURE__ */ new Set();
@@ -841,15 +895,20 @@ Split these into separate @MiddlewareClass classes, or merge the logic into a si
841
895
  if (method === "USE" && fn.length >= 4) {
842
896
  const middlewareFn = async (err, request, response, next) => {
843
897
  try {
844
- const result = fn.bind(controllerInstance)(err, request, response, next);
845
- if (result instanceof ResponseEntity) {
846
- response.contentType("application/json").status(result.getStatusCode()).set(result.getHeaders()).send(Sapling.serialize(result.getBody()));
847
- return;
848
- }
849
- if (result instanceof RedirectView) {
850
- response.redirect(result.getUrl());
851
- return;
852
- }
898
+ await validate({
899
+ target,
900
+ fnName,
901
+ request
902
+ });
903
+ await handleResult({
904
+ result: fn.bind(controllerInstance)(err, request, response, next),
905
+ response,
906
+ target,
907
+ fnName,
908
+ method,
909
+ path: path instanceof RegExp ? path.source : fp,
910
+ isErrorMiddleware: true
911
+ });
853
912
  } catch (e) {
854
913
  console.error(e);
855
914
  next(e);
@@ -859,35 +918,52 @@ Split these into separate @MiddlewareClass classes, or merge the logic into a si
859
918
  return;
860
919
  }
861
920
  router[methodName](fp, async (request, response, next) => {
862
- const schemas = _getValidatorSchema(target, fnName);
863
- if (schemas) {
864
- if (schemas.requestBody) request.body = await _parseOrThrow(schemas.requestBody, request.body, "reqbody");
865
- if (schemas.requestParam) request.params = await _parseOrThrow(schemas.requestParam, request.params, "reqparams");
866
- if (schemas.requestQuery) {
867
- const parsedQuery = await _parseOrThrow(schemas.requestQuery, request.query, "reqquery");
868
- Object.defineProperty(request, "query", {
869
- value: parsedQuery,
870
- writable: true,
871
- configurable: true
872
- });
873
- }
874
- }
875
- const result = await fn.bind(controllerInstance)(request, response, next);
876
- if (result instanceof ResponseEntity) {
877
- const body = schemas && schemas.responseBody ? await _parseOrThrow(schemas.responseBody, result.getBody(), "resbody") : result.getBody();
878
- response.contentType("application/json").status(result.getStatusCode()).set(result.getHeaders()).send(Sapling.serialize(body));
879
- return;
880
- }
881
- if (result instanceof RedirectView) {
882
- response.redirect(result.getUrl());
883
- return;
884
- }
885
- if (method !== "USE" && !response.writableEnded) response.status(404).send(Html404ErrorPage(`Cannot ${methodName.toUpperCase()} ${path instanceof RegExp ? path.source : fp}`));
921
+ await validate({
922
+ target,
923
+ fnName,
924
+ request
925
+ });
926
+ await handleResult({
927
+ result: await fn.bind(controllerInstance)(request, response, next),
928
+ response,
929
+ target,
930
+ fnName,
931
+ method,
932
+ path: path instanceof RegExp ? path.source : fp
933
+ });
886
934
  });
887
935
  }
888
936
  _ControllerRegistry.set(targetClass, router);
889
937
  };
890
938
  }
939
+ async function handleResult({ result, target, fnName, response, method, path, isErrorMiddleware = false }) {
940
+ const schemas = _getValidatorSchema(target, fnName);
941
+ if (result instanceof ResponseEntity) {
942
+ const body = schemas && schemas.responseBody ? await _parseOrThrow(schemas.responseBody, result.getBody(), "resbody", fnName) : result.getBody();
943
+ response.contentType("application/json").status(result.getStatusCode()).set(result.getHeaders()).send(Sapling.serialize(body));
944
+ return;
945
+ }
946
+ if (result instanceof RedirectView) {
947
+ response.redirect(result.getUrl());
948
+ return;
949
+ }
950
+ if (!isErrorMiddleware && method !== "USE" && !response.writableEnded) response.status(404).send(Html404ErrorPage(`Cannot ${method} ${path}`));
951
+ }
952
+ async function validate({ target, fnName, request }) {
953
+ const schemas = _getValidatorSchema(target, fnName);
954
+ if (schemas) {
955
+ if (schemas.requestBody) request.body = await _parseOrThrow(schemas.requestBody, request.body, "reqbody", fnName);
956
+ if (schemas.requestParam) request.params = await _parseOrThrow(schemas.requestParam, request.params, "reqparams", fnName);
957
+ if (schemas.requestQuery) {
958
+ const parsedQuery = await _parseOrThrow(schemas.requestQuery, request.query, "reqquery", fnName);
959
+ Object.defineProperty(request, "query", {
960
+ value: parsedQuery,
961
+ writable: true,
962
+ configurable: true
963
+ });
964
+ }
965
+ }
966
+ }
891
967
  //#endregion
892
968
  //#region src/annotation/middleware.ts
893
969
  /**
@@ -922,7 +998,10 @@ DefaultBaseErrorMiddleware = __decorate([MiddlewareClass()], DefaultBaseErrorMid
922
998
  //#region src/middleware/default/error/parse.ts
923
999
  let DefaultParserErrorMiddleware = class DefaultParserErrorMiddleware {
924
1000
  handle(err, _request, _response, next) {
925
- if (err instanceof ParserError) return ResponseEntity.status(err.status).body({ message: err.message });
1001
+ if (err instanceof ParserError) {
1002
+ console.warn(err);
1003
+ return ResponseEntity.status(err.status).body({ message: err.message });
1004
+ }
926
1005
  next(err);
927
1006
  }
928
1007
  };
@@ -949,17 +1028,48 @@ __decorate([GET(_settings.doc.openApiPath)], DefaultOpenApiMiddleware.prototype,
949
1028
  DefaultOpenApiMiddleware = __decorate([MiddlewareClass()], DefaultOpenApiMiddleware);
950
1029
  //#endregion
951
1030
  //#region src/middleware/default/swagger/index.ts
1031
+ /**
1032
+ * Enable the serving of the Swagger endpoint used to serve the OpenAPI spec generated by Sapling.
1033
+ *
1034
+ * Configure any middleware-specific settings with `Sapling.Extras.swaggerAndOpenApi`
1035
+ *
1036
+ * You must register `DefaultSwaggerMiddleware.Serve` & `DefaultSwaggerMiddleware.Setup` after `DefaultOpenApiMiddleware`
1037
+ *
1038
+ * ```ts
1039
+ * const middlewares = [
1040
+ * DefaultOpenApiMiddleware,
1041
+ * DefaultSwaggerMiddleware.Serve,
1042
+ * DefaultSwaggerMiddleware.Setup,
1043
+ * ];
1044
+ * middlewares.map(Sapling.resolve).forEach((r) => app.use(r));
1045
+ * ```
1046
+ */
952
1047
  let Serve = class Serve {
953
- constructor() {
954
- this.handlers = swagger.serve;
955
- }
1048
+ handlers = swagger.serve;
956
1049
  handle(request, response, next) {
957
1050
  return Sapling.chainHandlers(this.handlers, request, response, next);
958
1051
  }
959
1052
  };
960
1053
  __decorate([Middleware(_settings.doc.swaggerPath)], Serve.prototype, "handle", null);
961
1054
  Serve = __decorate([MiddlewareClass()], Serve);
1055
+ /**
1056
+ * Enable the serving of the Swagger endpoint used to serve the OpenAPI spec generated by Sapling.
1057
+ *
1058
+ * Configure any middleware-specific settings with `Sapling.Extras.swaggerAndOpenApi`
1059
+ *
1060
+ * You must register `DefaultSwaggerMiddleware.Serve` & `DefaultSwaggerMiddleware.Setup` after `DefaultOpenApiMiddleware`
1061
+ *
1062
+ * ```ts
1063
+ * const middlewares = [
1064
+ * DefaultOpenApiMiddleware,
1065
+ * DefaultSwaggerMiddleware.Serve,
1066
+ * DefaultSwaggerMiddleware.Setup,
1067
+ * ];
1068
+ * middlewares.map(Sapling.resolve).forEach((r) => app.use(r));
1069
+ * ```
1070
+ */
962
1071
  let Setup = class Setup {
1072
+ handler;
963
1073
  constructor() {
964
1074
  this.handler = swagger.setup(null, { swaggerOptions: { url: _settings.doc.openApiPath } });
965
1075
  }
@@ -969,9 +1079,25 @@ let Setup = class Setup {
969
1079
  };
970
1080
  __decorate([Middleware(_settings.doc.swaggerPath)], Setup.prototype, "handle", null);
971
1081
  Setup = __decorate([MiddlewareClass()], Setup);
1082
+ /**
1083
+ * Enable the serving of the Swagger endpoint used to serve the OpenAPI spec generated by Sapling.
1084
+ *
1085
+ * Configure any middleware-specific settings with `Sapling.Extras.swaggerAndOpenApi`
1086
+ *
1087
+ * You must register `DefaultSwaggerMiddleware.Serve` & `DefaultSwaggerMiddleware.Setup` after `DefaultOpenApiMiddleware`
1088
+ *
1089
+ * ```ts
1090
+ * const middlewares = [
1091
+ * DefaultOpenApiMiddleware,
1092
+ * DefaultSwaggerMiddleware.Serve,
1093
+ * DefaultSwaggerMiddleware.Setup,
1094
+ * ];
1095
+ * middlewares.map(Sapling.resolve).forEach((r) => app.use(r));
1096
+ * ```
1097
+ */
972
1098
  const DefaultSwaggerMiddleware = {
973
1099
  Serve,
974
1100
  Setup
975
1101
  };
976
1102
  //#endregion
977
- 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 };
1103
+ 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, _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.ac279593",
3
+ "version": "2.0.5-beta.e0403942",
4
4
  "author": "Tahmid Ahmed",
5
5
  "description": "A library to help you write cleaner Express.js code",
6
6
  "repository": {