@nestia/core 2.5.8-dev.20240216 → 2.5.9-dev.20240223

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.
Files changed (45) hide show
  1. package/README.md +9 -6
  2. package/lib/decorators/SwaggerCustomizer.d.ts +16 -0
  3. package/lib/decorators/SwaggerCustomizer.js +11 -0
  4. package/lib/decorators/SwaggerCustomizer.js.map +1 -0
  5. package/lib/module.d.ts +1 -0
  6. package/lib/module.js +1 -0
  7. package/lib/module.js.map +1 -1
  8. package/lib/structures/ISwagger.d.ts +72 -0
  9. package/lib/structures/ISwagger.js +3 -0
  10. package/lib/structures/ISwagger.js.map +1 -0
  11. package/lib/structures/ISwaggerComponents.d.ts +26 -0
  12. package/lib/structures/ISwaggerComponents.js +3 -0
  13. package/lib/structures/ISwaggerComponents.js.map +1 -0
  14. package/lib/structures/ISwaggerInfo.d.ts +71 -0
  15. package/lib/structures/ISwaggerInfo.js +3 -0
  16. package/lib/structures/ISwaggerInfo.js.map +1 -0
  17. package/lib/structures/ISwaggerRoute.d.ts +46 -0
  18. package/lib/structures/ISwaggerRoute.js +3 -0
  19. package/lib/structures/ISwaggerRoute.js.map +1 -0
  20. package/lib/structures/ISwaggerSecurityScheme.d.ts +56 -0
  21. package/lib/structures/ISwaggerSecurityScheme.js +3 -0
  22. package/lib/structures/ISwaggerSecurityScheme.js.map +1 -0
  23. package/package.json +3 -3
  24. package/src/decorators/EncryptedBody.ts +105 -105
  25. package/src/decorators/EncryptedModule.ts +96 -96
  26. package/src/decorators/PlainBody.ts +75 -75
  27. package/src/decorators/SwaggerCustomizer.ts +33 -0
  28. package/src/decorators/TypedBody.ts +62 -62
  29. package/src/decorators/TypedException.ts +90 -90
  30. package/src/decorators/TypedRoute.ts +144 -144
  31. package/src/decorators/internal/get_path_and_querify.ts +106 -106
  32. package/src/decorators/internal/load_controller.ts +51 -51
  33. package/src/decorators/internal/validate_request_body.ts +72 -72
  34. package/src/decorators/internal/validate_request_headers.ts +83 -83
  35. package/src/decorators/internal/validate_request_query.ts +71 -71
  36. package/src/module.ts +1 -0
  37. package/src/structures/ISwagger.ts +91 -0
  38. package/src/structures/ISwaggerComponents.ts +29 -0
  39. package/src/structures/ISwaggerInfo.ts +80 -0
  40. package/src/structures/ISwaggerRoute.ts +50 -0
  41. package/src/structures/ISwaggerSecurityScheme.ts +65 -0
  42. package/src/transformers/NodeTransformer.ts +16 -16
  43. package/src/transformers/TypedExceptionTransformer.ts +48 -48
  44. package/src/transformers/TypedRouteTransformer.ts +88 -88
  45. package/src/utils/Singleton.ts +20 -20
package/README.md CHANGED
@@ -6,17 +6,19 @@
6
6
  [![Downloads](https://img.shields.io/npm/dm/@nestia/core.svg)](https://www.npmjs.com/package/@nestia/core)
7
7
  [![Build Status](https://github.com/samchon/nestia/workflows/build/badge.svg)](https://github.com/samchon/nestia/actions?query=workflow%3Abuild)
8
8
  [![Guide Documents](https://img.shields.io/badge/guide-documents-forestgreen)](https://nestia.io/docs/)
9
+ [![Discord Badge](https://img.shields.io/badge/discord-NestJS/Nestia-d91965?style=flat&labelColor=5866f2&logo=discord&logoColor=white&link=https://discord.com/channels/520622812742811698/1197293125434093701)](https://discord.com/channels/520622812742811698/1181877086797967420)
9
10
 
10
11
  Nestia is a set of helper libraries for NestJS, supporting below features:
11
12
 
12
- - `@nestia/core`: super-fast decorators
13
+ - `@nestia/core`: Super-fast decorators
13
14
  - `@nestia/sdk`:
14
15
  - Swagger generator evolved than ever
15
16
  - SDK library generator for clients
16
17
  - Mockup Simulator for client applications
17
18
  - Automatic E2E test functions generator
18
- - `@nestia/migrate`: migration from Swagger to NestJS
19
- - `nestia`: just CLI (command line interface) tool
19
+ - `@nestia/migrate`: Migration from Swagger to NestJS
20
+ - `@nestia/editor`: Online TypeScript Swagger Editor
21
+ - `nestia`: Just CLI (command line interface) tool
20
22
 
21
23
  > **Note**
22
24
  >
@@ -25,8 +27,8 @@ Nestia is a set of helper libraries for NestJS, supporting below features:
25
27
  > - Runtime validator is **20,000x faster** than `class-validator`
26
28
  > - JSON serialization is **200x faster** than `class-transformer`
27
29
  > - Software Development Kit
28
- > - SDK is a collection of `fetch` functions with type definitions like [tRPC](https://trpc.io/)
29
- > - Mockup simulator means embedded backend simulator in SDK
30
+ > - Collection of typed `fetch` functions with DTO structures like [tRPC](https://trpc.io/)
31
+ > - Mockup simulator means embedded backend simulator in the SDK
30
32
  > - similar with [msw](https://mswjs.io/), but fully automated
31
33
 
32
34
  ![nestia-sdk-demo](https://user-images.githubusercontent.com/13158709/215004990-368c589d-7101-404e-b81b-fbc936382f05.gif)
@@ -59,7 +61,7 @@ Check out the document in the [website](https://nestia.io/docs/):
59
61
  - [TypedRoute](https://nestia.io/docs/core/TypedRoute/)
60
62
  - [TypedBody](https://nestia.io/docs/core/TypedBody/)
61
63
  - [TypedParam](https://nestia.io/docs/core/TypedParam/)
62
- - [TypedQuery](https://nestia.io/docs/core/TypedRoute/)
64
+ - [TypedQuery](https://nestia.io/docs/core/TypedQuery/)
63
65
  - [TypedHeaders](https://nestia.io/docs/core/TypedHeaders/)
64
66
  - [TypedException](https://nestia.io/docs/core/TypedException/)
65
67
  - Generators
@@ -68,6 +70,7 @@ Check out the document in the [website](https://nestia.io/docs/):
68
70
  - [E2E Functions](https://nestia.io/docs/sdk/e2e/)
69
71
  - [Mockup Simulator](https://nestia.io/docs/sdk/simulator/)
70
72
  - [Swagger to NestJS](https://nestia.io/docs/migrate/)
73
+ - [TypeScript Swagger Editor](https://nestia.io/docs/editor/)
71
74
 
72
75
  ### 🔗 Appendix
73
76
  - [⇲ Benchmark Result](https://github.com/samchon/nestia/tree/master/benchmark/results/11th%20Gen%20Intel(R)%20Core(TM)%20i5-1135G7%20%40%202.40GHz)
@@ -0,0 +1,16 @@
1
+ import { ISwagger } from "../structures/ISwagger";
2
+ import { ISwaggerRoute } from "../structures/ISwaggerRoute";
3
+ export declare function SwaggerCustomizer(closure: (props: SwaggerCustomizer.IProps) => unknown): MethodDecorator;
4
+ export declare namespace SwaggerCustomizer {
5
+ interface IProps {
6
+ swagger: ISwagger;
7
+ method: string;
8
+ path: string;
9
+ route: ISwaggerRoute;
10
+ get(accessor: IAccessor): ISwaggerRoute | undefined;
11
+ }
12
+ interface IAccessor {
13
+ path: string;
14
+ method: string;
15
+ }
16
+ }
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SwaggerCustomizer = void 0;
4
+ function SwaggerCustomizer(closure) {
5
+ return function SwaggerCustomizer(target, propertyKey, descriptor) {
6
+ Reflect.defineMetadata("nestia/SwaggerCustomizer", closure, target, propertyKey);
7
+ return descriptor;
8
+ };
9
+ }
10
+ exports.SwaggerCustomizer = SwaggerCustomizer;
11
+ //# sourceMappingURL=SwaggerCustomizer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SwaggerCustomizer.js","sourceRoot":"","sources":["../../src/decorators/SwaggerCustomizer.ts"],"names":[],"mappings":";;;AAGA,SAAgB,iBAAiB,CAC/B,OAAqD;IAErD,OAAO,SAAS,iBAAiB,CAC/B,MAAc,EACd,WAA4B,EAC5B,UAAwC;QAExC,OAAO,CAAC,cAAc,CACpB,0BAA0B,EAC1B,OAAO,EACP,MAAM,EACN,WAAW,CACZ,CAAC;QACF,OAAO,UAAU,CAAC;IACpB,CAAC,CAAC;AACJ,CAAC;AAhBD,8CAgBC"}
package/lib/module.d.ts CHANGED
@@ -5,6 +5,7 @@ export * from "./decorators/EncryptedModule";
5
5
  export * from "./decorators/EncryptedRoute";
6
6
  export * from "./utils/ExceptionManager";
7
7
  export * from "./decorators/PlainBody";
8
+ export * from "./decorators/SwaggerCustomizer";
8
9
  export * from "./decorators/TypedBody";
9
10
  export * from "./decorators/TypedException";
10
11
  export * from "./decorators/TypedHeaders";
package/lib/module.js CHANGED
@@ -21,6 +21,7 @@ __exportStar(require("./decorators/EncryptedModule"), exports);
21
21
  __exportStar(require("./decorators/EncryptedRoute"), exports);
22
22
  __exportStar(require("./utils/ExceptionManager"), exports);
23
23
  __exportStar(require("./decorators/PlainBody"), exports);
24
+ __exportStar(require("./decorators/SwaggerCustomizer"), exports);
24
25
  __exportStar(require("./decorators/TypedBody"), exports);
25
26
  __exportStar(require("./decorators/TypedException"), exports);
26
27
  __exportStar(require("./decorators/TypedHeaders"), exports);
package/lib/module.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"module.js","sourceRoot":"","sources":["../src/module.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,6DAA2C;AAC3C,6DAA2C;AAC3C,mEAAiD;AACjD,+DAA6C;AAC7C,8DAA4C;AAC5C,2DAAyC;AACzC,yDAAuC;AACvC,yDAAuC;AACvC,8DAA4C;AAC5C,4DAA0C;AAC1C,6DAA2C;AAC3C,0DAAwC;AACxC,0DAAwC;AACxC,0DAAwC;AACxC,oEAAkD"}
1
+ {"version":3,"file":"module.js","sourceRoot":"","sources":["../src/module.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,6DAA2C;AAC3C,6DAA2C;AAC3C,mEAAiD;AACjD,+DAA6C;AAC7C,8DAA4C;AAC5C,2DAAyC;AACzC,yDAAuC;AACvC,iEAA+C;AAC/C,yDAAuC;AACvC,8DAA4C;AAC5C,4DAA0C;AAC1C,6DAA2C;AAC3C,0DAAwC;AACxC,0DAAwC;AACxC,0DAAwC;AACxC,oEAAkD"}
@@ -0,0 +1,72 @@
1
+ import { ISwaggerComponents } from "./ISwaggerComponents";
2
+ import { ISwaggerInfo } from "./ISwaggerInfo";
3
+ import { ISwaggerRoute } from "./ISwaggerRoute";
4
+ /**
5
+ * Swagger Document.
6
+ *
7
+ * `ISwagger` is a data structure representing content of `swagger.json` file
8
+ * generated by Nestia. Note that, this is not an universal structure, but a dedicated
9
+ * structure only for Nestia.
10
+ *
11
+ * @author Jeongho Nam - https://github.com/samchon
12
+ */
13
+ export interface ISwagger {
14
+ /**
15
+ * The version of the OpenAPI document.
16
+ *
17
+ * Nestia always generate OpenAPI 3.0.x document.
18
+ */
19
+ openapi: `3.0.${number}`;
20
+ /**
21
+ * List of servers that provide the API.
22
+ */
23
+ servers: ISwagger.IServer[];
24
+ /**
25
+ * Information about the API.
26
+ */
27
+ info: ISwaggerInfo;
28
+ /**
29
+ * The available paths and operations for the API.
30
+ *
31
+ * The 1st key is the path, and the 2nd key is the HTTP method.
32
+ */
33
+ paths: Record<string, Record<string, ISwaggerRoute>>;
34
+ /**
35
+ * An object to hold reusable data structures.
36
+ *
37
+ * It stores both DTO schemas and security schemes.
38
+ *
39
+ * For reference, `nestia` defines every object and alias types as reusable DTO
40
+ * schemas. The alias type means that defined by `type` keyword in TypeScript.
41
+ */
42
+ components: ISwaggerComponents;
43
+ }
44
+ export declare namespace ISwagger {
45
+ /**
46
+ * Remote server definition.
47
+ */
48
+ interface IServer {
49
+ /**
50
+ * A URL to the target host.
51
+ *
52
+ * @format uri
53
+ */
54
+ url: string;
55
+ /**
56
+ * An optional string describing the target server.
57
+ */
58
+ description?: string;
59
+ }
60
+ interface IExternalDocs {
61
+ /**
62
+ * The URL for target documentation.
63
+ *
64
+ * @format uri
65
+ */
66
+ url: string;
67
+ /**
68
+ * A short description of the target documentation.
69
+ */
70
+ description?: string;
71
+ }
72
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=ISwagger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ISwagger.js","sourceRoot":"","sources":["../../src/structures/ISwagger.ts"],"names":[],"mappings":""}
@@ -0,0 +1,26 @@
1
+ import { IJsonComponents } from "typia";
2
+ import { ISwaggerSecurityScheme } from "./ISwaggerSecurityScheme";
3
+ /**
4
+ * Reusable components in Swagger.
5
+ *
6
+ * `ISwaggerComponents` is a data structure representing content of `components` object
7
+ * in `swagger.json` file generated by Nestia. Note that, this is not an universal
8
+ * structure, but a dedicated structure only for Nestia.
9
+ *
10
+ * @author Jeongho Nam - https://github.com/samchon
11
+ */
12
+ export interface ISwaggerComponents {
13
+ /**
14
+ * An object to hold reusable DTO schemas.
15
+ *
16
+ * For reference, `nestia` stores every object and alias types as reusable DTO
17
+ * schemas. The alias type means that defined by `type` keyword in TypeScript.
18
+ */
19
+ schemas?: Record<string, IJsonComponents.IAlias>;
20
+ /**
21
+ * An object to hold reusable security schemes.
22
+ *
23
+ * This property be configured by user in `nestia.config.ts` file.
24
+ */
25
+ securitySchemes?: Record<string, ISwaggerSecurityScheme>;
26
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=ISwaggerComponents.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ISwaggerComponents.js","sourceRoot":"","sources":["../../src/structures/ISwaggerComponents.ts"],"names":[],"mappings":""}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Information about the API.
3
+ *
4
+ * @author Samchon
5
+ */
6
+ export interface ISwaggerInfo {
7
+ /**
8
+ * The title of the API.
9
+ */
10
+ title: string;
11
+ /**
12
+ * A short description of the API.
13
+ */
14
+ description?: string;
15
+ /**
16
+ * A URL to the Terms of Service for the API.
17
+ *
18
+ * @format uri
19
+ */
20
+ termsOfService?: string;
21
+ /**
22
+ * The contact information for the exposed API.
23
+ */
24
+ contact?: ISwaggerInfo.IContact;
25
+ /**
26
+ * The license information for the exposed API.
27
+ */
28
+ license?: ISwaggerInfo.ILicense;
29
+ /**
30
+ * Version of the API.
31
+ */
32
+ version: string;
33
+ }
34
+ export declare namespace ISwaggerInfo {
35
+ /**
36
+ * Contact information for the exposed API.
37
+ */
38
+ interface IContact {
39
+ /**
40
+ * The identifying name of the contact person/organization.
41
+ */
42
+ name?: string;
43
+ /**
44
+ * The URL pointing to the contact information.
45
+ *
46
+ * @format uri
47
+ */
48
+ url?: string;
49
+ /**
50
+ * The email address of the contact person/organization.
51
+ *
52
+ * @format email
53
+ */
54
+ email?: string;
55
+ }
56
+ /**
57
+ * License information for the exposed API.
58
+ */
59
+ interface ILicense {
60
+ /**
61
+ * The license name used for the API.
62
+ */
63
+ name: string;
64
+ /**
65
+ * A URL to the license used for the API.
66
+ *
67
+ * @format uri
68
+ */
69
+ url?: string;
70
+ }
71
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=ISwaggerInfo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ISwaggerInfo.js","sourceRoot":"","sources":["../../src/structures/ISwaggerInfo.ts"],"names":[],"mappings":""}
@@ -0,0 +1,46 @@
1
+ import { IJsonSchema } from "typia";
2
+ export interface ISwaggerRoute {
3
+ deprecated?: boolean;
4
+ security?: Record<string, string[]>[];
5
+ operationId?: string;
6
+ tags: string[];
7
+ parameters: ISwaggerRoute.IParameter[];
8
+ requestBody?: ISwaggerRoute.IRequestBody;
9
+ responses: ISwaggerRoute.IResponseBody;
10
+ summary?: string;
11
+ description?: string;
12
+ }
13
+ export declare namespace ISwaggerRoute {
14
+ interface IParameter {
15
+ name: string;
16
+ in: string;
17
+ schema: IJsonSchema;
18
+ required: boolean;
19
+ description?: string;
20
+ }
21
+ interface IRequestBody {
22
+ description?: string;
23
+ content: IContent;
24
+ required: true;
25
+ "x-nestia-encrypted"?: boolean;
26
+ }
27
+ type IResponseBody = Record<string, {
28
+ description: string;
29
+ content?: IContent;
30
+ "x-nestia-encrypted"?: boolean;
31
+ }>;
32
+ interface IContent {
33
+ "application/x-www-form-urlencoded"?: {
34
+ schema: IJsonSchema;
35
+ };
36
+ "application/json"?: {
37
+ schema: IJsonSchema;
38
+ };
39
+ "text/plain"?: {
40
+ schema: IJsonSchema;
41
+ };
42
+ "multipart/form-data"?: {
43
+ schema: IJsonSchema;
44
+ };
45
+ }
46
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=ISwaggerRoute.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ISwaggerRoute.js","sourceRoot":"","sources":["../../src/structures/ISwaggerRoute.ts"],"names":[],"mappings":""}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Security scheme of Swagger Documents.
3
+ *
4
+ * `ISwaggerSecurityScheme` is a data structure representing content of
5
+ * `securitySchemes` in `swagger.json` file. It is composed with 5 types of security
6
+ * schemes as an union type like below.
7
+ *
8
+ * @reference https://swagger.io/specification/#security-scheme-object
9
+ * @author Jeongho Nam - https://github.com/samchon
10
+ */
11
+ export type ISwaggerSecurityScheme = ISwaggerSecurityScheme.IHttpBasic | ISwaggerSecurityScheme.IHttpBearer | ISwaggerSecurityScheme.IApiKey | ISwaggerSecurityScheme.IOpenId | ISwaggerSecurityScheme.IOAuth2;
12
+ export declare namespace ISwaggerSecurityScheme {
13
+ interface IHttpBasic {
14
+ type: "http";
15
+ scheme: "basic";
16
+ }
17
+ interface IHttpBearer {
18
+ type: "http";
19
+ scheme: "bearer";
20
+ bearerFormat?: string;
21
+ }
22
+ interface IApiKey {
23
+ type: "apiKey";
24
+ /**
25
+ * @default header
26
+ */
27
+ in?: "header" | "query" | "cookie";
28
+ /**
29
+ * @default Authorization
30
+ */
31
+ name?: string;
32
+ }
33
+ interface IOpenId {
34
+ type: "openIdConnect";
35
+ openIdConnectUrl: string;
36
+ }
37
+ interface IOAuth2 {
38
+ type: "oauth2";
39
+ flows: IOAuth2.IFlowSet;
40
+ description?: string;
41
+ }
42
+ namespace IOAuth2 {
43
+ interface IFlowSet {
44
+ authorizationCode?: IFlow;
45
+ implicit?: Omit<IFlow, "tokenUrl">;
46
+ password?: Omit<IFlow, "authorizationUrl">;
47
+ clientCredentials?: Omit<IFlow, "authorizationUrl">;
48
+ }
49
+ interface IFlow {
50
+ authorizationUrl: string;
51
+ tokenUrl: string;
52
+ refreshUrl: string;
53
+ scopes?: Record<string, string>;
54
+ }
55
+ }
56
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=ISwaggerSecurityScheme.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ISwaggerSecurityScheme.js","sourceRoot":"","sources":["../../src/structures/ISwaggerSecurityScheme.ts"],"names":[],"mappings":""}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nestia/core",
3
- "version": "2.5.8-dev.20240216",
3
+ "version": "2.5.9-dev.20240223",
4
4
  "description": "Super-fast validation decorators of NestJS",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
@@ -36,7 +36,7 @@
36
36
  },
37
37
  "homepage": "https://nestia.io",
38
38
  "dependencies": {
39
- "@nestia/fetcher": "^2.5.8-dev.20240216",
39
+ "@nestia/fetcher": "^2.5.9-dev.20240223",
40
40
  "@nestjs/common": ">=7.0.1",
41
41
  "@nestjs/core": ">=7.0.1",
42
42
  "detect-ts-node": "^1.0.5",
@@ -48,7 +48,7 @@
48
48
  "typia": "^5.4.5"
49
49
  },
50
50
  "peerDependencies": {
51
- "@nestia/fetcher": ">=2.5.8-dev.20240216",
51
+ "@nestia/fetcher": ">=2.5.9-dev.20240223",
52
52
  "@nestjs/common": ">=7.0.1",
53
53
  "@nestjs/core": ">=7.0.1",
54
54
  "reflect-metadata": ">=0.1.12",
@@ -1,105 +1,105 @@
1
- import { AesPkcs5 } from "@nestia/fetcher/lib/AesPkcs5";
2
- import { IEncryptionPassword } from "@nestia/fetcher/lib/IEncryptionPassword";
3
- import {
4
- BadRequestException,
5
- ExecutionContext,
6
- createParamDecorator,
7
- } from "@nestjs/common";
8
- import type express from "express";
9
- import type { FastifyRequest } from "fastify";
10
- import { assert, is, validate } from "typia";
11
-
12
- import { IRequestBodyValidator } from "../options/IRequestBodyValidator";
13
- import { Singleton } from "../utils/Singleton";
14
- import { ENCRYPTION_METADATA_KEY } from "./internal/EncryptedConstant";
15
- import { get_text_body } from "./internal/get_text_body";
16
- import { headers_to_object } from "./internal/headers_to_object";
17
- import { validate_request_body } from "./internal/validate_request_body";
18
-
19
- /**
20
- * Encrypted body decorator.
21
- *
22
- * `EncryptedBody` is a decorator function getting `application/json` typed data from
23
- * requeset body which has been encrypted by AES-128/256 algorithm. Also,
24
- * `EncyrptedBody` validates the request body data type through
25
- * [typia](https://github.com/samchon/typia) ad the validation speed is
26
- * maximum 15,000x times faster than `class-validator`.
27
- *
28
- * For reference, when the request body data is not following the promised type `T`,
29
- * `BadRequestException` error (status code: 400) would be thrown. Also,
30
- * `EncryptedRoute` decrypts request body using those options.
31
- *
32
- * - AES-128/256
33
- * - CBC mode
34
- * - PKCS #5 Padding
35
- * - Base64 Encoding
36
- *
37
- * @return Parameter decorator
38
- * @author Jeongho Nam - https://github.com/samchon
39
- */
40
- export function EncryptedBody<T>(
41
- validator?: IRequestBodyValidator<T>,
42
- ): ParameterDecorator {
43
- const checker = validate_request_body("EncryptedBody")(validator);
44
- return createParamDecorator(async function EncryptedBody(
45
- _unknown: any,
46
- context: ExecutionContext,
47
- ) {
48
- const request: express.Request | FastifyRequest = context
49
- .switchToHttp()
50
- .getRequest();
51
- if (isTextPlain(request.headers["content-type"]) === false)
52
- throw new BadRequestException(`Request body type is not "text/plain".`);
53
-
54
- const param: IEncryptionPassword | IEncryptionPassword.Closure | undefined =
55
- Reflect.getMetadata(ENCRYPTION_METADATA_KEY, context.getClass());
56
- if (!param)
57
- throw new Error(
58
- "Error on nestia.core.EncryptedBody(): no encryption password is given.",
59
- );
60
-
61
- // GET BODY DATA
62
- const headers: Singleton<Record<string, string>> = new Singleton(() =>
63
- headers_to_object(request.headers),
64
- );
65
- const body: string = await get_text_body(request);
66
- const password: IEncryptionPassword =
67
- typeof param === "function"
68
- ? param({ headers: headers.get(), body, direction: "decode" })
69
- : param;
70
-
71
- // PARSE AND VALIDATE DATA
72
- const data: any = JSON.parse(decrypt(body, password.key, password.iv));
73
- const error: Error | null = checker(data);
74
- if (error !== null) throw error;
75
- return data;
76
- })();
77
- }
78
- Object.assign(EncryptedBody, is);
79
- Object.assign(EncryptedBody, assert);
80
- Object.assign(EncryptedBody, validate);
81
-
82
- /**
83
- * @internal
84
- */
85
- const decrypt = (body: string, key: string, iv: string): string => {
86
- try {
87
- return AesPkcs5.decrypt(body, key, iv);
88
- } catch (exp) {
89
- if (exp instanceof Error)
90
- throw new BadRequestException(
91
- "Failed to decrypt the request body. Check your body content or encryption password.",
92
- );
93
- else throw exp;
94
- }
95
- };
96
-
97
- /**
98
- * @internal
99
- */
100
- const isTextPlain = (text?: string): boolean =>
101
- text !== undefined &&
102
- text
103
- .split(";")
104
- .map((str) => str.trim())
105
- .some((str) => str === "text/plain");
1
+ import { AesPkcs5 } from "@nestia/fetcher/lib/AesPkcs5";
2
+ import { IEncryptionPassword } from "@nestia/fetcher/lib/IEncryptionPassword";
3
+ import {
4
+ BadRequestException,
5
+ ExecutionContext,
6
+ createParamDecorator,
7
+ } from "@nestjs/common";
8
+ import type express from "express";
9
+ import type { FastifyRequest } from "fastify";
10
+ import { assert, is, validate } from "typia";
11
+
12
+ import { IRequestBodyValidator } from "../options/IRequestBodyValidator";
13
+ import { Singleton } from "../utils/Singleton";
14
+ import { ENCRYPTION_METADATA_KEY } from "./internal/EncryptedConstant";
15
+ import { get_text_body } from "./internal/get_text_body";
16
+ import { headers_to_object } from "./internal/headers_to_object";
17
+ import { validate_request_body } from "./internal/validate_request_body";
18
+
19
+ /**
20
+ * Encrypted body decorator.
21
+ *
22
+ * `EncryptedBody` is a decorator function getting `application/json` typed data from
23
+ * requeset body which has been encrypted by AES-128/256 algorithm. Also,
24
+ * `EncyrptedBody` validates the request body data type through
25
+ * [typia](https://github.com/samchon/typia) ad the validation speed is
26
+ * maximum 15,000x times faster than `class-validator`.
27
+ *
28
+ * For reference, when the request body data is not following the promised type `T`,
29
+ * `BadRequestException` error (status code: 400) would be thrown. Also,
30
+ * `EncryptedRoute` decrypts request body using those options.
31
+ *
32
+ * - AES-128/256
33
+ * - CBC mode
34
+ * - PKCS #5 Padding
35
+ * - Base64 Encoding
36
+ *
37
+ * @return Parameter decorator
38
+ * @author Jeongho Nam - https://github.com/samchon
39
+ */
40
+ export function EncryptedBody<T>(
41
+ validator?: IRequestBodyValidator<T>,
42
+ ): ParameterDecorator {
43
+ const checker = validate_request_body("EncryptedBody")(validator);
44
+ return createParamDecorator(async function EncryptedBody(
45
+ _unknown: any,
46
+ context: ExecutionContext,
47
+ ) {
48
+ const request: express.Request | FastifyRequest = context
49
+ .switchToHttp()
50
+ .getRequest();
51
+ if (isTextPlain(request.headers["content-type"]) === false)
52
+ throw new BadRequestException(`Request body type is not "text/plain".`);
53
+
54
+ const param: IEncryptionPassword | IEncryptionPassword.Closure | undefined =
55
+ Reflect.getMetadata(ENCRYPTION_METADATA_KEY, context.getClass());
56
+ if (!param)
57
+ throw new Error(
58
+ "Error on nestia.core.EncryptedBody(): no encryption password is given.",
59
+ );
60
+
61
+ // GET BODY DATA
62
+ const headers: Singleton<Record<string, string>> = new Singleton(() =>
63
+ headers_to_object(request.headers),
64
+ );
65
+ const body: string = await get_text_body(request);
66
+ const password: IEncryptionPassword =
67
+ typeof param === "function"
68
+ ? param({ headers: headers.get(), body, direction: "decode" })
69
+ : param;
70
+
71
+ // PARSE AND VALIDATE DATA
72
+ const data: any = JSON.parse(decrypt(body, password.key, password.iv));
73
+ const error: Error | null = checker(data);
74
+ if (error !== null) throw error;
75
+ return data;
76
+ })();
77
+ }
78
+ Object.assign(EncryptedBody, is);
79
+ Object.assign(EncryptedBody, assert);
80
+ Object.assign(EncryptedBody, validate);
81
+
82
+ /**
83
+ * @internal
84
+ */
85
+ const decrypt = (body: string, key: string, iv: string): string => {
86
+ try {
87
+ return AesPkcs5.decrypt(body, key, iv);
88
+ } catch (exp) {
89
+ if (exp instanceof Error)
90
+ throw new BadRequestException(
91
+ "Failed to decrypt the request body. Check your body content or encryption password.",
92
+ );
93
+ else throw exp;
94
+ }
95
+ };
96
+
97
+ /**
98
+ * @internal
99
+ */
100
+ const isTextPlain = (text?: string): boolean =>
101
+ text !== undefined &&
102
+ text
103
+ .split(";")
104
+ .map((str) => str.trim())
105
+ .some((str) => str === "text/plain");