@tahminator/sapling 2.0.4 → 2.0.5-beta.18e683d9

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
@@ -1,4 +1,5 @@
1
1
  import e, { Router } from "express";
2
+ import swagger from "swagger-ui-express";
2
3
  //#region src/html/404.ts
3
4
  /**
4
5
  * Default Express.js 404 error page, as a string.
@@ -232,15 +233,20 @@ var ParserError = class ParserError extends ResponseStatusError {
232
233
  case "reqbody": return "request body";
233
234
  case "reqparams": return "request params";
234
235
  case "reqquery": return "request query";
236
+ case "resbody": return "response body";
235
237
  }
236
238
  })()}: ${formatted}`;
237
239
  }
238
240
  };
239
241
  //#endregion
240
242
  //#region src/helper/sapling.ts
241
- const settings = {
243
+ const _settings = {
242
244
  serialize: JSON.stringify,
243
- deserialize: JSON.parse
245
+ deserialize: JSON.parse,
246
+ doc: {
247
+ openApiPath: "/openapi.json",
248
+ swaggerPath: "/swagger.html"
249
+ }
244
250
  };
245
251
  /**
246
252
  * Collection of utility functions which are essential for Sapling to function.
@@ -319,13 +325,13 @@ var Sapling = class Sapling {
319
325
  * @defaultValue `JSON.stringify`
320
326
  */
321
327
  static serialize(value) {
322
- return settings.serialize(value);
328
+ return _settings.serialize(value);
323
329
  }
324
330
  /**
325
331
  * Replace the function used for `serialize`.
326
332
  */
327
333
  static setSerializeFn(fn) {
328
- settings.serialize = fn;
334
+ _settings.serialize = fn;
329
335
  }
330
336
  /**
331
337
  * De-serialize a JSON string back to a JavaScript object.
@@ -337,16 +343,287 @@ var Sapling = class Sapling {
337
343
  * @defaultValue `JSON.parse`
338
344
  */
339
345
  static deserialize(value) {
340
- return settings.deserialize(value);
346
+ return _settings.deserialize(value);
341
347
  }
342
348
  /**
343
349
  * Replace the function used for `deserialize`
344
350
  */
345
351
  static setDeserializeFn(fn) {
346
- settings.deserialize = fn;
352
+ _settings.deserialize = fn;
353
+ }
354
+ static setOpenApiPath(path) {
355
+ _settings.doc.openApiPath = path;
356
+ }
357
+ static setSwaggerPath(path) {
358
+ _settings.doc.swaggerPath = path;
359
+ }
360
+ static chainHandlers(handlers, request, response, next, index = 0) {
361
+ if (index >= handlers.length) {
362
+ next();
363
+ return;
364
+ }
365
+ handlers[index]?.(request, response, (err) => {
366
+ if (err) {
367
+ next(err);
368
+ return;
369
+ }
370
+ Sapling.chainHandlers(handlers, request, response, next, index + 1);
371
+ });
347
372
  }
348
373
  };
349
374
  //#endregion
375
+ //#region src/annotation/route.ts
376
+ const _routeStore = /* @__PURE__ */ new WeakMap();
377
+ /**
378
+ * Custom annotation that will store all routes inside of a map,
379
+ * which can then be used to initialize all the routes to the router.
380
+ */
381
+ function _Route({ method, path = "" }) {
382
+ return (target, propertyKey) => {
383
+ const ctor = target.constructor;
384
+ const list = _routeStore.get(ctor) ?? [];
385
+ list.push({
386
+ method,
387
+ path: path ?? "",
388
+ fnName: String(propertyKey)
389
+ });
390
+ _routeStore.set(ctor, list);
391
+ };
392
+ }
393
+ /**
394
+ * Register GET route on the given path (default "") for the given controller.
395
+ */
396
+ const GET = (path = "") => _Route({
397
+ method: "GET",
398
+ path
399
+ });
400
+ /**
401
+ * Register POST route on the given path (default "") for the given controller.
402
+ */
403
+ const POST = (path = "") => _Route({
404
+ method: "POST",
405
+ path
406
+ });
407
+ /**
408
+ * Register PUT route on the given path (default "") for the given controller.
409
+ */
410
+ const PUT = (path = "") => _Route({
411
+ method: "PUT",
412
+ path
413
+ });
414
+ /**
415
+ * Register DELETE route on the given path (default "") for the given controller.
416
+ */
417
+ const DELETE = (path = "") => _Route({
418
+ method: "DELETE",
419
+ path
420
+ });
421
+ /**
422
+ * Register OPTIONS route on the given path (default "") for the given controller.
423
+ */
424
+ const OPTIONS = (path = "") => _Route({
425
+ method: "OPTIONS",
426
+ path
427
+ });
428
+ /**
429
+ * Register PATCH route on the given path (default "") for the given controller.
430
+ */
431
+ const PATCH = (path = "") => _Route({
432
+ method: "PATCH",
433
+ path
434
+ });
435
+ /**
436
+ * Register HEAD route on the given path (default "") for the given controller.
437
+ */
438
+ const HEAD = (path = "") => _Route({
439
+ method: "HEAD",
440
+ path
441
+ });
442
+ /**
443
+ * Register a middleware route on the given path (default "") for the given controller.
444
+ */
445
+ const Middleware = (path = "") => _Route({
446
+ method: "USE",
447
+ path
448
+ });
449
+ /**
450
+ * Given a class constructor, fetch all the routes attached.
451
+ */
452
+ function _getRoutes(ctor) {
453
+ return _routeStore.get(ctor) ?? [];
454
+ }
455
+ //#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
+ //#region src/annotation/schema.ts
466
+ const _routeSchemaStore = /* @__PURE__ */ new WeakMap();
467
+ const _controllerSchemaStore = /* @__PURE__ */ new WeakMap();
468
+ function ControllerSchema(options) {
469
+ return (target) => {
470
+ _setControllerSchema(target, options);
471
+ };
472
+ }
473
+ function RouteSchema(options) {
474
+ return (target, propertyKey) => {
475
+ const ctor = target.constructor;
476
+ _setRouteSchema(ctor, String(propertyKey), options);
477
+ };
478
+ }
479
+ function _setRouteSchema(ctor, fnName, options) {
480
+ _getOrCreateMap(_routeSchemaStore, ctor).set(fnName, options);
481
+ }
482
+ function _setControllerSchema(ctor, options) {
483
+ _controllerSchemaStore.set(ctor, options);
484
+ }
485
+ function _getRouteSchema(ctor, fnName) {
486
+ return _routeSchemaStore.get(ctor)?.get(fnName);
487
+ }
488
+ function _getControllerSchema(ctor) {
489
+ return _controllerSchemaStore.get(ctor);
490
+ }
491
+ //#endregion
492
+ //#region src/helper/openapi.ts
493
+ 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
+ }
504
+ registerController(controllerClass, prefix) {
505
+ this.controllers.add({
506
+ class: controllerClass,
507
+ prefix
508
+ });
509
+ }
510
+ generateSpec() {
511
+ const config = this.config;
512
+ const paths = {};
513
+ const tags = [];
514
+ for (const { class: controllerClass, prefix } of this.controllers) {
515
+ const routes = _getRoutes(controllerClass);
516
+ const controllerSchema = _getControllerSchema(controllerClass);
517
+ if (controllerSchema?.title) tags.push({
518
+ name: controllerSchema.title,
519
+ description: controllerSchema.description
520
+ });
521
+ for (const route of routes) {
522
+ if (route.method === "USE") continue;
523
+ const schemas = _getValidatorSchema(controllerClass, route.fnName);
524
+ const routeSchema = _getRouteSchema(controllerClass, route.fnName);
525
+ if (route.path instanceof RegExp) throw new Error(`You have a route with a regex path of ${route.path.source}. This is not compatible with OpenAPI.`);
526
+ const openApiPath = (prefix + route.path).replace(/:([A-Za-z0-9_]+)/g, "{$1}");
527
+ if (!paths[openApiPath]) paths[openApiPath] = {};
528
+ const responses = {};
529
+ if (schemas?.responseBody) {
530
+ const responseSchema = this.toJsonSchema(schemas.responseBody, "output");
531
+ responses["200"] = {
532
+ description: responseSchema.description ?? "Successful response",
533
+ content: { "application/json": { schema: responseSchema } }
534
+ };
535
+ } else responses["200"] = { description: "Successful response" };
536
+ if (routeSchema?.responses) for (const resp of routeSchema.responses) {
537
+ const statusCode = String(resp.statusCode);
538
+ const existingResponse = responses[statusCode];
539
+ const existingSchema = existingResponse && "content" in existingResponse ? existingResponse.content?.["application/json"]?.schema : void 0;
540
+ const responseSchema = resp.schema ? this.toJsonSchema(resp.schema, "output") : statusCode === "200" ? existingSchema : void 0;
541
+ responses[statusCode] = {
542
+ ...existingResponse,
543
+ description: resp.description ?? responseSchema?.description ?? existingResponse?.description ?? `Response ${resp.statusCode}`,
544
+ ...responseSchema ? { content: { "application/json": { schema: responseSchema } } } : {}
545
+ };
546
+ }
547
+ const operation = {
548
+ responses,
549
+ summary: routeSchema?.summary,
550
+ description: routeSchema?.description,
551
+ tags: controllerSchema?.title ? [controllerSchema.title] : void 0
552
+ };
553
+ const parameters = [];
554
+ if (schemas?.requestParam) {
555
+ const paramSchema = this.toJsonSchema(schemas.requestParam, "input");
556
+ if (paramSchema.type === "object" && paramSchema.properties) for (const [name, schema] of Object.entries(paramSchema.properties)) {
557
+ const parameterSchema = schema;
558
+ parameters.push({
559
+ name,
560
+ in: "path",
561
+ required: true,
562
+ description: parameterSchema.description,
563
+ schema: parameterSchema
564
+ });
565
+ }
566
+ }
567
+ if (schemas?.requestQuery) {
568
+ const querySchema = this.toJsonSchema(schemas.requestQuery, "input");
569
+ if (querySchema.type === "object" && querySchema.properties) for (const [name, schema] of Object.entries(querySchema.properties)) {
570
+ const isRequired = Array.isArray(querySchema.required) && querySchema.required.includes(name);
571
+ const parameterSchema = schema;
572
+ parameters.push({
573
+ name,
574
+ in: "query",
575
+ required: isRequired,
576
+ description: parameterSchema.description,
577
+ schema: parameterSchema
578
+ });
579
+ }
580
+ }
581
+ if (parameters.length > 0) operation.parameters = parameters;
582
+ if (schemas?.requestBody) {
583
+ const requestSchema = this.toJsonSchema(schemas.requestBody, "input");
584
+ operation.requestBody = {
585
+ required: true,
586
+ description: requestSchema.description,
587
+ content: { "application/json": { schema: requestSchema } }
588
+ };
589
+ }
590
+ const method = route.method.toLowerCase();
591
+ paths[openApiPath][method] = operation;
592
+ }
593
+ }
594
+ return {
595
+ openapi: "3.0.0",
596
+ info: {
597
+ title: config.title,
598
+ version: config.version,
599
+ description: config.description
600
+ },
601
+ tags: tags.length > 0 ? tags : void 0,
602
+ paths
603
+ };
604
+ }
605
+ toJsonSchema(schema, direction = "output") {
606
+ try {
607
+ 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" });
610
+ } 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`);
612
+ throw e;
613
+ }
614
+ }
615
+ };
616
+ const openApiGenerator = new OpenAPIGenerator();
617
+ function _registerControllerClass(controllerClass, prefix) {
618
+ openApiGenerator.registerController(controllerClass, prefix);
619
+ }
620
+ function setOpenApiConfig(config) {
621
+ openApiGenerator.setConfig(config);
622
+ }
623
+ function generateOpenApiSpec() {
624
+ return openApiGenerator.generateSpec();
625
+ }
626
+ //#endregion
350
627
  //#region src/types.ts
351
628
  const methodResolve = {
352
629
  GET: "get",
@@ -479,212 +756,58 @@ function _resolve(ctor) {
479
756
  return _InjectableRegistry.get(ctor);
480
757
  }
481
758
  //#endregion
482
- //#region src/annotation/request.ts
483
- const _requestSchemaStore = /* @__PURE__ */ new WeakMap();
484
- /**
485
- * Apply to a route method to have `request.body` be parsed by `schema`.
486
- *
487
- * This annotation will parse `request.body` & then override `request.body`.
488
- * You can then just simply cast `request.body` for your use
489
- *
490
- * @example
491
- * ```ts
492
- * const CREATE_BOOK_REQUEST_BODY_SCHEMA = z.object({
493
- * name: z.string(),
494
- * description: z.string().optional(),
495
- * });
496
- *
497
- * ⠀@Controller({ prefix: "/api/book" })
498
- * class BookController {
499
- * ⠀@RequestBody(CREATE_BOOK_REQUEST_BODY_SCHEMA)
500
- * ⠀@POST()
501
- * public createBook(request: e.Request) {
502
- * const { name, description } = request.body as unknown as z.infer<
503
- * typeof CREATE_BOOK_REQUEST_BODY_SCHEMA
504
- * >;
505
- * }
506
- * }
507
- * ```
508
- */
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
+ }
509
768
  function RequestBody(schema) {
510
769
  return (target, propertyKey) => {
511
770
  const ctor = target.constructor;
512
771
  const fnName = String(propertyKey);
513
- _setOnce(_getOrCreateRequestSchemaDefinition(ctor, fnName), "body", schema, fnName);
772
+ _setOnce(_getOrCreateSchemaDefinition(ctor, fnName), "requestBody", schema, fnName);
514
773
  };
515
774
  }
516
- /**
517
- * Apply to a route method to have `request.param` be parsed by `schema`.
518
- *
519
- * This annotation will parse `request.param` & then override `request.param`.
520
- * You can then just simply cast `request.param` for your use
521
- *
522
- * @example
523
- * ```ts
524
- * const GET_BOOK_REQUEST_PARAM_SCHEMA = z.object({
525
- * bookId: z.string(),
526
- * });
527
- *
528
- * ⠀@Controller({ prefix: "/api/book" })
529
- * class BookController {
530
- * ⠀@RequestParam(GET_BOOK_REQUEST_PARAM_SCHEMA)
531
- * ⠀@GET("/:bookId")
532
- * public getBook(request: e.Request) {
533
- * const { bookId } = request.param as unknown as z.infer<
534
- * typeof GET_BOOK_REQUEST_PARAM_SCHEMA
535
- * >;
536
- * }
537
- * }
538
- * ```
539
- */
540
775
  function RequestParam(schema) {
541
776
  return (target, propertyKey) => {
542
777
  const ctor = target.constructor;
543
778
  const fnName = String(propertyKey);
544
- _setOnce(_getOrCreateRequestSchemaDefinition(ctor, fnName), "param", schema, fnName);
779
+ _setOnce(_getOrCreateSchemaDefinition(ctor, fnName), "requestParam", schema, fnName);
545
780
  };
546
781
  }
547
- /**
548
- * Apply to a route method to have `request.query` be parsed by `schema`.
549
- *
550
- * This annotation will parse `request.query` & then override `request.query`.
551
- * You can then just simply cast `request.query` for your use
552
- *
553
- * @example
554
- * ```ts
555
- * const LIST_BOOKS_REQUEST_QUERY_SCHEMA = z.object({
556
- * sort: z.enum(["name", "createdAt"]).optional(),
557
- * q: z.string().optional(),
558
- * });
559
- *
560
- * ⠀@Controller({ prefix: "/api/book" })
561
- * class BookController {
562
- * ⠀@RequestQuery(LIST_BOOKS_REQUEST_QUERY_SCHEMA)
563
- * ⠀@GET()
564
- * public listBooks(request: e.Request) {
565
- * const { sort, q } = request.query as unknown as z.infer<
566
- * typeof LIST_BOOKS_REQUEST_QUERY_SCHEMA
567
- * >;
568
- * }
569
- * }
570
- * ```
571
- */
572
782
  function RequestQuery(schema) {
573
783
  return (target, propertyKey) => {
574
784
  const ctor = target.constructor;
575
785
  const fnName = String(propertyKey);
576
- _setOnce(_getOrCreateRequestSchemaDefinition(ctor, fnName), "query", schema, fnName);
786
+ _setOnce(_getOrCreateSchemaDefinition(ctor, fnName), "requestQuery", schema, fnName);
577
787
  };
578
788
  }
579
- function _getOrCreateRequestSchemaDefinition(ctor, fnName) {
580
- const byFn = (() => {
581
- const fn = _requestSchemaStore.get(ctor);
582
- if (fn) return fn;
583
- const newFn = /* @__PURE__ */ new Map();
584
- _requestSchemaStore.set(ctor, newFn);
585
- return newFn;
586
- })();
789
+ function _getOrCreateSchemaDefinition(ctor, fnName) {
790
+ const byFn = _getOrCreateMap(_validatorSchemaStore, ctor);
587
791
  const existing = byFn.get(fnName);
588
792
  if (existing) return existing;
589
793
  const created = {};
590
794
  byFn.set(fnName, created);
591
795
  return created;
592
796
  }
593
- function _setOnce(def, key, schema, fnName) {
594
- if (def[key]) throw new Error(`Duplicate request schema for "${String(key)}" on method "${fnName}"`);
595
- def[key] = schema;
596
- }
597
- function _getRequestSchemas(ctor, fnName) {
598
- return _requestSchemaStore.get(ctor)?.get(fnName);
599
- }
600
797
  async function _parseOrThrow(schema, input, kind) {
601
798
  const result = await schema["~standard"].validate(input);
602
799
  if (result.issues) {
603
- console.debug(`Failed to parse a schema`);
800
+ console.debug(`Failed to parse ${schema["~standard"].vendor} schema\nissues: ${result.issues}`);
604
801
  throw new ParserError(kind, result.issues, schema["~standard"].vendor);
605
802
  }
606
803
  return result.value;
607
804
  }
608
- //#endregion
609
- //#region src/annotation/route.ts
610
- const _routeStore = /* @__PURE__ */ new WeakMap();
611
- /**
612
- * Custom annotation that will store all routes inside of a map,
613
- * which can then be used to initialize all the routes to the router.
614
- */
615
- function _Route({ method, path = "" }) {
616
- return (target, propertyKey) => {
617
- const ctor = target.constructor;
618
- const list = _routeStore.get(ctor) ?? [];
619
- list.push({
620
- method,
621
- path: path ?? "",
622
- fnName: String(propertyKey)
623
- });
624
- _routeStore.set(ctor, list);
625
- };
805
+ function _getValidatorSchema(ctor, fnName) {
806
+ return _validatorSchemaStore.get(ctor)?.get(fnName);
626
807
  }
627
- /**
628
- * Register GET route on the given path (default "") for the given controller.
629
- */
630
- const GET = (path = "") => _Route({
631
- method: "GET",
632
- path
633
- });
634
- /**
635
- * Register POST route on the given path (default "") for the given controller.
636
- */
637
- const POST = (path = "") => _Route({
638
- method: "POST",
639
- path
640
- });
641
- /**
642
- * Register PUT route on the given path (default "") for the given controller.
643
- */
644
- const PUT = (path = "") => _Route({
645
- method: "PUT",
646
- path
647
- });
648
- /**
649
- * Register DELETE route on the given path (default "") for the given controller.
650
- */
651
- const DELETE = (path = "") => _Route({
652
- method: "DELETE",
653
- path
654
- });
655
- /**
656
- * Register OPTIONS route on the given path (default "") for the given controller.
657
- */
658
- const OPTIONS = (path = "") => _Route({
659
- method: "OPTIONS",
660
- path
661
- });
662
- /**
663
- * Register PATCH route on the given path (default "") for the given controller.
664
- */
665
- const PATCH = (path = "") => _Route({
666
- method: "PATCH",
667
- path
668
- });
669
- /**
670
- * Register HEAD route on the given path (default "") for the given controller.
671
- */
672
- const HEAD = (path = "") => _Route({
673
- method: "HEAD",
674
- path
675
- });
676
- /**
677
- * Register a middleware route on the given path (default "") for the given controller.
678
- */
679
- const Middleware = (path = "") => _Route({
680
- method: "USE",
681
- path
682
- });
683
- /**
684
- * Given a class constructor, fetch all the routes attached.
685
- */
686
- function _getRoutes(ctor) {
687
- return _routeStore.get(ctor) ?? [];
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;
688
811
  }
689
812
  //#endregion
690
813
  //#region src/annotation/controller.ts
@@ -698,6 +821,7 @@ const _ControllerRegistry = /* @__PURE__ */ new WeakMap();
698
821
  function Controller({ prefix = "", deps = [] } = {}) {
699
822
  return (target) => {
700
823
  const targetClass = target;
824
+ _registerControllerClass(target, prefix);
701
825
  const router = Router();
702
826
  const routes = _getRoutes(target);
703
827
  const usedRoutes = /* @__PURE__ */ new Set();
@@ -740,12 +864,12 @@ Split these into separate @MiddlewareClass classes, or merge the logic into a si
740
864
  return;
741
865
  }
742
866
  router[methodName](fp, async (request, response, next) => {
743
- const schemas = _getRequestSchemas(target, fnName);
867
+ const schemas = _getValidatorSchema(target, fnName);
744
868
  if (schemas) {
745
- if (schemas.body) request.body = await _parseOrThrow(schemas.body, request.body, "reqbody");
746
- if (schemas.param) request.params = await _parseOrThrow(schemas.param, request.params, "reqparams");
747
- if (schemas.query) {
748
- const parsedQuery = await _parseOrThrow(schemas.query, request.query, "reqquery");
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");
749
873
  Object.defineProperty(request, "query", {
750
874
  value: parsedQuery,
751
875
  writable: true,
@@ -755,7 +879,8 @@ Split these into separate @MiddlewareClass classes, or merge the logic into a si
755
879
  }
756
880
  const result = await fn.bind(controllerInstance)(request, response, next);
757
881
  if (result instanceof ResponseEntity) {
758
- response.contentType("application/json").status(result.getStatusCode()).set(result.getHeaders()).send(Sapling.serialize(result.getBody()));
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));
759
884
  return;
760
885
  }
761
886
  if (result instanceof RedirectView) {
@@ -789,7 +914,7 @@ function __decorate(decorators, target, key, desc) {
789
914
  return c > 3 && r && Object.defineProperty(target, key, r), r;
790
915
  }
791
916
  //#endregion
792
- //#region src/middleware/default/base.ts
917
+ //#region src/middleware/default/error/base.ts
793
918
  let DefaultBaseErrorMiddleware = class DefaultBaseErrorMiddleware {
794
919
  handle(err, _request, _response, _next) {
795
920
  console.error("[Error]", err);
@@ -799,7 +924,17 @@ let DefaultBaseErrorMiddleware = class DefaultBaseErrorMiddleware {
799
924
  __decorate([Middleware()], DefaultBaseErrorMiddleware.prototype, "handle", null);
800
925
  DefaultBaseErrorMiddleware = __decorate([MiddlewareClass()], DefaultBaseErrorMiddleware);
801
926
  //#endregion
802
- //#region src/middleware/default/responsestatus.ts
927
+ //#region src/middleware/default/error/parse.ts
928
+ let DefaultParserErrorMiddleware = class DefaultParserErrorMiddleware {
929
+ handle(err, _request, _response, next) {
930
+ if (err instanceof ParserError) return ResponseEntity.status(err.status).body({ message: err.message });
931
+ next(err);
932
+ }
933
+ };
934
+ __decorate([Middleware()], DefaultParserErrorMiddleware.prototype, "handle", null);
935
+ DefaultParserErrorMiddleware = __decorate([MiddlewareClass()], DefaultParserErrorMiddleware);
936
+ //#endregion
937
+ //#region src/middleware/default/error/responsestatus.ts
803
938
  let DefaultResponseStatusErrorMiddleware = class DefaultResponseStatusErrorMiddleware {
804
939
  handle(err, _request, _response, next) {
805
940
  if (err instanceof ResponseStatusError) return ResponseEntity.status(err.status).body({ message: err.message });
@@ -809,4 +944,39 @@ let DefaultResponseStatusErrorMiddleware = class DefaultResponseStatusErrorMiddl
809
944
  __decorate([Middleware()], DefaultResponseStatusErrorMiddleware.prototype, "handle", null);
810
945
  DefaultResponseStatusErrorMiddleware = __decorate([MiddlewareClass()], DefaultResponseStatusErrorMiddleware);
811
946
  //#endregion
812
- export { Controller, DELETE, DefaultBaseErrorMiddleware, DefaultResponseStatusErrorMiddleware, GET, HEAD, Html404ErrorPage, HttpStatus, Injectable, Middleware, MiddlewareClass, OPTIONS, PATCH, POST, PUT, ParserError, RedirectView, RequestBody, RequestParam, RequestQuery, ResponseEntity, ResponseEntityBuilder, ResponseStatusError, Sapling, _ControllerRegistry, _InjectableDeps, _InjectableRegistry, _Route, _getRequestSchemas, _getRoutes, _parseOrThrow, _resolve, methodResolve };
947
+ //#region src/middleware/default/openapi/index.ts
948
+ let DefaultOpenApiMiddleware = class DefaultOpenApiMiddleware {
949
+ handle(_request, _response, _next) {
950
+ return ResponseEntity.ok().body(generateOpenApiSpec());
951
+ }
952
+ };
953
+ __decorate([GET(_settings.doc.openApiPath)], DefaultOpenApiMiddleware.prototype, "handle", null);
954
+ DefaultOpenApiMiddleware = __decorate([MiddlewareClass()], DefaultOpenApiMiddleware);
955
+ //#endregion
956
+ //#region src/middleware/default/swagger/index.ts
957
+ let Serve = class Serve {
958
+ constructor() {
959
+ this.handlers = swagger.serve;
960
+ }
961
+ handle(request, response, next) {
962
+ return Sapling.chainHandlers(this.handlers, request, response, next);
963
+ }
964
+ };
965
+ __decorate([Middleware(_settings.doc.swaggerPath)], Serve.prototype, "handle", null);
966
+ Serve = __decorate([MiddlewareClass()], Serve);
967
+ let Setup = class Setup {
968
+ constructor() {
969
+ this.handler = swagger.setup(null, { swaggerOptions: { url: _settings.doc.openApiPath } });
970
+ }
971
+ handle(request, response, next) {
972
+ return this.handler(request, response, next);
973
+ }
974
+ };
975
+ __decorate([Middleware(_settings.doc.swaggerPath)], Setup.prototype, "handle", null);
976
+ Setup = __decorate([MiddlewareClass()], Setup);
977
+ const DefaultSwaggerMiddleware = {
978
+ Serve,
979
+ Setup
980
+ };
981
+ //#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 };