@tahminator/sapling 2.0.4 → 2.0.5-beta.23c37926

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -200,12 +200,71 @@ class UserController {
200
200
  }
201
201
  ```
202
202
 
203
- Make sure to register an error handler middleware:
203
+ Sapling ships with default error middlewares, and you can also write your own.
204
+ Register error middlewares after your regular middlewares and controllers:
204
205
 
205
206
  ```typescript
206
- Sapling.loadResponseStatusErrorMiddleware(app, (err, req, res, next) => {
207
- res.status(err.status).json({ error: err.message });
208
- });
207
+ import {
208
+ DefaultBaseErrorMiddleware,
209
+ DefaultResponseStatusErrorMiddleware,
210
+ } from "@tahminator/sapling";
211
+
212
+ // regular middlewares & controllers first
213
+ const middlewares: Class<any>[] = [CookieParserMiddleware];
214
+ middlewares.map(Sapling.resolve).forEach((r) => app.use(r));
215
+
216
+ const controllers: Class<any>[] = [UserController];
217
+ controllers.map(Sapling.resolve).forEach((r) => app.use(r));
218
+
219
+ // error middlewares last
220
+ const errorMiddlewares: Class<any>[] = [
221
+ DefaultResponseStatusErrorMiddleware,
222
+ DefaultBaseErrorMiddleware,
223
+ ];
224
+ errorMiddlewares.map(Sapling.resolve).forEach((r) => app.use(r));
225
+ ```
226
+
227
+ You can also write your own error middlewares. A specific handler should call
228
+ `next(err)` when it does not handle the error, and a base handler should be last
229
+ and return a response:
230
+
231
+ ```typescript
232
+ @MiddlewareClass()
233
+ class ResponseStatusErrorMiddleware {
234
+ @Middleware()
235
+ handle(
236
+ err: unknown,
237
+ _request: Request,
238
+ _response: Response,
239
+ next: NextFunction,
240
+ ) {
241
+ if (err instanceof ResponseStatusError) {
242
+ return ResponseEntity.status(err.status).body({ message: err.message });
243
+ }
244
+
245
+ // MUST call next(err) to continue the chain
246
+ next(err);
247
+ }
248
+ }
249
+
250
+ @MiddlewareClass()
251
+ class BaseErrorMiddleware {
252
+ @Middleware()
253
+ handle(
254
+ err: unknown,
255
+ _request: Request,
256
+ _response: Response,
257
+ _next: NextFunction,
258
+ ) {
259
+ console.error("[Error]", err);
260
+
261
+ return ResponseEntity.status(500).body({
262
+ message: "Internal Server Error",
263
+ });
264
+
265
+ // no next(err) since last middleware in chain, we are done propagating
266
+ }
267
+ }
209
268
  ```
210
269
 
211
270
  ### Middleware
@@ -234,10 +293,41 @@ class CookieParserMiddleware {
234
293
  // Register it like any controller
235
294
  app.use(Sapling.resolve(CookieParserMiddleware));
236
295
 
296
+ // Register middlewares before controllers
297
+ app.use(Sapling.resolve(UserController));
298
+
237
299
  // You can also still choose to load plugins the Express.js way
238
300
  app.use(cookieParser());
239
301
  ```
240
302
 
303
+ You can also write custom middlewares as well. It is functionally the same way as Express: call `next()` explicitly to
304
+ continue down the chain:
305
+
306
+ ```typescript
307
+ import { MiddlewareClass, Middleware } from "@tahminator/sapling";
308
+ import { NextFunction, Request, Response } from "express";
309
+
310
+ @MiddlewareClass()
311
+ class RequestTimerMiddleware {
312
+ @Middleware()
313
+ handle(request: Request, _response: Response, next: NextFunction) {
314
+ const start = Date.now();
315
+
316
+ request.on("finish", () => {
317
+ const elapsedMs = Date.now() - start;
318
+ console.log(`[Request] ${request.method} ${request.path} ${elapsedMs}ms`);
319
+ });
320
+
321
+ // MUST call next() to continue the chain
322
+ next();
323
+ }
324
+ }
325
+
326
+ // Register middlewares before controllers
327
+ app.use(Sapling.resolve(RequestTimerMiddleware));
328
+ app.use(Sapling.resolve(UserController));
329
+ ```
330
+
241
331
  ### Request Validation
242
332
 
243
333
  Validate and transform request bodies, route params, and query strings at the controller level using `@RequestBody`, `@RequestParam`, and `@RequestQuery`. These decorators accept any [Standard Schema](https://github.com/standard-schema/standard-schema) compatible validator (Zod, Valibot, ArkType, etc.).
package/dist/index.cjs CHANGED
@@ -23,6 +23,8 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
23
23
  //#endregion
24
24
  let express = require("express");
25
25
  express = __toESM(express);
26
+ let swagger_ui_express = require("swagger-ui-express");
27
+ swagger_ui_express = __toESM(swagger_ui_express);
26
28
  //#region src/html/404.ts
27
29
  /**
28
30
  * Default Express.js 404 error page, as a string.
@@ -262,9 +264,13 @@ var ParserError = class ParserError extends ResponseStatusError {
262
264
  };
263
265
  //#endregion
264
266
  //#region src/helper/sapling.ts
265
- const settings = {
267
+ const _settings = {
266
268
  serialize: JSON.stringify,
267
- deserialize: JSON.parse
269
+ deserialize: JSON.parse,
270
+ doc: {
271
+ openApiPath: "/openapi.json",
272
+ swaggerPath: "/swagger.html"
273
+ }
268
274
  };
269
275
  /**
270
276
  * Collection of utility functions which are essential for Sapling to function.
@@ -343,13 +349,13 @@ var Sapling = class Sapling {
343
349
  * @defaultValue `JSON.stringify`
344
350
  */
345
351
  static serialize(value) {
346
- return settings.serialize(value);
352
+ return _settings.serialize(value);
347
353
  }
348
354
  /**
349
355
  * Replace the function used for `serialize`.
350
356
  */
351
357
  static setSerializeFn(fn) {
352
- settings.serialize = fn;
358
+ _settings.serialize = fn;
353
359
  }
354
360
  /**
355
361
  * De-serialize a JSON string back to a JavaScript object.
@@ -361,148 +367,22 @@ var Sapling = class Sapling {
361
367
  * @defaultValue `JSON.parse`
362
368
  */
363
369
  static deserialize(value) {
364
- return settings.deserialize(value);
370
+ return _settings.deserialize(value);
365
371
  }
366
372
  /**
367
373
  * Replace the function used for `deserialize`
368
374
  */
369
375
  static setDeserializeFn(fn) {
370
- settings.deserialize = fn;
376
+ _settings.deserialize = fn;
371
377
  }
372
- };
373
- //#endregion
374
- //#region src/types.ts
375
- const methodResolve = {
376
- GET: "get",
377
- PUT: "put",
378
- POST: "post",
379
- DELETE: "delete",
380
- OPTIONS: "options",
381
- PATCH: "patch",
382
- HEAD: "head",
383
- USE: "use"
384
- };
385
- //#endregion
386
- //#region lib/weakmap.ts
387
- /**
388
- * WeakMap that is iterable.
389
- */
390
- var IterableWeakMap = class IterableWeakMap {
391
- #weakMap = /* @__PURE__ */ new WeakMap();
392
- #refSet = /* @__PURE__ */ new Set();
393
- #finalizationGroup = new FinalizationRegistry(IterableWeakMap.#cleanup);
394
- static #cleanup(heldValue) {
395
- heldValue.set.delete(heldValue.ref);
378
+ static setOpenApiPath(path) {
379
+ _settings.doc.openApiPath = path;
396
380
  }
397
- constructor(iterable) {
398
- if (iterable) for (const [key, value] of iterable) this.set(key, value);
399
- }
400
- set(key, value) {
401
- const ref = new WeakRef(key);
402
- this.#weakMap.set(key, {
403
- value,
404
- ref
405
- });
406
- this.#refSet.add(ref);
407
- this.#finalizationGroup.register(key, {
408
- set: this.#refSet,
409
- ref
410
- }, ref);
411
- return this;
412
- }
413
- get(key) {
414
- return this.#weakMap.get(key)?.value;
415
- }
416
- delete(key) {
417
- const entry = this.#weakMap.get(key);
418
- if (!entry) return false;
419
- this.#weakMap.delete(key);
420
- this.#refSet.delete(entry.ref);
421
- this.#finalizationGroup.unregister(entry.ref);
422
- return true;
423
- }
424
- *[Symbol.iterator]() {
425
- for (const ref of this.#refSet) {
426
- const key = ref.deref();
427
- if (!key) continue;
428
- const entry = this.#weakMap.get(key);
429
- if (entry) yield [key, entry.value];
430
- }
431
- }
432
- entries() {
433
- return this[Symbol.iterator]();
434
- }
435
- *keys() {
436
- for (const [key] of this) yield key;
437
- }
438
- *values() {
439
- for (const [, value] of this) yield value;
440
- }
441
- forEach(callback, thisArg) {
442
- for (const [key, value] of this) callback.call(thisArg, value, key, this);
381
+ static setSwaggerPath(path) {
382
+ _settings.doc.swaggerPath = path;
443
383
  }
444
384
  };
445
385
  //#endregion
446
- //#region src/annotation/injectable.ts
447
- const _InjectableRegistry = /* @__PURE__ */ new WeakMap();
448
- const _InjectableDeps = new IterableWeakMap();
449
- /**
450
- * Mark the class as an injectable to be handled by Sapling. The class can now be
451
- * be injected into other classes, as well as allow the class to inject other `@Injectable` classes.
452
- *
453
- * @argument deps - An optional array to define any dependencies that this class may require.
454
- */
455
- function Injectable(deps = []) {
456
- return function(target) {
457
- _InjectableRegistry.set(target, null);
458
- _InjectableDeps.set(target, deps);
459
- };
460
- }
461
- /**
462
- * Resolves and instantiates a class along with all of it's transitive dependencies.
463
- *
464
- * Uses topological sort (Kahn's algorithm) to ensure that the dependency graph is created
465
- * in a correct order.
466
- *
467
- * When `resolve` is first called (usually during controller registration),
468
- * it will compute the dependency graph of all `@Injectable` classes and instantiates
469
- * them in the correct order.
470
- *
471
- * Subsequent calls to dependencies that have already been resolved are cached, so they will
472
- * re-use the created singletons instead of re-instantiation.
473
- */
474
- function _resolve(ctor) {
475
- const inDegree = /* @__PURE__ */ new Map();
476
- const graph = /* @__PURE__ */ new Map();
477
- _InjectableDeps.forEach((deps, node) => {
478
- inDegree.set(node, inDegree.get(node) || 0);
479
- deps.forEach((dep) => {
480
- if (dep === void 0) throw new Error(`There is an @Injectable (${node.name}) which has a dependency that cannot be found. This is likely caused by a circular dependency.`);
481
- inDegree.set(dep, inDegree.get(dep) || 0);
482
- inDegree.set(node, inDegree.get(node) + 1);
483
- if (!graph.has(dep)) graph.set(dep, []);
484
- graph.get(dep).push(node);
485
- });
486
- });
487
- const queue = [];
488
- inDegree.forEach((deg, node) => {
489
- if (deg === 0) queue.push(node);
490
- });
491
- while (queue.length) {
492
- const current = queue.shift();
493
- if (!_InjectableRegistry.get(current)) {
494
- const instance = new current(...(_InjectableDeps.get(current) || []).map((dep) => _InjectableRegistry.get(dep)));
495
- _InjectableRegistry.set(current, instance);
496
- }
497
- (graph.get(current) || []).forEach((neighbor) => {
498
- inDegree.set(neighbor, (inDegree.get(neighbor) ?? 0) - 1);
499
- if (inDegree.get(neighbor) === 0) queue.push(neighbor);
500
- });
501
- }
502
- if (!_InjectableRegistry.get(ctor)) throw new Error("Circular dependency detected or injectable not registered");
503
- return _InjectableRegistry.get(ctor);
504
- }
505
- //#endregion
506
386
  //#region src/annotation/request.ts
507
387
  const _requestSchemaStore = /* @__PURE__ */ new WeakMap();
508
388
  /**
@@ -711,6 +591,229 @@ function _getRoutes(ctor) {
711
591
  return _routeStore.get(ctor) ?? [];
712
592
  }
713
593
  //#endregion
594
+ //#region src/helper/openapi.ts
595
+ var OpenAPIGenerator = class {
596
+ constructor() {
597
+ this.controllers = /* @__PURE__ */ new Set();
598
+ this.config = {
599
+ title: "API",
600
+ version: "1.0.0"
601
+ };
602
+ }
603
+ setConfig(config) {
604
+ this.config = config;
605
+ }
606
+ registerController(controllerClass, prefix) {
607
+ this.controllers.add({
608
+ class: controllerClass,
609
+ prefix
610
+ });
611
+ }
612
+ generateSpec() {
613
+ const config = this.config;
614
+ const paths = {};
615
+ for (const { class: controllerClass, prefix } of this.controllers) {
616
+ const routes = _getRoutes(controllerClass);
617
+ for (const route of routes) {
618
+ if (route.method === "USE") continue;
619
+ const schemas = _getRequestSchemas(controllerClass, route.fnName);
620
+ const fullPath = route.path instanceof RegExp ? route.path.source : prefix + route.path;
621
+ const openApiPath = typeof fullPath === "string" ? fullPath.replace(/:(\w+)/g, "{$1}") : fullPath;
622
+ if (!paths[openApiPath]) paths[openApiPath] = {};
623
+ const operation = { responses: { "200": { description: "Successful response" } } };
624
+ const parameters = [];
625
+ if (schemas?.param) {
626
+ const paramSchema = this.toJsonSchema(schemas.param);
627
+ if (paramSchema.type === "object" && paramSchema.properties) for (const [name, schema] of Object.entries(paramSchema.properties)) parameters.push({
628
+ name,
629
+ in: "path",
630
+ required: true,
631
+ schema
632
+ });
633
+ }
634
+ if (schemas?.query) {
635
+ const querySchema = this.toJsonSchema(schemas.query);
636
+ if (querySchema.type === "object" && querySchema.properties) for (const [name, schema] of Object.entries(querySchema.properties)) {
637
+ const isRequired = Array.isArray(querySchema.required) && querySchema.required.includes(name);
638
+ parameters.push({
639
+ name,
640
+ in: "query",
641
+ required: isRequired,
642
+ schema
643
+ });
644
+ }
645
+ }
646
+ if (parameters.length > 0) operation.parameters = parameters;
647
+ if (schemas?.body) operation.requestBody = {
648
+ required: true,
649
+ content: { "application/json": { schema: this.toJsonSchema(schemas.body) } }
650
+ };
651
+ const method = route.method.toLowerCase();
652
+ paths[openApiPath][method] = operation;
653
+ }
654
+ }
655
+ return {
656
+ openapi: "3.0.0",
657
+ info: {
658
+ title: config.title,
659
+ version: config.version,
660
+ description: config.description
661
+ },
662
+ paths
663
+ };
664
+ }
665
+ toJsonSchema(schema) {
666
+ try {
667
+ return schema["~standard"].jsonSchema.output({ target: "openapi-3.0" });
668
+ } catch (e) {
669
+ 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`);
670
+ throw e;
671
+ }
672
+ }
673
+ };
674
+ const openApiGenerator = new OpenAPIGenerator();
675
+ function _registerControllerClass(controllerClass, prefix) {
676
+ openApiGenerator.registerController(controllerClass, prefix);
677
+ }
678
+ function _setOpenApiConfig(config) {
679
+ openApiGenerator.setConfig(config);
680
+ }
681
+ function _generateOpenApiSpec() {
682
+ return openApiGenerator.generateSpec();
683
+ }
684
+ //#endregion
685
+ //#region src/types.ts
686
+ const methodResolve = {
687
+ GET: "get",
688
+ PUT: "put",
689
+ POST: "post",
690
+ DELETE: "delete",
691
+ OPTIONS: "options",
692
+ PATCH: "patch",
693
+ HEAD: "head",
694
+ USE: "use"
695
+ };
696
+ //#endregion
697
+ //#region lib/weakmap.ts
698
+ /**
699
+ * WeakMap that is iterable.
700
+ */
701
+ var IterableWeakMap = class IterableWeakMap {
702
+ #weakMap = /* @__PURE__ */ new WeakMap();
703
+ #refSet = /* @__PURE__ */ new Set();
704
+ #finalizationGroup = new FinalizationRegistry(IterableWeakMap.#cleanup);
705
+ static #cleanup(heldValue) {
706
+ heldValue.set.delete(heldValue.ref);
707
+ }
708
+ constructor(iterable) {
709
+ if (iterable) for (const [key, value] of iterable) this.set(key, value);
710
+ }
711
+ set(key, value) {
712
+ const ref = new WeakRef(key);
713
+ this.#weakMap.set(key, {
714
+ value,
715
+ ref
716
+ });
717
+ this.#refSet.add(ref);
718
+ this.#finalizationGroup.register(key, {
719
+ set: this.#refSet,
720
+ ref
721
+ }, ref);
722
+ return this;
723
+ }
724
+ get(key) {
725
+ return this.#weakMap.get(key)?.value;
726
+ }
727
+ delete(key) {
728
+ const entry = this.#weakMap.get(key);
729
+ if (!entry) return false;
730
+ this.#weakMap.delete(key);
731
+ this.#refSet.delete(entry.ref);
732
+ this.#finalizationGroup.unregister(entry.ref);
733
+ return true;
734
+ }
735
+ *[Symbol.iterator]() {
736
+ for (const ref of this.#refSet) {
737
+ const key = ref.deref();
738
+ if (!key) continue;
739
+ const entry = this.#weakMap.get(key);
740
+ if (entry) yield [key, entry.value];
741
+ }
742
+ }
743
+ entries() {
744
+ return this[Symbol.iterator]();
745
+ }
746
+ *keys() {
747
+ for (const [key] of this) yield key;
748
+ }
749
+ *values() {
750
+ for (const [, value] of this) yield value;
751
+ }
752
+ forEach(callback, thisArg) {
753
+ for (const [key, value] of this) callback.call(thisArg, value, key, this);
754
+ }
755
+ };
756
+ //#endregion
757
+ //#region src/annotation/injectable.ts
758
+ const _InjectableRegistry = /* @__PURE__ */ new WeakMap();
759
+ const _InjectableDeps = new IterableWeakMap();
760
+ /**
761
+ * Mark the class as an injectable to be handled by Sapling. The class can now be
762
+ * be injected into other classes, as well as allow the class to inject other `@Injectable` classes.
763
+ *
764
+ * @argument deps - An optional array to define any dependencies that this class may require.
765
+ */
766
+ function Injectable(deps = []) {
767
+ return function(target) {
768
+ _InjectableRegistry.set(target, null);
769
+ _InjectableDeps.set(target, deps);
770
+ };
771
+ }
772
+ /**
773
+ * Resolves and instantiates a class along with all of it's transitive dependencies.
774
+ *
775
+ * Uses topological sort (Kahn's algorithm) to ensure that the dependency graph is created
776
+ * in a correct order.
777
+ *
778
+ * When `resolve` is first called (usually during controller registration),
779
+ * it will compute the dependency graph of all `@Injectable` classes and instantiates
780
+ * them in the correct order.
781
+ *
782
+ * Subsequent calls to dependencies that have already been resolved are cached, so they will
783
+ * re-use the created singletons instead of re-instantiation.
784
+ */
785
+ function _resolve(ctor) {
786
+ const inDegree = /* @__PURE__ */ new Map();
787
+ const graph = /* @__PURE__ */ new Map();
788
+ _InjectableDeps.forEach((deps, node) => {
789
+ inDegree.set(node, inDegree.get(node) || 0);
790
+ deps.forEach((dep) => {
791
+ if (dep === void 0) throw new Error(`There is an @Injectable (${node.name}) which has a dependency that cannot be found. This is likely caused by a circular dependency.`);
792
+ inDegree.set(dep, inDegree.get(dep) || 0);
793
+ inDegree.set(node, inDegree.get(node) + 1);
794
+ if (!graph.has(dep)) graph.set(dep, []);
795
+ graph.get(dep).push(node);
796
+ });
797
+ });
798
+ const queue = [];
799
+ inDegree.forEach((deg, node) => {
800
+ if (deg === 0) queue.push(node);
801
+ });
802
+ while (queue.length) {
803
+ const current = queue.shift();
804
+ if (!_InjectableRegistry.get(current)) {
805
+ const instance = new current(...(_InjectableDeps.get(current) || []).map((dep) => _InjectableRegistry.get(dep)));
806
+ _InjectableRegistry.set(current, instance);
807
+ }
808
+ (graph.get(current) || []).forEach((neighbor) => {
809
+ inDegree.set(neighbor, (inDegree.get(neighbor) ?? 0) - 1);
810
+ if (inDegree.get(neighbor) === 0) queue.push(neighbor);
811
+ });
812
+ }
813
+ if (!_InjectableRegistry.get(ctor)) throw new Error("Circular dependency detected or injectable not registered");
814
+ return _InjectableRegistry.get(ctor);
815
+ }
816
+ //#endregion
714
817
  //#region src/annotation/controller.ts
715
818
  const _ControllerRegistry = /* @__PURE__ */ new WeakMap();
716
819
  /**
@@ -722,6 +825,7 @@ const _ControllerRegistry = /* @__PURE__ */ new WeakMap();
722
825
  function Controller({ prefix = "", deps = [] } = {}) {
723
826
  return (target) => {
724
827
  const targetClass = target;
828
+ _registerControllerClass(target, prefix);
725
829
  const router = (0, express.Router)();
726
830
  const routes = _getRoutes(target);
727
831
  const usedRoutes = /* @__PURE__ */ new Set();
@@ -813,7 +917,7 @@ function __decorate(decorators, target, key, desc) {
813
917
  return c > 3 && r && Object.defineProperty(target, key, r), r;
814
918
  }
815
919
  //#endregion
816
- //#region src/middleware/default/base.ts
920
+ //#region src/middleware/default/error/base.ts
817
921
  let DefaultBaseErrorMiddleware = class DefaultBaseErrorMiddleware {
818
922
  handle(err, _request, _response, _next) {
819
923
  console.error("[Error]", err);
@@ -823,7 +927,17 @@ let DefaultBaseErrorMiddleware = class DefaultBaseErrorMiddleware {
823
927
  __decorate([Middleware()], DefaultBaseErrorMiddleware.prototype, "handle", null);
824
928
  DefaultBaseErrorMiddleware = __decorate([MiddlewareClass()], DefaultBaseErrorMiddleware);
825
929
  //#endregion
826
- //#region src/middleware/default/responsestatus.ts
930
+ //#region src/middleware/default/error/parse.ts
931
+ let DefaultParserErrorMiddleware = class DefaultParserErrorMiddleware {
932
+ handle(err, _request, _response, next) {
933
+ if (err instanceof ParserError) return ResponseEntity.status(err.status).body({ message: err.message });
934
+ next(err);
935
+ }
936
+ };
937
+ __decorate([Middleware()], DefaultParserErrorMiddleware.prototype, "handle", null);
938
+ DefaultParserErrorMiddleware = __decorate([MiddlewareClass()], DefaultParserErrorMiddleware);
939
+ //#endregion
940
+ //#region src/middleware/default/error/responsestatus.ts
827
941
  let DefaultResponseStatusErrorMiddleware = class DefaultResponseStatusErrorMiddleware {
828
942
  handle(err, _request, _response, next) {
829
943
  if (err instanceof ResponseStatusError) return ResponseEntity.status(err.status).body({ message: err.message });
@@ -833,6 +947,41 @@ let DefaultResponseStatusErrorMiddleware = class DefaultResponseStatusErrorMiddl
833
947
  __decorate([Middleware()], DefaultResponseStatusErrorMiddleware.prototype, "handle", null);
834
948
  DefaultResponseStatusErrorMiddleware = __decorate([MiddlewareClass()], DefaultResponseStatusErrorMiddleware);
835
949
  //#endregion
950
+ //#region src/middleware/default/openapi/index.ts
951
+ let DefaultOpenApiMiddleware = class DefaultOpenApiMiddleware {
952
+ handle(_request, _response, _next) {
953
+ return ResponseEntity.ok().body(_generateOpenApiSpec());
954
+ }
955
+ };
956
+ __decorate([GET(_settings.doc.openApiPath)], DefaultOpenApiMiddleware.prototype, "handle", null);
957
+ DefaultOpenApiMiddleware = __decorate([MiddlewareClass()], DefaultOpenApiMiddleware);
958
+ //#endregion
959
+ //#region src/middleware/default/swagger/index.ts
960
+ let Serve = class Serve {
961
+ constructor() {
962
+ this.handlers = swagger_ui_express.default.serve;
963
+ }
964
+ handle(_request, _response, _next) {
965
+ return this.handlers;
966
+ }
967
+ };
968
+ __decorate([Middleware(_settings.doc.swaggerPath)], Serve.prototype, "handle", null);
969
+ Serve = __decorate([MiddlewareClass()], Serve);
970
+ let Setup = class Setup {
971
+ constructor() {
972
+ this.handler = swagger_ui_express.default.setup(void 0, { swaggerOptions: { url: _settings.doc.openApiPath } });
973
+ }
974
+ handle(request, response, next) {
975
+ return this.handler(request, response, next);
976
+ }
977
+ };
978
+ __decorate([Middleware(_settings.doc.swaggerPath)], Setup.prototype, "handle", null);
979
+ Setup = __decorate([MiddlewareClass()], Setup);
980
+ const DefaultSwaggerMiddleware = {
981
+ Serve,
982
+ Setup
983
+ };
984
+ //#endregion
836
985
  exports.Controller = Controller;
837
986
  exports.DELETE = DELETE;
838
987
  Object.defineProperty(exports, "DefaultBaseErrorMiddleware", {
@@ -841,12 +990,25 @@ Object.defineProperty(exports, "DefaultBaseErrorMiddleware", {
841
990
  return DefaultBaseErrorMiddleware;
842
991
  }
843
992
  });
993
+ Object.defineProperty(exports, "DefaultOpenApiMiddleware", {
994
+ enumerable: true,
995
+ get: function() {
996
+ return DefaultOpenApiMiddleware;
997
+ }
998
+ });
999
+ Object.defineProperty(exports, "DefaultParserErrorMiddleware", {
1000
+ enumerable: true,
1001
+ get: function() {
1002
+ return DefaultParserErrorMiddleware;
1003
+ }
1004
+ });
844
1005
  Object.defineProperty(exports, "DefaultResponseStatusErrorMiddleware", {
845
1006
  enumerable: true,
846
1007
  get: function() {
847
1008
  return DefaultResponseStatusErrorMiddleware;
848
1009
  }
849
1010
  });
1011
+ exports.DefaultSwaggerMiddleware = DefaultSwaggerMiddleware;
850
1012
  exports.GET = GET;
851
1013
  exports.HEAD = HEAD;
852
1014
  exports.Html404ErrorPage = Html404ErrorPage;
@@ -871,8 +1033,13 @@ exports._ControllerRegistry = _ControllerRegistry;
871
1033
  exports._InjectableDeps = _InjectableDeps;
872
1034
  exports._InjectableRegistry = _InjectableRegistry;
873
1035
  exports._Route = _Route;
1036
+ exports._generateOpenApiSpec = _generateOpenApiSpec;
874
1037
  exports._getRequestSchemas = _getRequestSchemas;
875
1038
  exports._getRoutes = _getRoutes;
876
1039
  exports._parseOrThrow = _parseOrThrow;
1040
+ exports._registerControllerClass = _registerControllerClass;
877
1041
  exports._resolve = _resolve;
1042
+ exports._setOpenApiConfig = _setOpenApiConfig;
1043
+ exports._settings = _settings;
878
1044
  exports.methodResolve = methodResolve;
1045
+ exports.openApiGenerator = openApiGenerator;