@nestia/core 14.0.0 → 14.0.2
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/MIGRATION.md +20 -0
- package/README.md +1 -1
- package/lib/adaptors/McpAdaptor.d.ts +29 -3
- package/lib/adaptors/McpAdaptor.js +150 -24
- package/lib/adaptors/McpAdaptor.js.map +1 -1
- package/lib/adaptors/WebSocketAdaptor.d.ts +37 -0
- package/lib/adaptors/WebSocketAdaptor.js +184 -48
- package/lib/adaptors/WebSocketAdaptor.js.map +1 -1
- package/lib/adaptors/internal/RoutePathMatcher.d.ts +1 -0
- package/lib/adaptors/internal/RoutePathMatcher.js +88 -0
- package/lib/adaptors/internal/RoutePathMatcher.js.map +1 -0
- package/lib/adaptors/internal/external_context.d.ts +1 -0
- package/lib/adaptors/internal/external_context.js +56 -0
- package/lib/adaptors/internal/external_context.js.map +1 -0
- package/lib/decorators/DynamicModule.d.ts +12 -0
- package/lib/decorators/DynamicModule.js +12 -0
- package/lib/decorators/DynamicModule.js.map +1 -1
- package/lib/decorators/EncryptedBody.d.ts +14 -6
- package/lib/decorators/EncryptedBody.js +39 -16
- package/lib/decorators/EncryptedBody.js.map +1 -1
- package/lib/decorators/EncryptedController.d.ts +6 -1
- package/lib/decorators/EncryptedController.js +7 -2
- package/lib/decorators/EncryptedController.js.map +1 -1
- package/lib/decorators/EncryptedModule.d.ts +25 -6
- package/lib/decorators/EncryptedModule.js +87 -18
- package/lib/decorators/EncryptedModule.js.map +1 -1
- package/lib/decorators/EncryptedRoute.d.ts +20 -11
- package/lib/decorators/EncryptedRoute.js +27 -13
- package/lib/decorators/EncryptedRoute.js.map +1 -1
- package/lib/decorators/HumanRoute.d.ts +5 -0
- package/lib/decorators/HumanRoute.js +5 -0
- package/lib/decorators/HumanRoute.js.map +1 -1
- package/lib/decorators/McpRoute.d.ts +31 -19
- package/lib/decorators/McpRoute.js +12 -1
- package/lib/decorators/McpRoute.js.map +1 -1
- package/lib/decorators/PlainBody.d.ts +7 -1
- package/lib/decorators/PlainBody.js +16 -8
- package/lib/decorators/PlainBody.js.map +1 -1
- package/lib/decorators/SwaggerCustomizer.d.ts +15 -0
- package/lib/decorators/SwaggerCustomizer.js +5 -0
- package/lib/decorators/SwaggerCustomizer.js.map +1 -1
- package/lib/decorators/SwaggerExample.d.ts +51 -22
- package/lib/decorators/SwaggerExample.js +35 -22
- package/lib/decorators/SwaggerExample.js.map +1 -1
- package/lib/decorators/TypedBody.d.ts +10 -3
- package/lib/decorators/TypedBody.js +20 -10
- package/lib/decorators/TypedBody.js.map +1 -1
- package/lib/decorators/TypedException.d.ts +10 -0
- package/lib/decorators/TypedFormData.d.ts +81 -9
- package/lib/decorators/TypedFormData.js +121 -31
- package/lib/decorators/TypedFormData.js.map +1 -1
- package/lib/decorators/TypedHeaders.d.ts +5 -0
- package/lib/decorators/TypedHeaders.js +5 -0
- package/lib/decorators/TypedHeaders.js.map +1 -1
- package/lib/decorators/TypedParam.d.ts +12 -3
- package/lib/decorators/TypedParam.js +12 -3
- package/lib/decorators/TypedParam.js.map +1 -1
- package/lib/decorators/TypedQuery.d.ts +17 -1
- package/lib/decorators/TypedQuery.js +25 -4
- package/lib/decorators/TypedQuery.js.map +1 -1
- package/lib/decorators/TypedRoute.d.ts +25 -10
- package/lib/decorators/TypedRoute.js +19 -10
- package/lib/decorators/TypedRoute.js.map +1 -1
- package/lib/decorators/WebSocketRoute.d.ts +18 -1
- package/lib/decorators/WebSocketRoute.js +18 -1
- package/lib/decorators/WebSocketRoute.js.map +1 -1
- package/lib/decorators/doNotThrowTransformError.d.ts +14 -0
- package/lib/decorators/doNotThrowTransformError.js +14 -0
- package/lib/decorators/doNotThrowTransformError.js.map +1 -1
- package/lib/decorators/internal/EncryptedConstant.js +13 -2
- package/lib/decorators/internal/EncryptedConstant.js.map +1 -1
- package/lib/decorators/internal/IRequestBodyValidation.d.ts +66 -0
- package/lib/decorators/internal/IRequestBodyValidation.js +3 -0
- package/lib/decorators/internal/IRequestBodyValidation.js.map +1 -0
- package/lib/decorators/internal/IWebSocketRouteReflect.d.ts +93 -1
- package/lib/decorators/internal/get_encryption_password.d.ts +1 -0
- package/lib/decorators/internal/get_encryption_password.js +14 -0
- package/lib/decorators/internal/get_encryption_password.js.map +1 -0
- package/lib/decorators/internal/get_path_and_querify.js +23 -9
- package/lib/decorators/internal/get_path_and_querify.js.map +1 -1
- package/lib/decorators/internal/get_path_and_stringify.js +3 -7
- package/lib/decorators/internal/get_path_and_stringify.js.map +1 -1
- package/lib/decorators/internal/get_text_body.js +9 -3
- package/lib/decorators/internal/get_text_body.js.map +1 -1
- package/lib/decorators/internal/group_entries.d.ts +1 -0
- package/lib/decorators/internal/group_entries.js +19 -0
- package/lib/decorators/internal/group_entries.js.map +1 -0
- package/lib/decorators/internal/load_controller.d.ts +14 -0
- package/lib/decorators/internal/load_controller.js +14 -0
- package/lib/decorators/internal/load_controller.js.map +1 -1
- package/lib/decorators/internal/split_route_arguments.d.ts +1 -0
- package/lib/decorators/internal/split_route_arguments.js +22 -0
- package/lib/decorators/internal/split_route_arguments.js.map +1 -0
- package/lib/decorators/internal/validate_request_body.js +68 -25
- package/lib/decorators/internal/validate_request_body.js.map +1 -1
- package/lib/decorators/internal/validate_request_form_data.js +3 -1
- package/lib/decorators/internal/validate_request_form_data.js.map +1 -1
- package/lib/decorators/internal/validate_request_headers.js +2 -1
- package/lib/decorators/internal/validate_request_headers.js.map +1 -1
- package/lib/decorators/internal/validate_request_query.js +3 -1
- package/lib/decorators/internal/validate_request_query.js.map +1 -1
- package/lib/options/IRequestBodyValidator.d.ts +71 -0
- package/lib/options/IRequestFormDataProps.d.ts +80 -0
- package/lib/options/IRequestHeadersValidator.d.ts +67 -0
- package/lib/options/IRequestQueryValidator.d.ts +68 -0
- package/lib/options/IResponseBodyQuerifier.d.ts +125 -1
- package/lib/options/IResponseBodyStringifier.d.ts +107 -0
- package/lib/typings/Creator.d.ts +10 -0
- package/lib/utils/ArrayUtil.d.ts +21 -0
- package/lib/utils/ArrayUtil.js +22 -1
- package/lib/utils/ArrayUtil.js.map +1 -1
- package/lib/utils/ExceptionManager.d.ts +43 -4
- package/lib/utils/ExceptionManager.js +44 -6
- package/lib/utils/ExceptionManager.js.map +1 -1
- package/lib/utils/SourceFinder.d.ts +22 -0
- package/lib/utils/SourceFinder.js +60 -10
- package/lib/utils/SourceFinder.js.map +1 -1
- package/lib/utils/VersioningStrategy.d.ts +45 -2
- package/lib/utils/VersioningStrategy.js +40 -7
- package/lib/utils/VersioningStrategy.js.map +1 -1
- package/native/go.mod +1 -1
- package/native/go.sum +2 -2
- package/native/plugin/plan.go +68 -2
- package/native/transform/ast.go +23 -3
- package/native/transform/build.go +51 -57
- package/native/transform/buildoutput/output.go +147 -0
- package/native/transform/contributor.go +9 -0
- package/native/transform/core_querify.go +63 -9
- package/native/transform/core_transform.go +180 -98
- package/native/transform/core_websocket.go +111 -14
- package/native/transform/node_transform.go +17 -8
- package/native/transform/package.go +55 -0
- package/native/transform/printer.go +1 -3
- package/native/transform/run.go +18 -0
- package/native/transform/schemaprojection/project.go +213 -0
- package/native/transform/transform.go +29 -18
- package/native/transform/typia_fast.go +6 -0
- package/native/transform.cjs +49 -0
- package/package.json +13 -15
- package/src/adaptors/McpAdaptor.ts +215 -33
- package/src/adaptors/WebSocketAdaptor.ts +202 -52
- package/src/adaptors/internal/RoutePathMatcher.ts +91 -0
- package/src/adaptors/internal/external_context.ts +81 -0
- package/src/decorators/DynamicModule.ts +12 -0
- package/src/decorators/EncryptedBody.ts +39 -15
- package/src/decorators/EncryptedController.ts +12 -3
- package/src/decorators/EncryptedModule.ts +89 -18
- package/src/decorators/EncryptedRoute.ts +27 -16
- package/src/decorators/HumanRoute.ts +5 -0
- package/src/decorators/McpRoute.ts +31 -19
- package/src/decorators/PlainBody.ts +20 -10
- package/src/decorators/SwaggerCustomizer.ts +15 -0
- package/src/decorators/SwaggerExample.ts +51 -22
- package/src/decorators/TypedBody.ts +18 -9
- package/src/decorators/TypedException.ts +10 -0
- package/src/decorators/TypedFormData.ts +207 -45
- package/src/decorators/TypedHeaders.ts +5 -0
- package/src/decorators/TypedParam.ts +12 -3
- package/src/decorators/TypedQuery.ts +35 -7
- package/src/decorators/TypedRoute.ts +25 -10
- package/src/decorators/WebSocketRoute.ts +18 -1
- package/src/decorators/doNotThrowTransformError.ts +14 -0
- package/src/decorators/internal/EncryptedConstant.ts +14 -1
- package/src/decorators/internal/IMcpRouteReflect.ts +7 -1
- package/src/decorators/internal/IRequestBodyValidation.ts +65 -0
- package/src/decorators/internal/IWebSocketRouteReflect.ts +95 -1
- package/src/decorators/internal/get_encryption_password.ts +19 -0
- package/src/decorators/internal/get_path_and_querify.ts +31 -10
- package/src/decorators/internal/get_path_and_stringify.ts +3 -9
- package/src/decorators/internal/get_text_body.ts +8 -4
- package/src/decorators/internal/group_entries.ts +17 -0
- package/src/decorators/internal/load_controller.ts +14 -0
- package/src/decorators/internal/split_route_arguments.ts +20 -0
- package/src/decorators/internal/validate_request_body.ts +87 -34
- package/src/decorators/internal/validate_request_form_data.ts +3 -1
- package/src/decorators/internal/validate_request_headers.ts +2 -2
- package/src/decorators/internal/validate_request_query.ts +3 -2
- package/src/options/IRequestBodyValidator.ts +71 -0
- package/src/options/IRequestFormDataProps.ts +80 -0
- package/src/options/IRequestHeadersValidator.ts +67 -0
- package/src/options/IRequestQueryValidator.ts +68 -0
- package/src/options/IResponseBodyQuerifier.ts +126 -1
- package/src/options/IResponseBodyStringifier.ts +107 -0
- package/src/typings/Creator.ts +10 -0
- package/src/utils/ArrayUtil.ts +22 -3
- package/src/utils/ExceptionManager.ts +50 -6
- package/src/utils/SourceFinder.ts +62 -10
- package/src/utils/VersioningStrategy.ts +55 -11
- package/lib/transform.d.ts +0 -10
- package/lib/transform.js +0 -25
- package/lib/transform.js.map +0 -1
- package/src/transform.ts +0 -26
|
@@ -3,21 +3,29 @@ import { IRequestBodyValidator } from "../options/IRequestBodyValidator";
|
|
|
3
3
|
* Encrypted body decorator.
|
|
4
4
|
*
|
|
5
5
|
* `EncryptedBody` is a decorator function getting `application/json` typed data
|
|
6
|
-
* from request body which has been encrypted by AES-128/256 algorithm.
|
|
7
|
-
* `EncryptedBody` validates the request body data type through
|
|
8
|
-
* [typia](https://github.com/samchon/typia)
|
|
9
|
-
*
|
|
6
|
+
* from request body which has been encrypted by AES-128/192/256 algorithm.
|
|
7
|
+
* Also, `EncryptedBody` validates the request body data type through
|
|
8
|
+
* [typia](https://github.com/samchon/typia) using the declared TypeScript
|
|
9
|
+
* type.
|
|
10
10
|
*
|
|
11
11
|
* For reference, when the request body data is not following the promised type
|
|
12
12
|
* `T`, `BadRequestException` error (status code: 400) would be thrown. Also,
|
|
13
|
-
*
|
|
13
|
+
* This decorator decrypts the request body using these options.
|
|
14
14
|
*
|
|
15
|
-
* - AES-128/256
|
|
15
|
+
* - AES-128/192/256
|
|
16
16
|
* - CBC mode
|
|
17
17
|
* - PKCS #5 Padding
|
|
18
18
|
* - Base64 Encoding
|
|
19
19
|
*
|
|
20
|
+
* Successful validator data becomes the decorated argument, including copies
|
|
21
|
+
* returned by clone validators after decryption and JSON parsing.
|
|
22
|
+
*
|
|
20
23
|
* @author Jeongho Nam - https://github.com/samchon
|
|
21
24
|
* @returns Parameter decorator
|
|
25
|
+
* @evidence contracts/common.md#principled-implementation The body must be `text/plain` ciphertext; it is decrypted with the password of the controller or module, the plain text is parsed as JSON and validated by the transformed validator, and a decryption or parse failure becomes a 400 with one fixed message that does not echo the ciphertext and does not tell the two failures apart; a key or initialization vector the cipher itself refuses is the server's configuration, independent of the request, and is thrown as it is.
|
|
26
|
+
* @evidence contracts/common.md#clear-and-simple-design One parameter decorator composes shared text reading, password lookup and validator resolution; the successfully resolved data becomes the argument without repeating validation or changing decryption error handling.
|
|
27
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts The algorithm comes from `AesPkcs5` of the fetcher, the same one the client uses, and no key is embedded; a missing password is an error rather than a plain pass-through.
|
|
28
|
+
* @evidence contracts/common.md#meaningful-documentation The comment describes the protocol and the requirement of a password on the controller or module, and the private decode helper documents why every decryption failure collapses into one response.
|
|
29
|
+
* @evidenceExclude contracts/portability.md#os-neutral-implementation Ciphertext parsing, AES decryption and request validation operate on HTTP values, with no native filesystem or subprocess boundary.
|
|
22
30
|
*/
|
|
23
31
|
export declare function EncryptedBody<T>(validator?: IRequestBodyValidator<T>): ParameterDecorator;
|
|
@@ -13,7 +13,7 @@ exports.EncryptedBody = EncryptedBody;
|
|
|
13
13
|
const AesPkcs5_1 = require("@nestia/fetcher/lib/AesPkcs5");
|
|
14
14
|
const common_1 = require("@nestjs/common");
|
|
15
15
|
const Singleton_1 = require("../utils/Singleton");
|
|
16
|
-
const
|
|
16
|
+
const get_encryption_password_1 = require("./internal/get_encryption_password");
|
|
17
17
|
const get_text_body_1 = require("./internal/get_text_body");
|
|
18
18
|
const headers_to_object_1 = require("./internal/headers_to_object");
|
|
19
19
|
const is_media_type_1 = require("./internal/is_media_type");
|
|
@@ -22,22 +22,30 @@ const validate_request_body_1 = require("./internal/validate_request_body");
|
|
|
22
22
|
* Encrypted body decorator.
|
|
23
23
|
*
|
|
24
24
|
* `EncryptedBody` is a decorator function getting `application/json` typed data
|
|
25
|
-
* from request body which has been encrypted by AES-128/256 algorithm.
|
|
26
|
-
* `EncryptedBody` validates the request body data type through
|
|
27
|
-
* [typia](https://github.com/samchon/typia)
|
|
28
|
-
*
|
|
25
|
+
* from request body which has been encrypted by AES-128/192/256 algorithm.
|
|
26
|
+
* Also, `EncryptedBody` validates the request body data type through
|
|
27
|
+
* [typia](https://github.com/samchon/typia) using the declared TypeScript
|
|
28
|
+
* type.
|
|
29
29
|
*
|
|
30
30
|
* For reference, when the request body data is not following the promised type
|
|
31
31
|
* `T`, `BadRequestException` error (status code: 400) would be thrown. Also,
|
|
32
|
-
*
|
|
32
|
+
* This decorator decrypts the request body using these options.
|
|
33
33
|
*
|
|
34
|
-
* - AES-128/256
|
|
34
|
+
* - AES-128/192/256
|
|
35
35
|
* - CBC mode
|
|
36
36
|
* - PKCS #5 Padding
|
|
37
37
|
* - Base64 Encoding
|
|
38
38
|
*
|
|
39
|
+
* Successful validator data becomes the decorated argument, including copies
|
|
40
|
+
* returned by clone validators after decryption and JSON parsing.
|
|
41
|
+
*
|
|
39
42
|
* @author Jeongho Nam - https://github.com/samchon
|
|
40
43
|
* @returns Parameter decorator
|
|
44
|
+
* @evidence contracts/common.md#principled-implementation The body must be `text/plain` ciphertext; it is decrypted with the password of the controller or module, the plain text is parsed as JSON and validated by the transformed validator, and a decryption or parse failure becomes a 400 with one fixed message that does not echo the ciphertext and does not tell the two failures apart; a key or initialization vector the cipher itself refuses is the server's configuration, independent of the request, and is thrown as it is.
|
|
45
|
+
* @evidence contracts/common.md#clear-and-simple-design One parameter decorator composes shared text reading, password lookup and validator resolution; the successfully resolved data becomes the argument without repeating validation or changing decryption error handling.
|
|
46
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts The algorithm comes from `AesPkcs5` of the fetcher, the same one the client uses, and no key is embedded; a missing password is an error rather than a plain pass-through.
|
|
47
|
+
* @evidence contracts/common.md#meaningful-documentation The comment describes the protocol and the requirement of a password on the controller or module, and the private decode helper documents why every decryption failure collapses into one response.
|
|
48
|
+
* @evidenceExclude contracts/portability.md#os-neutral-implementation Ciphertext parsing, AES decryption and request validation operate on HTTP values, with no native filesystem or subprocess boundary.
|
|
41
49
|
*/
|
|
42
50
|
function EncryptedBody(validator) {
|
|
43
51
|
const checker = (0, validate_request_body_1.validate_request_body)("EncryptedBody")(validator);
|
|
@@ -48,7 +56,7 @@ function EncryptedBody(validator) {
|
|
|
48
56
|
.getRequest();
|
|
49
57
|
if ((0, is_media_type_1.is_media_type)(request.headers["content-type"], "text/plain") === false)
|
|
50
58
|
throw new common_1.BadRequestException(`Request body type is not "text/plain".`);
|
|
51
|
-
const param =
|
|
59
|
+
const param = (0, get_encryption_password_1.get_encryption_password)(context.getClass());
|
|
52
60
|
if (!param)
|
|
53
61
|
throw new Error("Error on nestia.core.EncryptedBody(): no encryption password is given.");
|
|
54
62
|
// GET BODY DATA
|
|
@@ -59,10 +67,10 @@ function EncryptedBody(validator) {
|
|
|
59
67
|
: param;
|
|
60
68
|
// PARSE AND VALIDATE DATA
|
|
61
69
|
const data = decode(body, password.key, password.iv);
|
|
62
|
-
const
|
|
63
|
-
if (
|
|
64
|
-
throw error;
|
|
65
|
-
return data;
|
|
70
|
+
const result = checker.resolve(data);
|
|
71
|
+
if (!result.success)
|
|
72
|
+
throw result.error;
|
|
73
|
+
return result.data;
|
|
66
74
|
});
|
|
67
75
|
})();
|
|
68
76
|
}
|
|
@@ -79,9 +87,13 @@ function EncryptedBody(validator) {
|
|
|
79
87
|
*
|
|
80
88
|
* Both failure modes must therefore collapse into one indistinguishable
|
|
81
89
|
* `BadRequestException` (identical status, message, and body). Only the
|
|
82
|
-
* downstream type validation of an already-parsed body
|
|
83
|
-
*
|
|
84
|
-
*
|
|
90
|
+
* downstream type validation of an already-parsed body reports its own distinct
|
|
91
|
+
* error. AES-CBC provides no authentication; collapsing parse and padding
|
|
92
|
+
* errors does not establish ciphertext authenticity.
|
|
93
|
+
*
|
|
94
|
+
* A key or initialization vector the cipher refuses is thrown as it is. It says
|
|
95
|
+
* nothing about the body, so it opens no oracle, and it is a defect of the
|
|
96
|
+
* server's configuration that a 400 would blame on the client.
|
|
85
97
|
*
|
|
86
98
|
* @internal
|
|
87
99
|
*/
|
|
@@ -90,10 +102,21 @@ const decode = (body, key, iv) => {
|
|
|
90
102
|
return JSON.parse(AesPkcs5_1.AesPkcs5.decrypt(body, key, iv));
|
|
91
103
|
}
|
|
92
104
|
catch (exp) {
|
|
93
|
-
|
|
105
|
+
// A password the cipher itself refuses is the server's configuration, which
|
|
106
|
+
// no request body can influence, so it is no oracle and no client's fault.
|
|
107
|
+
if (exp instanceof Error && PASSWORD_ERRORS.has(exp.code))
|
|
108
|
+
throw exp;
|
|
109
|
+
else if (exp instanceof Error)
|
|
94
110
|
throw new common_1.BadRequestException("Failed to decrypt the request body. Check your body content or encryption password.");
|
|
95
111
|
else
|
|
96
112
|
throw exp;
|
|
97
113
|
}
|
|
98
114
|
};
|
|
115
|
+
/** The error codes of a key or an initialization vector the cipher refuses. */
|
|
116
|
+
const PASSWORD_ERRORS = new Set([
|
|
117
|
+
"ERR_INVALID_ARG_TYPE",
|
|
118
|
+
"ERR_CRYPTO_INVALID_IV",
|
|
119
|
+
"ERR_CRYPTO_INVALID_KEYLEN",
|
|
120
|
+
"ERR_CRYPTO_UNKNOWN_CIPHER",
|
|
121
|
+
]);
|
|
99
122
|
//# sourceMappingURL=EncryptedBody.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EncryptedBody.js","sourceRoot":"","sources":["../../src/decorators/EncryptedBody.ts"],"names":[],"mappings":";;;;;;;;;;;;AACA,2DAAwD;AACxD,2CAIwB;AAKxB,kDAA+C;AAC/C,
|
|
1
|
+
{"version":3,"file":"EncryptedBody.js","sourceRoot":"","sources":["../../src/decorators/EncryptedBody.ts"],"names":[],"mappings":";;;;;;;;;;;;AACA,2DAAwD;AACxD,2CAIwB;AAKxB,kDAA+C;AAC/C,gFAA6E;AAC7E,4DAAyD;AACzD,oEAAiE;AACjE,4DAAyD;AACzD,4EAAyE;AAEzE;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,uBACE,SAAoC;IAEpC,MAAM,OAAO,GAAG,IAAA,6CAAqB,EAAC,eAAe,CAAC,CAAC,SAAS,CAAC,CAAC;IAClE,OAAO,IAAA,6BAAoB,EAAC,SAAe,aAAa,CACtD,QAAa,EACb,OAAyB;;YAEzB,MAAM,OAAO,GAAqC,OAAO;iBACtD,YAAY,EAAE;iBACd,UAAU,EAAE,CAAC;YAChB,IAAI,IAAA,6BAAa,EAAC,OAAO,CAAC,OAAO,CAAC,cAAc,CAAC,EAAE,YAAY,CAAC,KAAK,KAAK;gBACxE,MAAM,IAAI,4BAAmB,CAAC,wCAAwC,CAAC,CAAC;YAE1E,MAAM,KAAK,GACT,IAAA,iDAAuB,EAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;YAC9C,IAAI,CAAC,KAAK;gBACR,MAAM,IAAI,KAAK,CACb,wEAAwE,CACzE,CAAC;YAEJ,gBAAgB;YAChB,MAAM,OAAO,GAAsC,IAAI,qBAAS,CAAC,GAAG,EAAE,CACpE,IAAA,qCAAiB,EAAC,OAAO,CAAC,OAAO,CAAC,CACnC,CAAC;YACF,MAAM,IAAI,GAAW,MAAM,IAAA,6BAAa,EAAC,OAAO,CAAC,CAAC;YAClD,MAAM,QAAQ,GACZ,OAAO,KAAK,KAAK,UAAU;gBACzB,CAAC,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC;gBAC9D,CAAC,CAAC,KAAK,CAAC;YAEZ,0BAA0B;YAC1B,MAAM,IAAI,GAAQ,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC;YAC1D,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YACrC,IAAI,CAAC,MAAM,CAAC,OAAO;gBAAE,MAAM,MAAM,CAAC,KAAK,CAAC;YACxC,OAAO,MAAM,CAAC,IAAI,CAAC;QACrB,CAAC;KAAA,CAAC,EAAE,CAAC;AACP,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,MAAM,GAAG,CAAC,IAAY,EAAE,GAAW,EAAE,EAAU,EAAW,EAAE;IAChE,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,mBAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;IACrD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,4EAA4E;QAC5E,2EAA2E;QAC3E,IAAI,GAAG,YAAY,KAAK,IAAI,eAAe,CAAC,GAAG,CAAE,GAAW,CAAC,IAAI,CAAC;YAChE,MAAM,GAAG,CAAC;aACP,IAAI,GAAG,YAAY,KAAK;YAC3B,MAAM,IAAI,4BAAmB,CAC3B,qFAAqF,CACtF,CAAC;;YACC,MAAM,GAAG,CAAC;IACjB,CAAC;AACH,CAAC,CAAC;AAEF,+EAA+E;AAC/E,MAAM,eAAe,GAAiB,IAAI,GAAG,CAAC;IAC5C,sBAAsB;IACtB,uBAAuB;IACvB,2BAA2B;IAC3B,2BAA2B;CAC5B,CAAC,CAAC"}
|
|
@@ -3,7 +3,7 @@ import { IEncryptionPassword } from "@nestia/fetcher";
|
|
|
3
3
|
* Encrypted controller.
|
|
4
4
|
*
|
|
5
5
|
* `EncryptedController` is an extension of the {@link nest.Controller} class
|
|
6
|
-
* decorator function who configures encryption password of the AES-128/256
|
|
6
|
+
* decorator function who configures encryption password of the AES-128/192/256
|
|
7
7
|
* algorithm. The encryption algorithm and password would be used by
|
|
8
8
|
* {@link EncryptedRoute} and {@link EncryptedBody} to encrypt the request and
|
|
9
9
|
* response body of the HTTP protocol.
|
|
@@ -24,5 +24,10 @@ import { IEncryptionPassword } from "@nestia/fetcher";
|
|
|
24
24
|
* @param path Path of the HTTP request
|
|
25
25
|
* @param password Encryption password or its getter function
|
|
26
26
|
* @returns Class decorator
|
|
27
|
+
* @evidence contracts/common.md#principled-implementation The decorator stores the password as metadata on the class and then applies Nest's `Controller(path)`, so the encrypted decorators can find the password by reading the class.
|
|
28
|
+
* @evidence contracts/common.md#clear-and-simple-design One decorator that composes a metadata write with the standard decorator.
|
|
29
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts It uses Nest's public `Controller` decorator and the reflect metadata API.
|
|
30
|
+
* @evidence contracts/common.md#meaningful-documentation The comment states the password forms and the encrypted decorators it enables.
|
|
31
|
+
* @evidenceExclude contracts/portability.md#os-neutral-implementation Controller paths are HTTP routing metadata and passwords are in-memory values; neither is a native filesystem path.
|
|
27
32
|
*/
|
|
28
33
|
export declare function EncryptedController(path: string, password: IEncryptionPassword | IEncryptionPassword.Closure): ClassDecorator;
|
|
@@ -7,7 +7,7 @@ const EncryptedConstant_1 = require("./internal/EncryptedConstant");
|
|
|
7
7
|
* Encrypted controller.
|
|
8
8
|
*
|
|
9
9
|
* `EncryptedController` is an extension of the {@link nest.Controller} class
|
|
10
|
-
* decorator function who configures encryption password of the AES-128/256
|
|
10
|
+
* decorator function who configures encryption password of the AES-128/192/256
|
|
11
11
|
* algorithm. The encryption algorithm and password would be used by
|
|
12
12
|
* {@link EncryptedRoute} and {@link EncryptedBody} to encrypt the request and
|
|
13
13
|
* response body of the HTTP protocol.
|
|
@@ -28,10 +28,15 @@ const EncryptedConstant_1 = require("./internal/EncryptedConstant");
|
|
|
28
28
|
* @param path Path of the HTTP request
|
|
29
29
|
* @param password Encryption password or its getter function
|
|
30
30
|
* @returns Class decorator
|
|
31
|
+
* @evidence contracts/common.md#principled-implementation The decorator stores the password as metadata on the class and then applies Nest's `Controller(path)`, so the encrypted decorators can find the password by reading the class.
|
|
32
|
+
* @evidence contracts/common.md#clear-and-simple-design One decorator that composes a metadata write with the standard decorator.
|
|
33
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts It uses Nest's public `Controller` decorator and the reflect metadata API.
|
|
34
|
+
* @evidence contracts/common.md#meaningful-documentation The comment states the password forms and the encrypted decorators it enables.
|
|
35
|
+
* @evidenceExclude contracts/portability.md#os-neutral-implementation Controller paths are HTTP routing metadata and passwords are in-memory values; neither is a native filesystem path.
|
|
31
36
|
*/
|
|
32
37
|
function EncryptedController(path, password) {
|
|
33
38
|
return function (target) {
|
|
34
|
-
Reflect.defineMetadata(EncryptedConstant_1.
|
|
39
|
+
Reflect.defineMetadata(EncryptedConstant_1.ENCRYPTION_CONTROLLER_METADATA_KEY, password, target);
|
|
35
40
|
(0, common_1.Controller)(path)(target);
|
|
36
41
|
};
|
|
37
42
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EncryptedController.js","sourceRoot":"","sources":["../../src/decorators/EncryptedController.ts"],"names":[],"mappings":";;;AACA,2CAA4C;AAE5C,
|
|
1
|
+
{"version":3,"file":"EncryptedController.js","sourceRoot":"","sources":["../../src/decorators/EncryptedController.ts"],"names":[],"mappings":";;;AACA,2CAA4C;AAE5C,oEAAkF;AAElF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,6BACE,IAAY,EACZ,QAA2D;IAE3D,OAAO,UAAU,MAAW;QAC1B,OAAO,CAAC,cAAc,CACpB,sDAAkC,EAClC,QAAQ,EACR,MAAM,CACP,CAAC;QACF,IAAA,mBAAU,EAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC;IAC3B,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -4,16 +4,20 @@ import { Module } from "@nestjs/common";
|
|
|
4
4
|
* Encrypted module.
|
|
5
5
|
*
|
|
6
6
|
* `EncryptedModule` is an extension of the {@link Module} class decorator
|
|
7
|
-
* function who configures encryption password of the AES-128/256 algorithm.
|
|
8
|
-
* encryption algorithm and password would be used by {@link EncryptedRoute}
|
|
9
|
-
* {@link EncryptedBody} to encrypt the request and response bod of the HTTP
|
|
7
|
+
* function who configures encryption password of the AES-128/192/256 algorithm.
|
|
8
|
+
* The encryption algorithm and password would be used by {@link EncryptedRoute}
|
|
9
|
+
* and {@link EncryptedBody} to encrypt the request and response bod of the HTTP
|
|
10
10
|
* protocol.
|
|
11
11
|
*
|
|
12
12
|
* By using this `EncryptedModule` decorator function, all of the
|
|
13
13
|
* {@link Controller controllers} configured in the _metadata_ would be
|
|
14
|
-
* automatically changed to the {@link EncryptedController} with the _password_
|
|
15
|
-
*
|
|
16
|
-
*
|
|
14
|
+
* automatically changed to the {@link EncryptedController} with the _password_,
|
|
15
|
+
* and so would the controllers of every module it imports: module classes,
|
|
16
|
+
* dynamic modules (`{ module, imports, controllers }`), `forwardRef()`s, and
|
|
17
|
+
* promises of them, however deep and even when cyclic. If there're some
|
|
18
|
+
* original {@link EncryptedController} decorated classes in the _metadata_,
|
|
19
|
+
* their encryption password would be kept, as would a subclass's that inherits
|
|
20
|
+
* one.
|
|
17
21
|
*
|
|
18
22
|
* Therefore, if you're planning to place original {@link EncryptedController}
|
|
19
23
|
* decorated classes in the _metadata_, I hope them to have different encryption
|
|
@@ -29,8 +33,23 @@ import { Module } from "@nestjs/common";
|
|
|
29
33
|
* @param metadata Module configuration metadata
|
|
30
34
|
* @param password Encryption password or its getter function
|
|
31
35
|
* @returns Class decorator
|
|
36
|
+
* @evidence contracts/common.md#principled-implementation A visited set breaks import cycles, the controllers of each visited module get the password as metadata, asynchronous modules are awaited through the same promise Nest awaits, and a forward reference is resolved once its class exists.
|
|
37
|
+
* @evidence contracts/common.md#clear-and-simple-design One decorator whose traversal is a private function; the dynamic-module helper is in the merged namespace.
|
|
38
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts The traversal uses the public metadata keys of Nest modules; no module name is special-cased.
|
|
39
|
+
* @evidence contracts/common.md#meaningful-documentation The comment states which module shapes are followed.
|
|
40
|
+
* @evidence contracts/portability.md#os-neutral-implementation The decorator traverses Nest module metadata in memory; its dynamic helper delegates native paths and file-URL imports to load_controllers instead of composing platform-specific import strings.
|
|
32
41
|
*/
|
|
33
42
|
export declare function EncryptedModule(metadata: Parameters<typeof Module>[0], password: IEncryptionPassword.Closure): ClassDecorator;
|
|
43
|
+
/**
|
|
44
|
+
* Helpers of {@link EncryptedModule}, namely `dynamic`, which builds an
|
|
45
|
+
* encrypted module from controller paths.
|
|
46
|
+
*
|
|
47
|
+
* @evidence contracts/common.md#principled-implementation `dynamic` loads the controllers with the shared loader, wraps an object password into a closure, and returns a class decorated by `EncryptedModule`.
|
|
48
|
+
* @evidence contracts/common.md#clear-and-simple-design One function that reuses the loader and the decorator.
|
|
49
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts Paths and password are caller input.
|
|
50
|
+
* @evidence contracts/common.md#meaningful-documentation The comment documents the path forms and the password argument.
|
|
51
|
+
* @evidence contracts/portability.md#os-neutral-implementation The decorator traverses Nest module metadata in memory; its dynamic helper delegates native paths and file-URL imports to load_controllers instead of composing platform-specific import strings.
|
|
52
|
+
*/
|
|
34
53
|
export declare namespace EncryptedModule {
|
|
35
54
|
/**
|
|
36
55
|
* Dynamic encrypted module.
|
|
@@ -55,16 +55,20 @@ const load_controller_1 = require("./internal/load_controller");
|
|
|
55
55
|
* Encrypted module.
|
|
56
56
|
*
|
|
57
57
|
* `EncryptedModule` is an extension of the {@link Module} class decorator
|
|
58
|
-
* function who configures encryption password of the AES-128/256 algorithm.
|
|
59
|
-
* encryption algorithm and password would be used by {@link EncryptedRoute}
|
|
60
|
-
* {@link EncryptedBody} to encrypt the request and response bod of the HTTP
|
|
58
|
+
* function who configures encryption password of the AES-128/192/256 algorithm.
|
|
59
|
+
* The encryption algorithm and password would be used by {@link EncryptedRoute}
|
|
60
|
+
* and {@link EncryptedBody} to encrypt the request and response bod of the HTTP
|
|
61
61
|
* protocol.
|
|
62
62
|
*
|
|
63
63
|
* By using this `EncryptedModule` decorator function, all of the
|
|
64
64
|
* {@link Controller controllers} configured in the _metadata_ would be
|
|
65
|
-
* automatically changed to the {@link EncryptedController} with the _password_
|
|
66
|
-
*
|
|
67
|
-
*
|
|
65
|
+
* automatically changed to the {@link EncryptedController} with the _password_,
|
|
66
|
+
* and so would the controllers of every module it imports: module classes,
|
|
67
|
+
* dynamic modules (`{ module, imports, controllers }`), `forwardRef()`s, and
|
|
68
|
+
* promises of them, however deep and even when cyclic. If there're some
|
|
69
|
+
* original {@link EncryptedController} decorated classes in the _metadata_,
|
|
70
|
+
* their encryption password would be kept, as would a subclass's that inherits
|
|
71
|
+
* one.
|
|
68
72
|
*
|
|
69
73
|
* Therefore, if you're planning to place original {@link EncryptedController}
|
|
70
74
|
* decorated classes in the _metadata_, I hope them to have different encryption
|
|
@@ -80,6 +84,11 @@ const load_controller_1 = require("./internal/load_controller");
|
|
|
80
84
|
* @param metadata Module configuration metadata
|
|
81
85
|
* @param password Encryption password or its getter function
|
|
82
86
|
* @returns Class decorator
|
|
87
|
+
* @evidence contracts/common.md#principled-implementation A visited set breaks import cycles, the controllers of each visited module get the password as metadata, asynchronous modules are awaited through the same promise Nest awaits, and a forward reference is resolved once its class exists.
|
|
88
|
+
* @evidence contracts/common.md#clear-and-simple-design One decorator whose traversal is a private function; the dynamic-module helper is in the merged namespace.
|
|
89
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts The traversal uses the public metadata keys of Nest modules; no module name is special-cased.
|
|
90
|
+
* @evidence contracts/common.md#meaningful-documentation The comment states which module shapes are followed.
|
|
91
|
+
* @evidence contracts/portability.md#os-neutral-implementation The decorator traverses Nest module metadata in memory; its dynamic helper delegates native paths and file-URL imports to load_controllers instead of composing platform-specific import strings.
|
|
83
92
|
*/
|
|
84
93
|
function EncryptedModule(metadata, password) {
|
|
85
94
|
return function (target) {
|
|
@@ -87,6 +96,16 @@ function EncryptedModule(metadata, password) {
|
|
|
87
96
|
iterate(password)(target);
|
|
88
97
|
};
|
|
89
98
|
}
|
|
99
|
+
/**
|
|
100
|
+
* Helpers of {@link EncryptedModule}, namely `dynamic`, which builds an
|
|
101
|
+
* encrypted module from controller paths.
|
|
102
|
+
*
|
|
103
|
+
* @evidence contracts/common.md#principled-implementation `dynamic` loads the controllers with the shared loader, wraps an object password into a closure, and returns a class decorated by `EncryptedModule`.
|
|
104
|
+
* @evidence contracts/common.md#clear-and-simple-design One function that reuses the loader and the decorator.
|
|
105
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts Paths and password are caller input.
|
|
106
|
+
* @evidence contracts/common.md#meaningful-documentation The comment documents the path forms and the password argument.
|
|
107
|
+
* @evidence contracts/portability.md#os-neutral-implementation The decorator traverses Nest module metadata in memory; its dynamic helper delegates native paths and file-URL imports to load_controllers instead of composing platform-specific import strings.
|
|
108
|
+
*/
|
|
90
109
|
(function (EncryptedModule) {
|
|
91
110
|
/**
|
|
92
111
|
* Dynamic encrypted module.
|
|
@@ -128,17 +147,67 @@ function EncryptedModule(metadata, password) {
|
|
|
128
147
|
}
|
|
129
148
|
EncryptedModule.dynamic = dynamic;
|
|
130
149
|
})(EncryptedModule || (exports.EncryptedModule = EncryptedModule = {}));
|
|
131
|
-
/**
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
150
|
+
/**
|
|
151
|
+
* Gives every controller the module reaches the module's password: those of the
|
|
152
|
+
* module itself and of each import, whether a module class, a dynamic module
|
|
153
|
+
* (its `module`, and its own `imports` and `controllers`), a `forwardRef()`, or
|
|
154
|
+
* a promise of one. Each module is visited once, so a cyclic import graph
|
|
155
|
+
* terminates.
|
|
156
|
+
*
|
|
157
|
+
* @internal
|
|
158
|
+
*/
|
|
159
|
+
const iterate = (password) => {
|
|
160
|
+
const visited = new Set();
|
|
161
|
+
const controllers = (list) => {
|
|
162
|
+
if (Array.isArray(list))
|
|
163
|
+
for (const c of list)
|
|
164
|
+
if (typeof c === "function")
|
|
165
|
+
Reflect.defineMetadata(EncryptedConstant_1.ENCRYPTION_METADATA_KEY, password, c);
|
|
166
|
+
};
|
|
167
|
+
const imports = (list) => {
|
|
168
|
+
if (Array.isArray(list))
|
|
169
|
+
for (const imp of list)
|
|
170
|
+
visit(imp);
|
|
171
|
+
};
|
|
172
|
+
const visit = (input) => {
|
|
173
|
+
if (typeof input !== "function" &&
|
|
174
|
+
(typeof input !== "object" || input === null))
|
|
175
|
+
return;
|
|
176
|
+
if (visited.has(input))
|
|
177
|
+
return;
|
|
178
|
+
visited.add(input);
|
|
179
|
+
if (typeof input === "function") {
|
|
180
|
+
imports(Reflect.getMetadata("imports", input));
|
|
181
|
+
controllers(Reflect.getMetadata("controllers", input));
|
|
182
|
+
}
|
|
183
|
+
else if (typeof input.then === "function")
|
|
184
|
+
// an asynchronous dynamic module; NestJS awaits the same promise while
|
|
185
|
+
// scanning, after this callback, registered first, has run
|
|
186
|
+
input.then(visit, () => { });
|
|
187
|
+
else if (typeof input.forwardRef === "function") {
|
|
188
|
+
// the class a forward reference names may not be defined yet while the
|
|
189
|
+
// decorators run; it is once the synchronous module graph has loaded
|
|
190
|
+
const resolve = () => {
|
|
191
|
+
try {
|
|
192
|
+
return input.forwardRef();
|
|
193
|
+
}
|
|
194
|
+
catch (_a) {
|
|
195
|
+
return undefined;
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
const target = resolve();
|
|
199
|
+
if (target !== undefined)
|
|
200
|
+
visit(target);
|
|
201
|
+
else
|
|
202
|
+
void Promise.resolve().then(() => visit(resolve()));
|
|
203
|
+
}
|
|
204
|
+
else {
|
|
205
|
+
const dynamic = input;
|
|
206
|
+
visit(dynamic.module);
|
|
207
|
+
imports(dynamic.imports);
|
|
208
|
+
controllers(dynamic.controllers);
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
return visit;
|
|
143
212
|
};
|
|
144
213
|
//# sourceMappingURL=EncryptedModule.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EncryptedModule.js","sourceRoot":"","sources":["../../src/decorators/EncryptedModule.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,2CAAwC;AAGxC,oEAAuE;AACvE,gEAA8D;AAE9D
|
|
1
|
+
{"version":3,"file":"EncryptedModule.js","sourceRoot":"","sources":["../../src/decorators/EncryptedModule.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,22 +4,26 @@ import { TypedRoute } from "./TypedRoute";
|
|
|
4
4
|
* Encrypted router decorator functions.
|
|
5
5
|
*
|
|
6
6
|
* `EncryptedRoute` is a module containing router decorator functions which
|
|
7
|
-
* encrypts response body data through AES-128/256 encryption
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* [typia](https://github.com/samchon/typia).
|
|
7
|
+
* encrypts response body data through AES-128/192/256 encryption after
|
|
8
|
+
* serializing it with a [typia](https://github.com/samchon/typia) function
|
|
9
|
+
* generated from the declared return type.
|
|
11
10
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* `
|
|
15
|
-
*
|
|
11
|
+
* The default assert serializer rejects a response outside the declared type
|
|
12
|
+
* with a 500 error. The configured stringify mode chooses the validation policy
|
|
13
|
+
* before encryption; `validate.log` logs failures and serializes the original
|
|
14
|
+
* value. Interceptors running afterwards receive ciphertext.
|
|
16
15
|
*
|
|
17
|
-
* - AES-128/256
|
|
16
|
+
* - AES-128/192/256
|
|
18
17
|
* - CBC mode
|
|
19
18
|
* - PKCS #5 Padding
|
|
20
19
|
* - Base64 Encoding
|
|
21
20
|
*
|
|
22
21
|
* @author Jeongho Nam - https://github.com/samchon
|
|
22
|
+
* @evidence contracts/common.md#principled-implementation Each route method decorates Nest's router decorator with an interceptor that serializes the value as the transform chose, encrypts it with the password of the controller or module, and answers `text/plain` on success only, so an error keeps its own JSON type.
|
|
23
|
+
* @evidence contracts/common.md#clear-and-simple-design One generator function creates the five HTTP-method decorators, and the interceptor and the router table are module-private.
|
|
24
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts The password lookup and the serializer come from shared modules; the loop after the namespace copies the marker properties of typia's stringify functions onto the five decorators as the transform expects, which mutates only these exported functions.
|
|
25
|
+
* @evidence contracts/common.md#meaningful-documentation The comment documents the decorator family and its password requirement.
|
|
26
|
+
* @evidenceExclude contracts/portability.md#os-neutral-implementation Route paths and serialized ciphertext are HTTP protocol values; response interception does not access native files or launch a process.
|
|
23
27
|
*/
|
|
24
28
|
export declare namespace EncryptedRoute {
|
|
25
29
|
/**
|
|
@@ -34,7 +38,7 @@ export declare namespace EncryptedRoute {
|
|
|
34
38
|
<T>(path: string | string[], stringify?: IResponseBodyStringifier<T> | null): MethodDecorator;
|
|
35
39
|
};
|
|
36
40
|
/**
|
|
37
|
-
* Encrypted router decorator function for the
|
|
41
|
+
* Encrypted router decorator function for the POST method.
|
|
38
42
|
*
|
|
39
43
|
* @param paths Path(s) of the HTTP request
|
|
40
44
|
* @returns Method decorator
|
|
@@ -83,7 +87,7 @@ export declare namespace EncryptedRoute {
|
|
|
83
87
|
* If you've configured the transformation option to `validate.log` in the
|
|
84
88
|
* `tsconfig.json` file, then the error log information of the response
|
|
85
89
|
* validation failure would be logged through this function instead of
|
|
86
|
-
* throwing the
|
|
90
|
+
* throwing the 500 internal server error.
|
|
87
91
|
*
|
|
88
92
|
* By the way, be careful. If you've configured the response transformation
|
|
89
93
|
* option to be `validate.log`, client may get wrong response data. Therefore,
|
|
@@ -91,6 +95,11 @@ export declare namespace EncryptedRoute {
|
|
|
91
95
|
*
|
|
92
96
|
* @default console.log
|
|
93
97
|
* @param func Logger function
|
|
98
|
+
* @evidence contracts/common.md#principled-implementation It stores the logger in `TypedRoute`, which owns the single logger both route families use.
|
|
99
|
+
* @evidence contracts/common.md#clear-and-simple-design A one-line delegation, so the logger has one owner.
|
|
100
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts It changes only the logger variable.
|
|
101
|
+
* @evidence contracts/common.md#meaningful-documentation The comment states which validate mode uses the logger.
|
|
102
|
+
* @evidenceExclude contracts/portability.md#os-neutral-implementation Route paths and serialized ciphertext are HTTP protocol values; response interception does not access native files or launch a process.
|
|
94
103
|
*/
|
|
95
104
|
function setValidateErrorLogger(func: (log: IValidateErrorLog) => void): void;
|
|
96
105
|
export import IValidateErrorLog = TypedRoute.IValidateErrorLog;
|
|
@@ -10,7 +10,7 @@ const operators_1 = require("rxjs/operators");
|
|
|
10
10
|
const typia_1 = __importDefault(require("typia"));
|
|
11
11
|
const Singleton_1 = require("../utils/Singleton");
|
|
12
12
|
const TypedRoute_1 = require("./TypedRoute");
|
|
13
|
-
const
|
|
13
|
+
const get_encryption_password_1 = require("./internal/get_encryption_password");
|
|
14
14
|
const get_path_and_stringify_1 = require("./internal/get_path_and_stringify");
|
|
15
15
|
const headers_to_object_1 = require("./internal/headers_to_object");
|
|
16
16
|
const route_error_1 = require("./internal/route_error");
|
|
@@ -18,22 +18,26 @@ const route_error_1 = require("./internal/route_error");
|
|
|
18
18
|
* Encrypted router decorator functions.
|
|
19
19
|
*
|
|
20
20
|
* `EncryptedRoute` is a module containing router decorator functions which
|
|
21
|
-
* encrypts response body data through AES-128/256 encryption
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
* [typia](https://github.com/samchon/typia).
|
|
21
|
+
* encrypts response body data through AES-128/192/256 encryption after
|
|
22
|
+
* serializing it with a [typia](https://github.com/samchon/typia) function
|
|
23
|
+
* generated from the declared return type.
|
|
25
24
|
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
* `
|
|
29
|
-
*
|
|
25
|
+
* The default assert serializer rejects a response outside the declared type
|
|
26
|
+
* with a 500 error. The configured stringify mode chooses the validation policy
|
|
27
|
+
* before encryption; `validate.log` logs failures and serializes the original
|
|
28
|
+
* value. Interceptors running afterwards receive ciphertext.
|
|
30
29
|
*
|
|
31
|
-
* - AES-128/256
|
|
30
|
+
* - AES-128/192/256
|
|
32
31
|
* - CBC mode
|
|
33
32
|
* - PKCS #5 Padding
|
|
34
33
|
* - Base64 Encoding
|
|
35
34
|
*
|
|
36
35
|
* @author Jeongho Nam - https://github.com/samchon
|
|
36
|
+
* @evidence contracts/common.md#principled-implementation Each route method decorates Nest's router decorator with an interceptor that serializes the value as the transform chose, encrypts it with the password of the controller or module, and answers `text/plain` on success only, so an error keeps its own JSON type.
|
|
37
|
+
* @evidence contracts/common.md#clear-and-simple-design One generator function creates the five HTTP-method decorators, and the interceptor and the router table are module-private.
|
|
38
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts The password lookup and the serializer come from shared modules; the loop after the namespace copies the marker properties of typia's stringify functions onto the five decorators as the transform expects, which mutates only these exported functions.
|
|
39
|
+
* @evidence contracts/common.md#meaningful-documentation The comment documents the decorator family and its password requirement.
|
|
40
|
+
* @evidenceExclude contracts/portability.md#os-neutral-implementation Route paths and serialized ciphertext are HTTP protocol values; response interception does not access native files or launch a process.
|
|
37
41
|
*/
|
|
38
42
|
var EncryptedRoute;
|
|
39
43
|
(function (EncryptedRoute) {
|
|
@@ -45,7 +49,7 @@ var EncryptedRoute;
|
|
|
45
49
|
*/
|
|
46
50
|
EncryptedRoute.Get = Generator("Get");
|
|
47
51
|
/**
|
|
48
|
-
* Encrypted router decorator function for the
|
|
52
|
+
* Encrypted router decorator function for the POST method.
|
|
49
53
|
*
|
|
50
54
|
* @param paths Path(s) of the HTTP request
|
|
51
55
|
* @returns Method decorator
|
|
@@ -78,7 +82,7 @@ var EncryptedRoute;
|
|
|
78
82
|
* If you've configured the transformation option to `validate.log` in the
|
|
79
83
|
* `tsconfig.json` file, then the error log information of the response
|
|
80
84
|
* validation failure would be logged through this function instead of
|
|
81
|
-
* throwing the
|
|
85
|
+
* throwing the 500 internal server error.
|
|
82
86
|
*
|
|
83
87
|
* By the way, be careful. If you've configured the response transformation
|
|
84
88
|
* option to be `validate.log`, client may get wrong response data. Therefore,
|
|
@@ -86,6 +90,11 @@ var EncryptedRoute;
|
|
|
86
90
|
*
|
|
87
91
|
* @default console.log
|
|
88
92
|
* @param func Logger function
|
|
93
|
+
* @evidence contracts/common.md#principled-implementation It stores the logger in `TypedRoute`, which owns the single logger both route families use.
|
|
94
|
+
* @evidence contracts/common.md#clear-and-simple-design A one-line delegation, so the logger has one owner.
|
|
95
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts It changes only the logger variable.
|
|
96
|
+
* @evidence contracts/common.md#meaningful-documentation The comment states which validate mode uses the logger.
|
|
97
|
+
* @evidenceExclude contracts/portability.md#os-neutral-implementation Route paths and serialized ciphertext are HTTP protocol values; response interception does not access native files or launch a process.
|
|
89
98
|
*/
|
|
90
99
|
function setValidateErrorLogger(func) {
|
|
91
100
|
TypedRoute_1.TypedRoute.setValidateErrorLogger(func);
|
|
@@ -124,7 +133,7 @@ class EncryptedRouteInterceptor {
|
|
|
124
133
|
intercept(context, next) {
|
|
125
134
|
const http = context.switchToHttp();
|
|
126
135
|
return next.handle().pipe((0, operators_1.map)((value) => {
|
|
127
|
-
const param =
|
|
136
|
+
const param = (0, get_encryption_password_1.get_encryption_password)(context.getClass());
|
|
128
137
|
if (!param)
|
|
129
138
|
throw new Error(`Error on EncryptedRoute.${this.method}(): no password found.`);
|
|
130
139
|
const request = http.getRequest();
|
|
@@ -139,6 +148,11 @@ class EncryptedRouteInterceptor {
|
|
|
139
148
|
: param;
|
|
140
149
|
if (body === undefined)
|
|
141
150
|
return body;
|
|
151
|
+
// the ciphertext is text/plain, as the document declares; set on the
|
|
152
|
+
// success path alone, so an error keeps its JSON body's type (Express
|
|
153
|
+
// would otherwise send a string as text/html)
|
|
154
|
+
const response = http.getResponse();
|
|
155
|
+
response.header("Content-Type", "text/plain");
|
|
142
156
|
return AesPkcs5_1.AesPkcs5.encrypt(body, password.key, password.iv);
|
|
143
157
|
}), (0, operators_1.catchError)((err) => (0, route_error_1.route_error)(http.getRequest(), err)));
|
|
144
158
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EncryptedRoute.js","sourceRoot":"","sources":["../../src/decorators/EncryptedRoute.ts"],"names":[],"mappings":";;;;;;AACA,2DAAwD;AACxD,2CAWwB;AAGxB,8CAAiD;AACjD,kDAA0B;AAG1B,kDAA+C;AAC/C,6CAA0C;AAC1C,
|
|
1
|
+
{"version":3,"file":"EncryptedRoute.js","sourceRoot":"","sources":["../../src/decorators/EncryptedRoute.ts"],"names":[],"mappings":"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"}
|
|
@@ -11,5 +11,10 @@
|
|
|
11
11
|
*
|
|
12
12
|
* @author Jeongho Nam - https://github.com/samchon
|
|
13
13
|
* @returns Method decorator
|
|
14
|
+
* @evidence contracts/common.md#principled-implementation The decorator marks the operation with the `x-samchon-human` extension through `SwaggerCustomizer`, so the generated document carries the mark without another metadata path.
|
|
15
|
+
* @evidence contracts/common.md#clear-and-simple-design One call to the customizer.
|
|
16
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts The extension name is the documented contract of the generated document.
|
|
17
|
+
* @evidence contracts/common.md#meaningful-documentation The comment states that a marked API is left out of the LLM function calling schema.
|
|
18
|
+
* @evidenceExclude contracts/portability.md#os-neutral-implementation The OpenAPI extension is an in-memory document property and has no native path or process representation.
|
|
14
19
|
*/
|
|
15
20
|
export declare function HumanRoute(): MethodDecorator;
|