Skip to content

Commit

Permalink
Merge pull request #1053 from samchon/feature/validate.log
Browse files Browse the repository at this point in the history
Allow only `validate.log` option and use `typia.json.validateStringify()`.
  • Loading branch information
samchon authored Sep 26, 2024
2 parents 40d4e04 + 4136e6e commit eea1532
Show file tree
Hide file tree
Showing 21 changed files with 65 additions and 52 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"private": true,
"name": "@nestia/station",
"version": "3.15.0",
"version": "3.16.0",
"description": "Nestia station",
"scripts": {
"build": "node build/index.js",
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "nestia",
"version": "6.1.0",
"version": "6.2.0",
"description": "Nestia CLI tool",
"main": "bin/index.js",
"bin": {
Expand Down
1 change: 1 addition & 0 deletions packages/cli/src/internal/PluginConfigurator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ export namespace PluginConfigurator {
* - "assert": Use typia.assertStringify() function
* - "is": Use typia.isStringify() function
* - "validate": Use typia.validateStringify() function
* - "validate.log": typia.validateStringify(), but do not throw and just log it
* - "stringify": Use typia.stringify() function, but dangerous
* - null: Just use JSON.stringify() function, without boosting
*/
Expand Down
6 changes: 3 additions & 3 deletions packages/core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@nestia/core",
"version": "3.15.0",
"version": "3.16.0",
"description": "Super-fast validation decorators of NestJS",
"main": "lib/index.js",
"typings": "lib/index.d.ts",
Expand Down Expand Up @@ -36,7 +36,7 @@
},
"homepage": "https://nestia.io",
"dependencies": {
"@nestia/fetcher": "^3.15.0",
"@nestia/fetcher": "^3.16.0",
"@nestjs/common": ">=7.0.1",
"@nestjs/core": ">=7.0.1",
"@samchon/openapi": "^1.1.0",
Expand All @@ -53,7 +53,7 @@
"ws": "^7.5.3"
},
"peerDependencies": {
"@nestia/fetcher": ">=3.15.0",
"@nestia/fetcher": ">=3.16.0",
"@nestjs/common": ">=7.0.1",
"@nestjs/core": ">=7.0.1",
"reflect-metadata": ">=0.1.12",
Expand Down
6 changes: 3 additions & 3 deletions packages/core/src/decorators/EncryptedRoute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,9 @@ export namespace EncryptedRoute {
* instead of throwing the 400 bad request error.
*
* By the way, be careful. If you've configured the response
* transformation option to be `validate.log` or `validateEquals.log`,
* client may get wrong response data. Therefore, this way is not
* recommended in the common backend server case.
* transformation option to be `validate.log`, client may get wrong
* response data. Therefore, this way is not recommended in the common
* backend server case.
*
* @param func Logger function
* @default console.log
Expand Down
11 changes: 8 additions & 3 deletions packages/core/src/decorators/TypedRoute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,9 @@ export namespace TypedRoute {
* instead of throwing the 400 bad request error.
*
* By the way, be careful. If you've configured the response
* transformation option to be `validate.log` or `validateEquals.log`,
* client may get wrong response data. Therefore, this way is not
* recommendedin the common backend server case.
* transformation option to be `validate.log`, client may get wrong
* response data. Therefore, this way is not recommended in the common
* backend server case.
*
* @param func Logger function
* @default console.log
Expand Down Expand Up @@ -126,6 +126,11 @@ export namespace TypedRoute {
* Validation error informations with detailed reasons.
*/
errors: IValidation.IError[];

/**
* Data that is not following the promised type `T`.
*/
data: unknown;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,7 @@ const take =
else if (functor.type === "assert") return assert(functor.assert);
else if (functor.type === "is") return is(functor.is);
else if (functor.type === "validate") return validate(functor.validate);
else if (
functor.type === "validate.log" ||
functor.type === "validateEquals.log"
)
else if (functor.type === "validate.log")
return validateLog(logger)(functor.validate);
throw new Error(
`Error on nestia.core.${method}(): invalid typed stringify function.`,
Expand Down Expand Up @@ -107,12 +104,14 @@ const validateLog =
(logger: () => (log: TypedRoute.IValidateErrorLog) => void) =>
<T>(closure: (data: T) => IValidation<any>) =>
(data: T, method: string, path: string): string => {
const result: IValidation<any> = closure(data);
const result: IValidation<string> = closure(data);
if (result.success === true) return result.data;
if (result.success === false)
logger()({
errors: result.errors,
method,
path,
data,
});
return JSON.stringify(data);
};
Expand Down
1 change: 0 additions & 1 deletion packages/core/src/options/INestiaTransformOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ export interface INestiaTransformOptions {
| "is"
| "validate"
| "validate.log"
| "validateEquals.log"
| null;
throws?: boolean;
}
4 changes: 2 additions & 2 deletions packages/core/src/options/IResponseBodyStringifier.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export namespace IResponseBodyStringifier {
validate: (input: T) => IValidation<string>;
}
export interface IValidateLog<T> {
type: "validate.log" | "validateEquals.log";
validate: (input: T) => IValidation<T>;
type: "validate.log";
validate: (input: T) => IValidation<string>;
}
}
11 changes: 1 addition & 10 deletions packages/core/src/programmers/TypedRouteProgrammer.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import ts from "typescript";
import { ValidateProgrammer } from "typia/lib/programmers/ValidateProgrammer";
import { JsonAssertStringifyProgrammer } from "typia/lib/programmers/json/JsonAssertStringifyProgrammer";
import { JsonIsStringifyProgrammer } from "typia/lib/programmers/json/JsonIsStringifyProgrammer";
import { JsonStringifyProgrammer } from "typia/lib/programmers/json/JsonStringifyProgrammer";
Expand Down Expand Up @@ -60,15 +59,7 @@ export namespace TypedRouteProgrammer {
return parameter({
type: "validate.log",
key: "validate",
programmer: (project) => (modulo) =>
ValidateProgrammer.write(project)(modulo)(false),
});
else if (project.options.stringify === "validateEquals.log")
return parameter({
type: "validateEquals.log",
key: "validate",
programmer: (project) => (modulo) =>
ValidateProgrammer.write(project)(modulo)(true),
programmer: JsonValidateStringifyProgrammer.write,
});
else if (project.options.stringify === null)
return ts.factory.createNull();
Expand Down
2 changes: 1 addition & 1 deletion packages/fetcher/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@nestia/fetcher",
"version": "3.15.0",
"version": "3.16.0",
"description": "Fetcher library of Nestia SDK",
"main": "lib/index.js",
"typings": "lib/index.d.ts",
Expand Down
10 changes: 5 additions & 5 deletions packages/sdk/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@nestia/sdk",
"version": "3.15.0",
"version": "3.16.0",
"description": "Nestia SDK and Swagger generator",
"main": "lib/index.js",
"typings": "lib/index.d.ts",
Expand Down Expand Up @@ -32,8 +32,8 @@
},
"homepage": "https://nestia.io",
"dependencies": {
"@nestia/core": "^3.15.0",
"@nestia/fetcher": "^3.15.0",
"@nestia/core": "^3.16.0",
"@nestia/fetcher": "^3.16.0",
"@samchon/openapi": "^1.1.0",
"cli": "^1.0.1",
"get-function-location": "^2.0.0",
Expand All @@ -47,8 +47,8 @@
"typia": "^6.11.0"
},
"peerDependencies": {
"@nestia/core": ">=3.15.0",
"@nestia/fetcher": ">=3.15.0",
"@nestia/core": ">=3.16.0",
"@nestia/fetcher": ">=3.16.0",
"@nestjs/common": ">=7.0.1",
"@nestjs/core": ">=7.0.1",
"reflect-metadata": ">=0.1.12",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ export const test_api_bbs_article_at = async (
],
method: "GET",
path: `/bbs/articles/${id}`,
data: {
id,
title: "Hello, world!",
body: "This is a test article.",
thumbnail: null,
created_at: "wrong-data",
},
},
]);
};
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"openapi":"3.1.0","servers":[{"url":"https://github.com/samchon/nestia","description":"insert your server url"}],"info":{"version":"3.15.0-dev.20240926","title":"@samchon/nestia-test","description":"Test program of Nestia","license":{"name":"MIT"}},"paths":{"/bbs/articles/{id}":{"get":{"tags":[],"parameters":[{"name":"id","in":"path","schema":{"type":"string","format":"uuid"},"required":true}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IBbsArticle"}}}}}}},"/health":{"get":{"tags":[],"parameters":[],"responses":{"200":{"description":"","content":{"application/json":{}}}}}}},"components":{"schemas":{"IBbsArticle":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"},"body":{"type":"string"},"thumbnail":{"oneOf":[{"type":"null"},{"type":"string","format":"uri","contentMediaType":"image/*"}]},"created_at":{"type":"string","format":"date-time"}},"required":["id","title","body","thumbnail","created_at"]}},"securitySchemes":{"bearer":{"type":"apiKey"}}},"tags":[],"x-samchon-emended":true}
{"openapi":"3.1.0","servers":[{"url":"https://github.com/samchon/nestia","description":"insert your server url"}],"info":{"version":"3.16.0-dev.20240926","title":"@samchon/nestia-test","description":"Test program of Nestia","license":{"name":"MIT"}},"paths":{"/bbs/articles/{id}":{"get":{"tags":[],"parameters":[{"name":"id","in":"path","schema":{"type":"string","format":"uuid"},"required":true}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IBbsArticle"}}}}}}},"/health":{"get":{"tags":[],"parameters":[],"responses":{"200":{"description":"","content":{"application/json":{}}}}}}},"components":{"schemas":{"IBbsArticle":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"},"body":{"type":"string"},"thumbnail":{"oneOf":[{"type":"null"},{"type":"string","format":"uri","contentMediaType":"image/*"}]},"created_at":{"type":"string","format":"date-time"}},"required":["id","title","body","thumbnail","created_at"]}},"securitySchemes":{"bearer":{"type":"apiKey"}}},"tags":[],"x-samchon-emended":true}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ export const test_api_bbs_article_at = async (
],
method: "GET",
path: `/bbs/articles/${id}`,
data: {
id,
title: "Hello, world!",
body: "This is a test article.",
thumbnail: null,
created_at: "wrong-data",
},
},
]);
};
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"openapi":"3.1.0","servers":[{"url":"https://github.com/samchon/nestia","description":"insert your server url"}],"info":{"version":"3.15.0-dev.20240926","title":"@samchon/nestia-test","description":"Test program of Nestia","license":{"name":"MIT"}},"paths":{"/bbs/articles/{id}":{"get":{"tags":[],"parameters":[{"name":"id","in":"path","schema":{"type":"string","format":"uuid"},"required":true}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IBbsArticle"}}}}}}},"/health":{"get":{"tags":[],"parameters":[],"responses":{"200":{"description":"","content":{"application/json":{}}}}}}},"components":{"schemas":{"IBbsArticle":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"},"body":{"type":"string"},"thumbnail":{"oneOf":[{"type":"null"},{"type":"string","format":"uri","contentMediaType":"image/*"}]},"created_at":{"type":"string","format":"date-time"}},"required":["id","title","body","thumbnail","created_at"]}},"securitySchemes":{"bearer":{"type":"apiKey"}}},"tags":[],"x-samchon-emended":true}
{"openapi":"3.1.0","servers":[{"url":"https://github.com/samchon/nestia","description":"insert your server url"}],"info":{"version":"3.16.0-dev.20240926","title":"@samchon/nestia-test","description":"Test program of Nestia","license":{"name":"MIT"}},"paths":{"/bbs/articles/{id}":{"get":{"tags":[],"parameters":[{"name":"id","in":"path","schema":{"type":"string","format":"uuid"},"required":true}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IBbsArticle"}}}}}}},"/health":{"get":{"tags":[],"parameters":[],"responses":{"200":{"description":"","content":{"application/json":{}}}}}}},"components":{"schemas":{"IBbsArticle":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"},"body":{"type":"string"},"thumbnail":{"oneOf":[{"type":"null"},{"type":"string","format":"uri","contentMediaType":"image/*"}]},"created_at":{"type":"string","format":"date-time"}},"required":["id","title","body","thumbnail","created_at"]}},"securitySchemes":{"bearer":{"type":"apiKey"}}},"tags":[],"x-samchon-emended":true}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ export const test_api_bbs_article_at = async (
],
method: "GET",
path: `/bbs/articles/${id}`,
data: {
id,
title: "Hello, world!",
body: "This is a test article.",
thumbnail: null,
created_at: "wrong-data",
},
},
]);
};
2 changes: 1 addition & 1 deletion test/features/route-manual-validate-log/swagger.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"openapi":"3.1.0","servers":[{"url":"https://github.com/samchon/nestia","description":"insert your server url"}],"info":{"version":"3.15.0-dev.20240926","title":"@samchon/nestia-test","description":"Test program of Nestia","license":{"name":"MIT"}},"paths":{"/bbs/articles/{id}":{"get":{"tags":[],"parameters":[{"name":"id","in":"path","schema":{"type":"string","format":"uuid"},"required":true}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IBbsArticle"}}}}}}},"/health":{"get":{"tags":[],"parameters":[],"responses":{"200":{"description":"","content":{"application/json":{}}}}}}},"components":{"schemas":{"IBbsArticle":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"},"body":{"type":"string"},"thumbnail":{"oneOf":[{"type":"null"},{"type":"string","format":"uri","contentMediaType":"image/*"}]},"created_at":{"type":"string","format":"date-time"}},"required":["id","title","body","thumbnail","created_at"]}},"securitySchemes":{"bearer":{"type":"apiKey"}}},"tags":[],"x-samchon-emended":true}
{"openapi":"3.1.0","servers":[{"url":"https://github.com/samchon/nestia","description":"insert your server url"}],"info":{"version":"3.16.0-dev.20240926","title":"@samchon/nestia-test","description":"Test program of Nestia","license":{"name":"MIT"}},"paths":{"/bbs/articles/{id}":{"get":{"tags":[],"parameters":[{"name":"id","in":"path","schema":{"type":"string","format":"uuid"},"required":true}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IBbsArticle"}}}}}}},"/health":{"get":{"tags":[],"parameters":[],"responses":{"200":{"description":"","content":{"application/json":{}}}}}}},"components":{"schemas":{"IBbsArticle":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"},"body":{"type":"string"},"thumbnail":{"oneOf":[{"type":"null"},{"type":"string","format":"uri","contentMediaType":"image/*"}]},"created_at":{"type":"string","format":"date-time"}},"required":["id","title","body","thumbnail","created_at"]}},"securitySchemes":{"bearer":{"type":"apiKey"}}},"tags":[],"x-samchon-emended":true}
8 changes: 4 additions & 4 deletions test/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"private": true,
"name": "@samchon/nestia-test",
"version": "3.15.0",
"version": "3.16.0",
"description": "Test program of Nestia",
"main": "index.js",
"scripts": {
Expand All @@ -26,7 +26,7 @@
},
"homepage": "https://nestia.io",
"devDependencies": {
"@nestia/sdk": "^3.15.0",
"@nestia/sdk": "^3.16.0",
"@nestjs/swagger": "^7.4.2",
"@samchon/openapi": "^1.1.0",
"@types/express": "^4.17.17",
Expand All @@ -40,9 +40,9 @@
},
"dependencies": {
"@fastify/multipart": "^8.1.0",
"@nestia/core": "^3.15.0",
"@nestia/core": "^3.16.0",
"@nestia/e2e": "^0.7.0",
"@nestia/fetcher": "^3.15.0",
"@nestia/fetcher": "^3.16.0",
"@nestjs/common": "^10.4.4",
"@nestjs/core": "^10.4.4",
"@nestjs/platform-express": "^10.4.4",
Expand Down
16 changes: 7 additions & 9 deletions website/pages/docs/core/TypedRoute.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -551,12 +551,11 @@ For reference, such encryption spec is not supported in the [Swagger-UI](../sdk/
{
"transform": "@nestia/core/lib/transform",
"stringify": "assert",
// "stringify": typia.stringify without validation
// "assert": typia.assertStringify
// "is": typia.isStringify
// "validate": typia.validateStringify
// "validate.log": do not throw error, just log
// "validateEquals".log: do not throw error, just log
// "assert": typia.assertStringify<T>()
// "is": typia.isStringify<T>()
// "validate": typia.validateStringify<T>()
// "validate.log": typia.validateStringify<T>(), but do not throw error and just log it
// "stringify": typia.stringify<T>() without validation
}
]
}
Expand All @@ -573,13 +572,12 @@ Here is the list of available options.
- `assert`: [`typia.json.assertStringify<T>()`](https://typia.io/docs/json/stringify/)
- `is`: [`typia.json.isStringify<T>()`](https://typia.io/docs/json/stringify/)
- `validate`: [`typia.json.validateStringify<T>()`](https://typia.io/docs/json/stringify/)
- `validate.log`: [`typia.json.validateStringify<T>()`](https://typia.io/docs/json/stringify/), but do not throw error and just log it
- `null`: just use `JSON.stringify()` function without validation
- `validate.log`: do not throw error, but just log by [`typia.validate<T>()`](https://typia.io/docs/validators/validate/)
- `validateEquals.log`: do not throw error, but just log by [`typia.validateEquals<T>()`](https://typia.io/docs/validators/validate/#validateequals-function)

By the way, this is not a recommended way, but you can skip the response type validation for. If you set the `stringify` property to `null`, the response type validation will be skipped and just `JSON.stringify()` function be used.

Also, `validate.log` and `validateEquals.log` perform the validation, but do not throw 500 internal server error. When type error be detected, it seralizes response data by `JSON.stringify()` function, and logs the error message to the console or somewhere you've specified. It is useful when you want to know the error message, but do not want to throw 500 internal server error to the client application.
Also, `validate.log` performs the validation, but does not throw 500 internal server error. When type error be detected, it seralizes response data by `JSON.stringify()` function, and logs the error message to the console or somewhere you've specified. It is useful when you want to know the error message, but do not want to throw 500 internal server error to the client application.

```typescript
TypedRoute.setValidateErrorLogger((err: TypedRoute.IValidateErrorLog) => {
Expand Down
1 change: 0 additions & 1 deletion website/pages/docs/setup.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,6 @@ As `@nestia/core` and `typia` are generating optimal validation and JSON seriali
- [`assertClone`](https://typia.io/docs/misc/#clone-functions) or [`validateClone`](https://typia.io/docs/misc/#clone-functions): deep clone with type checking for faster pruning
- Only for `stringify`
- [`validate.log`](https://typia.io/docs/validators/validate/): check response data, but do not throw error and just log it
- [`validateEquals.log`](https://typia.io/docs/validators/validate/#validateequals-function): check response data, but do not throw error and just log it

Also, never forget to configure `strict` (or `strictNullChecks`) as `true`. It is essential option for modern TypeScript development.

Expand Down

0 comments on commit eea1532

Please sign in to comment.