@tahminator/sapling 2.0.3 → 2.0.5-beta.18ab8bae
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 +94 -4
- package/dist/index.cjs +368 -118
- package/dist/index.d.cts +464 -17
- package/dist/index.d.mts +464 -17
- package/dist/index.mjs +340 -118
- package/package.json +8 -2
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.
|
|
@@ -256,15 +258,20 @@ var ParserError = class ParserError extends ResponseStatusError {
|
|
|
256
258
|
case "reqbody": return "request body";
|
|
257
259
|
case "reqparams": return "request params";
|
|
258
260
|
case "reqquery": return "request query";
|
|
261
|
+
case "resbody": return "response body";
|
|
259
262
|
}
|
|
260
263
|
})()}: ${formatted}`;
|
|
261
264
|
}
|
|
262
265
|
};
|
|
263
266
|
//#endregion
|
|
264
267
|
//#region src/helper/sapling.ts
|
|
265
|
-
const
|
|
268
|
+
const _settings = {
|
|
266
269
|
serialize: JSON.stringify,
|
|
267
|
-
deserialize: JSON.parse
|
|
270
|
+
deserialize: JSON.parse,
|
|
271
|
+
doc: {
|
|
272
|
+
openApiPath: "/openapi.json",
|
|
273
|
+
swaggerPath: "/swagger.html"
|
|
274
|
+
}
|
|
268
275
|
};
|
|
269
276
|
/**
|
|
270
277
|
* Collection of utility functions which are essential for Sapling to function.
|
|
@@ -343,13 +350,13 @@ var Sapling = class Sapling {
|
|
|
343
350
|
* @defaultValue `JSON.stringify`
|
|
344
351
|
*/
|
|
345
352
|
static serialize(value) {
|
|
346
|
-
return
|
|
353
|
+
return _settings.serialize(value);
|
|
347
354
|
}
|
|
348
355
|
/**
|
|
349
356
|
* Replace the function used for `serialize`.
|
|
350
357
|
*/
|
|
351
358
|
static setSerializeFn(fn) {
|
|
352
|
-
|
|
359
|
+
_settings.serialize = fn;
|
|
353
360
|
}
|
|
354
361
|
/**
|
|
355
362
|
* De-serialize a JSON string back to a JavaScript object.
|
|
@@ -361,16 +368,265 @@ var Sapling = class Sapling {
|
|
|
361
368
|
* @defaultValue `JSON.parse`
|
|
362
369
|
*/
|
|
363
370
|
static deserialize(value) {
|
|
364
|
-
return
|
|
371
|
+
return _settings.deserialize(value);
|
|
365
372
|
}
|
|
366
373
|
/**
|
|
367
374
|
* Replace the function used for `deserialize`
|
|
368
375
|
*/
|
|
369
376
|
static setDeserializeFn(fn) {
|
|
370
|
-
|
|
377
|
+
_settings.deserialize = fn;
|
|
378
|
+
}
|
|
379
|
+
static setOpenApiPath(path) {
|
|
380
|
+
_settings.doc.openApiPath = path;
|
|
381
|
+
}
|
|
382
|
+
static setSwaggerPath(path) {
|
|
383
|
+
_settings.doc.swaggerPath = path;
|
|
384
|
+
}
|
|
385
|
+
static chainHandlers(handlers, request, response, next, index = 0) {
|
|
386
|
+
if (index >= handlers.length) {
|
|
387
|
+
next();
|
|
388
|
+
return;
|
|
389
|
+
}
|
|
390
|
+
handlers[index]?.(request, response, (err) => {
|
|
391
|
+
if (err) {
|
|
392
|
+
next(err);
|
|
393
|
+
return;
|
|
394
|
+
}
|
|
395
|
+
Sapling.chainHandlers(handlers, request, response, next, index + 1);
|
|
396
|
+
});
|
|
371
397
|
}
|
|
372
398
|
};
|
|
373
399
|
//#endregion
|
|
400
|
+
//#region src/annotation/route.ts
|
|
401
|
+
const _routeStore = /* @__PURE__ */ new WeakMap();
|
|
402
|
+
/**
|
|
403
|
+
* Custom annotation that will store all routes inside of a map,
|
|
404
|
+
* which can then be used to initialize all the routes to the router.
|
|
405
|
+
*/
|
|
406
|
+
function _Route({ method, path = "" }) {
|
|
407
|
+
return (target, propertyKey) => {
|
|
408
|
+
const ctor = target.constructor;
|
|
409
|
+
const list = _routeStore.get(ctor) ?? [];
|
|
410
|
+
list.push({
|
|
411
|
+
method,
|
|
412
|
+
path: path ?? "",
|
|
413
|
+
fnName: String(propertyKey)
|
|
414
|
+
});
|
|
415
|
+
_routeStore.set(ctor, list);
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
/**
|
|
419
|
+
* Register GET route on the given path (default "") for the given controller.
|
|
420
|
+
*/
|
|
421
|
+
const GET = (path = "") => _Route({
|
|
422
|
+
method: "GET",
|
|
423
|
+
path
|
|
424
|
+
});
|
|
425
|
+
/**
|
|
426
|
+
* Register POST route on the given path (default "") for the given controller.
|
|
427
|
+
*/
|
|
428
|
+
const POST = (path = "") => _Route({
|
|
429
|
+
method: "POST",
|
|
430
|
+
path
|
|
431
|
+
});
|
|
432
|
+
/**
|
|
433
|
+
* Register PUT route on the given path (default "") for the given controller.
|
|
434
|
+
*/
|
|
435
|
+
const PUT = (path = "") => _Route({
|
|
436
|
+
method: "PUT",
|
|
437
|
+
path
|
|
438
|
+
});
|
|
439
|
+
/**
|
|
440
|
+
* Register DELETE route on the given path (default "") for the given controller.
|
|
441
|
+
*/
|
|
442
|
+
const DELETE = (path = "") => _Route({
|
|
443
|
+
method: "DELETE",
|
|
444
|
+
path
|
|
445
|
+
});
|
|
446
|
+
/**
|
|
447
|
+
* Register OPTIONS route on the given path (default "") for the given controller.
|
|
448
|
+
*/
|
|
449
|
+
const OPTIONS = (path = "") => _Route({
|
|
450
|
+
method: "OPTIONS",
|
|
451
|
+
path
|
|
452
|
+
});
|
|
453
|
+
/**
|
|
454
|
+
* Register PATCH route on the given path (default "") for the given controller.
|
|
455
|
+
*/
|
|
456
|
+
const PATCH = (path = "") => _Route({
|
|
457
|
+
method: "PATCH",
|
|
458
|
+
path
|
|
459
|
+
});
|
|
460
|
+
/**
|
|
461
|
+
* Register HEAD route on the given path (default "") for the given controller.
|
|
462
|
+
*/
|
|
463
|
+
const HEAD = (path = "") => _Route({
|
|
464
|
+
method: "HEAD",
|
|
465
|
+
path
|
|
466
|
+
});
|
|
467
|
+
/**
|
|
468
|
+
* Register a middleware route on the given path (default "") for the given controller.
|
|
469
|
+
*/
|
|
470
|
+
const Middleware = (path = "") => _Route({
|
|
471
|
+
method: "USE",
|
|
472
|
+
path
|
|
473
|
+
});
|
|
474
|
+
/**
|
|
475
|
+
* Given a class constructor, fetch all the routes attached.
|
|
476
|
+
*/
|
|
477
|
+
function _getRoutes(ctor) {
|
|
478
|
+
return _routeStore.get(ctor) ?? [];
|
|
479
|
+
}
|
|
480
|
+
//#endregion
|
|
481
|
+
//#region src/utils.ts
|
|
482
|
+
function _getOrCreateMap(store, ctor) {
|
|
483
|
+
const existing = store.get(ctor);
|
|
484
|
+
if (existing) return existing;
|
|
485
|
+
const created = /* @__PURE__ */ new Map();
|
|
486
|
+
store.set(ctor, created);
|
|
487
|
+
return created;
|
|
488
|
+
}
|
|
489
|
+
//#endregion
|
|
490
|
+
//#region src/annotation/schema.ts
|
|
491
|
+
const _routeSchemaStore = /* @__PURE__ */ new WeakMap();
|
|
492
|
+
const _controllerSchemaStore = /* @__PURE__ */ new WeakMap();
|
|
493
|
+
function ControllerSchema(options) {
|
|
494
|
+
return (target) => {
|
|
495
|
+
_setControllerSchema(target, options);
|
|
496
|
+
};
|
|
497
|
+
}
|
|
498
|
+
function RouteSchema(options) {
|
|
499
|
+
return (target, propertyKey) => {
|
|
500
|
+
const ctor = target.constructor;
|
|
501
|
+
_setRouteSchema(ctor, String(propertyKey), options);
|
|
502
|
+
};
|
|
503
|
+
}
|
|
504
|
+
function _setRouteSchema(ctor, fnName, options) {
|
|
505
|
+
_getOrCreateMap(_routeSchemaStore, ctor).set(fnName, options);
|
|
506
|
+
}
|
|
507
|
+
function _setControllerSchema(ctor, options) {
|
|
508
|
+
_controllerSchemaStore.set(ctor, options);
|
|
509
|
+
}
|
|
510
|
+
function _getRouteSchema(ctor, fnName) {
|
|
511
|
+
return _routeSchemaStore.get(ctor)?.get(fnName);
|
|
512
|
+
}
|
|
513
|
+
function _getControllerSchema(ctor) {
|
|
514
|
+
return _controllerSchemaStore.get(ctor);
|
|
515
|
+
}
|
|
516
|
+
//#endregion
|
|
517
|
+
//#region src/helper/openapi.ts
|
|
518
|
+
var OpenAPIGenerator = class {
|
|
519
|
+
constructor() {
|
|
520
|
+
this.controllers = /* @__PURE__ */ new Set();
|
|
521
|
+
this.config = {
|
|
522
|
+
title: "API",
|
|
523
|
+
version: "1.0.0"
|
|
524
|
+
};
|
|
525
|
+
}
|
|
526
|
+
setConfig(config) {
|
|
527
|
+
this.config = config;
|
|
528
|
+
}
|
|
529
|
+
registerController(controllerClass, prefix) {
|
|
530
|
+
this.controllers.add({
|
|
531
|
+
class: controllerClass,
|
|
532
|
+
prefix
|
|
533
|
+
});
|
|
534
|
+
}
|
|
535
|
+
generateSpec() {
|
|
536
|
+
const config = this.config;
|
|
537
|
+
const paths = {};
|
|
538
|
+
const tags = [];
|
|
539
|
+
for (const { class: controllerClass, prefix } of this.controllers) {
|
|
540
|
+
const routes = _getRoutes(controllerClass);
|
|
541
|
+
const controllerSchema = _getControllerSchema(controllerClass);
|
|
542
|
+
if (controllerSchema?.title) tags.push({
|
|
543
|
+
name: controllerSchema.title,
|
|
544
|
+
description: controllerSchema.description
|
|
545
|
+
});
|
|
546
|
+
for (const route of routes) {
|
|
547
|
+
if (route.method === "USE") continue;
|
|
548
|
+
const schemas = _getValidatorSchema(controllerClass, route.fnName);
|
|
549
|
+
const routeSchema = _getRouteSchema(controllerClass, route.fnName);
|
|
550
|
+
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.`);
|
|
551
|
+
const openApiPath = prefix + route.path;
|
|
552
|
+
if (!paths[openApiPath]) paths[openApiPath] = {};
|
|
553
|
+
const responses = {};
|
|
554
|
+
if (schemas?.responseBody) responses["200"] = {
|
|
555
|
+
description: "Successful response",
|
|
556
|
+
content: { "application/json": { schema: this.toJsonSchema(schemas.responseBody) } }
|
|
557
|
+
};
|
|
558
|
+
else responses["200"] = { description: "Successful response" };
|
|
559
|
+
if (routeSchema?.responses) for (const resp of routeSchema.responses) responses[String(resp.statusCode)] = {
|
|
560
|
+
description: `Response ${resp.statusCode}`,
|
|
561
|
+
content: { "application/json": { schema: this.toJsonSchema(resp.schema) } }
|
|
562
|
+
};
|
|
563
|
+
const operation = {
|
|
564
|
+
responses,
|
|
565
|
+
description: routeSchema?.description,
|
|
566
|
+
tags: controllerSchema?.title ? [controllerSchema.title] : void 0
|
|
567
|
+
};
|
|
568
|
+
const parameters = [];
|
|
569
|
+
if (schemas?.requestParam) {
|
|
570
|
+
const paramSchema = this.toJsonSchema(schemas.requestParam);
|
|
571
|
+
if (paramSchema.type === "object" && paramSchema.properties) for (const [name, schema] of Object.entries(paramSchema.properties)) parameters.push({
|
|
572
|
+
name,
|
|
573
|
+
in: "path",
|
|
574
|
+
required: true,
|
|
575
|
+
schema
|
|
576
|
+
});
|
|
577
|
+
}
|
|
578
|
+
if (schemas?.requestQuery) {
|
|
579
|
+
const querySchema = this.toJsonSchema(schemas.requestQuery);
|
|
580
|
+
if (querySchema.type === "object" && querySchema.properties) for (const [name, schema] of Object.entries(querySchema.properties)) {
|
|
581
|
+
const isRequired = Array.isArray(querySchema.required) && querySchema.required.includes(name);
|
|
582
|
+
parameters.push({
|
|
583
|
+
name,
|
|
584
|
+
in: "query",
|
|
585
|
+
required: isRequired,
|
|
586
|
+
schema
|
|
587
|
+
});
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
if (parameters.length > 0) operation.parameters = parameters;
|
|
591
|
+
if (schemas?.requestBody) operation.requestBody = {
|
|
592
|
+
required: true,
|
|
593
|
+
content: { "application/json": { schema: this.toJsonSchema(schemas.requestBody) } }
|
|
594
|
+
};
|
|
595
|
+
const method = route.method.toLowerCase();
|
|
596
|
+
paths[openApiPath][method] = operation;
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
return {
|
|
600
|
+
openapi: "3.0.0",
|
|
601
|
+
info: {
|
|
602
|
+
title: config.title,
|
|
603
|
+
version: config.version,
|
|
604
|
+
description: config.description
|
|
605
|
+
},
|
|
606
|
+
tags: tags.length > 0 ? tags : void 0,
|
|
607
|
+
paths
|
|
608
|
+
};
|
|
609
|
+
}
|
|
610
|
+
toJsonSchema(schema) {
|
|
611
|
+
try {
|
|
612
|
+
return schema["~standard"].jsonSchema.output({ target: "openapi-3.0" });
|
|
613
|
+
} catch (e) {
|
|
614
|
+
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`);
|
|
615
|
+
throw e;
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
};
|
|
619
|
+
const openApiGenerator = new OpenAPIGenerator();
|
|
620
|
+
function _registerControllerClass(controllerClass, prefix) {
|
|
621
|
+
openApiGenerator.registerController(controllerClass, prefix);
|
|
622
|
+
}
|
|
623
|
+
function setOpenApiConfig(config) {
|
|
624
|
+
openApiGenerator.setConfig(config);
|
|
625
|
+
}
|
|
626
|
+
function generateOpenApiSpec() {
|
|
627
|
+
return openApiGenerator.generateSpec();
|
|
628
|
+
}
|
|
629
|
+
//#endregion
|
|
374
630
|
//#region src/types.ts
|
|
375
631
|
const methodResolve = {
|
|
376
632
|
GET: "get",
|
|
@@ -503,49 +759,43 @@ function _resolve(ctor) {
|
|
|
503
759
|
return _InjectableRegistry.get(ctor);
|
|
504
760
|
}
|
|
505
761
|
//#endregion
|
|
506
|
-
//#region src/annotation/
|
|
507
|
-
const
|
|
508
|
-
function
|
|
509
|
-
|
|
510
|
-
const
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
return newFn;
|
|
515
|
-
})();
|
|
516
|
-
const existing = byFn.get(fnName);
|
|
517
|
-
if (existing) return existing;
|
|
518
|
-
const created = {};
|
|
519
|
-
byFn.set(fnName, created);
|
|
520
|
-
return created;
|
|
521
|
-
}
|
|
522
|
-
function _setOnce(def, key, schema, fnName) {
|
|
523
|
-
if (def[key]) throw new Error(`Duplicate request schema for "${String(key)}" on method "${fnName}"`);
|
|
524
|
-
def[key] = schema;
|
|
762
|
+
//#region src/annotation/validator.ts
|
|
763
|
+
const _validatorSchemaStore = /* @__PURE__ */ new WeakMap();
|
|
764
|
+
function ResponseBody(schema) {
|
|
765
|
+
return (target, propertyKey) => {
|
|
766
|
+
const ctor = target.constructor;
|
|
767
|
+
const fnName = String(propertyKey);
|
|
768
|
+
_setOnce(_getOrCreateSchemaDefinition(ctor, fnName), "responseBody", schema, fnName);
|
|
769
|
+
};
|
|
525
770
|
}
|
|
526
771
|
function RequestBody(schema) {
|
|
527
772
|
return (target, propertyKey) => {
|
|
528
773
|
const ctor = target.constructor;
|
|
529
774
|
const fnName = String(propertyKey);
|
|
530
|
-
_setOnce(
|
|
775
|
+
_setOnce(_getOrCreateSchemaDefinition(ctor, fnName), "requestBody", schema, fnName);
|
|
531
776
|
};
|
|
532
777
|
}
|
|
533
778
|
function RequestParam(schema) {
|
|
534
779
|
return (target, propertyKey) => {
|
|
535
780
|
const ctor = target.constructor;
|
|
536
781
|
const fnName = String(propertyKey);
|
|
537
|
-
_setOnce(
|
|
782
|
+
_setOnce(_getOrCreateSchemaDefinition(ctor, fnName), "requestParam", schema, fnName);
|
|
538
783
|
};
|
|
539
784
|
}
|
|
540
785
|
function RequestQuery(schema) {
|
|
541
786
|
return (target, propertyKey) => {
|
|
542
787
|
const ctor = target.constructor;
|
|
543
788
|
const fnName = String(propertyKey);
|
|
544
|
-
_setOnce(
|
|
789
|
+
_setOnce(_getOrCreateSchemaDefinition(ctor, fnName), "requestQuery", schema, fnName);
|
|
545
790
|
};
|
|
546
791
|
}
|
|
547
|
-
function
|
|
548
|
-
|
|
792
|
+
function _getOrCreateSchemaDefinition(ctor, fnName) {
|
|
793
|
+
const byFn = _getOrCreateMap(_validatorSchemaStore, ctor);
|
|
794
|
+
const existing = byFn.get(fnName);
|
|
795
|
+
if (existing) return existing;
|
|
796
|
+
const created = {};
|
|
797
|
+
byFn.set(fnName, created);
|
|
798
|
+
return created;
|
|
549
799
|
}
|
|
550
800
|
async function _parseOrThrow(schema, input, kind) {
|
|
551
801
|
const result = await schema["~standard"].validate(input);
|
|
@@ -555,86 +805,12 @@ async function _parseOrThrow(schema, input, kind) {
|
|
|
555
805
|
}
|
|
556
806
|
return result.value;
|
|
557
807
|
}
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
const _routeStore = /* @__PURE__ */ new WeakMap();
|
|
561
|
-
/**
|
|
562
|
-
* Custom annotation that will store all routes inside of a map,
|
|
563
|
-
* which can then be used to initialize all the routes to the router.
|
|
564
|
-
*/
|
|
565
|
-
function _Route({ method, path = "" }) {
|
|
566
|
-
return (target, propertyKey) => {
|
|
567
|
-
const ctor = target.constructor;
|
|
568
|
-
const list = _routeStore.get(ctor) ?? [];
|
|
569
|
-
list.push({
|
|
570
|
-
method,
|
|
571
|
-
path: path ?? "",
|
|
572
|
-
fnName: String(propertyKey)
|
|
573
|
-
});
|
|
574
|
-
_routeStore.set(ctor, list);
|
|
575
|
-
};
|
|
808
|
+
function _getValidatorSchema(ctor, fnName) {
|
|
809
|
+
return _validatorSchemaStore.get(ctor)?.get(fnName);
|
|
576
810
|
}
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
const GET = (path = "") => _Route({
|
|
581
|
-
method: "GET",
|
|
582
|
-
path
|
|
583
|
-
});
|
|
584
|
-
/**
|
|
585
|
-
* Register POST route on the given path (default "") for the given controller.
|
|
586
|
-
*/
|
|
587
|
-
const POST = (path = "") => _Route({
|
|
588
|
-
method: "POST",
|
|
589
|
-
path
|
|
590
|
-
});
|
|
591
|
-
/**
|
|
592
|
-
* Register PUT route on the given path (default "") for the given controller.
|
|
593
|
-
*/
|
|
594
|
-
const PUT = (path = "") => _Route({
|
|
595
|
-
method: "PUT",
|
|
596
|
-
path
|
|
597
|
-
});
|
|
598
|
-
/**
|
|
599
|
-
* Register DELETE route on the given path (default "") for the given controller.
|
|
600
|
-
*/
|
|
601
|
-
const DELETE = (path = "") => _Route({
|
|
602
|
-
method: "DELETE",
|
|
603
|
-
path
|
|
604
|
-
});
|
|
605
|
-
/**
|
|
606
|
-
* Register OPTIONS route on the given path (default "") for the given controller.
|
|
607
|
-
*/
|
|
608
|
-
const OPTIONS = (path = "") => _Route({
|
|
609
|
-
method: "OPTIONS",
|
|
610
|
-
path
|
|
611
|
-
});
|
|
612
|
-
/**
|
|
613
|
-
* Register PATCH route on the given path (default "") for the given controller.
|
|
614
|
-
*/
|
|
615
|
-
const PATCH = (path = "") => _Route({
|
|
616
|
-
method: "PATCH",
|
|
617
|
-
path
|
|
618
|
-
});
|
|
619
|
-
/**
|
|
620
|
-
* Register HEAD route on the given path (default "") for the given controller.
|
|
621
|
-
*/
|
|
622
|
-
const HEAD = (path = "") => _Route({
|
|
623
|
-
method: "HEAD",
|
|
624
|
-
path
|
|
625
|
-
});
|
|
626
|
-
/**
|
|
627
|
-
* Register a middleware route on the given path (default "") for the given controller.
|
|
628
|
-
*/
|
|
629
|
-
const Middleware = (path = "") => _Route({
|
|
630
|
-
method: "USE",
|
|
631
|
-
path
|
|
632
|
-
});
|
|
633
|
-
/**
|
|
634
|
-
* Given a class constructor, fetch all the routes attached.
|
|
635
|
-
*/
|
|
636
|
-
function _getRoutes(ctor) {
|
|
637
|
-
return _routeStore.get(ctor) ?? [];
|
|
811
|
+
function _setOnce(def, key, schema, fnName) {
|
|
812
|
+
if (def[key]) throw new Error(`Duplicate schema for "${String(key)}" on method "${fnName}"`);
|
|
813
|
+
def[key] = schema;
|
|
638
814
|
}
|
|
639
815
|
//#endregion
|
|
640
816
|
//#region src/annotation/controller.ts
|
|
@@ -648,6 +824,7 @@ const _ControllerRegistry = /* @__PURE__ */ new WeakMap();
|
|
|
648
824
|
function Controller({ prefix = "", deps = [] } = {}) {
|
|
649
825
|
return (target) => {
|
|
650
826
|
const targetClass = target;
|
|
827
|
+
_registerControllerClass(target, prefix);
|
|
651
828
|
const router = (0, express.Router)();
|
|
652
829
|
const routes = _getRoutes(target);
|
|
653
830
|
const usedRoutes = /* @__PURE__ */ new Set();
|
|
@@ -690,12 +867,12 @@ Split these into separate @MiddlewareClass classes, or merge the logic into a si
|
|
|
690
867
|
return;
|
|
691
868
|
}
|
|
692
869
|
router[methodName](fp, async (request, response, next) => {
|
|
693
|
-
const schemas =
|
|
870
|
+
const schemas = _getValidatorSchema(target, fnName);
|
|
694
871
|
if (schemas) {
|
|
695
|
-
if (schemas.
|
|
696
|
-
if (schemas.
|
|
697
|
-
if (schemas.
|
|
698
|
-
const parsedQuery = await _parseOrThrow(schemas.
|
|
872
|
+
if (schemas.requestBody) request.body = await _parseOrThrow(schemas.requestBody, request.body, "reqbody");
|
|
873
|
+
if (schemas.requestParam) request.params = await _parseOrThrow(schemas.requestParam, request.params, "reqparams");
|
|
874
|
+
if (schemas.requestQuery) {
|
|
875
|
+
const parsedQuery = await _parseOrThrow(schemas.requestQuery, request.query, "reqquery");
|
|
699
876
|
Object.defineProperty(request, "query", {
|
|
700
877
|
value: parsedQuery,
|
|
701
878
|
writable: true,
|
|
@@ -705,7 +882,8 @@ Split these into separate @MiddlewareClass classes, or merge the logic into a si
|
|
|
705
882
|
}
|
|
706
883
|
const result = await fn.bind(controllerInstance)(request, response, next);
|
|
707
884
|
if (result instanceof ResponseEntity) {
|
|
708
|
-
|
|
885
|
+
const body = schemas && schemas.responseBody ? await _parseOrThrow(schemas.responseBody, result.getBody(), "resbody") : result.getBody();
|
|
886
|
+
response.contentType("application/json").status(result.getStatusCode()).set(result.getHeaders()).send(Sapling.serialize(body));
|
|
709
887
|
return;
|
|
710
888
|
}
|
|
711
889
|
if (result instanceof RedirectView) {
|
|
@@ -739,7 +917,7 @@ function __decorate(decorators, target, key, desc) {
|
|
|
739
917
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
740
918
|
}
|
|
741
919
|
//#endregion
|
|
742
|
-
//#region src/middleware/default/base.ts
|
|
920
|
+
//#region src/middleware/default/error/base.ts
|
|
743
921
|
let DefaultBaseErrorMiddleware = class DefaultBaseErrorMiddleware {
|
|
744
922
|
handle(err, _request, _response, _next) {
|
|
745
923
|
console.error("[Error]", err);
|
|
@@ -749,7 +927,17 @@ let DefaultBaseErrorMiddleware = class DefaultBaseErrorMiddleware {
|
|
|
749
927
|
__decorate([Middleware()], DefaultBaseErrorMiddleware.prototype, "handle", null);
|
|
750
928
|
DefaultBaseErrorMiddleware = __decorate([MiddlewareClass()], DefaultBaseErrorMiddleware);
|
|
751
929
|
//#endregion
|
|
752
|
-
//#region src/middleware/default/
|
|
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
|
|
753
941
|
let DefaultResponseStatusErrorMiddleware = class DefaultResponseStatusErrorMiddleware {
|
|
754
942
|
handle(err, _request, _response, next) {
|
|
755
943
|
if (err instanceof ResponseStatusError) return ResponseEntity.status(err.status).body({ message: err.message });
|
|
@@ -759,7 +947,43 @@ let DefaultResponseStatusErrorMiddleware = class DefaultResponseStatusErrorMiddl
|
|
|
759
947
|
__decorate([Middleware()], DefaultResponseStatusErrorMiddleware.prototype, "handle", null);
|
|
760
948
|
DefaultResponseStatusErrorMiddleware = __decorate([MiddlewareClass()], DefaultResponseStatusErrorMiddleware);
|
|
761
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 Sapling.chainHandlers(this.handlers, request, response, next);
|
|
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(null, { 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
|
|
762
985
|
exports.Controller = Controller;
|
|
986
|
+
exports.ControllerSchema = ControllerSchema;
|
|
763
987
|
exports.DELETE = DELETE;
|
|
764
988
|
Object.defineProperty(exports, "DefaultBaseErrorMiddleware", {
|
|
765
989
|
enumerable: true,
|
|
@@ -767,12 +991,25 @@ Object.defineProperty(exports, "DefaultBaseErrorMiddleware", {
|
|
|
767
991
|
return DefaultBaseErrorMiddleware;
|
|
768
992
|
}
|
|
769
993
|
});
|
|
994
|
+
Object.defineProperty(exports, "DefaultOpenApiMiddleware", {
|
|
995
|
+
enumerable: true,
|
|
996
|
+
get: function() {
|
|
997
|
+
return DefaultOpenApiMiddleware;
|
|
998
|
+
}
|
|
999
|
+
});
|
|
1000
|
+
Object.defineProperty(exports, "DefaultParserErrorMiddleware", {
|
|
1001
|
+
enumerable: true,
|
|
1002
|
+
get: function() {
|
|
1003
|
+
return DefaultParserErrorMiddleware;
|
|
1004
|
+
}
|
|
1005
|
+
});
|
|
770
1006
|
Object.defineProperty(exports, "DefaultResponseStatusErrorMiddleware", {
|
|
771
1007
|
enumerable: true,
|
|
772
1008
|
get: function() {
|
|
773
1009
|
return DefaultResponseStatusErrorMiddleware;
|
|
774
1010
|
}
|
|
775
1011
|
});
|
|
1012
|
+
exports.DefaultSwaggerMiddleware = DefaultSwaggerMiddleware;
|
|
776
1013
|
exports.GET = GET;
|
|
777
1014
|
exports.HEAD = HEAD;
|
|
778
1015
|
exports.Html404ErrorPage = Html404ErrorPage;
|
|
@@ -789,16 +1026,29 @@ exports.RedirectView = RedirectView;
|
|
|
789
1026
|
exports.RequestBody = RequestBody;
|
|
790
1027
|
exports.RequestParam = RequestParam;
|
|
791
1028
|
exports.RequestQuery = RequestQuery;
|
|
1029
|
+
exports.ResponseBody = ResponseBody;
|
|
792
1030
|
exports.ResponseEntity = ResponseEntity;
|
|
793
1031
|
exports.ResponseEntityBuilder = ResponseEntityBuilder;
|
|
794
1032
|
exports.ResponseStatusError = ResponseStatusError;
|
|
1033
|
+
exports.RouteSchema = RouteSchema;
|
|
795
1034
|
exports.Sapling = Sapling;
|
|
796
1035
|
exports._ControllerRegistry = _ControllerRegistry;
|
|
797
1036
|
exports._InjectableDeps = _InjectableDeps;
|
|
798
1037
|
exports._InjectableRegistry = _InjectableRegistry;
|
|
799
1038
|
exports._Route = _Route;
|
|
800
|
-
exports.
|
|
1039
|
+
exports._getControllerSchema = _getControllerSchema;
|
|
1040
|
+
exports._getOrCreateSchemaDefinition = _getOrCreateSchemaDefinition;
|
|
1041
|
+
exports._getRouteSchema = _getRouteSchema;
|
|
801
1042
|
exports._getRoutes = _getRoutes;
|
|
1043
|
+
exports._getValidatorSchema = _getValidatorSchema;
|
|
802
1044
|
exports._parseOrThrow = _parseOrThrow;
|
|
1045
|
+
exports._registerControllerClass = _registerControllerClass;
|
|
803
1046
|
exports._resolve = _resolve;
|
|
1047
|
+
exports._setControllerSchema = _setControllerSchema;
|
|
1048
|
+
exports._setOnce = _setOnce;
|
|
1049
|
+
exports._setRouteSchema = _setRouteSchema;
|
|
1050
|
+
exports._settings = _settings;
|
|
1051
|
+
exports.generateOpenApiSpec = generateOpenApiSpec;
|
|
804
1052
|
exports.methodResolve = methodResolve;
|
|
1053
|
+
exports.openApiGenerator = openApiGenerator;
|
|
1054
|
+
exports.setOpenApiConfig = setOpenApiConfig;
|