Skip to content

Commit

Permalink
Merge pull request #238 from samchon/features/comments
Browse files Browse the repository at this point in the history
Complement #209 - documentation by comments
  • Loading branch information
samchon authored Jan 27, 2023
2 parents 3b20be0 + be2871c commit 741dbe8
Show file tree
Hide file tree
Showing 14 changed files with 105 additions and 53 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ All functions in `typia` require **only one line**. You don't need any extra ded

Also, as `typia` performs AOT (Ahead of Time) compilation skill, its performance is much faster than other competitive libaries. For an example, when comparing validate function `is()` with other competitive libraries, `typia` is maximum **15,000x times faster** than `class-validator`.

## Reactia
### Reactia
> https://github.com/samchon/reactia
>
> Not published yet, but soon
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "nestia",
"version": "4.0.4",
"version": "4.0.5",
"description": "Nestia CLI",
"main": "bin/index.js",
"bin": {
Expand Down
2 changes: 1 addition & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@nestia/core",
"version": "1.0.9",
"version": "1.0.10",
"description": "Super-fast validation decorators of NestJS",
"main": "lib/index.js",
"typings": "lib/index.d.ts",
Expand Down
23 changes: 21 additions & 2 deletions packages/core/src/decorators/DynamicModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,35 @@ import { ModuleMetadata } from "@nestjs/common/interfaces";
import { Creator } from "../typings/Creator";
import { load_controllers } from "./internal/load_controller";

/**
* Dynamic module.
*
* `DynamicModule` is a namespace wrapping a convenient function, which can load
* controller classes dynamically just by specifying their directory path.
*
* @author Jeongho Nam - https://github.com/samchon
*/
export namespace DynamicModule {
/**
* Mount dynamic module.
*
* Constructs a module instance with directory path of controller classes.
*
* Every controller classes in the target directory would be dynamically mounted.
*
* @param path Path of controllers
* @param metadata Addtional metadata except controllers
* @returns module instance
*/
export async function mount(
path: string,
options: Omit<ModuleMetadata, "controllers"> = {},
metadata: Omit<ModuleMetadata, "controllers"> = {},
): Promise<object> {
// LOAD CONTROLLERS
const controllers: Creator<object>[] = await load_controllers(path);

// RETURN WITH DECORATING
@Module({ ...options, controllers })
@Module({ ...metadata, controllers })
class NestiaModule {}
return NestiaModule;
}
Expand Down
20 changes: 12 additions & 8 deletions packages/core/src/decorators/EncryptedBody.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
} from "@nestjs/common";
import type express from "express";
import raw from "raw-body";

import { assert, is, validate } from "typia";

import { IRequestBodyValidator } from "../options/IRequestBodyValidator";
Expand All @@ -17,14 +18,15 @@ import { validate_request_body } from "./internal/validate_request_body";
/**
* Encrypted body decorator.
*
* `EncryptedBody` is a decorator function getting JSON data from HTTP request who've
* been encrypted by AES-128/256 algorithm. Also, `EncyrptedBody` validates the JSON
* data type through
* [`typia.assert()`](https://github.com/samchon/typia#runtime-type-checkers)
* function and throws `BadRequestException` error (status code: 400), if the JSON
* data is not following the promised type.
* `EncryptedBody` is a decorator function getting `application/json` typed data from
* requeset body which has been encrypted by AES-128/256 algorithm. Also,
* `EncyrptedBody` validates the request body data type through
* [typia](https://github.com/samchon/typia) ad the validation speed is
* maximum 15,000x times faster than `class-validator`.
*
* For reference, `EncryptedRoute` decrypts request body usnig those options.
* For reference, when the request body data is not following the promised type `T`,
* `BadRequestException` error (status code: 400) would be thrown. Also,
* `EncryptedRoute` decrypts request body usnig those options.
*
* - AES-128/256
* - CBC mode
Expand All @@ -34,7 +36,9 @@ import { validate_request_body } from "./internal/validate_request_body";
* @return Parameter decorator
* @author Jeongho Nam - https://github.com/samchon
*/
export function EncryptedBody<T>(validator?: IRequestBodyValidator<T>) {
export function EncryptedBody<T>(
validator?: IRequestBodyValidator<T>,
): ParameterDecorator {
const checker = validate_request_body("EncryptedBody")(validator);
return createParamDecorator(async function EncryptedBody(
_unknown: any,
Expand Down
21 changes: 10 additions & 11 deletions packages/core/src/decorators/EncryptedRoute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
import { HttpArgumentsHost } from "@nestjs/common/interfaces";
import express from "express";
import { Observable, catchError, map } from "rxjs";

import {
assertStringify,
isStringify,
Expand All @@ -24,6 +25,7 @@ import {
import { IResponseBodyStringifier } from "../options/IResponseBodyStringifier";
import { Singleton } from "../utils/Singleton";
import { ENCRYPTION_METADATA_KEY } from "./internal/EncryptedConstant";
import { TransformError } from "./internal/TransformError";
import { get_path_and_stringify } from "./internal/get_path_and_stringify";
import { headers_to_object } from "./internal/headers_to_object";
import { route_error } from "./internal/route_error";
Expand All @@ -32,21 +34,20 @@ import { route_error } from "./internal/route_error";
* Encrypted router decorator functions.
*
* `EncryptedRoute` is a module containing router decorator functions which encrypts
* response body data through AES-128/250 encryption. Also, those decorator functions
* can boost up JSON string conversion speed about 5x times faster, through
* [`typia.stringify()`](https://github.com/samchon/typia#fastest-json-string-conversion).
* response body data through AES-128/250 encryption. Furthermore, they can boost
* up JSON string conversion speed about 10x times faster, even type safe through
* [typia](https://github.com/samchon/typia).
*
* For reference, `EncryptedRoute` encrypts response body usnig those options.
* For reference, router functions of `EncryptedRoute` can convert custom error classes
* to regular {@link nest.HttpException} class automatically, through
* {@link ExceptionManager}. Also, `EncryptedRoute` encrypts response body usnig those
* options.
*
* - AES-128/256
* - CBC mode
* - PKCS #5 Padding
* - Base64 Encoding
*
* Also, router functions in `EncryptedRoute` can convert custom error classes to the
* regular {@link nest.HttpException} class automatically, through
* {@link ExceptionManager}.
*
* @author Jeongho Nam - https://github.com/samchon
*/
export namespace EncryptedRoute {
Expand Down Expand Up @@ -155,9 +156,7 @@ class EncryptedRouteInterceptor implements NestInterceptor {
context.getClass(),
);
if (!param)
throw new Error(
`Error on nestia.core.EncryptedRoute.${this.method}(): no encryption password is given.`,
);
throw TransformError(`EncryptedRoute.${this.method}`);

const headers: Singleton<Record<string, string>> =
new Singleton(() => {
Expand Down
15 changes: 9 additions & 6 deletions packages/core/src/decorators/TypedBody.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,22 @@ import {
} from "@nestjs/common";
import type express from "express";
import raw from "raw-body";

import { assert, is, validate } from "typia";

import { IRequestBodyValidator } from "../options/IRequestBodyValidator";
import { validate_request_body } from "./internal/validate_request_body";

/**
* Safe body decorator.
* Type safe body decorator.
*
* `TypedBody` is a decoratur function getting `application/json` typed data from
* request body. Also, it validates the request body data type through
* [typia](https://github.com/samchon/typia) and the validation speed is
* maximum 15,000x times faster than `class-validator`.
*
* `TypedBody` is a decorator function getting JSON data from HTTP request. Also,
* it validates the JSON data type through
* [`typia.assert()`](https://github.com/samchon/typia#runtime-type-checkers)
* function and throws `BadRequestException` error (status code: 400), if the JSON
* data is not following the promised type.
* For reference, when the request body data is not following the promised type `T`,
* `BadRequestException` error (status code: 400) would be thrown.
*
* @param validator Custom validator if required. Default is `typia.assert()`
* @author Jeongho Nam - https://github.com/samchon
Expand Down
12 changes: 6 additions & 6 deletions packages/core/src/decorators/TypedParam.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ import {
import type express from "express";

/**
* URL parameter decorator with type.
* Type safe URL parameter decorator.
*
* `TypedParam` is a decorator function getting specific typed parameter from the HTTP
* request URL. It's almost same with the {@link nest.Param}, but `TypedParam` can specify
* the parameter type manually. Beside, the {@link nest.Param} always parses all of the
* parameters as string type.
* `TypedParam` is a decorator function getting specific typed parameter from the
* HTTP request URL. It's almost same with the {@link nest.Param}, but `TypedParam`
* can specify the parameter type manually. Beside, the {@link nest.Param} always
* parses all of the parameters as string type.
*
* ```typescript
* \@TypedRoute.Get("shopping/sales/:section/:id/:paused")
Expand All @@ -33,7 +33,7 @@ export function TypedParam(
name: string,
type: "boolean" | "number" | "string" | "uuid" = "string",
nullable: boolean = false,
) {
): ParameterDecorator {
return createParamDecorator(function TypedParam(
{}: any,
ctx: ExecutionContext,
Expand Down
25 changes: 22 additions & 3 deletions packages/core/src/decorators/TypedQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,25 @@ import express from "express";

import { assert } from "typia";

export function TypedQuery(decoder?: (params: URLSearchParams) => any) {
if (decoder === undefined)
throw new Error("Error on TypedQuery(): no decoder function provided.");
import { TransformError } from "./internal/TransformError";

/**
* Type safe URL query decorator.
*
* `TypedQuery` is a decorator function that can parse URL query string. It is almost
* same with {@link nest.Query}, but it can automatically cast property type following
* its DTO definition. Also, `TypedQuery` performs type validation.
*
* For referecen, when URL query parameters are different with their promised
* type `T`, `BadRequestException` error (status code: 400) would be thrown.
*
* @returns Parameter decorator
* @author Jeongho Nam - https://github.com/samchon
*/
export function TypedQuery<T>(
decoder?: (params: URLSearchParams) => T,
): ParameterDecorator {
if (decoder === undefined) throw TransformError("TypedQuery");

return createParamDecorator(async function TypedQuery(
_unknown: any,
Expand Down Expand Up @@ -36,6 +52,9 @@ export namespace TypedQuery {
}
Object.assign(TypedQuery, assert);

/**
* @internal
*/
function tail(url: string): string {
const index: number = url.indexOf("?");
return index === -1 ? "" : url.substring(index + 1);
Expand Down
11 changes: 6 additions & 5 deletions packages/core/src/decorators/TypedRoute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
import { HttpArgumentsHost } from "@nestjs/common/interfaces";
import express from "express";
import { Observable, catchError, map } from "rxjs";

import {
assertStringify,
isStringify,
Expand All @@ -25,14 +26,14 @@ import { get_path_and_stringify } from "./internal/get_path_and_stringify";
import { route_error } from "./internal/route_error";

/**
* Safe router decorator functions.
* Type safe router decorator functions.
*
* `TypedRoute` is a module containing router decorator functions which can boost up
* JSON string conversion speed about 5x times faster, through
* [`typia.stringify()`](https://github.com/samchon/typia#fastest-json-string-conversion).
* JSON string conversion speed about 10x times faster. Furthermore, such JSON string
* conversion is even type safe through [typia](https://github.com/samchon/typia).
*
* Also, router functions in `TypedRoute` can convert custom error classes to the
* regular {@link nest.HttpException} class automatically, through
* For reference, router functions of `TypedRoute` can convert custom error classes to
* the regular {@link nest.HttpException} class automatically, through
* {@link ExceptionManager}.
*
* @author Jeongho Nam - https://github.com/samchon
Expand Down
8 changes: 8 additions & 0 deletions packages/core/src/decorators/internal/TransformError.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/**
* @internal
*/
export function TransformError(method: string): Error {
return new Error(
`Error on nestia.core.${method}(): no transform has been configured. Configure "tsconfig.json" file following [Guide Documents](https://github.com/samchon/nestia/wiki/Setup#tsconfigjson).`,
);
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { InternalServerErrorException } from "@nestjs/common";

import { IValidation, TypeGuardError } from "typia";

import { IResponseBodyStringifier } from "../../options/IResponseBodyStringifier";
import { TransformError } from "./TransformError";

export const get_path_and_stringify =
(method: string) =>
Expand All @@ -22,10 +24,7 @@ export const get_path_and_stringify =
const take =
(method: string) =>
<T>(functor?: IResponseBodyStringifier<T> | null) => {
if (functor === undefined)
throw new Error(
`Error on nestia.core.${method}(): no stringify function provided.`,
);
if (functor === undefined) throw TransformError(method);
else if (functor === null) return JSON.stringify;
else if (functor.type === "stringify") return functor.stringify;
else if (functor.type === "assert") return assert(functor.assert);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import { BadRequestException } from "@nestjs/common";

import { IValidation, TypeGuardError } from "typia";

import { IRequestBodyValidator } from "../../options/IRequestBodyValidator";
import { TransformError } from "./TransformError";

export const validate_request_body =
(method: string) =>
<T>(validator?: IRequestBodyValidator<T>) => {
if (!validator)
throw new Error(
`Error on nestia.core.${method}(): no transformer.`,
);
if (!validator) throw TransformError(method);
else if (validator.type === "assert") return assert(validator.assert);
else if (validator.type === "is") return is(validator.is);
else if (validator.type === "validate")
Expand Down
3 changes: 2 additions & 1 deletion src/NestiaSetupWizard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ export namespace NestiaSetupWizard {
await fs.promises.readFile("package.json", "utf8"),
);
add(args.manager)(pack)("@nestia/core", false);
add(args.manager)(pack)("@nestia/sdk", false);
add(args.manager)(pack)("@nestia/sdk", true);
add(args.manager)(pack)("nestia", true);

const modulo: typeof import("@nestia/core/lib/executable/internal/CoreSetupWizard") =
await import(
Expand Down

0 comments on commit 741dbe8

Please sign in to comment.