@tahminator/sapling 2.0.3 → 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 +94 -4
- package/dist/index.cjs +383 -142
- package/dist/index.d.cts +503 -13
- package/dist/index.d.mts +503 -13
- package/dist/index.mjs +365 -143
- 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.
|
|
@@ -262,9 +264,13 @@ var ParserError = class ParserError extends ResponseStatusError {
|
|
|
262
264
|
};
|
|
263
265
|
//#endregion
|
|
264
266
|
//#region src/helper/sapling.ts
|
|
265
|
-
const
|
|
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
|
|
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
|
-
|
|
358
|
+
_settings.serialize = fn;
|
|
353
359
|
}
|
|
354
360
|
/**
|
|
355
361
|
* De-serialize a JSON string back to a JavaScript object.
|
|
@@ -361,16 +367,321 @@ var Sapling = class Sapling {
|
|
|
361
367
|
* @defaultValue `JSON.parse`
|
|
362
368
|
*/
|
|
363
369
|
static deserialize(value) {
|
|
364
|
-
return
|
|
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
|
-
|
|
376
|
+
_settings.deserialize = fn;
|
|
377
|
+
}
|
|
378
|
+
static setOpenApiPath(path) {
|
|
379
|
+
_settings.doc.openApiPath = path;
|
|
380
|
+
}
|
|
381
|
+
static setSwaggerPath(path) {
|
|
382
|
+
_settings.doc.swaggerPath = path;
|
|
371
383
|
}
|
|
372
384
|
};
|
|
373
385
|
//#endregion
|
|
386
|
+
//#region src/annotation/request.ts
|
|
387
|
+
const _requestSchemaStore = /* @__PURE__ */ new WeakMap();
|
|
388
|
+
/**
|
|
389
|
+
* Apply to a route method to have `request.body` be parsed by `schema`.
|
|
390
|
+
*
|
|
391
|
+
* This annotation will parse `request.body` & then override `request.body`.
|
|
392
|
+
* You can then just simply cast `request.body` for your use
|
|
393
|
+
*
|
|
394
|
+
* @example
|
|
395
|
+
* ```ts
|
|
396
|
+
* const CREATE_BOOK_REQUEST_BODY_SCHEMA = z.object({
|
|
397
|
+
* name: z.string(),
|
|
398
|
+
* description: z.string().optional(),
|
|
399
|
+
* });
|
|
400
|
+
*
|
|
401
|
+
* ⠀@Controller({ prefix: "/api/book" })
|
|
402
|
+
* class BookController {
|
|
403
|
+
* ⠀@RequestBody(CREATE_BOOK_REQUEST_BODY_SCHEMA)
|
|
404
|
+
* ⠀@POST()
|
|
405
|
+
* public createBook(request: e.Request) {
|
|
406
|
+
* const { name, description } = request.body as unknown as z.infer<
|
|
407
|
+
* typeof CREATE_BOOK_REQUEST_BODY_SCHEMA
|
|
408
|
+
* >;
|
|
409
|
+
* }
|
|
410
|
+
* }
|
|
411
|
+
* ```
|
|
412
|
+
*/
|
|
413
|
+
function RequestBody(schema) {
|
|
414
|
+
return (target, propertyKey) => {
|
|
415
|
+
const ctor = target.constructor;
|
|
416
|
+
const fnName = String(propertyKey);
|
|
417
|
+
_setOnce(_getOrCreateRequestSchemaDefinition(ctor, fnName), "body", schema, fnName);
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
/**
|
|
421
|
+
* Apply to a route method to have `request.param` be parsed by `schema`.
|
|
422
|
+
*
|
|
423
|
+
* This annotation will parse `request.param` & then override `request.param`.
|
|
424
|
+
* You can then just simply cast `request.param` for your use
|
|
425
|
+
*
|
|
426
|
+
* @example
|
|
427
|
+
* ```ts
|
|
428
|
+
* const GET_BOOK_REQUEST_PARAM_SCHEMA = z.object({
|
|
429
|
+
* bookId: z.string(),
|
|
430
|
+
* });
|
|
431
|
+
*
|
|
432
|
+
* ⠀@Controller({ prefix: "/api/book" })
|
|
433
|
+
* class BookController {
|
|
434
|
+
* ⠀@RequestParam(GET_BOOK_REQUEST_PARAM_SCHEMA)
|
|
435
|
+
* ⠀@GET("/:bookId")
|
|
436
|
+
* public getBook(request: e.Request) {
|
|
437
|
+
* const { bookId } = request.param as unknown as z.infer<
|
|
438
|
+
* typeof GET_BOOK_REQUEST_PARAM_SCHEMA
|
|
439
|
+
* >;
|
|
440
|
+
* }
|
|
441
|
+
* }
|
|
442
|
+
* ```
|
|
443
|
+
*/
|
|
444
|
+
function RequestParam(schema) {
|
|
445
|
+
return (target, propertyKey) => {
|
|
446
|
+
const ctor = target.constructor;
|
|
447
|
+
const fnName = String(propertyKey);
|
|
448
|
+
_setOnce(_getOrCreateRequestSchemaDefinition(ctor, fnName), "param", schema, fnName);
|
|
449
|
+
};
|
|
450
|
+
}
|
|
451
|
+
/**
|
|
452
|
+
* Apply to a route method to have `request.query` be parsed by `schema`.
|
|
453
|
+
*
|
|
454
|
+
* This annotation will parse `request.query` & then override `request.query`.
|
|
455
|
+
* You can then just simply cast `request.query` for your use
|
|
456
|
+
*
|
|
457
|
+
* @example
|
|
458
|
+
* ```ts
|
|
459
|
+
* const LIST_BOOKS_REQUEST_QUERY_SCHEMA = z.object({
|
|
460
|
+
* sort: z.enum(["name", "createdAt"]).optional(),
|
|
461
|
+
* q: z.string().optional(),
|
|
462
|
+
* });
|
|
463
|
+
*
|
|
464
|
+
* ⠀@Controller({ prefix: "/api/book" })
|
|
465
|
+
* class BookController {
|
|
466
|
+
* ⠀@RequestQuery(LIST_BOOKS_REQUEST_QUERY_SCHEMA)
|
|
467
|
+
* ⠀@GET()
|
|
468
|
+
* public listBooks(request: e.Request) {
|
|
469
|
+
* const { sort, q } = request.query as unknown as z.infer<
|
|
470
|
+
* typeof LIST_BOOKS_REQUEST_QUERY_SCHEMA
|
|
471
|
+
* >;
|
|
472
|
+
* }
|
|
473
|
+
* }
|
|
474
|
+
* ```
|
|
475
|
+
*/
|
|
476
|
+
function RequestQuery(schema) {
|
|
477
|
+
return (target, propertyKey) => {
|
|
478
|
+
const ctor = target.constructor;
|
|
479
|
+
const fnName = String(propertyKey);
|
|
480
|
+
_setOnce(_getOrCreateRequestSchemaDefinition(ctor, fnName), "query", schema, fnName);
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
function _getOrCreateRequestSchemaDefinition(ctor, fnName) {
|
|
484
|
+
const byFn = (() => {
|
|
485
|
+
const fn = _requestSchemaStore.get(ctor);
|
|
486
|
+
if (fn) return fn;
|
|
487
|
+
const newFn = /* @__PURE__ */ new Map();
|
|
488
|
+
_requestSchemaStore.set(ctor, newFn);
|
|
489
|
+
return newFn;
|
|
490
|
+
})();
|
|
491
|
+
const existing = byFn.get(fnName);
|
|
492
|
+
if (existing) return existing;
|
|
493
|
+
const created = {};
|
|
494
|
+
byFn.set(fnName, created);
|
|
495
|
+
return created;
|
|
496
|
+
}
|
|
497
|
+
function _setOnce(def, key, schema, fnName) {
|
|
498
|
+
if (def[key]) throw new Error(`Duplicate request schema for "${String(key)}" on method "${fnName}"`);
|
|
499
|
+
def[key] = schema;
|
|
500
|
+
}
|
|
501
|
+
function _getRequestSchemas(ctor, fnName) {
|
|
502
|
+
return _requestSchemaStore.get(ctor)?.get(fnName);
|
|
503
|
+
}
|
|
504
|
+
async function _parseOrThrow(schema, input, kind) {
|
|
505
|
+
const result = await schema["~standard"].validate(input);
|
|
506
|
+
if (result.issues) {
|
|
507
|
+
console.debug(`Failed to parse a schema`);
|
|
508
|
+
throw new ParserError(kind, result.issues, schema["~standard"].vendor);
|
|
509
|
+
}
|
|
510
|
+
return result.value;
|
|
511
|
+
}
|
|
512
|
+
//#endregion
|
|
513
|
+
//#region src/annotation/route.ts
|
|
514
|
+
const _routeStore = /* @__PURE__ */ new WeakMap();
|
|
515
|
+
/**
|
|
516
|
+
* Custom annotation that will store all routes inside of a map,
|
|
517
|
+
* which can then be used to initialize all the routes to the router.
|
|
518
|
+
*/
|
|
519
|
+
function _Route({ method, path = "" }) {
|
|
520
|
+
return (target, propertyKey) => {
|
|
521
|
+
const ctor = target.constructor;
|
|
522
|
+
const list = _routeStore.get(ctor) ?? [];
|
|
523
|
+
list.push({
|
|
524
|
+
method,
|
|
525
|
+
path: path ?? "",
|
|
526
|
+
fnName: String(propertyKey)
|
|
527
|
+
});
|
|
528
|
+
_routeStore.set(ctor, list);
|
|
529
|
+
};
|
|
530
|
+
}
|
|
531
|
+
/**
|
|
532
|
+
* Register GET route on the given path (default "") for the given controller.
|
|
533
|
+
*/
|
|
534
|
+
const GET = (path = "") => _Route({
|
|
535
|
+
method: "GET",
|
|
536
|
+
path
|
|
537
|
+
});
|
|
538
|
+
/**
|
|
539
|
+
* Register POST route on the given path (default "") for the given controller.
|
|
540
|
+
*/
|
|
541
|
+
const POST = (path = "") => _Route({
|
|
542
|
+
method: "POST",
|
|
543
|
+
path
|
|
544
|
+
});
|
|
545
|
+
/**
|
|
546
|
+
* Register PUT route on the given path (default "") for the given controller.
|
|
547
|
+
*/
|
|
548
|
+
const PUT = (path = "") => _Route({
|
|
549
|
+
method: "PUT",
|
|
550
|
+
path
|
|
551
|
+
});
|
|
552
|
+
/**
|
|
553
|
+
* Register DELETE route on the given path (default "") for the given controller.
|
|
554
|
+
*/
|
|
555
|
+
const DELETE = (path = "") => _Route({
|
|
556
|
+
method: "DELETE",
|
|
557
|
+
path
|
|
558
|
+
});
|
|
559
|
+
/**
|
|
560
|
+
* Register OPTIONS route on the given path (default "") for the given controller.
|
|
561
|
+
*/
|
|
562
|
+
const OPTIONS = (path = "") => _Route({
|
|
563
|
+
method: "OPTIONS",
|
|
564
|
+
path
|
|
565
|
+
});
|
|
566
|
+
/**
|
|
567
|
+
* Register PATCH route on the given path (default "") for the given controller.
|
|
568
|
+
*/
|
|
569
|
+
const PATCH = (path = "") => _Route({
|
|
570
|
+
method: "PATCH",
|
|
571
|
+
path
|
|
572
|
+
});
|
|
573
|
+
/**
|
|
574
|
+
* Register HEAD route on the given path (default "") for the given controller.
|
|
575
|
+
*/
|
|
576
|
+
const HEAD = (path = "") => _Route({
|
|
577
|
+
method: "HEAD",
|
|
578
|
+
path
|
|
579
|
+
});
|
|
580
|
+
/**
|
|
581
|
+
* Register a middleware route on the given path (default "") for the given controller.
|
|
582
|
+
*/
|
|
583
|
+
const Middleware = (path = "") => _Route({
|
|
584
|
+
method: "USE",
|
|
585
|
+
path
|
|
586
|
+
});
|
|
587
|
+
/**
|
|
588
|
+
* Given a class constructor, fetch all the routes attached.
|
|
589
|
+
*/
|
|
590
|
+
function _getRoutes(ctor) {
|
|
591
|
+
return _routeStore.get(ctor) ?? [];
|
|
592
|
+
}
|
|
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
|
|
374
685
|
//#region src/types.ts
|
|
375
686
|
const methodResolve = {
|
|
376
687
|
GET: "get",
|
|
@@ -503,140 +814,6 @@ function _resolve(ctor) {
|
|
|
503
814
|
return _InjectableRegistry.get(ctor);
|
|
504
815
|
}
|
|
505
816
|
//#endregion
|
|
506
|
-
//#region src/annotation/request.ts
|
|
507
|
-
const _requestSchemaStore = /* @__PURE__ */ new WeakMap();
|
|
508
|
-
function _getOrCreateRequestSchemaDefinition(ctor, fnName) {
|
|
509
|
-
const byFn = (() => {
|
|
510
|
-
const fn = _requestSchemaStore.get(ctor);
|
|
511
|
-
if (fn) return fn;
|
|
512
|
-
const newFn = /* @__PURE__ */ new Map();
|
|
513
|
-
_requestSchemaStore.set(ctor, newFn);
|
|
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;
|
|
525
|
-
}
|
|
526
|
-
function RequestBody(schema) {
|
|
527
|
-
return (target, propertyKey) => {
|
|
528
|
-
const ctor = target.constructor;
|
|
529
|
-
const fnName = String(propertyKey);
|
|
530
|
-
_setOnce(_getOrCreateRequestSchemaDefinition(ctor, fnName), "body", schema, fnName);
|
|
531
|
-
};
|
|
532
|
-
}
|
|
533
|
-
function RequestParam(schema) {
|
|
534
|
-
return (target, propertyKey) => {
|
|
535
|
-
const ctor = target.constructor;
|
|
536
|
-
const fnName = String(propertyKey);
|
|
537
|
-
_setOnce(_getOrCreateRequestSchemaDefinition(ctor, fnName), "param", schema, fnName);
|
|
538
|
-
};
|
|
539
|
-
}
|
|
540
|
-
function RequestQuery(schema) {
|
|
541
|
-
return (target, propertyKey) => {
|
|
542
|
-
const ctor = target.constructor;
|
|
543
|
-
const fnName = String(propertyKey);
|
|
544
|
-
_setOnce(_getOrCreateRequestSchemaDefinition(ctor, fnName), "query", schema, fnName);
|
|
545
|
-
};
|
|
546
|
-
}
|
|
547
|
-
function _getRequestSchemas(ctor, fnName) {
|
|
548
|
-
return _requestSchemaStore.get(ctor)?.get(fnName);
|
|
549
|
-
}
|
|
550
|
-
async function _parseOrThrow(schema, input, kind) {
|
|
551
|
-
const result = await schema["~standard"].validate(input);
|
|
552
|
-
if (result.issues) {
|
|
553
|
-
console.debug(`Failed to parse a schema`);
|
|
554
|
-
throw new ParserError(kind, result.issues, schema["~standard"].vendor);
|
|
555
|
-
}
|
|
556
|
-
return result.value;
|
|
557
|
-
}
|
|
558
|
-
//#endregion
|
|
559
|
-
//#region src/annotation/route.ts
|
|
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
|
-
};
|
|
576
|
-
}
|
|
577
|
-
/**
|
|
578
|
-
* Register GET route on the given path (default "") for the given controller.
|
|
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) ?? [];
|
|
638
|
-
}
|
|
639
|
-
//#endregion
|
|
640
817
|
//#region src/annotation/controller.ts
|
|
641
818
|
const _ControllerRegistry = /* @__PURE__ */ new WeakMap();
|
|
642
819
|
/**
|
|
@@ -648,6 +825,7 @@ const _ControllerRegistry = /* @__PURE__ */ new WeakMap();
|
|
|
648
825
|
function Controller({ prefix = "", deps = [] } = {}) {
|
|
649
826
|
return (target) => {
|
|
650
827
|
const targetClass = target;
|
|
828
|
+
_registerControllerClass(target, prefix);
|
|
651
829
|
const router = (0, express.Router)();
|
|
652
830
|
const routes = _getRoutes(target);
|
|
653
831
|
const usedRoutes = /* @__PURE__ */ new Set();
|
|
@@ -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,6 +947,41 @@ 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 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
|
|
762
985
|
exports.Controller = Controller;
|
|
763
986
|
exports.DELETE = DELETE;
|
|
764
987
|
Object.defineProperty(exports, "DefaultBaseErrorMiddleware", {
|
|
@@ -767,12 +990,25 @@ Object.defineProperty(exports, "DefaultBaseErrorMiddleware", {
|
|
|
767
990
|
return DefaultBaseErrorMiddleware;
|
|
768
991
|
}
|
|
769
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
|
+
});
|
|
770
1005
|
Object.defineProperty(exports, "DefaultResponseStatusErrorMiddleware", {
|
|
771
1006
|
enumerable: true,
|
|
772
1007
|
get: function() {
|
|
773
1008
|
return DefaultResponseStatusErrorMiddleware;
|
|
774
1009
|
}
|
|
775
1010
|
});
|
|
1011
|
+
exports.DefaultSwaggerMiddleware = DefaultSwaggerMiddleware;
|
|
776
1012
|
exports.GET = GET;
|
|
777
1013
|
exports.HEAD = HEAD;
|
|
778
1014
|
exports.Html404ErrorPage = Html404ErrorPage;
|
|
@@ -797,8 +1033,13 @@ exports._ControllerRegistry = _ControllerRegistry;
|
|
|
797
1033
|
exports._InjectableDeps = _InjectableDeps;
|
|
798
1034
|
exports._InjectableRegistry = _InjectableRegistry;
|
|
799
1035
|
exports._Route = _Route;
|
|
1036
|
+
exports._generateOpenApiSpec = _generateOpenApiSpec;
|
|
800
1037
|
exports._getRequestSchemas = _getRequestSchemas;
|
|
801
1038
|
exports._getRoutes = _getRoutes;
|
|
802
1039
|
exports._parseOrThrow = _parseOrThrow;
|
|
1040
|
+
exports._registerControllerClass = _registerControllerClass;
|
|
803
1041
|
exports._resolve = _resolve;
|
|
1042
|
+
exports._setOpenApiConfig = _setOpenApiConfig;
|
|
1043
|
+
exports._settings = _settings;
|
|
804
1044
|
exports.methodResolve = methodResolve;
|
|
1045
|
+
exports.openApiGenerator = openApiGenerator;
|