diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5cb1dd646..e7b309bbc 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -10,30 +10,8 @@ jobs: with: node-version: 16.x - - name: fetcher - working-directory: ./packages/fetcher + - name: test + working-directory: ./test run: | npm install - npm run build - - - name: core - working-directory: ./packages/core - run: | - npm install - npm run build - npm run build:test - npm run test - - - name: sdk - working-directory: ./packages/sdk - run: | - npm install - npm run build - npm run test - - - name: e2e - working-directory: ./packages/e2e - run: | - npm install - npm run build - npm run test \ No newline at end of file + npm run start \ No newline at end of file diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 000000000..43e075cde --- /dev/null +++ b/.prettierignore @@ -0,0 +1,4 @@ +api/functional +bin +lib +node_modules \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..e955fc350 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,10 @@ +{ + "editor.tabSize": 4, + "[typescript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true, + "editor.codeActionsOnSave": { + "source.fixAll.eslint": true + }, + } + } \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 000000000..0f60e9376 --- /dev/null +++ b/package.json @@ -0,0 +1,27 @@ +{ + "private": true, + "name": "@nestia/station", + "version": "0.0.0", + "description": "Nestia station", + "main": "prettier.config.js", + "directories": { + "test": "test" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/samchon/nestia.git" + }, + "author": "Jeongho Nam", + "license": "MIT", + "bugs": { + "url": "https://github.com/samchon/nestia/issues" + }, + "homepage": "https://github.com/samchon/nestia#readme", + "devDependencies": { + "@trivago/prettier-plugin-sort-imports": "^4.1.1", + "prettier": "^2.8.8" + } +} diff --git a/packages/core/package.json b/packages/core/package.json index 60f259ba4..e62dae073 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -6,15 +6,13 @@ "typings": "lib/index.d.ts", "scripts": { "build": "rimraf lib && tsc", - "build:test": "rimraf bin && tsc -p test/tsconfig.json", "dev": "npm run build -- --watch", "eslint": "eslint ./**/*.ts", "eslint:fix": "eslint ./**/*.ts --fix", - "package:latest": "npm run build && npm run build:test && npm run test && npm publish --access public", + "package:latest": "npm run build && npm publish --access public", "package:next": "npm run package:latest -- --tag next", "prepare": "ts-patch install", - "prettier": "prettier ./**/*.ts --write", - "test": "node bin/test" + "prettier": "prettier ./**/*.ts --write" }, "repository": { "type": "git", @@ -63,9 +61,9 @@ "prettier": "^2.8.7", "rimraf": "^3.0.2", "ts-node": "^10.9.1", - "ts-patch": "3.0.0-beta3", + "ts-patch": "^2.1.0", "tstl": "^2.5.13", - "typescript": "^5.0.4", + "typescript": "^4.9.5", "typescript-transform-paths": "^3.4.6" }, "files": [ diff --git a/packages/core/test/api/__internal/AesPkcs5.ts b/packages/core/test/api/__internal/AesPkcs5.ts deleted file mode 100644 index 641e52cbf..000000000 --- a/packages/core/test/api/__internal/AesPkcs5.ts +++ /dev/null @@ -1 +0,0 @@ -export { AesPkcs5 } from "@nestia/fetcher"; diff --git a/packages/core/test/api/__internal/Fetcher.ts b/packages/core/test/api/__internal/Fetcher.ts deleted file mode 100644 index c956d8fe1..000000000 --- a/packages/core/test/api/__internal/Fetcher.ts +++ /dev/null @@ -1 +0,0 @@ -export { Fetcher } from "@nestia/fetcher"; diff --git a/packages/core/test/api/functional/consumers/index.ts b/packages/core/test/api/functional/consumers/index.ts deleted file mode 100644 index 072a598bf..000000000 --- a/packages/core/test/api/functional/consumers/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -/** - * @packageDocumentation - * @module api.functional.consumers - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -//================================================================ -export * as sales from "./sales"; diff --git a/packages/core/test/api/functional/consumers/sales/articles/comments/index.ts b/packages/core/test/api/functional/consumers/sales/articles/comments/index.ts deleted file mode 100644 index 36e92ed58..000000000 --- a/packages/core/test/api/functional/consumers/sales/articles/comments/index.ts +++ /dev/null @@ -1,65 +0,0 @@ -/** - * @packageDocumentation - * @module api.functional.consumers.sales.articles.comments - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -//================================================================ -import { Fetcher, Primitive } from "@nestia/fetcher"; -import type { IConnection } from "@nestia/fetcher"; - -import type { ISaleArticleComment } from "./../../../../../structures/ISaleArticleComment"; - -/** - * Store a new comment. - * - * @param connection connection Information of the remote HTTP(s) server with headers (+encryption password) - * @param request Instance of the Express.Request - * @param section Code of the target section - * @param saleId ID of the target sale - * @param articleId ID of the target article - * @param input Content to write - * @return Newly archived comment - * @throw 400 bad request error when type of the input data is not valid - * @throw 401 unauthorized error when you've not logged in yet - * @throw 403 forbidden error when you're a seller and the sale is not yours - * @throw 404 not found error when unable to find the matched record - * - * @controller ConsumerSaleArticleCommentsController.store() - * @path POST /consumers/:section/sales/:saleId/articles/:articleId/comments - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -export function store( - connection: IConnection, - section: string, - saleId: number, - articleId: number, - input: Primitive, -): Promise { - return Fetcher.fetch( - connection, - store.ENCRYPTED, - store.METHOD, - store.path(section, saleId, articleId), - input, - ); -} -export namespace store { - export type Input = Primitive; - export type Output = Primitive; - - export const METHOD = "POST" as const; - export const PATH: string = - "/consumers/:section/sales/:saleId/articles/:articleId/comments"; - export const ENCRYPTED: Fetcher.IEncrypted = { - request: false, - response: false, - }; - - export function path( - section: string, - saleId: number, - articleId: number, - ): string { - return `/consumers/${section}/sales/${saleId}/articles/${articleId}/comments`; - } -} diff --git a/packages/core/test/api/functional/consumers/sales/articles/index.ts b/packages/core/test/api/functional/consumers/sales/articles/index.ts deleted file mode 100644 index 55865877e..000000000 --- a/packages/core/test/api/functional/consumers/sales/articles/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -/** - * @packageDocumentation - * @module api.functional.consumers.sales.articles - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -//================================================================ -export * as comments from "./comments"; diff --git a/packages/core/test/api/functional/consumers/sales/index.ts b/packages/core/test/api/functional/consumers/sales/index.ts deleted file mode 100644 index dc03db970..000000000 --- a/packages/core/test/api/functional/consumers/sales/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -/** - * @packageDocumentation - * @module api.functional.consumers.sales - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -//================================================================ -export * as articles from "./articles"; -export * as questions from "./questions"; -export * as reviews from "./reviews"; diff --git a/packages/core/test/api/functional/consumers/sales/questions/index.ts b/packages/core/test/api/functional/consumers/sales/questions/index.ts deleted file mode 100644 index 4903e1660..000000000 --- a/packages/core/test/api/functional/consumers/sales/questions/index.ts +++ /dev/null @@ -1,59 +0,0 @@ -/** - * @packageDocumentation - * @module api.functional.consumers.sales.questions - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -//================================================================ -import { Fetcher, Primitive } from "@nestia/fetcher"; -import type { IConnection } from "@nestia/fetcher"; - -import type { ISaleArticle } from "./../../../../structures/ISaleArticle"; -import type { ISaleInquiry } from "./../../../../structures/ISaleInquiry"; - -/** - * Store a new inquiry. - * - * Write a new article inquirying about a sale. - * - * @param connection connection Information of the remote HTTP(s) server with headers (+encryption password) - * @param request Instance of the Express.Request - * @param section Code of the target section - * @param saleId ID of the target sale - * @param input Content to archive - * @return Newly archived inquiry - * @throw 400 bad request error when type of the input data is not valid - * @throw 401 unauthorized error when you've not logged in yet - * - * @controller ConsumerSaleQuestionsController.store() - * @path POST /consumers/:section/sales/:saleId/questions - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -export function store( - connection: IConnection, - section: string, - saleId: string, - input: Primitive, -): Promise { - return Fetcher.fetch( - connection, - store.ENCRYPTED, - store.METHOD, - store.path(section, saleId), - input, - ); -} -export namespace store { - export type Input = Primitive; - export type Output = Primitive>; - - export const METHOD = "POST" as const; - export const PATH: string = "/consumers/:section/sales/:saleId/questions"; - export const ENCRYPTED: Fetcher.IEncrypted = { - request: false, - response: false, - }; - - export function path(section: string, saleId: string): string { - return `/consumers/${section}/sales/${saleId}/questions`; - } -} diff --git a/packages/core/test/api/functional/consumers/sales/reviews/index.ts b/packages/core/test/api/functional/consumers/sales/reviews/index.ts deleted file mode 100644 index 2774d295d..000000000 --- a/packages/core/test/api/functional/consumers/sales/reviews/index.ts +++ /dev/null @@ -1,59 +0,0 @@ -/** - * @packageDocumentation - * @module api.functional.consumers.sales.reviews - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -//================================================================ -import { Fetcher, Primitive } from "@nestia/fetcher"; -import type { IConnection } from "@nestia/fetcher"; - -import type { ISaleInquiry } from "./../../../../structures/ISaleInquiry"; -import type { ISaleReview } from "./../../../../structures/ISaleReview"; - -/** - * Store a new inquiry. - * - * Write a new article inquirying about a sale. - * - * @param connection connection Information of the remote HTTP(s) server with headers (+encryption password) - * @param request Instance of the Express.Request - * @param section Code of the target section - * @param saleId ID of the target sale - * @param input Content to archive - * @return Newly archived inquiry - * @throw 400 bad request error when type of the input data is not valid - * @throw 401 unauthorized error when you've not logged in yet - * - * @controller ConsumerSaleReviewsController.store() - * @path POST /consumers/:section/sales/:saleId/reviews - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -export function store( - connection: IConnection, - section: string, - saleId: string, - input: Primitive, -): Promise { - return Fetcher.fetch( - connection, - store.ENCRYPTED, - store.METHOD, - store.path(section, saleId), - input, - ); -} -export namespace store { - export type Input = Primitive; - export type Output = Primitive>; - - export const METHOD = "POST" as const; - export const PATH: string = "/consumers/:section/sales/:saleId/reviews"; - export const ENCRYPTED: Fetcher.IEncrypted = { - request: false, - response: false, - }; - - export function path(section: string, saleId: string): string { - return `/consumers/${section}/sales/${saleId}/reviews`; - } -} diff --git a/packages/core/test/api/functional/filesystem/index.ts b/packages/core/test/api/functional/filesystem/index.ts deleted file mode 100644 index 46c80e70a..000000000 --- a/packages/core/test/api/functional/filesystem/index.ts +++ /dev/null @@ -1,52 +0,0 @@ -/** - * @packageDocumentation - * @module api.functional.filesystem - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -//================================================================ -import { Fetcher, Primitive } from "@nestia/fetcher"; -import type { IConnection } from "@nestia/fetcher"; - -import type { IFilesystemBucket } from "./../../structures/IFilesystemBucket"; - -/** - * @controller FilesystemController.get() - * @path GET /filesystem - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -export function get( - connection: IConnection, - query: get.Query, -): Promise { - return Fetcher.fetch( - connection, - get.ENCRYPTED, - get.METHOD, - get.path(query), - ); -} -export namespace get { - export type Output = Primitive>; - export type Query = Primitive; - - export const METHOD = "GET" as const; - export const PATH: string = "/filesystem"; - export const ENCRYPTED: Fetcher.IEncrypted = { - request: false, - response: false, - }; - - export function path(query: Query): string { - const variables = { - ...query, - }; - const search = new URLSearchParams(); - for (const [key, value] of Object.entries(variables)) - if (value === undefined) continue; - else if (Array.isArray(value)) - value.forEach((elem) => search.append(key, String(elem))); - else search.set(key, String(value)); - const encoded: string = new URLSearchParams(search).toString(); - return `/filesystem${encoded.length ? `?${encoded}` : ""}`; - } -} diff --git a/packages/core/test/api/functional/index.ts b/packages/core/test/api/functional/index.ts deleted file mode 100644 index 3b8006c9b..000000000 --- a/packages/core/test/api/functional/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -/** - * @packageDocumentation - * @module api.functional - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -//================================================================ -export * as consumers from "./consumers"; -export * as filesystem from "./filesystem"; -export * as system from "./system"; diff --git a/packages/core/test/api/functional/monitors/index.ts b/packages/core/test/api/functional/monitors/index.ts deleted file mode 100644 index d75f754da..000000000 --- a/packages/core/test/api/functional/monitors/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -/** - * @packageDocumentation - * @module api.functional.monitors - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -//================================================================ -export * as system from "./system"; diff --git a/packages/core/test/api/structures/IAttachmentFile.ts b/packages/core/test/api/structures/IAttachmentFile.ts deleted file mode 100644 index 12bcdfdd8..000000000 --- a/packages/core/test/api/structures/IAttachmentFile.ts +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Attachemd (physical) file info. - * - * @author Jeongho Nam - https://github.com/samchon - */ -export interface IAttachmentFile { - /** - * Primary Key. - */ - id: number; - - /** - * Name of the file. - */ - name: string; - - /** - * Extension of the file, but ommitable. - */ - extension: string | null; - - /** - * Full URL path of the file. - */ - url: string; -} diff --git a/packages/core/test/api/structures/IFilesystemBucket.ts b/packages/core/test/api/structures/IFilesystemBucket.ts deleted file mode 100644 index 4dc89816f..000000000 --- a/packages/core/test/api/structures/IFilesystemBucket.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { IFilesystemDirectory } from "./IFilesystemDirectory"; -import { IFilesystemFile } from "./IFilesystemFile"; -import { IPage } from "./IPage"; - -export type IFilesystemBucket = IFilesystemDirectory | IFilesystemFile; -export namespace IFilesystemBucket { - export interface IBase { - type: Type; - id: string; - name: string; - } - - export interface IRequest extends IPage.IRequest { - extension?: string; - trashed?: boolean; - locations: string[]; - } -} diff --git a/packages/core/test/api/structures/IFilesystemDirectory.ts b/packages/core/test/api/structures/IFilesystemDirectory.ts deleted file mode 100644 index 1c32cc211..000000000 --- a/packages/core/test/api/structures/IFilesystemDirectory.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { IFilesystemBucket } from "./IFilesystemBucket"; - -export interface IFilesystemDirectory - extends IFilesystemBucket.IBase<"directory"> { - children: IFilesystemBucket[]; -} diff --git a/packages/core/test/api/structures/IFilesystemFile.ts b/packages/core/test/api/structures/IFilesystemFile.ts deleted file mode 100644 index 49d3da77b..000000000 --- a/packages/core/test/api/structures/IFilesystemFile.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { IFilesystemBucket } from "./IFilesystemBucket"; -import { IFilesystemImageFile } from "./IFilesystemImageFile"; -import { IFilesystemTextFile } from "./IFilesystemTextFile"; -import { IFilesystemZipFile } from "./IFilesystemZipFile"; - -export type IFilesystemFile = - | IFilesystemImageFile - | IFilesystemTextFile - | IFilesystemZipFile; -export namespace IFilesystemFile { - export interface IBase - extends IFilesystemBucket.IBase<"file"> { - extension: Extension; - size: number; - } -} diff --git a/packages/core/test/api/structures/IFilesystemImageFile.ts b/packages/core/test/api/structures/IFilesystemImageFile.ts deleted file mode 100644 index b9b374b09..000000000 --- a/packages/core/test/api/structures/IFilesystemImageFile.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { IFilesystemFile } from "./IFilesystemFile"; - -export interface IFilesystemImageFile - extends IFilesystemFile.IBase<"jpg" | "png" | "gif"> { - width: number; - height: number; - url: string; -} diff --git a/packages/core/test/api/structures/IFilesystemTextFile.ts b/packages/core/test/api/structures/IFilesystemTextFile.ts deleted file mode 100644 index 0e158f010..000000000 --- a/packages/core/test/api/structures/IFilesystemTextFile.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { IFilesystemFile } from "./IFilesystemFile"; - -export interface IFilesystemTextFile - extends IFilesystemFile.IBase<"txt" | "md" | "ts"> { - content: string; -} diff --git a/packages/core/test/api/structures/IFilesystemZipFile.ts b/packages/core/test/api/structures/IFilesystemZipFile.ts deleted file mode 100644 index 96c1ea9de..000000000 --- a/packages/core/test/api/structures/IFilesystemZipFile.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { IFilesystemFile } from "./IFilesystemFile"; - -export interface IFilesystemZipFile extends IFilesystemFile.IBase<"zip"> { - count: number; -} diff --git a/packages/core/test/api/structures/IPage.ts b/packages/core/test/api/structures/IPage.ts deleted file mode 100644 index 44e4eda45..000000000 --- a/packages/core/test/api/structures/IPage.ts +++ /dev/null @@ -1,21 +0,0 @@ -export interface IPage { - pagination: IPage.IPagination; - data: T[]; -} -export namespace IPage { - export interface IPagination { - page: number; - limit: number; - total_count: number; - total_pages: number; - } - export interface IRequest { - page?: number; - limit?: number; - } - export namespace IRequest { - export type Sort = Array< - `-${Literal}` | `+${Literal}` - >; - } -} diff --git a/packages/core/test/api/structures/ISaleArticle.ts b/packages/core/test/api/structures/ISaleArticle.ts deleted file mode 100644 index 3a2e26ad2..000000000 --- a/packages/core/test/api/structures/ISaleArticle.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { IAttachmentFile } from "./IAttachmentFile"; - -/** - * Article about a sale. - * - * The `ISaleArticle` is a super type interface. Many sub-type articles would be - * designed by extending this super type interface `ISaleArticle`. - * - * @template Content Content type. - * @author Jeongho Nam - https://github.com/samchon - */ -export interface ISaleArticle { - /** - * Primary Key. - */ - id: number; - - /** - * Hit count. - * - * How many consumers had read. - */ - hit: number; - - /** - * List of contents. - * - * When the article writer tries to modify content, it would not modify the article - * content but would be accumulated. Therefore, all of the people can read how - * the content has been changed. - */ - contents: Content[]; - - /** - * Creation time. - */ - created_at: string; -} -export namespace ISaleArticle { - /** - * Content info. - */ - export interface IContent extends IStore { - /** - * Primary Key - */ - id: string; - - /** - * Creation time. - */ - created_at: string; - } - - /** - * Store info. - */ - export interface IStore { - /** - * Title of the content. - */ - title: string; - - /** - * Body of the content. - */ - body: string; - - /** - * Attached files. - */ - files: IAttachmentFile[]; - } -} diff --git a/packages/core/test/api/structures/ISaleArticleComment.ts b/packages/core/test/api/structures/ISaleArticleComment.ts deleted file mode 100644 index 8ed21f4d8..000000000 --- a/packages/core/test/api/structures/ISaleArticleComment.ts +++ /dev/null @@ -1,88 +0,0 @@ -/** - * Comment wrote on a sale related article. - * - * When an article of a sale has been enrolled, all of the participants like consumers and - * sellers can write a comment on that article. However, when the writer is a consumer, the - * consumer can hide its name through the annoymous option. - * - * Also, writing a reply comment for a specific comment is possible and in that case, the - * {@link ISaleArticleComment.parent_id} property would be activated. - * - * @author Jeongho Nam - https://github.com/samchon - */ -export interface ISaleArticleComment { - /** - * Primary Key. - */ - id: number; - - /** - * Parent comment ID. - * - * Only When this comment has been written as a reply. - */ - parent_id: number | null; - - /** - * Type of the writer. - */ - writer_type: "seller" | "consumer"; - - /** - * Name of the writer. - * - * When this is a type of anonymous comment, writer name would be hidden. - */ - writer_name: string | null; - - /** - * Contents of the comments. - * - * When the comment writer tries to modify content, it would not modify the comment - * content but would be accumulated. Therefore, all of the people can read how - * the content has been changed. - */ - contents: ISaleArticleComment.IContent[]; - - /** - * Creation time. - */ - created_at: string; -} - -export namespace ISaleArticleComment { - /** - * Store info. - */ - export interface IStore { - /** - * Body of the content. - */ - body: string; - - /** - * Whether to hide the writer name or not. - */ - annonymous: boolean; - } - - /** - * Content info. - */ - export interface IContent { - /** - * Primary Key. - */ - id: string; - - /** - * Body of the content. - */ - body: string; - - /** - * Creation time. - */ - created_at: string; - } -} diff --git a/packages/core/test/api/structures/ISaleInquiry.ts b/packages/core/test/api/structures/ISaleInquiry.ts deleted file mode 100644 index 327bba7f3..000000000 --- a/packages/core/test/api/structures/ISaleInquiry.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { ISaleArticle } from "./ISaleArticle"; -import { ISaleInquiryAnswer } from "./ISaleInquiryAnswer"; - -/** - * Inquiry article. - * - * Sub-type of article and super-type of question and answer. - * - * @template Content Content type - * @author Jeongho Nam - https://github.com/samchon - */ -export interface ISaleInquiry - extends ISaleArticle { - /** - * Name of the writer. - */ - writer: string; - - /** - * Formal answer from the seller. - */ - answer: ISaleInquiryAnswer | null; -} -export namespace ISaleInquiry { - /** - * Content type of the inquiry article. - */ - export type IContent = ISaleArticle.IContent; - - /** - * Store info of the inquiry article. - */ - export type IStore = ISaleArticle.IStore; -} diff --git a/packages/core/test/api/structures/ISaleInquiryAnswer.ts b/packages/core/test/api/structures/ISaleInquiryAnswer.ts deleted file mode 100644 index 361d98b2b..000000000 --- a/packages/core/test/api/structures/ISaleInquiryAnswer.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { ISaleArticle } from "./ISaleArticle"; - -/** - * Formal answer from the seller. - * - * When a consumer writes an inquiry about a sale, the seller can write a formal - * answer article. This `ISaleInquiryAnswer` has been designed to represent such - * formal answer article from the seller. - * - * @author Jeongho Nam - https://github.com/samchon - */ -export type ISaleInquiryAnswer = ISaleArticle; -export namespace ISaleInquiryAnswer { - /** - * Content type of the answer. - */ - export type IContent = ISaleArticle.IContent; - - /** - * Store info of the answer. - */ - export type IStore = ISaleArticle.IContent; -} diff --git a/packages/core/test/api/structures/ISaleQuestion.ts b/packages/core/test/api/structures/ISaleQuestion.ts deleted file mode 100644 index bce431fe0..000000000 --- a/packages/core/test/api/structures/ISaleQuestion.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { ISaleInquiry } from "./ISaleInquiry"; - -/** - * Question article. - * - * The `ISaleQuestion` is a type of question article wrriten by a consumer - * who has something to ask about the sale. - * - * @author Jeongho Nam - https://github.com/samchon - */ -export type ISaleQuestion = ISaleInquiry; -export namespace ISaleQuestion { - /** - * Content info of the question. - */ - export type IContent = ISaleInquiry.IContent; - - /** - * Store info of the question. - */ - export type IStore = ISaleInquiry.IStore; -} diff --git a/packages/core/test/api/structures/ISaleReview.ts b/packages/core/test/api/structures/ISaleReview.ts deleted file mode 100644 index f27afff91..000000000 --- a/packages/core/test/api/structures/ISaleReview.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { ISaleInquiry } from "./ISaleInquiry"; - -/** - * Review article. - * - * The `ISaleReview` is a type of review article written by a consumer who've bought - * the sale good with the estimation score. - * - * @author Jeongho Nam - https://github.com/samchon - */ -export type ISaleReview = ISaleInquiry; -export namespace ISaleReview { - /** - * Content info of the review. - */ - export interface IContent extends ISaleInquiry.IContent { - /** - * Estimation score. - */ - score: number; - } - - /** - * Store info of the review. - */ - export interface IStore extends ISaleInquiry.IStore { - /** - * Estimation score. - */ - score: number; - } -} diff --git a/packages/core/test/controllers/ConsumerSaleArticleCommentsController.ts b/packages/core/test/controllers/ConsumerSaleArticleCommentsController.ts deleted file mode 100644 index 16d1f4533..000000000 --- a/packages/core/test/controllers/ConsumerSaleArticleCommentsController.ts +++ /dev/null @@ -1,54 +0,0 @@ -import core from "@nestia/core"; -import * as nest from "@nestjs/common"; -import * as express from "express"; - -import { ISaleArticleComment } from "../api/structures/ISaleArticleComment"; - -@nest.Controller( - "consumers/:section/sales/:saleId/articles/:articleId/comments", -) -export class ConsumerSaleArticleCommentsController { - /** - * Store a new comment. - * - * @param request Instance of the Express.Request - * @param section Code of the target section - * @param saleId ID of the target sale - * @param articleId ID of the target article - * @param input Content to write - * @return Newly archived comment - * - * @throw 400 bad request error when type of the input data is not valid - * @throw 401 unauthorized error when you've not logged in yet - * @throw 403 forbidden error when you're a seller and the sale is not yours - * @throw 404 not found error when unable to find the matched record - */ - @core.TypedRoute.Post() - public async store( - @nest.Request() request: express.Request, - @core.TypedParam("section", "string") section: string, - @core.TypedParam("saleId", "number") saleId: number, - @core.TypedParam("articleId", "number") articleId: number, - @core.TypedBody() input: ISaleArticleComment.IStore, - ): Promise { - request; - section; - saleId; - articleId; - - return { - id: 0, - parent_id: null, - writer_type: "consumer", - writer_name: input.annonymous ? null : "someone", - contents: [ - { - id: "some-id", - body: input.body, - created_at: new Date().toString(), - }, - ], - created_at: new Date().toString(), - }; - } -} diff --git a/packages/core/test/controllers/ConsumerSaleQuestionsController.ts b/packages/core/test/controllers/ConsumerSaleQuestionsController.ts deleted file mode 100644 index fec5c1c22..000000000 --- a/packages/core/test/controllers/ConsumerSaleQuestionsController.ts +++ /dev/null @@ -1,35 +0,0 @@ -import * as nest from "@nestjs/common"; -import typia from "typia"; - -import { ISaleQuestion } from "../api/structures/ISaleQuestion"; -import { SaleInquiriesController } from "./SaleInquiriesController"; - -@nest.Controller("consumers/:section/sales/:saleId/questions") -export class ConsumerSaleQuestionsController extends SaleInquiriesController< - ISaleQuestion.IContent, - ISaleQuestion.IStore, - ISaleQuestion ->({ - index: (input) => typia.assertStringify(input), - at: (input) => typia.isStringify(input), - assert: (input) => typia.assert(input), -}) { - public constructor() { - super((input) => ({ - id: 0, - writer: "someone", - contents: [ - { - id: "some-id", - title: input.title, - body: input.body, - files: input.files, - created_at: new Date().toString(), - }, - ], - answer: null, - hit: 0, - created_at: new Date().toString(), - })); - } -} diff --git a/packages/core/test/controllers/ConsumerSaleReviewsController.ts b/packages/core/test/controllers/ConsumerSaleReviewsController.ts deleted file mode 100644 index aa787ac53..000000000 --- a/packages/core/test/controllers/ConsumerSaleReviewsController.ts +++ /dev/null @@ -1,36 +0,0 @@ -import * as nest from "@nestjs/common"; -import typia from "typia"; - -import { ISaleReview } from "../api/structures/ISaleReview"; -import { SaleInquiriesController } from "./SaleInquiriesController"; - -@nest.Controller("consumers/:section/sales/:saleId/reviews") -export class ConsumerSaleReviewsController extends SaleInquiriesController< - ISaleReview.IContent, - ISaleReview.IStore, - ISaleReview ->({ - index: (input) => typia.assertStringify(input), - at: (input) => typia.isStringify(input), - assert: (input) => typia.assert(input), -}) { - public constructor() { - super((input) => ({ - id: 0, - writer: "someone", - contents: [ - { - id: "some-id", - title: input.title, - body: input.body, - score: input.score, - files: input.files, - created_at: new Date().toString(), - }, - ], - answer: null, - hit: 0, - created_at: new Date().toString(), - })); - } -} diff --git a/packages/core/test/controllers/FilesystemController.ts b/packages/core/test/controllers/FilesystemController.ts deleted file mode 100644 index 27a9859ab..000000000 --- a/packages/core/test/controllers/FilesystemController.ts +++ /dev/null @@ -1,54 +0,0 @@ -import core from "@nestia/core"; -import * as nest from "@nestjs/common"; - -import { IFilesystemBucket } from "../api/structures/IFilesystemBucket"; - -@nest.Controller("filesystem") -export class FilesystemController { - @core.TypedRoute.Get() - public get( - @core.TypedQuery() _input: IFilesystemBucket.IRequest, - ): IFilesystemBucket[] { - return [ - { - type: "directory", - id: "7b1068a4-dd6e-474a-8d85-09a2d77639cb", - name: "ixcWGOKI", - children: [ - { - type: "directory", - id: "5883e17c-b207-46d4-ad2d-be72249711ce", - name: "vecQwFGS", - children: [], - }, - { - type: "file", - id: "670b6556-a610-4a48-8a16-9c2da97a0d18", - name: "eStFddzX", - extension: "jpg", - size: 7, - width: 300, - height: 1200, - url: "https://github.com/samchon/typia", - }, - { - type: "file", - id: "85dc796d-9593-4833-b1a1-addc8ebf74ea", - name: "kTdUfwRJ", - extension: "ts", - size: 86, - content: 'console.log("Hello world");', - }, - { - type: "file", - id: "8933c86a-7a1e-4d4a-b0a6-17d6896fdf89", - name: "NBPkefUG", - extension: "zip", - size: 22, - count: 20, - }, - ], - }, - ]; - } -} diff --git a/packages/core/test/controllers/SaleInquiriesController.ts b/packages/core/test/controllers/SaleInquiriesController.ts deleted file mode 100644 index eeee00d13..000000000 --- a/packages/core/test/controllers/SaleInquiriesController.ts +++ /dev/null @@ -1,80 +0,0 @@ -import core from "@nestia/core"; -import * as nest from "@nestjs/common"; -import * as express from "express"; - -import { IPage } from "../api/structures/IPage"; -import { ISaleInquiry } from "../api/structures/ISaleInquiry"; - -export function SaleInquiriesController< - Content extends ISaleInquiry.IContent, - Store extends ISaleInquiry.IStore, - Json extends ISaleInquiry, ->(trait: SaleInquiriesController.ITrait) { - class SaleInquiriesController { - protected constructor( - private readonly convert: (input: Store) => Json, - ) {} - - @core.TypedRoute.Get({ - type: "assert", - assert: trait.index, - }) - public async index( - @nest.Request() request: express.Request, - @core.TypedParam("section", "string") section: string, - @core.TypedParam("saleId", "string") saleId: string, - @core.TypedBody() input: IPage.IRequest, - ): Promise> { - request; - section; - saleId; - input; - - return null!; - } - - /** - * Store a new inquiry. - * - * Write a new article inquirying about a sale. - * - * @param request Instance of the Express.Request - * @param section Code of the target section - * @param saleId ID of the target sale - * @param input Content to archive - * @return Newly archived inquiry - * - * @throw 400 bad request error when type of the input data is not valid - * @throw 401 unauthorized error when you've not logged in yet - */ - @core.TypedRoute.Post({ - type: "is", - is: trait.at, - }) - public async store( - @nest.Request() request: express.Request, - @core.TypedParam("section", "string") section: string, - @core.TypedParam("saleId", "string") saleId: string, - @core.TypedBody({ - type: "assert", - assert: trait.assert, - }) - input: Store, - ): Promise { - request; - section; - saleId; - - const data = this.convert(input); - return data; - } - } - return SaleInquiriesController; -} -export namespace SaleInquiriesController { - export interface ITrait { - index(input: IPage): string; - at(input: Json): string | null; - assert(input: Store): Store; - } -} diff --git a/packages/core/test/controllers/SystemController.ts b/packages/core/test/controllers/SystemController.ts deleted file mode 100644 index 8f5136c6a..000000000 --- a/packages/core/test/controllers/SystemController.ts +++ /dev/null @@ -1,55 +0,0 @@ -import core from "@nestia/core"; -import * as nest from "@nestjs/common"; -import fs from "fs"; -import git from "git-last-commit"; -import { randint } from "tstl/algorithm/random"; -import { Singleton } from "tstl/thread/Singleton"; - -import { ISystem } from "../api/structures/ISystem"; - -@nest.Controller("system") -export class SystemController { - @core.EncryptedRoute.Get() - public async get(): Promise { - return { - uid: uid_, - arguments: process.argv, - created_at: created_at_.toString(), - package: await package_.get(), - commit: await commit_.get(), - }; - } -} - -const uid_: number = randint(0, Number.MAX_SAFE_INTEGER); -const created_at_: Date = new Date(); - -const commit_: Singleton> = new Singleton( - () => - new Promise((resolve, reject) => { - git.getLastCommit((err, commit) => { - if (err) reject(err); - else - resolve({ - ...commit, - authored_at: new Date( - Number(commit.authoredOn) * 1000, - ).toString(), - commited_at: new Date( - Number(commit.committedOn) * 1000, - ).toString(), - }); - }); - }), -); -const package_: Singleton> = new Singleton( - async () => { - const content: string = await fs.promises.readFile( - `${__dirname}/../../../package.json`, - "utf8", - ); - return JSON.parse(content); - }, -); -commit_.get().catch(() => {}); -package_.get().catch(() => {}); diff --git a/packages/core/test/controllers/TypedParamController.ts b/packages/core/test/controllers/TypedParamController.ts deleted file mode 100644 index ce2535b8c..000000000 --- a/packages/core/test/controllers/TypedParamController.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { TypedParam } from "@nestia/core"; -import { Controller, Get } from "@nestjs/common"; - -const str = "string" as const; - -@Controller("typed") -export class TypedParamController { - @Get("auto/:p1") - public auto(@TypedParam("p1") p1: string): void { - p1; - } - - @Get("type/:p1") - public type(@TypedParam("p1", str) p1: string | null): void { - p1; - } - - @Get("nullable/:p1") - public nullable(@TypedParam("p1", str, true) p1: string | null): void { - p1; - } -} diff --git a/packages/core/test/features/test_comments.ts b/packages/core/test/features/test_comments.ts deleted file mode 100644 index 08f12df36..000000000 --- a/packages/core/test/features/test_comments.ts +++ /dev/null @@ -1,19 +0,0 @@ -import typia from "typia"; - -import api from "../api"; -import { ISaleArticleComment } from "../api/structures/ISaleArticleComment"; - -export async function test_comment(connection: api.IConnection): Promise { - const comment: ISaleArticleComment = - await api.functional.consumers.sales.articles.comments.store( - connection, - "general", - 0, - 0, - { - body: "Hello, world!", - annonymous: false, - }, - ); - typia.assertEquals(comment); -} diff --git a/packages/core/test/features/test_filesystem.ts b/packages/core/test/features/test_filesystem.ts deleted file mode 100644 index 2a89da042..000000000 --- a/packages/core/test/features/test_filesystem.ts +++ /dev/null @@ -1,31 +0,0 @@ -import typia from "typia"; - -import api from "../api"; -import { IFilesystemBucket } from "../api/structures/IFilesystemBucket"; - -export async function test_filesystem( - connection: api.IConnection, -): Promise { - const buckets: IFilesystemBucket[] = await api.functional.filesystem.get( - connection, - { - locations: ["a", "b", "c"], - trashed: false, - extension: "jpg", - }, - ); - typia.assertEquals(buckets); - - try { - await api.functional.filesystem.get(connection, { - locations: ["a", "b", "c"], - trashed: "something" as any, // WRONG - extension: "jpg", - }); - } catch (exp) { - if (exp instanceof api.HttpError) { - if (exp.status === 400) return; - } - } - throw new Error("Must be 400 error in here."); -} diff --git a/packages/core/test/features/test_questions.ts b/packages/core/test/features/test_questions.ts deleted file mode 100644 index ec0937a7f..000000000 --- a/packages/core/test/features/test_questions.ts +++ /dev/null @@ -1,21 +0,0 @@ -import typia from "typia"; - -import api from "../api"; -import { ISaleQuestion } from "../api/structures/ISaleQuestion"; - -export async function test_question( - connection: api.IConnection, -): Promise { - const question: ISaleQuestion = - await api.functional.consumers.sales.questions.store( - connection, - "generla", - "sale-id", - { - title: "some-title", - body: "some-body", - files: [], - }, - ); - typia.assertEquals(question); -} diff --git a/packages/core/test/features/test_reviews.ts b/packages/core/test/features/test_reviews.ts deleted file mode 100644 index e34d3ffbe..000000000 --- a/packages/core/test/features/test_reviews.ts +++ /dev/null @@ -1,20 +0,0 @@ -import typia from "typia"; - -import api from "../api"; -import { ISaleReview } from "../api/structures/ISaleReview"; - -export async function test_review(connection: api.IConnection): Promise { - const review: ISaleReview = - await api.functional.consumers.sales.reviews.store( - connection, - "generla", - "sale-id", - { - title: "some-title", - body: "some-body", - score: 100, - files: [], - }, - ); - typia.assertEquals(review); -} diff --git a/packages/core/test/features/test_system.ts b/packages/core/test/features/test_system.ts deleted file mode 100644 index 6bf221c02..000000000 --- a/packages/core/test/features/test_system.ts +++ /dev/null @@ -1,9 +0,0 @@ -import typia from "typia"; - -import api from "../api"; -import { ISystem } from "../api/structures/ISystem"; - -export async function test_system(connection: api.IConnection): Promise { - const system: ISystem = await api.functional.system.get(connection); - typia.assertEquals(system); -} diff --git a/packages/core/test/index.ts b/packages/core/test/index.ts deleted file mode 100644 index a83a136e1..000000000 --- a/packages/core/test/index.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { IEncryptionPassword } from "@nestia/fetcher"; -import { NestFactory } from "@nestjs/core"; - -import { EncryptedModule } from "../src"; -import api from "./api"; -import { test_comment } from "./features/test_comments"; -import { test_filesystem } from "./features/test_filesystem"; -import { test_question } from "./features/test_questions"; -import { test_review } from "./features/test_reviews"; -import { test_system } from "./features/test_system"; - -const ENCRYPTION_PASSWORD: IEncryptionPassword = { - key: "abcd".repeat(8), - iv: "abcd".repeat(4), -}; - -async function feature( - connection: api.IConnection, - func: (connection: api.IConnection) => Promise, -): Promise { - console.log(func.name); - await func(connection); -} - -async function main(): Promise { - // OPEN SERVER - const app = await NestFactory.create( - await EncryptedModule.dynamic( - __dirname + "/controllers", - ENCRYPTION_PASSWORD, - ), - ); - await app.listen(36999); - - // DO TEST - const connection: api.IConnection = { - host: "http://127.0.0.1:36999", - encryption: ENCRYPTION_PASSWORD, - }; - await feature(connection, test_comment); - await feature(connection, test_filesystem); - await feature(connection, test_question); - await feature(connection, test_review); - await feature(connection, test_system); - - // CLOSE - await app.close(); -} -main().catch((exp) => { - console.log(exp); - process.exit(-1); -}); diff --git a/packages/core/test/tsconfig.json b/packages/core/test/tsconfig.json deleted file mode 100644 index d91e23c81..000000000 --- a/packages/core/test/tsconfig.json +++ /dev/null @@ -1,112 +0,0 @@ -{ - "compilerOptions": { - /* Visit https://aka.ms/tsconfig.json to read more about this file */ - - /* Projects */ - // "incremental": true, /* Enable incremental compilation */ - // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ - // "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */ - // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */ - // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ - // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ - - /* Language and Environment */ - "target": "ES2015", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ - "lib": [ - "DOM", - "ES2015" - ], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ - // "jsx": "preserve", /* Specify what JSX code is generated. */ - "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ - "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ - // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */ - // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ - // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */ - // "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */ - // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ - // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ - - /* Modules */ - "module": "commonjs", /* Specify what module code is generated. */ - // "rootDir": "./", /* Specify the root folder within your source files. */ - // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ - // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ - "paths": { - "@nestia/core": ["../src"], - "@nestia/core/lib/*": ["../src/*"] - }, /* Specify a set of entries that re-map imports to additional lookup locations. */ - // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ - // "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */ - // "types": [], /* Specify type package names to be included without being referenced in a source file. */ - // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ - // "resolveJsonModule": true, /* Enable importing .json files */ - // "noResolve": true, /* Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project. */ - - /* JavaScript Support */ - // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */ - // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ - // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */ - - /* Emit */ - // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ - // "declarationMap": true, /* Create sourcemaps for d.ts files. */ - // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ - "sourceMap": true, /* Create source map files for emitted JavaScript files. */ - // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */ - "outDir": "../bin", /* Specify an output folder for all emitted files. */ - // "removeComments": true, /* Disable emitting comments. */ - // "noEmit": true, /* Disable emitting files from a compilation. */ - // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ - // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */ - "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ - // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ - // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ - // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ - // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ - // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ - // "newLine": "crlf", /* Set the newline character for emitting files. */ - // "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */ - // "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */ - // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ - // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */ - // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ - // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ - - /* Interop Constraints */ - // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ - // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ - "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */ - // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ - "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ - - /* Type Checking */ - "strict": true, /* Enable all strict type-checking options. */ - // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */ - // "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */ - // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ - // "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */ - // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ - // "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */ - // "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */ - // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ - // "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */ - // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */ - // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ - // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ - // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ - // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ - // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ - // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */ - // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ - // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ - - /* Completeness */ - // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ - "skipLibCheck": true, /* Skip type checking all .d.ts files. */ - "plugins": [ - { "transform": "../src/transform.ts" }, - { "transform": "typescript-transform-paths" }, - { "transform": "typia/lib/transform" }, - ] - } -} diff --git a/packages/sdk/demo/176/src/Configuration.ts b/packages/sdk/demo/176/src/Configuration.ts deleted file mode 100644 index 01a3f1f12..000000000 --- a/packages/sdk/demo/176/src/Configuration.ts +++ /dev/null @@ -1,7 +0,0 @@ -export namespace Configuration { - export const PORT = 12345; - export const ENCRYPTION_PASSWORD = { - key: "a".repeat(32), - iv: "b".repeat(16), - }; -} diff --git a/packages/sdk/demo/176/src/api/functional/userspace/index.ts b/packages/sdk/demo/176/src/api/functional/userspace/index.ts deleted file mode 100644 index 4f8300d3a..000000000 --- a/packages/sdk/demo/176/src/api/functional/userspace/index.ts +++ /dev/null @@ -1,87 +0,0 @@ -/** - * @packageDocumentation - * @module api.functional.userspace - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -//================================================================ -import { Fetcher, Primitive } from "@nestia/fetcher"; -import type { IConnection } from "@nestia/fetcher"; - -import type { Userspace } from "./../../structures/Userspace"; - -/** - * Type one. - * - * @returns something - * @deprecated - * - * @controller UserspaceController.type1() - * @path GET /userspace/type1 - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -export function type1 - ( - connection: IConnection - ): Promise -{ - return Fetcher.fetch - ( - connection, - type1.ENCRYPTED, - type1.METHOD, - type1.path() - ); -} -export namespace type1 -{ - export type Output = Primitive; - - export const METHOD = "GET" as const; - export const PATH: string = "/userspace/type1"; - export const ENCRYPTED: Fetcher.IEncrypted = { - request: false, - response: false, - }; - - export function path(): string - { - return `/userspace/type1`; - } -} - -/** - * @internal - * - * @controller UserspaceController.type2() - * @path GET /userspace/type2 - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -export function type2 - ( - connection: IConnection - ): Promise -{ - return Fetcher.fetch - ( - connection, - type2.ENCRYPTED, - type2.METHOD, - type2.path() - ); -} -export namespace type2 -{ - export type Output = Primitive; - - export const METHOD = "GET" as const; - export const PATH: string = "/userspace/type2"; - export const ENCRYPTED: Fetcher.IEncrypted = { - request: false, - response: false, - }; - - export function path(): string - { - return `/userspace/type2`; - } -} \ No newline at end of file diff --git a/packages/sdk/demo/176/src/api/index.ts b/packages/sdk/demo/176/src/api/index.ts deleted file mode 100644 index 541bef45a..000000000 --- a/packages/sdk/demo/176/src/api/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -import * as api from "./module"; - -/** - * @packageDocumentation - * @module api - */ -//================================================================ -export * from "./module"; - -export default api; diff --git a/packages/sdk/demo/176/src/api/structures/Userspace.ts b/packages/sdk/demo/176/src/api/structures/Userspace.ts deleted file mode 100644 index 72750cb6a..000000000 --- a/packages/sdk/demo/176/src/api/structures/Userspace.ts +++ /dev/null @@ -1,9 +0,0 @@ -export namespace Userspace { - interface User { - id: string; - name: string; - } - - export type UserType1 = Pick; - export type UserType2 = Pick & Pick; -} diff --git a/packages/sdk/demo/176/src/controllers/UserspaceController.ts b/packages/sdk/demo/176/src/controllers/UserspaceController.ts deleted file mode 100644 index 7a3999fc1..000000000 --- a/packages/sdk/demo/176/src/controllers/UserspaceController.ts +++ /dev/null @@ -1,31 +0,0 @@ -import core from "@nestia/core"; -import * as nest from "@nestjs/common"; - -import { Userspace } from "../api/structures/Userspace"; - -@nest.Controller("userspace") -export class UserspaceController { - /** - * Type one. - * - * @returns something - * @deprecated - */ - @core.TypedRoute.Get("type1") - public async type1(): Promise { - return { - id: "some-id", - }; - } - - /** - * @internal - */ - @nest.Get("type2") - public async type2(): Promise { - return { - id: "some-id", - name: "some-name", - }; - } -} diff --git a/packages/sdk/demo/176/src/test/features/test_userspace_type1.ts b/packages/sdk/demo/176/src/test/features/test_userspace_type1.ts deleted file mode 100644 index be016de72..000000000 --- a/packages/sdk/demo/176/src/test/features/test_userspace_type1.ts +++ /dev/null @@ -1,13 +0,0 @@ -import typia from "typia"; - -import api from "../../api"; -import { Userspace } from "../../api/structures/Userspace"; - -export async function test_userspace_type1( - connection: api.IConnection, -): Promise { - const data: Userspace.UserType1 = await api.functional.userspace.type1( - connection, - ); - typia.assert(data); -} diff --git a/packages/sdk/demo/176/src/test/features/test_userspace_type2.ts b/packages/sdk/demo/176/src/test/features/test_userspace_type2.ts deleted file mode 100644 index 1cf4b13b8..000000000 --- a/packages/sdk/demo/176/src/test/features/test_userspace_type2.ts +++ /dev/null @@ -1,13 +0,0 @@ -import typia from "typia"; - -import api from "../../api"; -import { Userspace } from "../../api/structures/Userspace"; - -export async function test_userspace_type2( - connection: api.IConnection, -): Promise { - const data: Userspace.UserType2 = await api.functional.userspace.type2( - connection, - ); - typia.assert(data); -} diff --git a/packages/sdk/demo/176/src/test/index.ts b/packages/sdk/demo/176/src/test/index.ts deleted file mode 100644 index 9a9c90c94..000000000 --- a/packages/sdk/demo/176/src/test/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { Backend } from "../Backend"; -import { Configuration } from "../Configuration"; -import api from "../api"; -import { DynamicImportIterator } from "./internal/DynamicImportIterator"; - -async function main(): Promise { - const server: Backend = new Backend(); - await server.open(); - - const connection: api.IConnection = { - host: `http://127.0.0.1:${Configuration.PORT}`, - encryption: Configuration.ENCRYPTION_PASSWORD, - }; - await DynamicImportIterator.main(__dirname, { - prefix: "test", - parameters: () => [connection], - }); - - await server.close(); -} -main().catch((exp) => { - console.log(exp); - process.exit(-1); -}); diff --git a/packages/sdk/demo/176/src/test/internal/DynamicImportIterator.ts b/packages/sdk/demo/176/src/test/internal/DynamicImportIterator.ts deleted file mode 100644 index 4a12a8b47..000000000 --- a/packages/sdk/demo/176/src/test/internal/DynamicImportIterator.ts +++ /dev/null @@ -1,109 +0,0 @@ -import cli from "cli"; -import fs from "fs"; -import { IPointer } from "tstl/functional/IPointer"; - -import { StopWatch } from "./StopWatch"; - -const EXTENSION = __filename.substr(-2); - -interface ICommand { - include?: string; - exclude?: string; -} - -export namespace DynamicImportIterator { - export type Closure = ( - ...args: Arguments - ) => Promise; - type Module = { - [key: string]: Closure; - }; - - export interface IOptions { - prefix: string; - parameters: () => Parameters; - wrapper?: (name: string, output: any) => Promise; - counter?: IPointer; - showElapsedTime?: boolean; - } - - export async function main( - path: string, - options: IOptions, - ): Promise { - const command: ICommand = cli.parse(); - await iterate(options, command, path); - } - - export async function force( - path: string, - options: IOptions, - ): Promise { - const command: ICommand = cli.parse(); - const exceptions: Error[] = []; - - await iterate(options, command, path, exceptions); - return exceptions; - } - - async function iterate( - options: IOptions, - command: ICommand, - path: string, - exceptions?: Error[], - ): Promise { - const directory: string[] = await fs.promises.readdir(path); - for (const file of directory) { - const current: string = `${path}/${file}`; - const stats: fs.Stats = await fs.promises.lstat(current); - - if (stats.isDirectory() === true) { - await iterate(options, command, current, exceptions); - continue; - } else if (file.substr(-3) !== `.${EXTENSION}`) continue; - - const external: Module = await import(current); - await execute(options, command, external, exceptions); - } - } - - async function execute( - options: IOptions, - command: ICommand, - external: Module, - exceptions?: Error[], - ): Promise { - for (const key in external) { - if (command.exclude && key.indexOf(command.exclude) !== -1) - continue; - else if (command.include && key.indexOf(command.include) === -1) - continue; - else if (key.substr(0, options.prefix.length) !== options.prefix) - continue; - else if (external[key] instanceof Function) { - const closure: Closure = external[key]; - const func = async () => { - const output = await closure(...options.parameters()); - if (options.wrapper) await options.wrapper(key, output); - }; - - try { - if (options.counter) ++options.counter.value; - if (options.showElapsedTime === false) { - await func(); - console.log(` - ${key}`); - } else { - const time: number = await StopWatch.measure(func); - console.log(` - ${key}: ${time.toLocaleString()} ms`); - } - } catch (exp) { - if (!(exp instanceof Error)) return; - - console.log(` - ${key} -> ${exp.name}`); - if (exceptions !== undefined) exceptions.push(exp); - else throw exp; - } - } - } - } -} diff --git a/packages/sdk/demo/176/src/test/internal/StopWatch.ts b/packages/sdk/demo/176/src/test/internal/StopWatch.ts deleted file mode 100644 index 862caf8c8..000000000 --- a/packages/sdk/demo/176/src/test/internal/StopWatch.ts +++ /dev/null @@ -1,15 +0,0 @@ -export namespace StopWatch { - export type Task = () => Promise; - - export async function measure(task: Task): Promise { - const time: number = Date.now(); - await task(); - return Date.now() - time; - } - - export async function trace(title: string, task: Task): Promise { - process.stdout.write(title); - const time: number = await measure(task); - console.log(`: ${time.toLocaleString()} ms`); - } -} diff --git a/packages/sdk/demo/176/swagger.json b/packages/sdk/demo/176/swagger.json deleted file mode 100644 index 8438dd721..000000000 --- a/packages/sdk/demo/176/swagger.json +++ /dev/null @@ -1,70 +0,0 @@ -{ - "openapi": "3.0.1", - "servers": [ - { - "url": "https://github.com/samchon/nestia", - "description": "insert your server url" - } - ], - "info": { - "version": "0.1.0", - "title": "Generated by nestia - https://github.com/samchon/nestia" - }, - "paths": { - "/userspace/type1": { - "get": { - "tags": [], - "parameters": [], - "responses": { - "200": { - "description": "something", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Userspace.UserType1" - } - } - }, - "x-nestia-encrypted": false - } - }, - "summary": "Type one", - "description": "Type one.", - "x-nestia-namespace": "userspace.type1.type1", - "x-nestia-jsDocTags": [ - { - "name": "returns", - "text": [ - { - "text": "something", - "kind": "text" - } - ] - }, - { - "name": "deprecated" - } - ] - } - } - }, - "components": { - "schemas": { - "Userspace.UserType1": { - "type": "object", - "properties": { - "id": { - "type": "string", - "nullable": false, - "x-typia-required": true - } - }, - "nullable": false, - "required": [ - "id" - ], - "x-typia-jsDocTags": [] - } - } - } -} \ No newline at end of file diff --git a/packages/sdk/demo/176/tsconfig.json b/packages/sdk/demo/176/tsconfig.json deleted file mode 100644 index 8e8705b08..000000000 --- a/packages/sdk/demo/176/tsconfig.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": "../tsconfig.base.json", -} \ No newline at end of file diff --git a/packages/sdk/demo/296/.gitignore b/packages/sdk/demo/296/.gitignore deleted file mode 100644 index 6dd29b7f8..000000000 --- a/packages/sdk/demo/296/.gitignore +++ /dev/null @@ -1 +0,0 @@ -bin/ \ No newline at end of file diff --git a/packages/sdk/demo/296/src/Configuration.ts b/packages/sdk/demo/296/src/Configuration.ts deleted file mode 100644 index 01a3f1f12..000000000 --- a/packages/sdk/demo/296/src/Configuration.ts +++ /dev/null @@ -1,7 +0,0 @@ -export namespace Configuration { - export const PORT = 12345; - export const ENCRYPTION_PASSWORD = { - key: "a".repeat(32), - iv: "b".repeat(16), - }; -} diff --git a/packages/sdk/demo/296/src/api/functional/user/index.ts b/packages/sdk/demo/296/src/api/functional/user/index.ts deleted file mode 100644 index f6220b9f5..000000000 --- a/packages/sdk/demo/296/src/api/functional/user/index.ts +++ /dev/null @@ -1,137 +0,0 @@ -/** - * @packageDocumentation - * @module api.functional.user - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -//================================================================ -import { Fetcher, Primitive } from "@nestia/fetcher"; -import type { IConnection } from "@nestia/fetcher"; - -import type { TryCatch, IFailure } from "./../../structures/exception.interface"; -import type { IUser } from "./../../structures/user.interface"; - -/** - * @summary 내 상세 정보 보기 API - * @tag user - * @returns 사용자 상세 정보 - * - * @controller UserController.getDetail() - * @path GET /user - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -export function getDetail - ( - connection: IConnection - ): Promise -{ - return Fetcher.fetch - ( - connection, - getDetail.ENCRYPTED, - getDetail.METHOD, - getDetail.path() - ); -} -export namespace getDetail -{ - export type Output = Primitive>; - - export const METHOD = "GET" as const; - export const PATH: string = "/user"; - export const ENCRYPTED: Fetcher.IEncrypted = { - request: false, - response: false, - }; - - export function path(): string - { - return `/user`; - } -} - -/** - * @summary 내 정보 수정 API - * @tag user - * @param connection connection Information of the remote HTTP(s) server with headers (+encryption password) - * @param body 수정할 정보를 포함합니다. - * @returns 수정된 상세 정보 - * - * @controller UserController.update() - * @path PATCH /user - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -export function update - ( - connection: IConnection, - body: Primitive - ): Promise -{ - return Fetcher.fetch - ( - connection, - update.ENCRYPTED, - update.METHOD, - update.path(), - body - ); -} -export namespace update -{ - export type Input = Primitive; - export type Output = Primitive>; - - export const METHOD = "PATCH" as const; - export const PATH: string = "/user"; - export const ENCRYPTED: Fetcher.IEncrypted = { - request: false, - response: false, - }; - - export function path(): string - { - return `/user`; - } -} - -/** - * 사용자는 로그인을 통해 계정을 활성화할 수 있습니다. - * - * 비활성화된 계정은 조회되지 않습니다. - * - * @summary 내 계정 비활성화 API - * @tag user - * @returns true - * - * @controller UserController.inActivate() - * @path DELETE /user - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -export function inActivate - ( - connection: IConnection - ): Promise -{ - return Fetcher.fetch - ( - connection, - inActivate.ENCRYPTED, - inActivate.METHOD, - inActivate.path() - ); -} -export namespace inActivate -{ - export type Output = Primitive>; - - export const METHOD = "DELETE" as const; - export const PATH: string = "/user"; - export const ENCRYPTED: Fetcher.IEncrypted = { - request: false, - response: false, - }; - - export function path(): string - { - return `/user`; - } -} \ No newline at end of file diff --git a/packages/sdk/demo/296/src/api/index.ts b/packages/sdk/demo/296/src/api/index.ts deleted file mode 100644 index 541bef45a..000000000 --- a/packages/sdk/demo/296/src/api/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -import * as api from "./module"; - -/** - * @packageDocumentation - * @module api - */ -//================================================================ -export * from "./module"; - -export default api; diff --git a/packages/sdk/demo/296/src/api/structures/auth.interface.ts b/packages/sdk/demo/296/src/api/structures/auth.interface.ts deleted file mode 100644 index 68165aaca..000000000 --- a/packages/sdk/demo/296/src/api/structures/auth.interface.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { IUser } from "./user.interface"; - -export namespace IAuthentication { - export type OauthProfile = Pick< - IUser, - "sub" | "oauth_type" | "email" | "name" - >; - export type AccessTokenPayload = Pick; - export type RefreshTokenPayload = Pick; - export type IdTokenPayload = IUser.Detail; - - export interface SignInBody { - readonly oauth_type: IUser.OauthType; - readonly code: string; - } - - export interface Credentials { - readonly access_token: string; - readonly refresh_token: string; - readonly id_token: string; - } - export interface RefreshedCredential { - readonly access_token: string; - } -} diff --git a/packages/sdk/demo/296/src/api/structures/exception.interface.ts b/packages/sdk/demo/296/src/api/structures/exception.interface.ts deleted file mode 100644 index 252d461ce..000000000 --- a/packages/sdk/demo/296/src/api/structures/exception.interface.ts +++ /dev/null @@ -1,86 +0,0 @@ -export interface ISuccess { - readonly type: "success"; - readonly data: T; -} - -export interface IFailure< - T extends IFailure.Type = IFailure.Type, - E extends string = string, -> { - readonly type: T; - readonly event: E; - readonly message: string; -} - -export type Try = ISuccess; - -export type TryCatch = ISuccess | E; - -export namespace IFailure { - export type Type = "internal" | "business"; - /** - * 애플리케이션 내부적으로 발생하는 예외 사항 - * - * 클라이언트에게 전달되지 않고 내부에서 처리되어야 한다. - * - * ex) DB같은 외부 시스템 및 라이브러리 오류 - */ - export type Internal = IFailure< - "internal", - T - >; - - export namespace Internal { - export type Type = "Invalid" | "Fail"; - /** - * 사용하는 데이터가 유효하지 않은 경우 - * - * ex) DB가 정상적으로 응답했으나, 예측한 것과 다른 경우 발생 가능 - * - * ex) 함수의 인자가 유효하지 않은 경우 - */ - export type Invalid = Internal<"Invalid">; - - /** - * DB등의 외부 시스템의 연결이 정상적인 응답을 하지 않은 경우 - */ - export type Fail = Internal<"Fail">; - } - - /** - * 서비스 논리상 발생하는 예외 사항 - * - * 클라이언트에게 전달될 수 있다. - * */ - export type Business = IFailure< - "business", - T - >; - - export namespace Business { - export type Type = "NotFound" | "Invalid" | "Forbidden" | "Fail"; - /** - * 요청한 대상을 찾지 못함 - */ - export type NotFound = Business<"NotFound">; - - /** - * 요청이 유효하지 않음 - * - * 비정상적인 방식으로 접근하거나 함수의 input이 적절하지 않음 - */ - export type Invalid = Business<"Invalid">; - - /** - * 요청이 차단됨 - * - * 요청자가 권한이 없는 경우 - */ - export type Forbidden = Business<"Forbidden">; - - /** - * 요청이 실패함 - */ - export type Fail = Business<"Fail">; - } -} diff --git a/packages/sdk/demo/296/src/api/structures/user.interface.ts b/packages/sdk/demo/296/src/api/structures/user.interface.ts deleted file mode 100644 index a3ee8f860..000000000 --- a/packages/sdk/demo/296/src/api/structures/user.interface.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { IAuthentication } from "./auth.interface"; - -export interface IUser { - /** - * @format uuid - */ - readonly id: string; - /** - * oauth server's user id - */ - readonly sub: string; - readonly oauth_type: IUser.OauthType; - /** - * @format email - */ - readonly email: string; - readonly name: string; - readonly address: string | null; - /** - * @pattern ^010-[0-9]{4}-[0-9]{4}$ - */ - readonly phone: string | null; - readonly role: IUser.Role; - readonly is_deleted: boolean; - /** - * ISO 8601 type - * @pattern ^\d{4}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])T(0[0-9]|1[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]).[0-9]{3}Z$ - */ - readonly created_at: string; - /** - * ISO 8601 type - * @pattern ^\d{4}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])T(0[0-9]|1[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]).[0-9]{3}Z$ - */ - readonly updated_at: string; -} - -export namespace IUser { - export type OauthType = "google" | "github"; - export type Role = "normal" | "vender" | "admin"; - export type Public = Pick; - export interface Detail extends Omit {} - - export interface CreateInput extends IAuthentication.OauthProfile {} - - export interface UpdateInput - extends Partial> {} -} diff --git a/packages/sdk/demo/296/src/controllers/user.controller.ts b/packages/sdk/demo/296/src/controllers/user.controller.ts deleted file mode 100644 index e8a5bbbec..000000000 --- a/packages/sdk/demo/296/src/controllers/user.controller.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { Body, Controller, Delete, Get, Patch } from "@nestjs/common"; - -import typia from "typia"; - -import { IFailure, TryCatch } from "../api/structures/exception.interface"; -import { IUser } from "../api/structures/user.interface"; - -@Controller("user") -export class UserController { - /** - * @summary 내 상세 정보 보기 API - * @tag user - * @returns 사용자 상세 정보 - */ - @Get() - async getDetail(): Promise< - TryCatch< - IUser.Detail, - IFailure.Business.Invalid | IFailure.Business.Fail - > - > { - return typia.random< - TryCatch< - IUser.Detail, - IFailure.Business.Invalid | IFailure.Business.Fail - > - >(); - } - - /** - * @summary 내 정보 수정 API - * @tag user - * @param body 수정할 정보를 포함합니다. - * @returns 수정된 상세 정보 - */ - @Patch() - async update( - @Body() body: IUser.UpdateInput, - ): Promise< - TryCatch< - IUser.Detail, - | IFailure.Business.Invalid - | IFailure.Business.NotFound - | IFailure.Business.Fail - > - > { - body; - return typia.random< - TryCatch< - IUser.Detail, - | IFailure.Business.Invalid - | IFailure.Business.NotFound - | IFailure.Business.Fail - > - >(); - } - - /** - * 사용자는 로그인을 통해 계정을 활성화할 수 있습니다. - * - * 비활성화된 계정은 조회되지 않습니다. - * - * @summary 내 계정 비활성화 API - * @tag user - * @returns true - */ - @Delete() - async inActivate(): Promise< - TryCatch - > { - return typia.random< - TryCatch - >(); - } -} diff --git a/packages/sdk/demo/296/src/test/index.ts b/packages/sdk/demo/296/src/test/index.ts deleted file mode 100644 index 9baa7117d..000000000 --- a/packages/sdk/demo/296/src/test/index.ts +++ /dev/null @@ -1 +0,0 @@ -import "../api"; diff --git a/packages/sdk/demo/296/swagger.json b/packages/sdk/demo/296/swagger.json deleted file mode 100644 index a3cdbde8b..000000000 --- a/packages/sdk/demo/296/swagger.json +++ /dev/null @@ -1,597 +0,0 @@ -{ - "openapi": "3.0.1", - "servers": [ - { - "url": "https://github.com/samchon/nestia", - "description": "insert your server url" - } - ], - "info": { - "version": "0.1.0", - "title": "Generated by nestia - https://github.com/samchon/nestia" - }, - "paths": { - "/user": { - "get": { - "tags": [ - "user" - ], - "parameters": [], - "responses": { - "200": { - "description": "사용자 상세 정보", - "content": { - "application/json": { - "schema": { - "oneOf": [ - { - "$ref": "#/components/schemas/IFailure.Business.Invalid" - }, - { - "$ref": "#/components/schemas/IFailure.Business.Fail" - }, - { - "$ref": "#/components/schemas/ISuccess_lt_IUser.Detail_gt_" - } - ] - } - } - }, - "x-nestia-encrypted": false - } - }, - "summary": "내 상세 정보 보기 API", - "description": "", - "x-nestia-namespace": "user.getDetail", - "x-nestia-jsDocTags": [ - { - "name": "summary", - "text": [ - { - "text": "내 상세 정보 보기 API", - "kind": "text" - } - ] - }, - { - "name": "tag", - "text": [ - { - "text": "user", - "kind": "text" - } - ] - }, - { - "name": "returns", - "text": [ - { - "text": "사용자 상세 정보", - "kind": "text" - } - ] - } - ] - }, - "patch": { - "tags": [ - "user" - ], - "parameters": [], - "requestBody": { - "description": "수정할 정보를 포함합니다.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/IUser.UpdateInput" - } - } - }, - "required": true, - "x-nestia-encrypted": false - }, - "responses": { - "201": { - "description": "수정된 상세 정보", - "content": { - "application/json": { - "schema": { - "oneOf": [ - { - "$ref": "#/components/schemas/IFailure.Business.Invalid" - }, - { - "$ref": "#/components/schemas/IFailure.Business.Fail" - }, - { - "$ref": "#/components/schemas/ISuccess_lt_IUser.Detail_gt_" - }, - { - "$ref": "#/components/schemas/IFailure.Business.NotFound" - } - ] - } - } - }, - "x-nestia-encrypted": false - } - }, - "summary": "내 정보 수정 API", - "description": "", - "x-nestia-namespace": "user.update", - "x-nestia-jsDocTags": [ - { - "name": "summary", - "text": [ - { - "text": "내 정보 수정 API", - "kind": "text" - } - ] - }, - { - "name": "tag", - "text": [ - { - "text": "user", - "kind": "text" - } - ] - }, - { - "name": "param", - "text": [ - { - "text": "body", - "kind": "parameterName" - }, - { - "text": " ", - "kind": "space" - }, - { - "text": "수정할 정보를 포함합니다.", - "kind": "text" - } - ] - }, - { - "name": "returns", - "text": [ - { - "text": "수정된 상세 정보", - "kind": "text" - } - ] - } - ] - }, - "delete": { - "tags": [ - "user" - ], - "parameters": [], - "responses": { - "200": { - "description": "true", - "content": { - "application/json": { - "schema": { - "oneOf": [ - { - "$ref": "#/components/schemas/IFailure.Business.Invalid" - }, - { - "$ref": "#/components/schemas/IFailure.Business.Fail" - }, - { - "$ref": "#/components/schemas/ISuccess_lt_true_gt_" - } - ] - } - } - }, - "x-nestia-encrypted": false - } - }, - "summary": "내 계정 비활성화 API", - "description": "사용자는 로그인을 통해 계정을 활성화할 수 있습니다.\n\n비활성화된 계정은 조회되지 않습니다.", - "x-nestia-namespace": "user.inActivate", - "x-nestia-jsDocTags": [ - { - "name": "summary", - "text": [ - { - "text": "내 계정 비활성화 API", - "kind": "text" - } - ] - }, - { - "name": "tag", - "text": [ - { - "text": "user", - "kind": "text" - } - ] - }, - { - "name": "returns", - "text": [ - { - "text": "true", - "kind": "text" - } - ] - } - ] - } - } - }, - "components": { - "schemas": { - "IFailure.Business.Invalid": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "business" - ], - "nullable": false, - "x-typia-required": true - }, - "event": { - "type": "string", - "enum": [ - "Invalid" - ], - "nullable": false, - "x-typia-required": true - }, - "message": { - "type": "string", - "nullable": false, - "x-typia-required": true - } - }, - "nullable": false, - "required": [ - "type", - "event", - "message" - ], - "x-typia-jsDocTags": [] - }, - "IFailure.Business.Fail": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "business" - ], - "nullable": false, - "x-typia-required": true - }, - "event": { - "type": "string", - "enum": [ - "Fail" - ], - "nullable": false, - "x-typia-required": true - }, - "message": { - "type": "string", - "nullable": false, - "x-typia-required": true - } - }, - "nullable": false, - "required": [ - "type", - "event", - "message" - ], - "x-typia-jsDocTags": [] - }, - "ISuccess_lt_IUser.Detail_gt_": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "success" - ], - "nullable": false, - "x-typia-required": true - }, - "data": { - "$ref": "#/components/schemas/IUser.Detail", - "x-typia-required": true - } - }, - "nullable": false, - "required": [ - "type", - "data" - ], - "x-typia-jsDocTags": [] - }, - "IUser.Detail": { - "type": "object", - "properties": { - "id": { - "type": "string", - "nullable": false, - "x-typia-metaTags": [ - { - "kind": "format", - "value": "uuid" - } - ], - "x-typia-jsDocTags": [ - { - "name": "format", - "text": [ - { - "text": "uuid", - "kind": "text" - } - ] - } - ], - "x-typia-required": true, - "format": "uuid" - }, - "email": { - "type": "string", - "nullable": false, - "x-typia-metaTags": [ - { - "kind": "format", - "value": "email" - } - ], - "x-typia-jsDocTags": [ - { - "name": "format", - "text": [ - { - "text": "email", - "kind": "text" - } - ] - } - ], - "x-typia-required": true, - "format": "email" - }, - "name": { - "type": "string", - "nullable": false, - "x-typia-required": true - }, - "address": { - "type": "string", - "nullable": true, - "x-typia-required": true - }, - "phone": { - "type": "string", - "nullable": true, - "x-typia-metaTags": [ - { - "kind": "pattern", - "value": "^010-[0-9]{4}-[0-9]{4}$" - } - ], - "x-typia-jsDocTags": [ - { - "name": "pattern", - "text": [ - { - "text": "^010-[0-9]{4}-[0-9]{4}$", - "kind": "text" - } - ] - } - ], - "x-typia-required": true, - "pattern": "^010-[0-9]{4}-[0-9]{4}$" - }, - "role": { - "type": "string", - "enum": [ - "normal", - "vender", - "admin" - ], - "nullable": false, - "x-typia-required": true - }, - "is_deleted": { - "type": "boolean", - "nullable": false, - "x-typia-required": true - }, - "created_at": { - "type": "string", - "nullable": false, - "description": "ISO 8601 type", - "x-typia-metaTags": [ - { - "kind": "pattern", - "value": "^\\d{4}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])T(0[0-9]|1[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]).[0-9]{3}Z$" - } - ], - "x-typia-jsDocTags": [ - { - "name": "pattern", - "text": [ - { - "text": "^\\d{4}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])T(0[0-9]|1[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]).[0-9]{3}Z$", - "kind": "text" - } - ] - } - ], - "x-typia-required": true, - "pattern": "^\\d{4}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])T(0[0-9]|1[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]).[0-9]{3}Z$" - }, - "updated_at": { - "type": "string", - "nullable": false, - "description": "ISO 8601 type", - "x-typia-metaTags": [ - { - "kind": "pattern", - "value": "^\\d{4}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])T(0[0-9]|1[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]).[0-9]{3}Z$" - } - ], - "x-typia-jsDocTags": [ - { - "name": "pattern", - "text": [ - { - "text": "^\\d{4}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])T(0[0-9]|1[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]).[0-9]{3}Z$", - "kind": "text" - } - ] - } - ], - "x-typia-required": true, - "pattern": "^\\d{4}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])T(0[0-9]|1[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]).[0-9]{3}Z$" - } - }, - "nullable": false, - "required": [ - "id", - "email", - "name", - "address", - "phone", - "role", - "is_deleted", - "created_at", - "updated_at" - ], - "x-typia-jsDocTags": [] - }, - "IUser.UpdateInput": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": false, - "x-typia-required": false - }, - "address": { - "type": "string", - "nullable": true, - "x-typia-required": false - }, - "phone": { - "type": "string", - "nullable": true, - "x-typia-metaTags": [ - { - "kind": "pattern", - "value": "^010-[0-9]{4}-[0-9]{4}$" - } - ], - "x-typia-jsDocTags": [ - { - "name": "pattern", - "text": [ - { - "text": "^010-[0-9]{4}-[0-9]{4}$", - "kind": "text" - } - ] - } - ], - "x-typia-required": false, - "pattern": "^010-[0-9]{4}-[0-9]{4}$" - } - }, - "nullable": false, - "x-typia-jsDocTags": [] - }, - "IFailure.Business.NotFound": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "business" - ], - "nullable": false, - "x-typia-required": true - }, - "event": { - "type": "string", - "enum": [ - "NotFound" - ], - "nullable": false, - "x-typia-required": true - }, - "message": { - "type": "string", - "nullable": false, - "x-typia-required": true - } - }, - "nullable": false, - "required": [ - "type", - "event", - "message" - ], - "x-typia-jsDocTags": [] - }, - "ISuccess_lt_true_gt_": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "success" - ], - "nullable": false, - "x-typia-required": true - }, - "data": { - "type": "boolean", - "enum": [ - true - ], - "nullable": false, - "x-typia-required": true - } - }, - "nullable": false, - "required": [ - "type", - "data" - ], - "x-typia-jsDocTags": [] - } - }, - "securitySchemes": { - "bearer": { - "type": "apiKey", - "in": "header", - "name": "Authorization" - } - } - }, - "security": [ - { - "bearer": [] - } - ] -} \ No newline at end of file diff --git a/packages/sdk/demo/296/tsconfig.json b/packages/sdk/demo/296/tsconfig.json deleted file mode 100644 index 8e8705b08..000000000 --- a/packages/sdk/demo/296/tsconfig.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": "../tsconfig.base.json", -} \ No newline at end of file diff --git a/packages/sdk/demo/encrypted/src/Backend.ts b/packages/sdk/demo/encrypted/src/Backend.ts deleted file mode 100644 index 4507166f0..000000000 --- a/packages/sdk/demo/encrypted/src/Backend.ts +++ /dev/null @@ -1,28 +0,0 @@ -import helper from "@nestia/core"; -import * as nest from "@nestjs/common"; -import { NestFactory } from "@nestjs/core"; - -import { Configuration } from "./Configuration"; - -export class Backend { - private application_?: nest.INestApplication; - - public async open(): Promise { - this.application_ = await NestFactory.create( - await helper.EncryptedModule.dynamic( - __dirname + "/controllers", - Configuration.ENCRYPTION_PASSWORD, - ), - { logger: false }, - ); - await this.application_.listen(Configuration.PORT); - } - - public async close(): Promise { - if (this.application_ === undefined) return; - - const app = this.application_; - delete this.application_; - await app.close(); - } -} diff --git a/packages/sdk/demo/encrypted/src/Configuration.ts b/packages/sdk/demo/encrypted/src/Configuration.ts deleted file mode 100644 index 01a3f1f12..000000000 --- a/packages/sdk/demo/encrypted/src/Configuration.ts +++ /dev/null @@ -1,7 +0,0 @@ -export namespace Configuration { - export const PORT = 12345; - export const ENCRYPTION_PASSWORD = { - key: "a".repeat(32), - iv: "b".repeat(16), - }; -} diff --git a/packages/sdk/demo/encrypted/src/api/index.ts b/packages/sdk/demo/encrypted/src/api/index.ts deleted file mode 100644 index 541bef45a..000000000 --- a/packages/sdk/demo/encrypted/src/api/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -import * as api from "./module"; - -/** - * @packageDocumentation - * @module api - */ -//================================================================ -export * from "./module"; - -export default api; diff --git a/packages/sdk/demo/encrypted/src/test/index.ts b/packages/sdk/demo/encrypted/src/test/index.ts deleted file mode 100644 index 9a9c90c94..000000000 --- a/packages/sdk/demo/encrypted/src/test/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { Backend } from "../Backend"; -import { Configuration } from "../Configuration"; -import api from "../api"; -import { DynamicImportIterator } from "./internal/DynamicImportIterator"; - -async function main(): Promise { - const server: Backend = new Backend(); - await server.open(); - - const connection: api.IConnection = { - host: `http://127.0.0.1:${Configuration.PORT}`, - encryption: Configuration.ENCRYPTION_PASSWORD, - }; - await DynamicImportIterator.main(__dirname, { - prefix: "test", - parameters: () => [connection], - }); - - await server.close(); -} -main().catch((exp) => { - console.log(exp); - process.exit(-1); -}); diff --git a/packages/sdk/demo/encrypted/src/test/internal/DynamicImportIterator.ts b/packages/sdk/demo/encrypted/src/test/internal/DynamicImportIterator.ts deleted file mode 100644 index 4a12a8b47..000000000 --- a/packages/sdk/demo/encrypted/src/test/internal/DynamicImportIterator.ts +++ /dev/null @@ -1,109 +0,0 @@ -import cli from "cli"; -import fs from "fs"; -import { IPointer } from "tstl/functional/IPointer"; - -import { StopWatch } from "./StopWatch"; - -const EXTENSION = __filename.substr(-2); - -interface ICommand { - include?: string; - exclude?: string; -} - -export namespace DynamicImportIterator { - export type Closure = ( - ...args: Arguments - ) => Promise; - type Module = { - [key: string]: Closure; - }; - - export interface IOptions { - prefix: string; - parameters: () => Parameters; - wrapper?: (name: string, output: any) => Promise; - counter?: IPointer; - showElapsedTime?: boolean; - } - - export async function main( - path: string, - options: IOptions, - ): Promise { - const command: ICommand = cli.parse(); - await iterate(options, command, path); - } - - export async function force( - path: string, - options: IOptions, - ): Promise { - const command: ICommand = cli.parse(); - const exceptions: Error[] = []; - - await iterate(options, command, path, exceptions); - return exceptions; - } - - async function iterate( - options: IOptions, - command: ICommand, - path: string, - exceptions?: Error[], - ): Promise { - const directory: string[] = await fs.promises.readdir(path); - for (const file of directory) { - const current: string = `${path}/${file}`; - const stats: fs.Stats = await fs.promises.lstat(current); - - if (stats.isDirectory() === true) { - await iterate(options, command, current, exceptions); - continue; - } else if (file.substr(-3) !== `.${EXTENSION}`) continue; - - const external: Module = await import(current); - await execute(options, command, external, exceptions); - } - } - - async function execute( - options: IOptions, - command: ICommand, - external: Module, - exceptions?: Error[], - ): Promise { - for (const key in external) { - if (command.exclude && key.indexOf(command.exclude) !== -1) - continue; - else if (command.include && key.indexOf(command.include) === -1) - continue; - else if (key.substr(0, options.prefix.length) !== options.prefix) - continue; - else if (external[key] instanceof Function) { - const closure: Closure = external[key]; - const func = async () => { - const output = await closure(...options.parameters()); - if (options.wrapper) await options.wrapper(key, output); - }; - - try { - if (options.counter) ++options.counter.value; - if (options.showElapsedTime === false) { - await func(); - console.log(` - ${key}`); - } else { - const time: number = await StopWatch.measure(func); - console.log(` - ${key}: ${time.toLocaleString()} ms`); - } - } catch (exp) { - if (!(exp instanceof Error)) return; - - console.log(` - ${key} -> ${exp.name}`); - if (exceptions !== undefined) exceptions.push(exp); - else throw exp; - } - } - } - } -} diff --git a/packages/sdk/demo/encrypted/src/test/internal/StopWatch.ts b/packages/sdk/demo/encrypted/src/test/internal/StopWatch.ts deleted file mode 100644 index 862caf8c8..000000000 --- a/packages/sdk/demo/encrypted/src/test/internal/StopWatch.ts +++ /dev/null @@ -1,15 +0,0 @@ -export namespace StopWatch { - export type Task = () => Promise; - - export async function measure(task: Task): Promise { - const time: number = Date.now(); - await task(); - return Date.now() - time; - } - - export async function trace(title: string, task: Task): Promise { - process.stdout.write(title); - const time: number = await measure(task); - console.log(`: ${time.toLocaleString()} ms`); - } -} diff --git a/packages/sdk/demo/encrypted/tsconfig.json b/packages/sdk/demo/encrypted/tsconfig.json deleted file mode 100644 index 0bab4309f..000000000 --- a/packages/sdk/demo/encrypted/tsconfig.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "extends": "../tsconfig.base.json", - "compilerOptions": { - // "target": "ESNext", - // "module": "ESNext", - // "moduleResolution": "node" - } -} \ No newline at end of file diff --git a/packages/sdk/demo/generic/nestia.config.ts b/packages/sdk/demo/generic/nestia.config.ts deleted file mode 100644 index 9d93f107c..000000000 --- a/packages/sdk/demo/generic/nestia.config.ts +++ /dev/null @@ -1,10 +0,0 @@ -const config = { - input: ["src/controllers"], - output: "src/api", - swagger: { - output: "swagger.json", - }, - assert: true, - json: true, -}; -export default config; diff --git a/packages/sdk/demo/generic/src/Configuration.ts b/packages/sdk/demo/generic/src/Configuration.ts deleted file mode 100644 index 01a3f1f12..000000000 --- a/packages/sdk/demo/generic/src/Configuration.ts +++ /dev/null @@ -1,7 +0,0 @@ -export namespace Configuration { - export const PORT = 12345; - export const ENCRYPTION_PASSWORD = { - key: "a".repeat(32), - iv: "b".repeat(16), - }; -} diff --git a/packages/sdk/demo/generic/src/api/functional/consumers/index.ts b/packages/sdk/demo/generic/src/api/functional/consumers/index.ts deleted file mode 100644 index 3ba654cad..000000000 --- a/packages/sdk/demo/generic/src/api/functional/consumers/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -/** - * @packageDocumentation - * @module api.functional.consumers - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -//================================================================ -export * as sales from "./sales"; \ No newline at end of file diff --git a/packages/sdk/demo/generic/src/api/functional/consumers/sales/index.ts b/packages/sdk/demo/generic/src/api/functional/consumers/sales/index.ts deleted file mode 100644 index 91b54e5c7..000000000 --- a/packages/sdk/demo/generic/src/api/functional/consumers/sales/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -/** - * @packageDocumentation - * @module api.functional.consumers.sales - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -//================================================================ -export * as questions from "./questions"; -export * as reviews from "./reviews"; \ No newline at end of file diff --git a/packages/sdk/demo/generic/src/api/functional/consumers/sales/questions/index.ts b/packages/sdk/demo/generic/src/api/functional/consumers/sales/questions/index.ts deleted file mode 100644 index 75841168b..000000000 --- a/packages/sdk/demo/generic/src/api/functional/consumers/sales/questions/index.ts +++ /dev/null @@ -1,174 +0,0 @@ -/** - * @packageDocumentation - * @module api.functional.consumers.sales.questions - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -//================================================================ -import { Fetcher, Primitive } from "@nestia/fetcher"; -import type { IConnection } from "@nestia/fetcher"; -import typia from "typia"; - -import type { ISaleArticle } from "./../../../../structures/ISaleArticle"; -import type { ISaleQuestion } from "./../../../../structures/ISaleQuestion"; - -/** - * Store a new inquiry. - * - * Write a new article inquirying about a sale. - * - * @param connection connection Information of the remote HTTP(s) server with headers (+encryption password) - * @param request Instance of the Express.Request - * @param section Code of the target section - * @param saleId ID of the target sale - * @param input Content to archive - * @return Newly archived inquiry - * @throw 400 bad request error when type of the input data is not valid - * @throw 401 unauthorized error when you've not logged in yet - * - * @controller ConsumerSaleQuestionsController.store() - * @path POST /consumers/:section/sales/:saleId/questions - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -export function store - ( - connection: IConnection, - section: string, - saleId: string, - input: Primitive - ): Promise -{ - typia.assert(section); - typia.assert(saleId); - typia.assert(input); - - return Fetcher.fetch - ( - connection, - store.ENCRYPTED, - store.METHOD, - store.path(section, saleId), - input, - store.stringify - ); -} -export namespace store -{ - export type Input = Primitive; - export type Output = Primitive; - - export const METHOD = "POST" as const; - export const PATH: string = "/consumers/:section/sales/:saleId/questions"; - export const ENCRYPTED: Fetcher.IEncrypted = { - request: false, - response: false, - }; - - export function path(section: string, saleId: string): string - { - return `/consumers/${encodeURIComponent(section)}/sales/${encodeURIComponent(saleId)}/questions`; - } - export const stringify = (input: Input) => typia.assertStringify(input); -} - -/** - * Update ordinary inquiry article. However, it would not modify the content reocrd - * {@link ISaleInquiry.IContent}, but be accumulated into the {@link ISaleInquiry.contents}. - * Therefore, all of the poeple can read how the content has been changed. - * - * @summary Update an inquiry. - * @param connection connection Information of the remote HTTP(s) server with headers (+encryption password) - * @param request Instance of the Express.Request - * @param section Code of the target section - * @param saleId ID of the target sale - * @param id ID of the target article to be updated - * @param input New content to be overwritten - * @return The newly created content record - * @throw 400 bad request error when type of the input data is not valid - * @throw 401 unauthorized error when you've not logged in yet - * @throw 403 forbidden error when the article is not yours - * - * @controller ConsumerSaleQuestionsController.update() - * @path PUT /consumers/:section/sales/:saleId/questions/:id - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -export function update - ( - connection: IConnection, - section: string, - saleId: string, - id: number, - input: Primitive - ): Promise -{ - typia.assert(section); - typia.assert(saleId); - typia.assert(id); - typia.assert(input); - - return Fetcher.fetch - ( - connection, - update.ENCRYPTED, - update.METHOD, - update.path(section, saleId, id), - input, - update.stringify - ); -} -export namespace update -{ - export type Input = Primitive; - export type Output = Primitive; - - export const METHOD = "PUT" as const; - export const PATH: string = "/consumers/:section/sales/:saleId/questions/:id"; - export const ENCRYPTED: Fetcher.IEncrypted = { - request: false, - response: false, - }; - - export function path(section: string, saleId: string, id: number): string - { - return `/consumers/${encodeURIComponent(section)}/sales/${encodeURIComponent(saleId)}/questions/${encodeURIComponent(id)}`; - } - export const stringify = (input: Input) => typia.assertStringify(input); -} - -/** - * @controller ConsumerSaleQuestionsController.refresh() - * @path PATCH /consumers/:section/sales/:saleId/questions/refresh - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -export function refresh - ( - connection: IConnection, - section: string, - saleId: string - ): Promise -{ - typia.assert(section); - typia.assert(saleId); - - return Fetcher.fetch - ( - connection, - refresh.ENCRYPTED, - refresh.METHOD, - refresh.path(section, saleId) - ); -} -export namespace refresh -{ - - export const METHOD = "PATCH" as const; - export const PATH: string = "/consumers/:section/sales/:saleId/questions/refresh"; - export const ENCRYPTED: Fetcher.IEncrypted = { - request: false, - response: false, - }; - - export function path(section: string, saleId: string): string - { - return `/consumers/${encodeURIComponent(section)}/sales/${encodeURIComponent(saleId)}/questions/refresh`; - } -} \ No newline at end of file diff --git a/packages/sdk/demo/generic/src/api/functional/consumers/sales/reviews/index.ts b/packages/sdk/demo/generic/src/api/functional/consumers/sales/reviews/index.ts deleted file mode 100644 index ccf0b167d..000000000 --- a/packages/sdk/demo/generic/src/api/functional/consumers/sales/reviews/index.ts +++ /dev/null @@ -1,173 +0,0 @@ -/** - * @packageDocumentation - * @module api.functional.consumers.sales.reviews - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -//================================================================ -import { Fetcher, Primitive } from "@nestia/fetcher"; -import type { IConnection } from "@nestia/fetcher"; -import typia from "typia"; - -import type { ISaleReview } from "./../../../../structures/ISaleReview"; - -/** - * Store a new inquiry. - * - * Write a new article inquirying about a sale. - * - * @param connection connection Information of the remote HTTP(s) server with headers (+encryption password) - * @param request Instance of the Express.Request - * @param section Code of the target section - * @param saleId ID of the target sale - * @param input Content to archive - * @return Newly archived inquiry - * @throw 400 bad request error when type of the input data is not valid - * @throw 401 unauthorized error when you've not logged in yet - * - * @controller ConsumerSaleReviewsController.store() - * @path POST /consumers/:section/sales/:saleId/reviews - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -export function store - ( - connection: IConnection, - section: string, - saleId: string, - input: Primitive - ): Promise -{ - typia.assert(section); - typia.assert(saleId); - typia.assert(input); - - return Fetcher.fetch - ( - connection, - store.ENCRYPTED, - store.METHOD, - store.path(section, saleId), - input, - store.stringify - ); -} -export namespace store -{ - export type Input = Primitive; - export type Output = Primitive; - - export const METHOD = "POST" as const; - export const PATH: string = "/consumers/:section/sales/:saleId/reviews"; - export const ENCRYPTED: Fetcher.IEncrypted = { - request: false, - response: false, - }; - - export function path(section: string, saleId: string): string - { - return `/consumers/${encodeURIComponent(section)}/sales/${encodeURIComponent(saleId)}/reviews`; - } - export const stringify = (input: Input) => typia.assertStringify(input); -} - -/** - * Update ordinary inquiry article. However, it would not modify the content reocrd - * {@link ISaleInquiry.IContent}, but be accumulated into the {@link ISaleInquiry.contents}. - * Therefore, all of the poeple can read how the content has been changed. - * - * @summary Update an inquiry. - * @param connection connection Information of the remote HTTP(s) server with headers (+encryption password) - * @param request Instance of the Express.Request - * @param section Code of the target section - * @param saleId ID of the target sale - * @param id ID of the target article to be updated - * @param input New content to be overwritten - * @return The newly created content record - * @throw 400 bad request error when type of the input data is not valid - * @throw 401 unauthorized error when you've not logged in yet - * @throw 403 forbidden error when the article is not yours - * - * @controller ConsumerSaleReviewsController.update() - * @path PUT /consumers/:section/sales/:saleId/reviews/:id - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -export function update - ( - connection: IConnection, - section: string, - saleId: string, - id: number, - input: Primitive - ): Promise -{ - typia.assert(section); - typia.assert(saleId); - typia.assert(id); - typia.assert(input); - - return Fetcher.fetch - ( - connection, - update.ENCRYPTED, - update.METHOD, - update.path(section, saleId, id), - input, - update.stringify - ); -} -export namespace update -{ - export type Input = Primitive; - export type Output = Primitive; - - export const METHOD = "PUT" as const; - export const PATH: string = "/consumers/:section/sales/:saleId/reviews/:id"; - export const ENCRYPTED: Fetcher.IEncrypted = { - request: false, - response: false, - }; - - export function path(section: string, saleId: string, id: number): string - { - return `/consumers/${encodeURIComponent(section)}/sales/${encodeURIComponent(saleId)}/reviews/${encodeURIComponent(id)}`; - } - export const stringify = (input: Input) => typia.assertStringify(input); -} - -/** - * @controller ConsumerSaleReviewsController.refresh() - * @path PATCH /consumers/:section/sales/:saleId/reviews/refresh - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -export function refresh - ( - connection: IConnection, - section: string, - saleId: string - ): Promise -{ - typia.assert(section); - typia.assert(saleId); - - return Fetcher.fetch - ( - connection, - refresh.ENCRYPTED, - refresh.METHOD, - refresh.path(section, saleId) - ); -} -export namespace refresh -{ - - export const METHOD = "PATCH" as const; - export const PATH: string = "/consumers/:section/sales/:saleId/reviews/refresh"; - export const ENCRYPTED: Fetcher.IEncrypted = { - request: false, - response: false, - }; - - export function path(section: string, saleId: string): string - { - return `/consumers/${encodeURIComponent(section)}/sales/${encodeURIComponent(saleId)}/reviews/refresh`; - } -} \ No newline at end of file diff --git a/packages/sdk/demo/generic/src/api/index.ts b/packages/sdk/demo/generic/src/api/index.ts deleted file mode 100644 index 541bef45a..000000000 --- a/packages/sdk/demo/generic/src/api/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -import * as api from "./module"; - -/** - * @packageDocumentation - * @module api - */ -//================================================================ -export * from "./module"; - -export default api; diff --git a/packages/sdk/demo/generic/src/api/structures/IAttachmentFile.ts b/packages/sdk/demo/generic/src/api/structures/IAttachmentFile.ts deleted file mode 100644 index 106e987a3..000000000 --- a/packages/sdk/demo/generic/src/api/structures/IAttachmentFile.ts +++ /dev/null @@ -1,21 +0,0 @@ -/** - * Attachemd (physical) file info. - * - * @author Jeongho Nam - https://github.com/samchon - */ -export interface IAttachmentFile { - /** - * Name of the file. - */ - name: string; - - /** - * Extension of the file, but ommitable. - */ - extension: string | null; - - /** - * Full URL path of the file. - */ - url: string; -} diff --git a/packages/sdk/demo/generic/src/api/structures/ISaleArticle.ts b/packages/sdk/demo/generic/src/api/structures/ISaleArticle.ts deleted file mode 100644 index f061557c3..000000000 --- a/packages/sdk/demo/generic/src/api/structures/ISaleArticle.ts +++ /dev/null @@ -1,79 +0,0 @@ -import { IAttachmentFile } from "./IAttachmentFile"; - -/** - * Article about a sale. - * - * The `ISaleArticle` is a super type interface. Many sub-type articles would be - * designed by extending this super type interface `ISaleArticle`. - * - * @template Content Content type. - * @author Jeongho Nam - https://github.com/samchon - */ -export interface ISaleArticle { - /** - * Primary Key. - */ - id: number; - - /** - * Hit count. - * - * How many consumers had read. - */ - hit: number; - - /** - * List of contents. - * - * When the article writer tries to modify content, it would not modify the article - * content but would be accumulated. Therefore, all of the people can read how - * the content has been changed. - */ - contents: Content[]; - - /** - * Creation time. - */ - created_at: string; -} -export namespace ISaleArticle { - /** - * Content info. - */ - export interface IContent extends IStore { - /** - * Primary Key - */ - id: string; - - /** - * Creation time. - */ - created_at: string; - } - - /** - * Store info. - */ - export interface IStore { - /** - * Title of the content. - */ - title: string; - - /** - * Body of the content. - */ - body: string; - - /** - * Extension, content type (format). - */ - extension: "html" | "md" | "txt"; - - /** - * Attached files. - */ - files: IAttachmentFile[]; - } -} diff --git a/packages/sdk/demo/generic/src/api/structures/ISaleInquiry.ts b/packages/sdk/demo/generic/src/api/structures/ISaleInquiry.ts deleted file mode 100644 index 327bba7f3..000000000 --- a/packages/sdk/demo/generic/src/api/structures/ISaleInquiry.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { ISaleArticle } from "./ISaleArticle"; -import { ISaleInquiryAnswer } from "./ISaleInquiryAnswer"; - -/** - * Inquiry article. - * - * Sub-type of article and super-type of question and answer. - * - * @template Content Content type - * @author Jeongho Nam - https://github.com/samchon - */ -export interface ISaleInquiry - extends ISaleArticle { - /** - * Name of the writer. - */ - writer: string; - - /** - * Formal answer from the seller. - */ - answer: ISaleInquiryAnswer | null; -} -export namespace ISaleInquiry { - /** - * Content type of the inquiry article. - */ - export type IContent = ISaleArticle.IContent; - - /** - * Store info of the inquiry article. - */ - export type IStore = ISaleArticle.IStore; -} diff --git a/packages/sdk/demo/generic/src/api/structures/ISaleInquiryAnswer.ts b/packages/sdk/demo/generic/src/api/structures/ISaleInquiryAnswer.ts deleted file mode 100644 index 361d98b2b..000000000 --- a/packages/sdk/demo/generic/src/api/structures/ISaleInquiryAnswer.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { ISaleArticle } from "./ISaleArticle"; - -/** - * Formal answer from the seller. - * - * When a consumer writes an inquiry about a sale, the seller can write a formal - * answer article. This `ISaleInquiryAnswer` has been designed to represent such - * formal answer article from the seller. - * - * @author Jeongho Nam - https://github.com/samchon - */ -export type ISaleInquiryAnswer = ISaleArticle; -export namespace ISaleInquiryAnswer { - /** - * Content type of the answer. - */ - export type IContent = ISaleArticle.IContent; - - /** - * Store info of the answer. - */ - export type IStore = ISaleArticle.IContent; -} diff --git a/packages/sdk/demo/generic/src/api/structures/ISaleQuestion.ts b/packages/sdk/demo/generic/src/api/structures/ISaleQuestion.ts deleted file mode 100644 index bce431fe0..000000000 --- a/packages/sdk/demo/generic/src/api/structures/ISaleQuestion.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { ISaleInquiry } from "./ISaleInquiry"; - -/** - * Question article. - * - * The `ISaleQuestion` is a type of question article wrriten by a consumer - * who has something to ask about the sale. - * - * @author Jeongho Nam - https://github.com/samchon - */ -export type ISaleQuestion = ISaleInquiry; -export namespace ISaleQuestion { - /** - * Content info of the question. - */ - export type IContent = ISaleInquiry.IContent; - - /** - * Store info of the question. - */ - export type IStore = ISaleInquiry.IStore; -} diff --git a/packages/sdk/demo/generic/src/api/structures/ISaleReview.ts b/packages/sdk/demo/generic/src/api/structures/ISaleReview.ts deleted file mode 100644 index f27afff91..000000000 --- a/packages/sdk/demo/generic/src/api/structures/ISaleReview.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { ISaleInquiry } from "./ISaleInquiry"; - -/** - * Review article. - * - * The `ISaleReview` is a type of review article written by a consumer who've bought - * the sale good with the estimation score. - * - * @author Jeongho Nam - https://github.com/samchon - */ -export type ISaleReview = ISaleInquiry; -export namespace ISaleReview { - /** - * Content info of the review. - */ - export interface IContent extends ISaleInquiry.IContent { - /** - * Estimation score. - */ - score: number; - } - - /** - * Store info of the review. - */ - export interface IStore extends ISaleInquiry.IStore { - /** - * Estimation score. - */ - score: number; - } -} diff --git a/packages/sdk/demo/generic/src/controllers/ConsumerSaleQuestionsController.ts b/packages/sdk/demo/generic/src/controllers/ConsumerSaleQuestionsController.ts deleted file mode 100644 index 7a70d929f..000000000 --- a/packages/sdk/demo/generic/src/controllers/ConsumerSaleQuestionsController.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { ISaleQuestion } from "@api/structures/ISaleQuestion"; -import * as nest from "@nestjs/common"; - -import typia from "typia"; - -import { SaleInquiriesController } from "./SaleInquiriesController"; - -@nest.Controller("consumers/:section/sales/:saleId/questions") -export class ConsumerSaleQuestionsController extends SaleInquiriesController< - ISaleQuestion.IContent, - ISaleQuestion.IStore, - ISaleQuestion ->({ - assert: (input) => typia.assert(input), - stringify: (input) => typia.stringify(input), - convert: (input) => ({ - id: 0, - hit: 0, - writer: "someone", - answer: null, - created_at: new Date().toString(), - contents: [ - { - id: "some-content-id", - title: input.title, - body: input.body, - extension: input.extension, - files: input.files, - created_at: new Date().toString(), - }, - ], - }), -}) {} diff --git a/packages/sdk/demo/generic/src/controllers/ConsumerSaleReviewsController.ts b/packages/sdk/demo/generic/src/controllers/ConsumerSaleReviewsController.ts deleted file mode 100644 index 68b27b6fc..000000000 --- a/packages/sdk/demo/generic/src/controllers/ConsumerSaleReviewsController.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { ISaleReview } from "@api/structures/ISaleReview"; -import * as nest from "@nestjs/common"; - -import typia from "typia"; - -import { SaleInquiriesController } from "./SaleInquiriesController"; - -@nest.Controller("consumers/:section/sales/:saleId/reviews") -export class ConsumerSaleReviewsController extends SaleInquiriesController< - ISaleReview.IContent, - ISaleReview.IStore, - ISaleReview ->({ - assert: (input) => typia.assert(input), - stringify: (input) => typia.stringify(input), - convert: (input) => ({ - id: 0, - hit: 0, - writer: "someone", - answer: null, - created_at: new Date().toString(), - contents: [ - { - id: "some-content-id", - title: input.title, - body: input.body, - extension: input.extension, - files: input.files, - created_at: new Date().toString(), - score: 100, - }, - ], - }), -}) {} diff --git a/packages/sdk/demo/generic/src/controllers/SaleInquiriesController.ts b/packages/sdk/demo/generic/src/controllers/SaleInquiriesController.ts deleted file mode 100644 index 9b4d15890..000000000 --- a/packages/sdk/demo/generic/src/controllers/SaleInquiriesController.ts +++ /dev/null @@ -1,108 +0,0 @@ -import { ISaleInquiry } from "@api/structures/ISaleInquiry"; -import core from "@nestia/core"; -import * as nest from "@nestjs/common"; -import * as express from "express"; - -export function SaleInquiriesController< - Content extends ISaleInquiry.IContent, - Store extends ISaleInquiry.IStore, - Json extends ISaleInquiry, ->(trait: SaleInquiriesController.ITrait) { - abstract class SaleInquiriesController { - /** - * Store a new inquiry. - * - * Write a new article inquirying about a sale. - * - * @param request Instance of the Express.Request - * @param section Code of the target section - * @param saleId ID of the target sale - * @param input Content to archive - * @return Newly archived inquiry - * - * @throw 400 bad request error when type of the input data is not valid - * @throw 401 unauthorized error when you've not logged in yet - */ - @core.TypedRoute.Post({ - type: "is", - is: trait.stringify, - }) - public async store( - @nest.Request() request: express.Request, - @core.TypedParam("section", "string") section: string, - @core.TypedParam("saleId", "string") saleId: string, - @core.TypedBody({ - type: "assert", - assert: trait.assert, - }) - input: Store, - ): Promise { - request; - section; - saleId; - - return trait.convert(input); - } - - /** - * Update ordinary inquiry article. However, it would not modify the content reocrd - * {@link ISaleInquiry.IContent}, but be accumulated into the {@link ISaleInquiry.contents}. - * Therefore, all of the poeple can read how the content has been changed. - * - * @summary Update an inquiry. - * @param request Instance of the Express.Request - * @param section Code of the target section - * @param saleId ID of the target sale - * @param id ID of the target article to be updated - * @param input New content to be overwritten - * @return The newly created content record - * - * @throw 400 bad request error when type of the input data is not valid - * @throw 401 unauthorized error when you've not logged in yet - * @throw 403 forbidden error when the article is not yours - */ - @core.TypedRoute.Put(":id", { - type: "is", - is: trait.stringify, - }) - public async update( - @nest.Request() request: express.Request, - @core.TypedParam("section", "string") section: string, - @core.TypedParam("saleId", "string") saleId: string, - @core.TypedParam("id", "number") id: number, - @core.TypedBody({ - type: "assert", - assert: trait.assert, - }) - input: Store, - ): Promise { - request; - section; - saleId; - id; - - return trait.convert(input); - } - - @core.TypedRoute.Patch("refresh") - public async refresh( - @core.TypedParam("section", "string") section: string, - @core.TypedParam("saleId", "string") saleId: string, - ): Promise { - section; - saleId; - } - } - return SaleInquiriesController; -} -export namespace SaleInquiriesController { - export interface ITrait< - Content extends ISaleInquiry.IContent, - Store extends ISaleInquiry.IStore, - Json extends ISaleInquiry, - > { - stringify(json: Json): string | null; - assert(input: Store): Store; - convert(input: Store): Json; - } -} diff --git a/packages/sdk/demo/generic/src/test/features/test_question_store.ts b/packages/sdk/demo/generic/src/test/features/test_question_store.ts deleted file mode 100644 index d94b47883..000000000 --- a/packages/sdk/demo/generic/src/test/features/test_question_store.ts +++ /dev/null @@ -1,22 +0,0 @@ -import api from "@api"; -import { ISaleQuestion } from "@api/structures/ISaleQuestion"; - -import typia from "typia"; - -export async function test_question_store( - connection: api.IConnection, -): Promise { - const question: ISaleQuestion = - await api.functional.consumers.sales.questions.store( - connection, - "general", - "some-sale-id", - { - title: "some-title", - body: "some-body-content", - files: [], - extension: "html", - }, - ); - typia.assert(question); -} diff --git a/packages/sdk/demo/generic/src/test/features/test_question_update.ts b/packages/sdk/demo/generic/src/test/features/test_question_update.ts deleted file mode 100644 index d326d163a..000000000 --- a/packages/sdk/demo/generic/src/test/features/test_question_update.ts +++ /dev/null @@ -1,43 +0,0 @@ -import api from "@api"; -import { ISaleQuestion } from "@api/structures/ISaleQuestion"; - -import typia from "typia"; - -export async function test_question_update( - connection: api.IConnection, -): Promise { - const question: ISaleQuestion = - await api.functional.consumers.sales.questions.store( - connection, - "general", - "some-sale-id", - { - title: "some-title", - body: "some-body-content", - files: [], - extension: "html", - }, - ); - typia.assert(question); - - const updated: ISaleQuestion = - await api.functional.consumers.sales.questions.update( - connection, - "general", - "some-sale-id", - question.id, - { - title: "new-title", - body: "new-content-body", - files: [ - { - name: "typia", - extension: "lnk", - url: "https://github.com/samchon/typia", - }, - ], - extension: "html", - }, - ); - typia.assert(updated); -} diff --git a/packages/sdk/demo/generic/src/test/features/test_review_store.ts b/packages/sdk/demo/generic/src/test/features/test_review_store.ts deleted file mode 100644 index dd5ad9576..000000000 --- a/packages/sdk/demo/generic/src/test/features/test_review_store.ts +++ /dev/null @@ -1,23 +0,0 @@ -import api from "@api"; -import { ISaleReview } from "@api/structures/ISaleReview"; - -import typia from "typia"; - -export async function test_review_store( - connection: api.IConnection, -): Promise { - const question: ISaleReview = - await api.functional.consumers.sales.reviews.store( - connection, - "general", - "some-sale-id", - { - title: "some-title", - body: "some-body-content", - files: [], - extension: "html", - score: 100, - }, - ); - typia.assert(question); -} diff --git a/packages/sdk/demo/generic/src/test/features/test_review_update.ts b/packages/sdk/demo/generic/src/test/features/test_review_update.ts deleted file mode 100644 index a104b3e9a..000000000 --- a/packages/sdk/demo/generic/src/test/features/test_review_update.ts +++ /dev/null @@ -1,45 +0,0 @@ -import api from "@api"; -import { ISaleReview } from "@api/structures/ISaleReview"; - -import typia from "typia"; - -export async function test_review_update( - connection: api.IConnection, -): Promise { - const question: ISaleReview = - await api.functional.consumers.sales.reviews.store( - connection, - "general", - "some-sale-id", - { - title: "some-title", - body: "some-body-content", - files: [], - extension: "html", - score: 100, - }, - ); - typia.assert(question); - - const updated: ISaleReview = - await api.functional.consumers.sales.reviews.update( - connection, - "general", - "some-sale-id", - question.id, - { - title: "new-title", - body: "new-content-body", - files: [ - { - name: "typia", - extension: "lnk", - url: "https://github.com/samchon/typia", - }, - ], - extension: "html", - score: 90, - }, - ); - typia.assert(updated); -} diff --git a/packages/sdk/demo/generic/src/test/index.ts b/packages/sdk/demo/generic/src/test/index.ts deleted file mode 100644 index 9a9c90c94..000000000 --- a/packages/sdk/demo/generic/src/test/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { Backend } from "../Backend"; -import { Configuration } from "../Configuration"; -import api from "../api"; -import { DynamicImportIterator } from "./internal/DynamicImportIterator"; - -async function main(): Promise { - const server: Backend = new Backend(); - await server.open(); - - const connection: api.IConnection = { - host: `http://127.0.0.1:${Configuration.PORT}`, - encryption: Configuration.ENCRYPTION_PASSWORD, - }; - await DynamicImportIterator.main(__dirname, { - prefix: "test", - parameters: () => [connection], - }); - - await server.close(); -} -main().catch((exp) => { - console.log(exp); - process.exit(-1); -}); diff --git a/packages/sdk/demo/generic/src/test/internal/DynamicImportIterator.ts b/packages/sdk/demo/generic/src/test/internal/DynamicImportIterator.ts deleted file mode 100644 index 4a12a8b47..000000000 --- a/packages/sdk/demo/generic/src/test/internal/DynamicImportIterator.ts +++ /dev/null @@ -1,109 +0,0 @@ -import cli from "cli"; -import fs from "fs"; -import { IPointer } from "tstl/functional/IPointer"; - -import { StopWatch } from "./StopWatch"; - -const EXTENSION = __filename.substr(-2); - -interface ICommand { - include?: string; - exclude?: string; -} - -export namespace DynamicImportIterator { - export type Closure = ( - ...args: Arguments - ) => Promise; - type Module = { - [key: string]: Closure; - }; - - export interface IOptions { - prefix: string; - parameters: () => Parameters; - wrapper?: (name: string, output: any) => Promise; - counter?: IPointer; - showElapsedTime?: boolean; - } - - export async function main( - path: string, - options: IOptions, - ): Promise { - const command: ICommand = cli.parse(); - await iterate(options, command, path); - } - - export async function force( - path: string, - options: IOptions, - ): Promise { - const command: ICommand = cli.parse(); - const exceptions: Error[] = []; - - await iterate(options, command, path, exceptions); - return exceptions; - } - - async function iterate( - options: IOptions, - command: ICommand, - path: string, - exceptions?: Error[], - ): Promise { - const directory: string[] = await fs.promises.readdir(path); - for (const file of directory) { - const current: string = `${path}/${file}`; - const stats: fs.Stats = await fs.promises.lstat(current); - - if (stats.isDirectory() === true) { - await iterate(options, command, current, exceptions); - continue; - } else if (file.substr(-3) !== `.${EXTENSION}`) continue; - - const external: Module = await import(current); - await execute(options, command, external, exceptions); - } - } - - async function execute( - options: IOptions, - command: ICommand, - external: Module, - exceptions?: Error[], - ): Promise { - for (const key in external) { - if (command.exclude && key.indexOf(command.exclude) !== -1) - continue; - else if (command.include && key.indexOf(command.include) === -1) - continue; - else if (key.substr(0, options.prefix.length) !== options.prefix) - continue; - else if (external[key] instanceof Function) { - const closure: Closure = external[key]; - const func = async () => { - const output = await closure(...options.parameters()); - if (options.wrapper) await options.wrapper(key, output); - }; - - try { - if (options.counter) ++options.counter.value; - if (options.showElapsedTime === false) { - await func(); - console.log(` - ${key}`); - } else { - const time: number = await StopWatch.measure(func); - console.log(` - ${key}: ${time.toLocaleString()} ms`); - } - } catch (exp) { - if (!(exp instanceof Error)) return; - - console.log(` - ${key} -> ${exp.name}`); - if (exceptions !== undefined) exceptions.push(exp); - else throw exp; - } - } - } - } -} diff --git a/packages/sdk/demo/generic/src/test/internal/StopWatch.ts b/packages/sdk/demo/generic/src/test/internal/StopWatch.ts deleted file mode 100644 index 862caf8c8..000000000 --- a/packages/sdk/demo/generic/src/test/internal/StopWatch.ts +++ /dev/null @@ -1,15 +0,0 @@ -export namespace StopWatch { - export type Task = () => Promise; - - export async function measure(task: Task): Promise { - const time: number = Date.now(); - await task(); - return Date.now() - time; - } - - export async function trace(title: string, task: Task): Promise { - process.stdout.write(title); - const time: number = await measure(task); - console.log(`: ${time.toLocaleString()} ms`); - } -} diff --git a/packages/sdk/demo/generic/swagger.json b/packages/sdk/demo/generic/swagger.json deleted file mode 100644 index aa9fc7d42..000000000 --- a/packages/sdk/demo/generic/swagger.json +++ /dev/null @@ -1,1330 +0,0 @@ -{ - "openapi": "3.0.1", - "servers": [ - { - "url": "https://github.com/samchon/nestia", - "description": "insert your server url" - } - ], - "info": { - "version": "0.1.0", - "title": "Generated by nestia - https://github.com/samchon/nestia" - }, - "paths": { - "/consumers/{section}/sales/{saleId}/questions": { - "post": { - "tags": [], - "parameters": [ - { - "name": "section", - "in": "path", - "description": "Code of the target section", - "schema": { - "type": "string", - "nullable": false - }, - "required": true - }, - { - "name": "saleId", - "in": "path", - "description": "ID of the target sale", - "schema": { - "type": "string", - "nullable": false - }, - "required": true - } - ], - "requestBody": { - "description": "Content to archive", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ISaleArticle.IStore" - } - } - }, - "required": true, - "x-nestia-encrypted": false - }, - "responses": { - "201": { - "description": "Newly archived inquiry", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ISaleQuestion" - } - } - }, - "x-nestia-encrypted": false - }, - "400": { - "description": "bad request error when type of the input data is not valid" - }, - "401": { - "description": "unauthorized error when you've not logged in yet" - } - }, - "summary": "Store a new inquiry", - "description": "Store a new inquiry.\n\nWrite a new article inquirying about a sale.", - "x-nestia-namespace": "consumers.sales.questions.store", - "x-nestia-jsDocTags": [ - { - "name": "param", - "text": [ - { - "text": "request", - "kind": "parameterName" - }, - { - "text": " ", - "kind": "space" - }, - { - "text": "Instance of the Express.Request", - "kind": "text" - } - ] - }, - { - "name": "param", - "text": [ - { - "text": "section", - "kind": "parameterName" - }, - { - "text": " ", - "kind": "space" - }, - { - "text": "Code of the target section", - "kind": "text" - } - ] - }, - { - "name": "param", - "text": [ - { - "text": "saleId", - "kind": "parameterName" - }, - { - "text": " ", - "kind": "space" - }, - { - "text": "ID of the target sale", - "kind": "text" - } - ] - }, - { - "name": "param", - "text": [ - { - "text": "input", - "kind": "parameterName" - }, - { - "text": " ", - "kind": "space" - }, - { - "text": "Content to archive", - "kind": "text" - } - ] - }, - { - "name": "return", - "text": [ - { - "text": "Newly archived inquiry", - "kind": "text" - } - ] - }, - { - "name": "throw", - "text": [ - { - "text": "400 bad request error when type of the input data is not valid", - "kind": "text" - } - ] - }, - { - "name": "throw", - "text": [ - { - "text": "401 unauthorized error when you've not logged in yet", - "kind": "text" - } - ] - } - ] - } - }, - "/consumers/{section}/sales/{saleId}/questions/{id}": { - "put": { - "tags": [], - "parameters": [ - { - "name": "section", - "in": "path", - "description": "Code of the target section", - "schema": { - "type": "string", - "nullable": false - }, - "required": true - }, - { - "name": "saleId", - "in": "path", - "description": "ID of the target sale", - "schema": { - "type": "string", - "nullable": false - }, - "required": true - }, - { - "name": "id", - "in": "path", - "description": "ID of the target article to be updated", - "schema": { - "type": "number", - "nullable": false - }, - "required": true - } - ], - "requestBody": { - "description": "New content to be overwritten", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ISaleArticle.IStore" - } - } - }, - "required": true, - "x-nestia-encrypted": false - }, - "responses": { - "201": { - "description": "The newly created content record", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ISaleQuestion" - } - } - }, - "x-nestia-encrypted": false - }, - "400": { - "description": "bad request error when type of the input data is not valid" - }, - "401": { - "description": "unauthorized error when you've not logged in yet" - }, - "403": { - "description": "forbidden error when the article is not yours" - } - }, - "summary": "Update an inquiry.", - "description": "Update ordinary inquiry article. However, it would not modify the content reocrd\n{@link ISaleInquiry.IContent}, but be accumulated into the {@link ISaleInquiry.contents}.\nTherefore, all of the poeple can read how the content has been changed.", - "x-nestia-namespace": "consumers.sales.questions.update", - "x-nestia-jsDocTags": [ - { - "name": "summary", - "text": [ - { - "text": "Update an inquiry.", - "kind": "text" - } - ] - }, - { - "name": "param", - "text": [ - { - "text": "request", - "kind": "parameterName" - }, - { - "text": " ", - "kind": "space" - }, - { - "text": "Instance of the Express.Request", - "kind": "text" - } - ] - }, - { - "name": "param", - "text": [ - { - "text": "section", - "kind": "parameterName" - }, - { - "text": " ", - "kind": "space" - }, - { - "text": "Code of the target section", - "kind": "text" - } - ] - }, - { - "name": "param", - "text": [ - { - "text": "saleId", - "kind": "parameterName" - }, - { - "text": " ", - "kind": "space" - }, - { - "text": "ID of the target sale", - "kind": "text" - } - ] - }, - { - "name": "param", - "text": [ - { - "text": "id", - "kind": "parameterName" - }, - { - "text": " ", - "kind": "space" - }, - { - "text": "ID of the target article to be updated", - "kind": "text" - } - ] - }, - { - "name": "param", - "text": [ - { - "text": "input", - "kind": "parameterName" - }, - { - "text": " ", - "kind": "space" - }, - { - "text": "New content to be overwritten", - "kind": "text" - } - ] - }, - { - "name": "return", - "text": [ - { - "text": "The newly created content record", - "kind": "text" - } - ] - }, - { - "name": "throw", - "text": [ - { - "text": "400 bad request error when type of the input data is not valid", - "kind": "text" - } - ] - }, - { - "name": "throw", - "text": [ - { - "text": "401 unauthorized error when you've not logged in yet", - "kind": "text" - } - ] - }, - { - "name": "throw", - "text": [ - { - "text": "403 forbidden error when the article is not yours", - "kind": "text" - } - ] - } - ] - } - }, - "/consumers/{section}/sales/{saleId}/questions/refresh": { - "patch": { - "tags": [], - "parameters": [ - { - "name": "section", - "in": "path", - "description": "", - "schema": { - "type": "string", - "nullable": false - }, - "required": true - }, - { - "name": "saleId", - "in": "path", - "description": "", - "schema": { - "type": "string", - "nullable": false - }, - "required": true - } - ], - "responses": { - "201": { - "description": "", - "x-nestia-encrypted": false - } - }, - "description": "", - "x-nestia-namespace": "consumers.sales.questions.refresh.refresh", - "x-nestia-jsDocTags": [] - } - }, - "/consumers/{section}/sales/{saleId}/reviews": { - "post": { - "tags": [], - "parameters": [ - { - "name": "section", - "in": "path", - "description": "Code of the target section", - "schema": { - "type": "string", - "nullable": false - }, - "required": true - }, - { - "name": "saleId", - "in": "path", - "description": "ID of the target sale", - "schema": { - "type": "string", - "nullable": false - }, - "required": true - } - ], - "requestBody": { - "description": "Content to archive", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ISaleReview.IStore" - } - } - }, - "required": true, - "x-nestia-encrypted": false - }, - "responses": { - "201": { - "description": "Newly archived inquiry", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ISaleReview" - } - } - }, - "x-nestia-encrypted": false - }, - "400": { - "description": "bad request error when type of the input data is not valid" - }, - "401": { - "description": "unauthorized error when you've not logged in yet" - } - }, - "summary": "Store a new inquiry", - "description": "Store a new inquiry.\n\nWrite a new article inquirying about a sale.", - "x-nestia-namespace": "consumers.sales.reviews.store", - "x-nestia-jsDocTags": [ - { - "name": "param", - "text": [ - { - "text": "request", - "kind": "parameterName" - }, - { - "text": " ", - "kind": "space" - }, - { - "text": "Instance of the Express.Request", - "kind": "text" - } - ] - }, - { - "name": "param", - "text": [ - { - "text": "section", - "kind": "parameterName" - }, - { - "text": " ", - "kind": "space" - }, - { - "text": "Code of the target section", - "kind": "text" - } - ] - }, - { - "name": "param", - "text": [ - { - "text": "saleId", - "kind": "parameterName" - }, - { - "text": " ", - "kind": "space" - }, - { - "text": "ID of the target sale", - "kind": "text" - } - ] - }, - { - "name": "param", - "text": [ - { - "text": "input", - "kind": "parameterName" - }, - { - "text": " ", - "kind": "space" - }, - { - "text": "Content to archive", - "kind": "text" - } - ] - }, - { - "name": "return", - "text": [ - { - "text": "Newly archived inquiry", - "kind": "text" - } - ] - }, - { - "name": "throw", - "text": [ - { - "text": "400 bad request error when type of the input data is not valid", - "kind": "text" - } - ] - }, - { - "name": "throw", - "text": [ - { - "text": "401 unauthorized error when you've not logged in yet", - "kind": "text" - } - ] - } - ] - } - }, - "/consumers/{section}/sales/{saleId}/reviews/{id}": { - "put": { - "tags": [], - "parameters": [ - { - "name": "section", - "in": "path", - "description": "Code of the target section", - "schema": { - "type": "string", - "nullable": false - }, - "required": true - }, - { - "name": "saleId", - "in": "path", - "description": "ID of the target sale", - "schema": { - "type": "string", - "nullable": false - }, - "required": true - }, - { - "name": "id", - "in": "path", - "description": "ID of the target article to be updated", - "schema": { - "type": "number", - "nullable": false - }, - "required": true - } - ], - "requestBody": { - "description": "New content to be overwritten", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ISaleReview.IStore" - } - } - }, - "required": true, - "x-nestia-encrypted": false - }, - "responses": { - "201": { - "description": "The newly created content record", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ISaleReview" - } - } - }, - "x-nestia-encrypted": false - }, - "400": { - "description": "bad request error when type of the input data is not valid" - }, - "401": { - "description": "unauthorized error when you've not logged in yet" - }, - "403": { - "description": "forbidden error when the article is not yours" - } - }, - "summary": "Update an inquiry.", - "description": "Update ordinary inquiry article. However, it would not modify the content reocrd\n{@link ISaleInquiry.IContent}, but be accumulated into the {@link ISaleInquiry.contents}.\nTherefore, all of the poeple can read how the content has been changed.", - "x-nestia-namespace": "consumers.sales.reviews.update", - "x-nestia-jsDocTags": [ - { - "name": "summary", - "text": [ - { - "text": "Update an inquiry.", - "kind": "text" - } - ] - }, - { - "name": "param", - "text": [ - { - "text": "request", - "kind": "parameterName" - }, - { - "text": " ", - "kind": "space" - }, - { - "text": "Instance of the Express.Request", - "kind": "text" - } - ] - }, - { - "name": "param", - "text": [ - { - "text": "section", - "kind": "parameterName" - }, - { - "text": " ", - "kind": "space" - }, - { - "text": "Code of the target section", - "kind": "text" - } - ] - }, - { - "name": "param", - "text": [ - { - "text": "saleId", - "kind": "parameterName" - }, - { - "text": " ", - "kind": "space" - }, - { - "text": "ID of the target sale", - "kind": "text" - } - ] - }, - { - "name": "param", - "text": [ - { - "text": "id", - "kind": "parameterName" - }, - { - "text": " ", - "kind": "space" - }, - { - "text": "ID of the target article to be updated", - "kind": "text" - } - ] - }, - { - "name": "param", - "text": [ - { - "text": "input", - "kind": "parameterName" - }, - { - "text": " ", - "kind": "space" - }, - { - "text": "New content to be overwritten", - "kind": "text" - } - ] - }, - { - "name": "return", - "text": [ - { - "text": "The newly created content record", - "kind": "text" - } - ] - }, - { - "name": "throw", - "text": [ - { - "text": "400 bad request error when type of the input data is not valid", - "kind": "text" - } - ] - }, - { - "name": "throw", - "text": [ - { - "text": "401 unauthorized error when you've not logged in yet", - "kind": "text" - } - ] - }, - { - "name": "throw", - "text": [ - { - "text": "403 forbidden error when the article is not yours", - "kind": "text" - } - ] - } - ] - } - }, - "/consumers/{section}/sales/{saleId}/reviews/refresh": { - "patch": { - "tags": [], - "parameters": [ - { - "name": "section", - "in": "path", - "description": "", - "schema": { - "type": "string", - "nullable": false - }, - "required": true - }, - { - "name": "saleId", - "in": "path", - "description": "", - "schema": { - "type": "string", - "nullable": false - }, - "required": true - } - ], - "responses": { - "201": { - "description": "", - "x-nestia-encrypted": false - } - }, - "description": "", - "x-nestia-namespace": "consumers.sales.reviews.refresh.refresh", - "x-nestia-jsDocTags": [] - } - } - }, - "components": { - "schemas": { - "ISaleArticle.IStore": { - "type": "object", - "properties": { - "title": { - "type": "string", - "nullable": false, - "description": "Title of the content.", - "x-typia-required": true - }, - "body": { - "type": "string", - "nullable": false, - "description": "Body of the content.", - "x-typia-required": true - }, - "extension": { - "type": "string", - "enum": [ - "html", - "md", - "txt" - ], - "nullable": false, - "description": "Extension, content type (format).", - "x-typia-required": true - }, - "files": { - "type": "array", - "items": { - "$ref": "#/components/schemas/IAttachmentFile", - "description": "Attached files.", - "x-typia-required": true - }, - "nullable": false, - "description": "Attached files.", - "x-typia-required": true - } - }, - "nullable": false, - "required": [ - "title", - "body", - "extension", - "files" - ], - "description": "Store info.", - "x-typia-jsDocTags": [] - }, - "IAttachmentFile": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": false, - "description": "Name of the file.", - "x-typia-required": true - }, - "extension": { - "type": "string", - "nullable": true, - "description": "Extension of the file, but ommitable.", - "x-typia-required": true - }, - "url": { - "type": "string", - "nullable": false, - "description": "Full URL path of the file.", - "x-typia-required": true - } - }, - "nullable": false, - "required": [ - "name", - "extension", - "url" - ], - "description": "Attachemd (physical) file info.", - "x-typia-jsDocTags": [ - { - "name": "author", - "text": [ - { - "text": "Jeongho Nam - https://github.com/samchon", - "kind": "text" - } - ] - } - ] - }, - "ISaleQuestion": { - "type": "object", - "properties": { - "writer": { - "type": "string", - "nullable": false, - "description": "Name of the writer.", - "x-typia-required": true - }, - "answer": { - "$ref": "#/components/schemas/ISaleInquiryAnswer.Nullable", - "description": "Formal answer from the seller.", - "x-typia-required": true - }, - "id": { - "type": "number", - "nullable": false, - "description": "Primary Key.", - "x-typia-required": true - }, - "hit": { - "type": "number", - "nullable": false, - "description": "Hit count.\n\nHow many consumers had read.", - "x-typia-required": true - }, - "contents": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ISaleArticle.IContent", - "description": "List of contents.\n\nWhen the article writer tries to modify content, it would not modify the article\ncontent but would be accumulated. Therefore, all of the people can read how\nthe content has been changed.", - "x-typia-required": true - }, - "nullable": false, - "description": "List of contents.\n\nWhen the article writer tries to modify content, it would not modify the article\ncontent but would be accumulated. Therefore, all of the people can read how\nthe content has been changed.", - "x-typia-required": true - }, - "created_at": { - "type": "string", - "nullable": false, - "description": "Creation time.", - "x-typia-required": true - } - }, - "nullable": false, - "required": [ - "writer", - "answer", - "id", - "hit", - "contents", - "created_at" - ], - "description": "Inquiry article.\n\nSub-type of article and super-type of question and answer.", - "x-typia-jsDocTags": [ - { - "name": "template", - "text": [ - { - "text": "Content", - "kind": "typeParameterName" - }, - { - "text": " ", - "kind": "space" - }, - { - "text": "Content type", - "kind": "text" - } - ] - }, - { - "name": "author", - "text": [ - { - "text": "Jeongho Nam - https://github.com/samchon", - "kind": "text" - } - ] - } - ] - }, - "ISaleInquiryAnswer.Nullable": { - "type": "object", - "properties": { - "id": { - "type": "number", - "nullable": false, - "description": "Primary Key.", - "x-typia-required": true - }, - "hit": { - "type": "number", - "nullable": false, - "description": "Hit count.\n\nHow many consumers had read.", - "x-typia-required": true - }, - "contents": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ISaleArticle.IContent", - "description": "List of contents.\n\nWhen the article writer tries to modify content, it would not modify the article\ncontent but would be accumulated. Therefore, all of the people can read how\nthe content has been changed.", - "x-typia-required": true - }, - "nullable": false, - "description": "List of contents.\n\nWhen the article writer tries to modify content, it would not modify the article\ncontent but would be accumulated. Therefore, all of the people can read how\nthe content has been changed.", - "x-typia-required": true - }, - "created_at": { - "type": "string", - "nullable": false, - "description": "Creation time.", - "x-typia-required": true - } - }, - "nullable": true, - "required": [ - "id", - "hit", - "contents", - "created_at" - ], - "description": "Article about a sale.\n\nThe `ISaleArticle` is a super type interface. Many sub-type articles would be\ndesigned by extending this super type interface `ISaleArticle`.", - "x-typia-jsDocTags": [ - { - "name": "template", - "text": [ - { - "text": "Content", - "kind": "typeParameterName" - }, - { - "text": " ", - "kind": "space" - }, - { - "text": "Content type.", - "kind": "text" - } - ] - }, - { - "name": "author", - "text": [ - { - "text": "Jeongho Nam - https://github.com/samchon", - "kind": "text" - } - ] - } - ] - }, - "ISaleArticle.IContent": { - "type": "object", - "properties": { - "id": { - "type": "string", - "nullable": false, - "description": "Primary Key", - "x-typia-required": true - }, - "created_at": { - "type": "string", - "nullable": false, - "description": "Creation time.", - "x-typia-required": true - }, - "title": { - "type": "string", - "nullable": false, - "description": "Title of the content.", - "x-typia-required": true - }, - "body": { - "type": "string", - "nullable": false, - "description": "Body of the content.", - "x-typia-required": true - }, - "extension": { - "type": "string", - "enum": [ - "html", - "md", - "txt" - ], - "nullable": false, - "description": "Extension, content type (format).", - "x-typia-required": true - }, - "files": { - "type": "array", - "items": { - "$ref": "#/components/schemas/IAttachmentFile", - "description": "Attached files.", - "x-typia-required": true - }, - "nullable": false, - "description": "Attached files.", - "x-typia-required": true - } - }, - "nullable": false, - "required": [ - "id", - "created_at", - "title", - "body", - "extension", - "files" - ], - "description": "Content info.", - "x-typia-jsDocTags": [] - }, - "ISaleReview.IStore": { - "type": "object", - "properties": { - "score": { - "type": "number", - "nullable": false, - "description": "Estimation score.", - "x-typia-required": true - }, - "title": { - "type": "string", - "nullable": false, - "description": "Title of the content.", - "x-typia-required": true - }, - "body": { - "type": "string", - "nullable": false, - "description": "Body of the content.", - "x-typia-required": true - }, - "extension": { - "type": "string", - "enum": [ - "html", - "md", - "txt" - ], - "nullable": false, - "description": "Extension, content type (format).", - "x-typia-required": true - }, - "files": { - "type": "array", - "items": { - "$ref": "#/components/schemas/IAttachmentFile", - "description": "Attached files.", - "x-typia-required": true - }, - "nullable": false, - "description": "Attached files.", - "x-typia-required": true - } - }, - "nullable": false, - "required": [ - "score", - "title", - "body", - "extension", - "files" - ], - "description": "Store info of the review.", - "x-typia-jsDocTags": [] - }, - "ISaleReview": { - "type": "object", - "properties": { - "writer": { - "type": "string", - "nullable": false, - "description": "Name of the writer.", - "x-typia-required": true - }, - "answer": { - "$ref": "#/components/schemas/ISaleInquiryAnswer.Nullable", - "description": "Formal answer from the seller.", - "x-typia-required": true - }, - "id": { - "type": "number", - "nullable": false, - "description": "Primary Key.", - "x-typia-required": true - }, - "hit": { - "type": "number", - "nullable": false, - "description": "Hit count.\n\nHow many consumers had read.", - "x-typia-required": true - }, - "contents": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ISaleReview.IContent", - "description": "List of contents.\n\nWhen the article writer tries to modify content, it would not modify the article\ncontent but would be accumulated. Therefore, all of the people can read how\nthe content has been changed.", - "x-typia-required": true - }, - "nullable": false, - "description": "List of contents.\n\nWhen the article writer tries to modify content, it would not modify the article\ncontent but would be accumulated. Therefore, all of the people can read how\nthe content has been changed.", - "x-typia-required": true - }, - "created_at": { - "type": "string", - "nullable": false, - "description": "Creation time.", - "x-typia-required": true - } - }, - "nullable": false, - "required": [ - "writer", - "answer", - "id", - "hit", - "contents", - "created_at" - ], - "description": "Inquiry article.\n\nSub-type of article and super-type of question and answer.", - "x-typia-jsDocTags": [ - { - "name": "template", - "text": [ - { - "text": "Content", - "kind": "typeParameterName" - }, - { - "text": " ", - "kind": "space" - }, - { - "text": "Content type", - "kind": "text" - } - ] - }, - { - "name": "author", - "text": [ - { - "text": "Jeongho Nam - https://github.com/samchon", - "kind": "text" - } - ] - } - ] - }, - "ISaleReview.IContent": { - "type": "object", - "properties": { - "score": { - "type": "number", - "nullable": false, - "description": "Estimation score.", - "x-typia-required": true - }, - "id": { - "type": "string", - "nullable": false, - "description": "Primary Key", - "x-typia-required": true - }, - "created_at": { - "type": "string", - "nullable": false, - "description": "Creation time.", - "x-typia-required": true - }, - "title": { - "type": "string", - "nullable": false, - "description": "Title of the content.", - "x-typia-required": true - }, - "body": { - "type": "string", - "nullable": false, - "description": "Body of the content.", - "x-typia-required": true - }, - "extension": { - "type": "string", - "enum": [ - "html", - "md", - "txt" - ], - "nullable": false, - "description": "Extension, content type (format).", - "x-typia-required": true - }, - "files": { - "type": "array", - "items": { - "$ref": "#/components/schemas/IAttachmentFile", - "description": "Attached files.", - "x-typia-required": true - }, - "nullable": false, - "description": "Attached files.", - "x-typia-required": true - } - }, - "nullable": false, - "required": [ - "score", - "id", - "created_at", - "title", - "body", - "extension", - "files" - ], - "description": "Content info of the review.", - "x-typia-jsDocTags": [] - } - } - } -} \ No newline at end of file diff --git a/packages/sdk/demo/generic/tsconfig.json b/packages/sdk/demo/generic/tsconfig.json deleted file mode 100644 index a4c7e4f62..000000000 --- a/packages/sdk/demo/generic/tsconfig.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "../tsconfig.base.json", - "compilerOptions": { - "paths": { - "@api": ["./src/api"], - "@api/*": ["./src/api/*"] - } - } -} \ No newline at end of file diff --git a/packages/sdk/demo/multiple-paths/src/Backend.ts b/packages/sdk/demo/multiple-paths/src/Backend.ts deleted file mode 100644 index 4507166f0..000000000 --- a/packages/sdk/demo/multiple-paths/src/Backend.ts +++ /dev/null @@ -1,28 +0,0 @@ -import helper from "@nestia/core"; -import * as nest from "@nestjs/common"; -import { NestFactory } from "@nestjs/core"; - -import { Configuration } from "./Configuration"; - -export class Backend { - private application_?: nest.INestApplication; - - public async open(): Promise { - this.application_ = await NestFactory.create( - await helper.EncryptedModule.dynamic( - __dirname + "/controllers", - Configuration.ENCRYPTION_PASSWORD, - ), - { logger: false }, - ); - await this.application_.listen(Configuration.PORT); - } - - public async close(): Promise { - if (this.application_ === undefined) return; - - const app = this.application_; - delete this.application_; - await app.close(); - } -} diff --git a/packages/sdk/demo/multiple-paths/src/Configuration.ts b/packages/sdk/demo/multiple-paths/src/Configuration.ts deleted file mode 100644 index 01a3f1f12..000000000 --- a/packages/sdk/demo/multiple-paths/src/Configuration.ts +++ /dev/null @@ -1,7 +0,0 @@ -export namespace Configuration { - export const PORT = 12345; - export const ENCRYPTION_PASSWORD = { - key: "a".repeat(32), - iv: "b".repeat(16), - }; -} diff --git a/packages/sdk/demo/multiple-paths/src/api/functional/consumers/index.ts b/packages/sdk/demo/multiple-paths/src/api/functional/consumers/index.ts deleted file mode 100644 index 3ba654cad..000000000 --- a/packages/sdk/demo/multiple-paths/src/api/functional/consumers/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -/** - * @packageDocumentation - * @module api.functional.consumers - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -//================================================================ -export * as sales from "./sales"; \ No newline at end of file diff --git a/packages/sdk/demo/multiple-paths/src/api/functional/consumers/sales/articles/comments/index.ts b/packages/sdk/demo/multiple-paths/src/api/functional/consumers/sales/articles/comments/index.ts deleted file mode 100644 index d65501be3..000000000 --- a/packages/sdk/demo/multiple-paths/src/api/functional/consumers/sales/articles/comments/index.ts +++ /dev/null @@ -1,65 +0,0 @@ -/** - * @packageDocumentation - * @module api.functional.consumers.sales.articles.comments - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -//================================================================ -import { Fetcher, Primitive } from "@nestia/fetcher"; -import type { IConnection } from "@nestia/fetcher"; - -import type { ISaleArticleComment } from "./../../../../../structures/ISaleArticleComment"; - -/** - * Store a new comment. - * - * @param connection connection Information of the remote HTTP(s) server with headers (+encryption password) - * @param request Instance of the Express.Request - * @param section Code of the target section - * @param saleId ID of the target sale - * @param articleId ID of the target article - * @param input Content to write - * @return Newly archived comment - * @throws 400 bad request error when type of the input data is not valid - * @throws 401 unauthorized error when you've not logged in yet - * @throws 403 forbidden error when you're a seller and the sale is not yours - * @throws 404 not found error when unable to find the matched record - * - * @controller MultipleCommentsController.store() - * @path POST /consumers/:section/sales/:saleId/articles/:articleId/comments - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -export function store - ( - connection: IConnection, - section: string, - saleId: number, - articleId: number, - input: Primitive - ): Promise -{ - return Fetcher.fetch - ( - connection, - store.ENCRYPTED, - store.METHOD, - store.path(section, saleId, articleId), - input - ); -} -export namespace store -{ - export type Input = Primitive; - export type Output = Primitive; - - export const METHOD = "POST" as const; - export const PATH: string = "/consumers/:section/sales/:saleId/articles/:articleId/comments"; - export const ENCRYPTED: Fetcher.IEncrypted = { - request: false, - response: false, - }; - - export function path(section: string, saleId: number, articleId: number): string - { - return `/consumers/${encodeURIComponent(section)}/sales/${encodeURIComponent(saleId)}/articles/${encodeURIComponent(articleId)}/comments`; - } -} \ No newline at end of file diff --git a/packages/sdk/demo/multiple-paths/src/api/functional/consumers/sales/articles/index.ts b/packages/sdk/demo/multiple-paths/src/api/functional/consumers/sales/articles/index.ts deleted file mode 100644 index af186a2ac..000000000 --- a/packages/sdk/demo/multiple-paths/src/api/functional/consumers/sales/articles/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -/** - * @packageDocumentation - * @module api.functional.consumers.sales.articles - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -//================================================================ -export * as comments from "./comments"; \ No newline at end of file diff --git a/packages/sdk/demo/multiple-paths/src/api/functional/consumers/sales/index.ts b/packages/sdk/demo/multiple-paths/src/api/functional/consumers/sales/index.ts deleted file mode 100644 index 31db5fd9f..000000000 --- a/packages/sdk/demo/multiple-paths/src/api/functional/consumers/sales/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -/** - * @packageDocumentation - * @module api.functional.consumers.sales - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -//================================================================ -export * as articles from "./articles"; \ No newline at end of file diff --git a/packages/sdk/demo/multiple-paths/src/api/functional/sellers/index.ts b/packages/sdk/demo/multiple-paths/src/api/functional/sellers/index.ts deleted file mode 100644 index 0a8c05fdb..000000000 --- a/packages/sdk/demo/multiple-paths/src/api/functional/sellers/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -/** - * @packageDocumentation - * @module api.functional.sellers - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -//================================================================ -export * as sales from "./sales"; \ No newline at end of file diff --git a/packages/sdk/demo/multiple-paths/src/api/functional/sellers/sales/articles/comments/index.ts b/packages/sdk/demo/multiple-paths/src/api/functional/sellers/sales/articles/comments/index.ts deleted file mode 100644 index d9b769bda..000000000 --- a/packages/sdk/demo/multiple-paths/src/api/functional/sellers/sales/articles/comments/index.ts +++ /dev/null @@ -1,65 +0,0 @@ -/** - * @packageDocumentation - * @module api.functional.sellers.sales.articles.comments - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -//================================================================ -import { Fetcher, Primitive } from "@nestia/fetcher"; -import type { IConnection } from "@nestia/fetcher"; - -import type { ISaleArticleComment } from "./../../../../../structures/ISaleArticleComment"; - -/** - * Store a new comment. - * - * @param connection connection Information of the remote HTTP(s) server with headers (+encryption password) - * @param request Instance of the Express.Request - * @param section Code of the target section - * @param saleId ID of the target sale - * @param articleId ID of the target article - * @param input Content to write - * @return Newly archived comment - * @throws 400 bad request error when type of the input data is not valid - * @throws 401 unauthorized error when you've not logged in yet - * @throws 403 forbidden error when you're a seller and the sale is not yours - * @throws 404 not found error when unable to find the matched record - * - * @controller MultipleCommentsController.store() - * @path POST /sellers/:section/sales/:saleId/articles/:articleId/comments - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -export function store - ( - connection: IConnection, - section: string, - saleId: number, - articleId: number, - input: Primitive - ): Promise -{ - return Fetcher.fetch - ( - connection, - store.ENCRYPTED, - store.METHOD, - store.path(section, saleId, articleId), - input - ); -} -export namespace store -{ - export type Input = Primitive; - export type Output = Primitive; - - export const METHOD = "POST" as const; - export const PATH: string = "/sellers/:section/sales/:saleId/articles/:articleId/comments"; - export const ENCRYPTED: Fetcher.IEncrypted = { - request: false, - response: false, - }; - - export function path(section: string, saleId: number, articleId: number): string - { - return `/sellers/${encodeURIComponent(section)}/sales/${encodeURIComponent(saleId)}/articles/${encodeURIComponent(articleId)}/comments`; - } -} \ No newline at end of file diff --git a/packages/sdk/demo/multiple-paths/src/api/functional/sellers/sales/articles/index.ts b/packages/sdk/demo/multiple-paths/src/api/functional/sellers/sales/articles/index.ts deleted file mode 100644 index 8f93ab439..000000000 --- a/packages/sdk/demo/multiple-paths/src/api/functional/sellers/sales/articles/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -/** - * @packageDocumentation - * @module api.functional.sellers.sales.articles - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -//================================================================ -export * as comments from "./comments"; \ No newline at end of file diff --git a/packages/sdk/demo/multiple-paths/src/api/index.ts b/packages/sdk/demo/multiple-paths/src/api/index.ts deleted file mode 100644 index 541bef45a..000000000 --- a/packages/sdk/demo/multiple-paths/src/api/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -import * as api from "./module"; - -/** - * @packageDocumentation - * @module api - */ -//================================================================ -export * from "./module"; - -export default api; diff --git a/packages/sdk/demo/multiple-paths/src/api/module.ts b/packages/sdk/demo/multiple-paths/src/api/module.ts deleted file mode 100644 index b731ce60c..000000000 --- a/packages/sdk/demo/multiple-paths/src/api/module.ts +++ /dev/null @@ -1,10 +0,0 @@ -/** - * @packageDocumentation - * @module api - */ -//================================================================ -export * from "./IConnection"; -export * from "./Primitive"; -export * from "./HttpError"; - -export * as functional from "./functional"; diff --git a/packages/sdk/demo/multiple-paths/src/api/structures/ISaleArticleComment.ts b/packages/sdk/demo/multiple-paths/src/api/structures/ISaleArticleComment.ts deleted file mode 100644 index c7c791853..000000000 --- a/packages/sdk/demo/multiple-paths/src/api/structures/ISaleArticleComment.ts +++ /dev/null @@ -1,93 +0,0 @@ -/** - * Comment wrote on a sale related article. - * - * When an article of a sale has been enrolled, all of the participants like consumers and - * sellers can write a comment on that article. However, when the writer is a consumer, the - * consumer can hide its name through the annoymous option. - * - * Also, writing a reply comment for a specific comment is possible and in that case, the - * {@link ISaleArticleComment.parent_id} property would be activated. - * - * @author Jeongho Nam - https://github.com/samchon - */ -export interface ISaleArticleComment { - /** - * Primary Key. - */ - id: number; - - /** - * Parent comment ID. - * - * Only When this comment has been written as a reply. - */ - parent_id: number | null; - - /** - * Type of the writer. - */ - writer_type: "seller" | "consumer"; - - /** - * Name of the writer. - * - * When this is a type of anonymous comment, writer name would be hidden. - */ - writer_name: string | null; - - /** - * Contents of the comments. - * - * When the comment writer tries to modify content, it would not modify the comment - * content but would be accumulated. Therefore, all of the people can read how - * the content has been changed. - */ - contents: ISaleArticleComment.IContent[]; - - /** - * Creation time. - */ - created_at: string; -} - -export namespace ISaleArticleComment { - /** - * Store info. - */ - export interface IStore { - /** - * Body of the content. - */ - body: string; - - /** - * Extension, content type (format). - */ - extension: "html" | "md" | "txt"; - - /** - * Whether to hide the writer name or not. - */ - annonymous: boolean; - } - - /** - * Content info. - */ - export interface IContent { - /** - * Primary Key. - */ - id: string; - - /** - * Body of the content. - */ - body: string; - - /** - * Creation time. - */ - created_at: string; - } -} diff --git a/packages/sdk/demo/multiple-paths/src/controllers/HealthController.ts b/packages/sdk/demo/multiple-paths/src/controllers/HealthController.ts deleted file mode 100644 index 74e1ec07c..000000000 --- a/packages/sdk/demo/multiple-paths/src/controllers/HealthController.ts +++ /dev/null @@ -1,7 +0,0 @@ -import * as nest from "@nestjs/common"; - -@nest.Controller(["health", "healthy"]) -export class HealthController { - @nest.Get(["check", "alive"]) - public check(): void {} -} diff --git a/packages/sdk/demo/multiple-paths/src/controllers/MultipleController.ts b/packages/sdk/demo/multiple-paths/src/controllers/MultipleController.ts deleted file mode 100644 index 6f6aaa642..000000000 --- a/packages/sdk/demo/multiple-paths/src/controllers/MultipleController.ts +++ /dev/null @@ -1,56 +0,0 @@ -import core from "@nestia/core"; -import * as nest from "@nestjs/common"; -import * as express from "express"; - -import { ISaleArticleComment } from "../api/structures/ISaleArticleComment"; - -@nest.Controller({ - path: [ - "consumers/:section/sales/:saleId/articles/:articleId/comments", - "sellers/:section/sales/:saleId/articles/:articleId/comments", - ], -}) -export class MultipleCommentsController { - /** - * Store a new comment. - * - * @param request Instance of the Express.Request - * @param section Code of the target section - * @param saleId ID of the target sale - * @param articleId ID of the target article - * @param input Content to write - * @return Newly archived comment - * - * @throws 400 bad request error when type of the input data is not valid - * @throws 401 unauthorized error when you've not logged in yet - * @throws 403 forbidden error when you're a seller and the sale is not yours - * @throws 404 not found error when unable to find the matched record - */ - @nest.Post([]) - public async store( - @nest.Request() request: express.Request, - @core.TypedParam("section", "string") section: string, - @core.TypedParam("saleId", "number") saleId: number, - @core.TypedParam("articleId", "number") articleId: number, - @nest.Body() input: ISaleArticleComment.IStore, - ): Promise { - section; - saleId; - articleId; - - return { - id: 0, - parent_id: null, - writer_type: request.path.indexOf("seller") ? "seller" : "consumer", - writer_name: input.annonymous ? null : "someone", - contents: [ - { - id: "some-id", - body: input.body, - created_at: new Date().toString(), - }, - ], - created_at: new Date().toString(), - }; - } -} diff --git a/packages/sdk/demo/multiple-paths/src/test/features/test_consumer_sale_article_comment_store.ts b/packages/sdk/demo/multiple-paths/src/test/features/test_consumer_sale_article_comment_store.ts deleted file mode 100644 index 82f603ea9..000000000 --- a/packages/sdk/demo/multiple-paths/src/test/features/test_consumer_sale_article_comment_store.ts +++ /dev/null @@ -1,22 +0,0 @@ -import typia from "typia"; - -import api from "../../api"; -import { ISaleArticleComment } from "../../api/structures/ISaleArticleComment"; - -export async function test_consumer_sale_article_comment_store( - connection: api.IConnection, -): Promise { - const comment: ISaleArticleComment = - await api.functional.consumers.sales.articles.comments.store( - connection, - "general", - 0, - 0, - { - body: "Some body content", - extension: "md", - annonymous: true, - }, - ); - typia.assert(comment); -} diff --git a/packages/sdk/demo/multiple-paths/src/test/features/test_health_checks.ts b/packages/sdk/demo/multiple-paths/src/test/features/test_health_checks.ts deleted file mode 100644 index 7eff6f6e4..000000000 --- a/packages/sdk/demo/multiple-paths/src/test/features/test_health_checks.ts +++ /dev/null @@ -1,10 +0,0 @@ -import api from "../../api"; - -export async function test_health_checks( - connection: api.IConnection, -): Promise { - await api.functional.health.check(connection); - await api.functional.health.alive.check(connection); - await api.functional.healthy.check(connection); - await api.functional.healthy.alive.check(connection); -} diff --git a/packages/sdk/demo/multiple-paths/src/test/features/test_seller_sale_article_store.ts b/packages/sdk/demo/multiple-paths/src/test/features/test_seller_sale_article_store.ts deleted file mode 100644 index 97b0cf678..000000000 --- a/packages/sdk/demo/multiple-paths/src/test/features/test_seller_sale_article_store.ts +++ /dev/null @@ -1,22 +0,0 @@ -import typia from "typia"; - -import api from "../../api"; -import { ISaleArticleComment } from "../../api/structures/ISaleArticleComment"; - -export async function test_consumer_seller_article_comment_store( - connection: api.IConnection, -): Promise { - const comment: ISaleArticleComment = - await api.functional.sellers.sales.articles.comments.store( - connection, - "general", - 0, - 0, - { - body: "Some body content", - extension: "txt", - annonymous: false, - }, - ); - typia.assert(comment); -} diff --git a/packages/sdk/demo/multiple-paths/src/test/index.ts b/packages/sdk/demo/multiple-paths/src/test/index.ts deleted file mode 100644 index 9a9c90c94..000000000 --- a/packages/sdk/demo/multiple-paths/src/test/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { Backend } from "../Backend"; -import { Configuration } from "../Configuration"; -import api from "../api"; -import { DynamicImportIterator } from "./internal/DynamicImportIterator"; - -async function main(): Promise { - const server: Backend = new Backend(); - await server.open(); - - const connection: api.IConnection = { - host: `http://127.0.0.1:${Configuration.PORT}`, - encryption: Configuration.ENCRYPTION_PASSWORD, - }; - await DynamicImportIterator.main(__dirname, { - prefix: "test", - parameters: () => [connection], - }); - - await server.close(); -} -main().catch((exp) => { - console.log(exp); - process.exit(-1); -}); diff --git a/packages/sdk/demo/multiple-paths/src/test/internal/DynamicImportIterator.ts b/packages/sdk/demo/multiple-paths/src/test/internal/DynamicImportIterator.ts deleted file mode 100644 index 4a12a8b47..000000000 --- a/packages/sdk/demo/multiple-paths/src/test/internal/DynamicImportIterator.ts +++ /dev/null @@ -1,109 +0,0 @@ -import cli from "cli"; -import fs from "fs"; -import { IPointer } from "tstl/functional/IPointer"; - -import { StopWatch } from "./StopWatch"; - -const EXTENSION = __filename.substr(-2); - -interface ICommand { - include?: string; - exclude?: string; -} - -export namespace DynamicImportIterator { - export type Closure = ( - ...args: Arguments - ) => Promise; - type Module = { - [key: string]: Closure; - }; - - export interface IOptions { - prefix: string; - parameters: () => Parameters; - wrapper?: (name: string, output: any) => Promise; - counter?: IPointer; - showElapsedTime?: boolean; - } - - export async function main( - path: string, - options: IOptions, - ): Promise { - const command: ICommand = cli.parse(); - await iterate(options, command, path); - } - - export async function force( - path: string, - options: IOptions, - ): Promise { - const command: ICommand = cli.parse(); - const exceptions: Error[] = []; - - await iterate(options, command, path, exceptions); - return exceptions; - } - - async function iterate( - options: IOptions, - command: ICommand, - path: string, - exceptions?: Error[], - ): Promise { - const directory: string[] = await fs.promises.readdir(path); - for (const file of directory) { - const current: string = `${path}/${file}`; - const stats: fs.Stats = await fs.promises.lstat(current); - - if (stats.isDirectory() === true) { - await iterate(options, command, current, exceptions); - continue; - } else if (file.substr(-3) !== `.${EXTENSION}`) continue; - - const external: Module = await import(current); - await execute(options, command, external, exceptions); - } - } - - async function execute( - options: IOptions, - command: ICommand, - external: Module, - exceptions?: Error[], - ): Promise { - for (const key in external) { - if (command.exclude && key.indexOf(command.exclude) !== -1) - continue; - else if (command.include && key.indexOf(command.include) === -1) - continue; - else if (key.substr(0, options.prefix.length) !== options.prefix) - continue; - else if (external[key] instanceof Function) { - const closure: Closure = external[key]; - const func = async () => { - const output = await closure(...options.parameters()); - if (options.wrapper) await options.wrapper(key, output); - }; - - try { - if (options.counter) ++options.counter.value; - if (options.showElapsedTime === false) { - await func(); - console.log(` - ${key}`); - } else { - const time: number = await StopWatch.measure(func); - console.log(` - ${key}: ${time.toLocaleString()} ms`); - } - } catch (exp) { - if (!(exp instanceof Error)) return; - - console.log(` - ${key} -> ${exp.name}`); - if (exceptions !== undefined) exceptions.push(exp); - else throw exp; - } - } - } - } -} diff --git a/packages/sdk/demo/multiple-paths/src/test/internal/StopWatch.ts b/packages/sdk/demo/multiple-paths/src/test/internal/StopWatch.ts deleted file mode 100644 index 862caf8c8..000000000 --- a/packages/sdk/demo/multiple-paths/src/test/internal/StopWatch.ts +++ /dev/null @@ -1,15 +0,0 @@ -export namespace StopWatch { - export type Task = () => Promise; - - export async function measure(task: Task): Promise { - const time: number = Date.now(); - await task(); - return Date.now() - time; - } - - export async function trace(title: string, task: Task): Promise { - process.stdout.write(title); - const time: number = await measure(task); - console.log(`: ${time.toLocaleString()} ms`); - } -} diff --git a/packages/sdk/demo/multiple-paths/swagger.json b/packages/sdk/demo/multiple-paths/swagger.json deleted file mode 100644 index ce1656d55..000000000 --- a/packages/sdk/demo/multiple-paths/swagger.json +++ /dev/null @@ -1,635 +0,0 @@ -{ - "openapi": "3.0.1", - "servers": [ - { - "url": "https://github.com/samchon/nestia", - "description": "insert your server url" - } - ], - "info": { - "version": "0.1.0", - "title": "Generated by nestia - https://github.com/samchon/nestia" - }, - "paths": { - "/health/check": { - "get": { - "tags": [], - "parameters": [], - "responses": { - "200": { - "description": "", - "x-nestia-encrypted": false - } - }, - "description": "", - "x-nestia-namespace": "health.check.check", - "x-nestia-jsDocTags": [] - } - }, - "/health/alive": { - "get": { - "tags": [], - "parameters": [], - "responses": { - "200": { - "description": "", - "x-nestia-encrypted": false - } - }, - "description": "", - "x-nestia-namespace": "health.alive.check", - "x-nestia-jsDocTags": [] - } - }, - "/healthy/check": { - "get": { - "tags": [], - "parameters": [], - "responses": { - "200": { - "description": "", - "x-nestia-encrypted": false - } - }, - "description": "", - "x-nestia-namespace": "healthy.check.check", - "x-nestia-jsDocTags": [] - } - }, - "/healthy/alive": { - "get": { - "tags": [], - "parameters": [], - "responses": { - "200": { - "description": "", - "x-nestia-encrypted": false - } - }, - "description": "", - "x-nestia-namespace": "healthy.alive.check", - "x-nestia-jsDocTags": [] - } - }, - "/consumers/{section}/sales/{saleId}/articles/{articleId}/comments": { - "post": { - "tags": [], - "parameters": [ - { - "name": "section", - "in": "path", - "description": "Code of the target section", - "schema": { - "type": "string", - "nullable": false - }, - "required": true - }, - { - "name": "saleId", - "in": "path", - "description": "ID of the target sale", - "schema": { - "type": "number", - "nullable": false - }, - "required": true - }, - { - "name": "articleId", - "in": "path", - "description": "ID of the target article", - "schema": { - "type": "number", - "nullable": false - }, - "required": true - } - ], - "requestBody": { - "description": "Content to write", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ISaleArticleComment.IStore" - } - } - }, - "required": true, - "x-nestia-encrypted": false - }, - "responses": { - "201": { - "description": "Newly archived comment", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ISaleArticleComment" - } - } - }, - "x-nestia-encrypted": false - }, - "400": { - "description": "bad request error when type of the input data is not valid" - }, - "401": { - "description": "unauthorized error when you've not logged in yet" - }, - "403": { - "description": "forbidden error when you're a seller and the sale is not yours" - }, - "404": { - "description": "not found error when unable to find the matched record" - } - }, - "summary": "Store a new comment", - "description": "Store a new comment.", - "x-nestia-namespace": "consumers.sales.articles.comments.store", - "x-nestia-jsDocTags": [ - { - "name": "param", - "text": [ - { - "text": "request", - "kind": "parameterName" - }, - { - "text": " ", - "kind": "space" - }, - { - "text": "Instance of the Express.Request", - "kind": "text" - } - ] - }, - { - "name": "param", - "text": [ - { - "text": "section", - "kind": "parameterName" - }, - { - "text": " ", - "kind": "space" - }, - { - "text": "Code of the target section", - "kind": "text" - } - ] - }, - { - "name": "param", - "text": [ - { - "text": "saleId", - "kind": "parameterName" - }, - { - "text": " ", - "kind": "space" - }, - { - "text": "ID of the target sale", - "kind": "text" - } - ] - }, - { - "name": "param", - "text": [ - { - "text": "articleId", - "kind": "parameterName" - }, - { - "text": " ", - "kind": "space" - }, - { - "text": "ID of the target article", - "kind": "text" - } - ] - }, - { - "name": "param", - "text": [ - { - "text": "input", - "kind": "parameterName" - }, - { - "text": " ", - "kind": "space" - }, - { - "text": "Content to write", - "kind": "text" - } - ] - }, - { - "name": "return", - "text": [ - { - "text": "Newly archived comment", - "kind": "text" - } - ] - }, - { - "name": "throws", - "text": [ - { - "text": "400 bad request error when type of the input data is not valid", - "kind": "text" - } - ] - }, - { - "name": "throws", - "text": [ - { - "text": "401 unauthorized error when you've not logged in yet", - "kind": "text" - } - ] - }, - { - "name": "throws", - "text": [ - { - "text": "403 forbidden error when you're a seller and the sale is not yours", - "kind": "text" - } - ] - }, - { - "name": "throws", - "text": [ - { - "text": "404 not found error when unable to find the matched record", - "kind": "text" - } - ] - } - ] - } - }, - "/sellers/{section}/sales/{saleId}/articles/{articleId}/comments": { - "post": { - "tags": [], - "parameters": [ - { - "name": "section", - "in": "path", - "description": "Code of the target section", - "schema": { - "type": "string", - "nullable": false - }, - "required": true - }, - { - "name": "saleId", - "in": "path", - "description": "ID of the target sale", - "schema": { - "type": "number", - "nullable": false - }, - "required": true - }, - { - "name": "articleId", - "in": "path", - "description": "ID of the target article", - "schema": { - "type": "number", - "nullable": false - }, - "required": true - } - ], - "requestBody": { - "description": "Content to write", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ISaleArticleComment.IStore" - } - } - }, - "required": true, - "x-nestia-encrypted": false - }, - "responses": { - "201": { - "description": "Newly archived comment", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ISaleArticleComment" - } - } - }, - "x-nestia-encrypted": false - }, - "400": { - "description": "bad request error when type of the input data is not valid" - }, - "401": { - "description": "unauthorized error when you've not logged in yet" - }, - "403": { - "description": "forbidden error when you're a seller and the sale is not yours" - }, - "404": { - "description": "not found error when unable to find the matched record" - } - }, - "summary": "Store a new comment", - "description": "Store a new comment.", - "x-nestia-namespace": "sellers.sales.articles.comments.store", - "x-nestia-jsDocTags": [ - { - "name": "param", - "text": [ - { - "text": "request", - "kind": "parameterName" - }, - { - "text": " ", - "kind": "space" - }, - { - "text": "Instance of the Express.Request", - "kind": "text" - } - ] - }, - { - "name": "param", - "text": [ - { - "text": "section", - "kind": "parameterName" - }, - { - "text": " ", - "kind": "space" - }, - { - "text": "Code of the target section", - "kind": "text" - } - ] - }, - { - "name": "param", - "text": [ - { - "text": "saleId", - "kind": "parameterName" - }, - { - "text": " ", - "kind": "space" - }, - { - "text": "ID of the target sale", - "kind": "text" - } - ] - }, - { - "name": "param", - "text": [ - { - "text": "articleId", - "kind": "parameterName" - }, - { - "text": " ", - "kind": "space" - }, - { - "text": "ID of the target article", - "kind": "text" - } - ] - }, - { - "name": "param", - "text": [ - { - "text": "input", - "kind": "parameterName" - }, - { - "text": " ", - "kind": "space" - }, - { - "text": "Content to write", - "kind": "text" - } - ] - }, - { - "name": "return", - "text": [ - { - "text": "Newly archived comment", - "kind": "text" - } - ] - }, - { - "name": "throws", - "text": [ - { - "text": "400 bad request error when type of the input data is not valid", - "kind": "text" - } - ] - }, - { - "name": "throws", - "text": [ - { - "text": "401 unauthorized error when you've not logged in yet", - "kind": "text" - } - ] - }, - { - "name": "throws", - "text": [ - { - "text": "403 forbidden error when you're a seller and the sale is not yours", - "kind": "text" - } - ] - }, - { - "name": "throws", - "text": [ - { - "text": "404 not found error when unable to find the matched record", - "kind": "text" - } - ] - } - ] - } - } - }, - "components": { - "schemas": { - "ISaleArticleComment.IStore": { - "type": "object", - "properties": { - "body": { - "type": "string", - "nullable": false, - "description": "Body of the content.", - "x-typia-required": true - }, - "extension": { - "type": "string", - "enum": [ - "html", - "md", - "txt" - ], - "nullable": false, - "description": "Extension, content type (format).", - "x-typia-required": true - }, - "annonymous": { - "type": "boolean", - "nullable": false, - "description": "Whether to hide the writer name or not.", - "x-typia-required": true - } - }, - "nullable": false, - "required": [ - "body", - "extension", - "annonymous" - ], - "description": "Store info.", - "x-typia-jsDocTags": [] - }, - "ISaleArticleComment": { - "type": "object", - "properties": { - "id": { - "type": "number", - "nullable": false, - "description": "Primary Key.", - "x-typia-required": true - }, - "parent_id": { - "type": "number", - "nullable": true, - "description": "Parent comment ID.\n\nOnly When this comment has been written as a reply.", - "x-typia-required": true - }, - "writer_type": { - "type": "string", - "enum": [ - "seller", - "consumer" - ], - "nullable": false, - "description": "Type of the writer.", - "x-typia-required": true - }, - "writer_name": { - "type": "string", - "nullable": true, - "description": "Name of the writer.\n\nWhen this is a type of anonymous comment, writer name would be hidden.", - "x-typia-required": true - }, - "contents": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ISaleArticleComment.IContent", - "description": "Contents of the comments.\n\nWhen the comment writer tries to modify content, it would not modify the comment\ncontent but would be accumulated. Therefore, all of the people can read how\nthe content has been changed.", - "x-typia-required": true - }, - "nullable": false, - "description": "Contents of the comments.\n\nWhen the comment writer tries to modify content, it would not modify the comment\ncontent but would be accumulated. Therefore, all of the people can read how\nthe content has been changed.", - "x-typia-required": true - }, - "created_at": { - "type": "string", - "nullable": false, - "description": "Creation time.", - "x-typia-required": true - } - }, - "nullable": false, - "required": [ - "id", - "parent_id", - "writer_type", - "writer_name", - "contents", - "created_at" - ], - "description": "Comment wrote on a sale related article.\n\nWhen an article of a sale has been enrolled, all of the participants like consumers and\nsellers can write a comment on that article. However, when the writer is a consumer, the\nconsumer can hide its name through the annoymous option.\n\nAlso, writing a reply comment for a specific comment is possible and in that case, the\n{@link ISaleArticleComment.parent_id} property would be activated.", - "x-typia-jsDocTags": [ - { - "name": "author", - "text": [ - { - "text": "Jeongho Nam - https://github.com/samchon", - "kind": "text" - } - ] - } - ] - }, - "ISaleArticleComment.IContent": { - "type": "object", - "properties": { - "id": { - "type": "string", - "nullable": false, - "description": "Primary Key.", - "x-typia-required": true - }, - "body": { - "type": "string", - "nullable": false, - "description": "Body of the content.", - "x-typia-required": true - }, - "created_at": { - "type": "string", - "nullable": false, - "description": "Creation time.", - "x-typia-required": true - } - }, - "nullable": false, - "required": [ - "id", - "body", - "created_at" - ], - "description": "Content info.", - "x-typia-jsDocTags": [] - } - } - } -} \ No newline at end of file diff --git a/packages/sdk/demo/multiple-paths/tsconfig.json b/packages/sdk/demo/multiple-paths/tsconfig.json deleted file mode 100644 index 8e8705b08..000000000 --- a/packages/sdk/demo/multiple-paths/tsconfig.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": "../tsconfig.base.json", -} \ No newline at end of file diff --git a/packages/sdk/demo/query/tsconfig.json b/packages/sdk/demo/query/tsconfig.json deleted file mode 100644 index 2f669d792..000000000 --- a/packages/sdk/demo/query/tsconfig.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": "../tsconfig.base.json", -} \ No newline at end of file diff --git a/packages/sdk/demo/recursive/src/Configuration.ts b/packages/sdk/demo/recursive/src/Configuration.ts deleted file mode 100644 index 01a3f1f12..000000000 --- a/packages/sdk/demo/recursive/src/Configuration.ts +++ /dev/null @@ -1,7 +0,0 @@ -export namespace Configuration { - export const PORT = 12345; - export const ENCRYPTION_PASSWORD = { - key: "a".repeat(32), - iv: "b".repeat(16), - }; -} diff --git a/packages/sdk/demo/recursive/src/api/functional/consumers/index.ts b/packages/sdk/demo/recursive/src/api/functional/consumers/index.ts deleted file mode 100644 index 6b6d4a7db..000000000 --- a/packages/sdk/demo/recursive/src/api/functional/consumers/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -/** - * @packageDocumentation - * @module api.functional.consumers - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -//================================================================ -export * as systematic from "./systematic"; \ No newline at end of file diff --git a/packages/sdk/demo/recursive/src/api/functional/consumers/systematic/categories/index.ts b/packages/sdk/demo/recursive/src/api/functional/consumers/systematic/categories/index.ts deleted file mode 100644 index 32937d577..000000000 --- a/packages/sdk/demo/recursive/src/api/functional/consumers/systematic/categories/index.ts +++ /dev/null @@ -1,117 +0,0 @@ -/** - * @packageDocumentation - * @module api.functional.consumers.systematic.categories - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -//================================================================ -import { Fetcher, Primitive } from "@nestia/fetcher"; -import type { IConnection } from "@nestia/fetcher"; - -import type { ICategory } from "./../../../../structures/ICategory"; - -/** - * @controller ConsumerCategoriesController.top() - * @path GET /consumers/systematic/categories - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -export function top - ( - connection: IConnection - ): Promise -{ - return Fetcher.fetch - ( - connection, - top.ENCRYPTED, - top.METHOD, - top.path() - ); -} -export namespace top -{ - export type Output = Primitive>; - - export const METHOD = "GET" as const; - export const PATH: string = "/consumers/systematic/categories"; - export const ENCRYPTED: Fetcher.IEncrypted = { - request: false, - response: false, - }; - - export function path(): string - { - return `/consumers/systematic/categories`; - } -} - -/** - * @controller ConsumerCategoriesController.at() - * @path GET /consumers/systematic/categories/:id - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -export function at - ( - connection: IConnection, - id: number - ): Promise -{ - return Fetcher.fetch - ( - connection, - at.ENCRYPTED, - at.METHOD, - at.path(id) - ); -} -export namespace at -{ - export type Output = Primitive; - - export const METHOD = "GET" as const; - export const PATH: string = "/consumers/systematic/categories/:id"; - export const ENCRYPTED: Fetcher.IEncrypted = { - request: false, - response: false, - }; - - export function path(id: number): string - { - return `/consumers/systematic/categories/${encodeURIComponent(id)}`; - } -} - -/** - * @controller ConsumerCategoriesController.invert() - * @path GET /consumers/systematic/categories/:id/invert - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -export function invert - ( - connection: IConnection, - id: number - ): Promise -{ - return Fetcher.fetch - ( - connection, - invert.ENCRYPTED, - invert.METHOD, - invert.path(id) - ); -} -export namespace invert -{ - export type Output = Primitive; - - export const METHOD = "GET" as const; - export const PATH: string = "/consumers/systematic/categories/:id/invert"; - export const ENCRYPTED: Fetcher.IEncrypted = { - request: false, - response: false, - }; - - export function path(id: number): string - { - return `/consumers/systematic/categories/${encodeURIComponent(id)}/invert`; - } -} \ No newline at end of file diff --git a/packages/sdk/demo/recursive/src/api/functional/consumers/systematic/index.ts b/packages/sdk/demo/recursive/src/api/functional/consumers/systematic/index.ts deleted file mode 100644 index a542cd90c..000000000 --- a/packages/sdk/demo/recursive/src/api/functional/consumers/systematic/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -/** - * @packageDocumentation - * @module api.functional.consumers.systematic - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -//================================================================ -export * as categories from "./categories"; \ No newline at end of file diff --git a/packages/sdk/demo/recursive/src/api/functional/index.ts b/packages/sdk/demo/recursive/src/api/functional/index.ts deleted file mode 100644 index 828f7e075..000000000 --- a/packages/sdk/demo/recursive/src/api/functional/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -/** - * @packageDocumentation - * @module api.functional - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -//================================================================ -export * as consumers from "./consumers"; \ No newline at end of file diff --git a/packages/sdk/demo/recursive/src/api/index.ts b/packages/sdk/demo/recursive/src/api/index.ts deleted file mode 100644 index 541bef45a..000000000 --- a/packages/sdk/demo/recursive/src/api/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -import * as api from "./module"; - -/** - * @packageDocumentation - * @module api - */ -//================================================================ -export * from "./module"; - -export default api; diff --git a/packages/sdk/demo/recursive/src/api/module.ts b/packages/sdk/demo/recursive/src/api/module.ts deleted file mode 100644 index b731ce60c..000000000 --- a/packages/sdk/demo/recursive/src/api/module.ts +++ /dev/null @@ -1,10 +0,0 @@ -/** - * @packageDocumentation - * @module api - */ -//================================================================ -export * from "./IConnection"; -export * from "./Primitive"; -export * from "./HttpError"; - -export * as functional from "./functional"; diff --git a/packages/sdk/demo/recursive/src/api/structures/ICategory.ts b/packages/sdk/demo/recursive/src/api/structures/ICategory.ts deleted file mode 100644 index 900186f01..000000000 --- a/packages/sdk/demo/recursive/src/api/structures/ICategory.ts +++ /dev/null @@ -1,49 +0,0 @@ -/** - * Systematic category info. - * - * This `ICategory` has been designed to represent a systematic classfication. Also, its - * classification has hierarchical and recursive relationship. Therefore, its structure has - * a tree shape through the {@link ICategory.children} property. - * - * If you want to see invert structure for getting parent information repeatedly, use the - * {@link ICategory.IInvert} type instead. - * - * @author Jeongho Nam - https://github.com/samchon - */ -export interface ICategory extends ICategory.IBase { - /** - * Children categories. - */ - children: ICategory[]; -} -export namespace ICategory { - /** - * Invert structure of the {@link ICategory}. - */ - export interface IInvert extends IBase { - /** - * Parent information. - */ - parent: IInvert | null; - } - - /** - * Basic information of the {@link ICategory}. - */ - export interface IBase { - /** - * Primary Key. - */ - id: number; - - /** - * Identifier code. - */ - code: string; - - /** - * Name of the category. - */ - name: string; - } -} diff --git a/packages/sdk/demo/recursive/src/consumer.categories.controller.ts b/packages/sdk/demo/recursive/src/consumer.categories.controller.ts deleted file mode 100644 index a06e87ff5..000000000 --- a/packages/sdk/demo/recursive/src/consumer.categories.controller.ts +++ /dev/null @@ -1,59 +0,0 @@ -import helper from "@nestia/core"; -import * as nest from "@nestjs/common"; -import { randint } from "tstl/algorithm/random"; - -import { ICategory } from "./api/structures/ICategory"; - -@nest.Controller("consumers/systematic/categories") -export class ConsumerCategoriesController { - @nest.Get() - public async top(): Promise { - return generate_random_categories(); - } - - @nest.Get(":id") - public async at( - @helper.TypedParam("id", "number") id: number, - ): Promise { - const category: ICategory = generate_random_categories(1)[0]; - category.id = id; - return category; - } - - @nest.Get(":id/invert") - public async invert( - @helper.TypedParam("id", "number") id: number, - ): Promise { - return { - id, - code: "target", - name: "target", - parent: { - id: 1, - code: "parent", - name: "parent", - parent: { - id: 2, - code: "grandparent", - name: "grandparent", - parent: { - id: 3, - code: "root", - name: "root", - parent: null, - }, - }, - }, - }; - } -} - -function generate_random_categories(level: number = 0): ICategory[] { - if (level === 3) return []; - return new Array(randint(2, 5)).fill("").map(() => ({ - id: randint(1, 100), - code: "code", - name: "name", - children: generate_random_categories(level + 1), - })); -} diff --git a/packages/sdk/demo/recursive/src/test/features/test_category_at.ts b/packages/sdk/demo/recursive/src/test/features/test_category_at.ts deleted file mode 100644 index 14fb7c040..000000000 --- a/packages/sdk/demo/recursive/src/test/features/test_category_at.ts +++ /dev/null @@ -1,12 +0,0 @@ -import typia from "typia"; - -import api from "../../api"; -import { ICategory } from "../../api/structures/ICategory"; - -export async function test_category_at( - connection: api.IConnection, -): Promise { - const category: ICategory = - await api.functional.consumers.systematic.categories.at(connection, 0); - typia.assert(category); -} diff --git a/packages/sdk/demo/recursive/src/test/features/test_category_invert.ts b/packages/sdk/demo/recursive/src/test/features/test_category_invert.ts deleted file mode 100644 index c28477e5e..000000000 --- a/packages/sdk/demo/recursive/src/test/features/test_category_invert.ts +++ /dev/null @@ -1,15 +0,0 @@ -import typia from "typia"; - -import api from "../../api"; -import { ICategory } from "../../api/structures/ICategory"; - -export async function test_category_invert( - connection: api.IConnection, -): Promise { - const category: ICategory.IInvert = - await api.functional.consumers.systematic.categories.invert( - connection, - 0, - ); - typia.assert(category); -} diff --git a/packages/sdk/demo/recursive/src/test/features/test_category_top.ts b/packages/sdk/demo/recursive/src/test/features/test_category_top.ts deleted file mode 100644 index d3ac816c9..000000000 --- a/packages/sdk/demo/recursive/src/test/features/test_category_top.ts +++ /dev/null @@ -1,12 +0,0 @@ -import typia from "typia"; - -import api from "../../api"; -import { ICategory } from "../../api/structures/ICategory"; - -export async function test_category_top( - connection: api.IConnection, -): Promise { - const categories: ICategory[] = - await api.functional.consumers.systematic.categories.top(connection); - typia.assert(categories); -} diff --git a/packages/sdk/demo/recursive/src/test/index.ts b/packages/sdk/demo/recursive/src/test/index.ts deleted file mode 100644 index 9a9c90c94..000000000 --- a/packages/sdk/demo/recursive/src/test/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { Backend } from "../Backend"; -import { Configuration } from "../Configuration"; -import api from "../api"; -import { DynamicImportIterator } from "./internal/DynamicImportIterator"; - -async function main(): Promise { - const server: Backend = new Backend(); - await server.open(); - - const connection: api.IConnection = { - host: `http://127.0.0.1:${Configuration.PORT}`, - encryption: Configuration.ENCRYPTION_PASSWORD, - }; - await DynamicImportIterator.main(__dirname, { - prefix: "test", - parameters: () => [connection], - }); - - await server.close(); -} -main().catch((exp) => { - console.log(exp); - process.exit(-1); -}); diff --git a/packages/sdk/demo/recursive/src/test/internal/DynamicImportIterator.ts b/packages/sdk/demo/recursive/src/test/internal/DynamicImportIterator.ts deleted file mode 100644 index 4a12a8b47..000000000 --- a/packages/sdk/demo/recursive/src/test/internal/DynamicImportIterator.ts +++ /dev/null @@ -1,109 +0,0 @@ -import cli from "cli"; -import fs from "fs"; -import { IPointer } from "tstl/functional/IPointer"; - -import { StopWatch } from "./StopWatch"; - -const EXTENSION = __filename.substr(-2); - -interface ICommand { - include?: string; - exclude?: string; -} - -export namespace DynamicImportIterator { - export type Closure = ( - ...args: Arguments - ) => Promise; - type Module = { - [key: string]: Closure; - }; - - export interface IOptions { - prefix: string; - parameters: () => Parameters; - wrapper?: (name: string, output: any) => Promise; - counter?: IPointer; - showElapsedTime?: boolean; - } - - export async function main( - path: string, - options: IOptions, - ): Promise { - const command: ICommand = cli.parse(); - await iterate(options, command, path); - } - - export async function force( - path: string, - options: IOptions, - ): Promise { - const command: ICommand = cli.parse(); - const exceptions: Error[] = []; - - await iterate(options, command, path, exceptions); - return exceptions; - } - - async function iterate( - options: IOptions, - command: ICommand, - path: string, - exceptions?: Error[], - ): Promise { - const directory: string[] = await fs.promises.readdir(path); - for (const file of directory) { - const current: string = `${path}/${file}`; - const stats: fs.Stats = await fs.promises.lstat(current); - - if (stats.isDirectory() === true) { - await iterate(options, command, current, exceptions); - continue; - } else if (file.substr(-3) !== `.${EXTENSION}`) continue; - - const external: Module = await import(current); - await execute(options, command, external, exceptions); - } - } - - async function execute( - options: IOptions, - command: ICommand, - external: Module, - exceptions?: Error[], - ): Promise { - for (const key in external) { - if (command.exclude && key.indexOf(command.exclude) !== -1) - continue; - else if (command.include && key.indexOf(command.include) === -1) - continue; - else if (key.substr(0, options.prefix.length) !== options.prefix) - continue; - else if (external[key] instanceof Function) { - const closure: Closure = external[key]; - const func = async () => { - const output = await closure(...options.parameters()); - if (options.wrapper) await options.wrapper(key, output); - }; - - try { - if (options.counter) ++options.counter.value; - if (options.showElapsedTime === false) { - await func(); - console.log(` - ${key}`); - } else { - const time: number = await StopWatch.measure(func); - console.log(` - ${key}: ${time.toLocaleString()} ms`); - } - } catch (exp) { - if (!(exp instanceof Error)) return; - - console.log(` - ${key} -> ${exp.name}`); - if (exceptions !== undefined) exceptions.push(exp); - else throw exp; - } - } - } - } -} diff --git a/packages/sdk/demo/recursive/src/test/internal/StopWatch.ts b/packages/sdk/demo/recursive/src/test/internal/StopWatch.ts deleted file mode 100644 index 862caf8c8..000000000 --- a/packages/sdk/demo/recursive/src/test/internal/StopWatch.ts +++ /dev/null @@ -1,15 +0,0 @@ -export namespace StopWatch { - export type Task = () => Promise; - - export async function measure(task: Task): Promise { - const time: number = Date.now(); - await task(); - return Date.now() - time; - } - - export async function trace(title: string, task: Task): Promise { - process.stdout.write(title); - const time: number = await measure(task); - console.log(`: ${time.toLocaleString()} ms`); - } -} diff --git a/packages/sdk/demo/recursive/swagger.json b/packages/sdk/demo/recursive/swagger.json deleted file mode 100644 index a536ef778..000000000 --- a/packages/sdk/demo/recursive/swagger.json +++ /dev/null @@ -1,238 +0,0 @@ -{ - "openapi": "3.0.1", - "servers": [ - { - "url": "https://github.com/samchon/nestia", - "description": "insert your server url" - } - ], - "info": { - "version": "0.1.0", - "title": "Generated by nestia - https://github.com/samchon/nestia" - }, - "paths": { - "/consumers/systematic/categories": { - "get": { - "tags": [], - "parameters": [], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ICategory" - }, - "nullable": false - } - } - }, - "x-nestia-encrypted": false - } - }, - "description": "", - "x-nestia-namespace": "consumers.systematic.categories.top", - "x-nestia-jsDocTags": [] - } - }, - "/consumers/systematic/categories/{id}": { - "get": { - "tags": [], - "parameters": [ - { - "name": "id", - "in": "path", - "description": "", - "schema": { - "type": "number", - "nullable": false - }, - "required": true - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ICategory" - } - } - }, - "x-nestia-encrypted": false - } - }, - "description": "", - "x-nestia-namespace": "consumers.systematic.categories.at", - "x-nestia-jsDocTags": [] - } - }, - "/consumers/systematic/categories/{id}/invert": { - "get": { - "tags": [], - "parameters": [ - { - "name": "id", - "in": "path", - "description": "", - "schema": { - "type": "number", - "nullable": false - }, - "required": true - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ICategory.IInvert" - } - } - }, - "x-nestia-encrypted": false - } - }, - "description": "", - "x-nestia-namespace": "consumers.systematic.categories.invert.invert", - "x-nestia-jsDocTags": [] - } - } - }, - "components": { - "schemas": { - "ICategory": { - "type": "object", - "properties": { - "children": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ICategory", - "description": "Children categories.", - "x-typia-required": true - }, - "nullable": false, - "description": "Children categories.", - "x-typia-required": true - }, - "id": { - "type": "number", - "nullable": false, - "description": "Primary Key.", - "x-typia-required": true - }, - "code": { - "type": "string", - "nullable": false, - "description": "Identifier code.", - "x-typia-required": true - }, - "name": { - "type": "string", - "nullable": false, - "description": "Name of the category.", - "x-typia-required": true - } - }, - "nullable": false, - "required": [ - "children", - "id", - "code", - "name" - ], - "description": "Systematic category info.\n\nThis `ICategory` has been designed to represent a systematic classfication. Also, its\nclassification has hierarchical and recursive relationship. Therefore, its structure has\na tree shape through the {@link ICategory.children} property.\n\nIf you want to see invert structure for getting parent information repeatedly, use the\n{@link ICategory.IInvert} type instead.", - "x-typia-jsDocTags": [ - { - "name": "author", - "text": [ - { - "text": "Jeongho Nam - https://github.com/samchon", - "kind": "text" - } - ] - } - ] - }, - "ICategory.IInvert": { - "type": "object", - "properties": { - "parent": { - "$ref": "#/components/schemas/ICategory.IInvert.Nullable", - "description": "Parent information.", - "x-typia-required": true - }, - "id": { - "type": "number", - "nullable": false, - "description": "Primary Key.", - "x-typia-required": true - }, - "code": { - "type": "string", - "nullable": false, - "description": "Identifier code.", - "x-typia-required": true - }, - "name": { - "type": "string", - "nullable": false, - "description": "Name of the category.", - "x-typia-required": true - } - }, - "nullable": false, - "required": [ - "parent", - "id", - "code", - "name" - ], - "description": "Invert structure of the {@link ICategory}.", - "x-typia-jsDocTags": [] - }, - "ICategory.IInvert.Nullable": { - "type": "object", - "properties": { - "parent": { - "$ref": "#/components/schemas/ICategory.IInvert.Nullable", - "description": "Parent information.", - "x-typia-required": true - }, - "id": { - "type": "number", - "nullable": false, - "description": "Primary Key.", - "x-typia-required": true - }, - "code": { - "type": "string", - "nullable": false, - "description": "Identifier code.", - "x-typia-required": true - }, - "name": { - "type": "string", - "nullable": false, - "description": "Name of the category.", - "x-typia-required": true - } - }, - "nullable": true, - "required": [ - "parent", - "id", - "code", - "name" - ], - "description": "Invert structure of the {@link ICategory}.", - "x-typia-jsDocTags": [] - } - } - } -} \ No newline at end of file diff --git a/packages/sdk/demo/recursive/tsconfig.json b/packages/sdk/demo/recursive/tsconfig.json deleted file mode 100644 index 8e8705b08..000000000 --- a/packages/sdk/demo/recursive/tsconfig.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": "../tsconfig.base.json", -} \ No newline at end of file diff --git a/packages/sdk/demo/safe/.gitignore b/packages/sdk/demo/safe/.gitignore deleted file mode 100644 index 6dd29b7f8..000000000 --- a/packages/sdk/demo/safe/.gitignore +++ /dev/null @@ -1 +0,0 @@ -bin/ \ No newline at end of file diff --git a/packages/sdk/demo/safe/src/Backend.ts b/packages/sdk/demo/safe/src/Backend.ts deleted file mode 100644 index 4507166f0..000000000 --- a/packages/sdk/demo/safe/src/Backend.ts +++ /dev/null @@ -1,28 +0,0 @@ -import helper from "@nestia/core"; -import * as nest from "@nestjs/common"; -import { NestFactory } from "@nestjs/core"; - -import { Configuration } from "./Configuration"; - -export class Backend { - private application_?: nest.INestApplication; - - public async open(): Promise { - this.application_ = await NestFactory.create( - await helper.EncryptedModule.dynamic( - __dirname + "/controllers", - Configuration.ENCRYPTION_PASSWORD, - ), - { logger: false }, - ); - await this.application_.listen(Configuration.PORT); - } - - public async close(): Promise { - if (this.application_ === undefined) return; - - const app = this.application_; - delete this.application_; - await app.close(); - } -} diff --git a/packages/sdk/demo/safe/src/Configuration.ts b/packages/sdk/demo/safe/src/Configuration.ts deleted file mode 100644 index 01a3f1f12..000000000 --- a/packages/sdk/demo/safe/src/Configuration.ts +++ /dev/null @@ -1,7 +0,0 @@ -export namespace Configuration { - export const PORT = 12345; - export const ENCRYPTION_PASSWORD = { - key: "a".repeat(32), - iv: "b".repeat(16), - }; -} diff --git a/packages/sdk/demo/safe/src/api/functional/consumers/index.ts b/packages/sdk/demo/safe/src/api/functional/consumers/index.ts deleted file mode 100644 index 3ba654cad..000000000 --- a/packages/sdk/demo/safe/src/api/functional/consumers/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -/** - * @packageDocumentation - * @module api.functional.consumers - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -//================================================================ -export * as sales from "./sales"; \ No newline at end of file diff --git a/packages/sdk/demo/safe/src/api/functional/consumers/sales/articles/comments/index.ts b/packages/sdk/demo/safe/src/api/functional/consumers/sales/articles/comments/index.ts deleted file mode 100644 index e895e3f3c..000000000 --- a/packages/sdk/demo/safe/src/api/functional/consumers/sales/articles/comments/index.ts +++ /dev/null @@ -1,69 +0,0 @@ -/** - * @packageDocumentation - * @module api.functional.consumers.sales.articles.comments - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -//================================================================ -import { Fetcher, Primitive } from "@nestia/fetcher"; -import type { IConnection } from "@nestia/fetcher"; - -import type { ISaleArticleComment } from "./../../../../../structures/ISaleArticleComment"; - -/** - * Store a new comment. - * - * Write a comment on a sale article. If you configure the comment to be - * `anonymous`, only administrator, you and seller of the sale can read - * the content. - * - * @param connection connection Information of the remote HTTP(s) server with headers (+encryption password) - * @param request Instance of the Express.Request - * @param sectionCode Code of the target section - * @param saleId ID of the target sale - * @param articleId ID of the target article - * @param input Content to write - * @return Newly archived comment - * @throw 400 bad request error when type of the input data is not valid - * @throw 401 unauthorized error when you've not logged in yet - * @throw 403 forbidden error when you're a seller and the sale is not yours - * @throw 404 not found error when unable to find the matched record - * - * @controller ConsumerSaleArticleCommentsController.store() - * @path POST /consumers/:section/sales/:saleId/articles/:articleId/comments - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -export function store - ( - connection: IConnection, - sectionCode: string, - saleId: string, - articleId: string, - input: Primitive - ): Promise -{ - return Fetcher.fetch - ( - connection, - store.ENCRYPTED, - store.METHOD, - store.path(sectionCode, saleId, articleId), - input - ); -} -export namespace store -{ - export type Input = Primitive; - export type Output = Primitive; - - export const METHOD = "POST" as const; - export const PATH: string = "/consumers/:section/sales/:saleId/articles/:articleId/comments"; - export const ENCRYPTED: Fetcher.IEncrypted = { - request: false, - response: false, - }; - - export function path(sectionCode: string, saleId: string, articleId: string): string - { - return `/consumers/${encodeURIComponent(sectionCode)}/sales/${encodeURIComponent(saleId)}/articles/${encodeURIComponent(articleId)}/comments`; - } -} \ No newline at end of file diff --git a/packages/sdk/demo/safe/src/api/functional/consumers/sales/articles/index.ts b/packages/sdk/demo/safe/src/api/functional/consumers/sales/articles/index.ts deleted file mode 100644 index af186a2ac..000000000 --- a/packages/sdk/demo/safe/src/api/functional/consumers/sales/articles/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -/** - * @packageDocumentation - * @module api.functional.consumers.sales.articles - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -//================================================================ -export * as comments from "./comments"; \ No newline at end of file diff --git a/packages/sdk/demo/safe/src/api/functional/consumers/sales/index.ts b/packages/sdk/demo/safe/src/api/functional/consumers/sales/index.ts deleted file mode 100644 index 31db5fd9f..000000000 --- a/packages/sdk/demo/safe/src/api/functional/consumers/sales/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -/** - * @packageDocumentation - * @module api.functional.consumers.sales - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -//================================================================ -export * as articles from "./articles"; \ No newline at end of file diff --git a/packages/sdk/demo/safe/src/api/functional/index.ts b/packages/sdk/demo/safe/src/api/functional/index.ts deleted file mode 100644 index 828f7e075..000000000 --- a/packages/sdk/demo/safe/src/api/functional/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -/** - * @packageDocumentation - * @module api.functional - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -//================================================================ -export * as consumers from "./consumers"; \ No newline at end of file diff --git a/packages/sdk/demo/safe/src/api/index.ts b/packages/sdk/demo/safe/src/api/index.ts deleted file mode 100644 index 541bef45a..000000000 --- a/packages/sdk/demo/safe/src/api/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -import * as api from "./module"; - -/** - * @packageDocumentation - * @module api - */ -//================================================================ -export * from "./module"; - -export default api; diff --git a/packages/sdk/demo/safe/src/api/module.ts b/packages/sdk/demo/safe/src/api/module.ts deleted file mode 100644 index b731ce60c..000000000 --- a/packages/sdk/demo/safe/src/api/module.ts +++ /dev/null @@ -1,10 +0,0 @@ -/** - * @packageDocumentation - * @module api - */ -//================================================================ -export * from "./IConnection"; -export * from "./Primitive"; -export * from "./HttpError"; - -export * as functional from "./functional"; diff --git a/packages/sdk/demo/safe/src/api/structures/ISaleArticleComment.ts b/packages/sdk/demo/safe/src/api/structures/ISaleArticleComment.ts deleted file mode 100644 index c7c791853..000000000 --- a/packages/sdk/demo/safe/src/api/structures/ISaleArticleComment.ts +++ /dev/null @@ -1,93 +0,0 @@ -/** - * Comment wrote on a sale related article. - * - * When an article of a sale has been enrolled, all of the participants like consumers and - * sellers can write a comment on that article. However, when the writer is a consumer, the - * consumer can hide its name through the annoymous option. - * - * Also, writing a reply comment for a specific comment is possible and in that case, the - * {@link ISaleArticleComment.parent_id} property would be activated. - * - * @author Jeongho Nam - https://github.com/samchon - */ -export interface ISaleArticleComment { - /** - * Primary Key. - */ - id: number; - - /** - * Parent comment ID. - * - * Only When this comment has been written as a reply. - */ - parent_id: number | null; - - /** - * Type of the writer. - */ - writer_type: "seller" | "consumer"; - - /** - * Name of the writer. - * - * When this is a type of anonymous comment, writer name would be hidden. - */ - writer_name: string | null; - - /** - * Contents of the comments. - * - * When the comment writer tries to modify content, it would not modify the comment - * content but would be accumulated. Therefore, all of the people can read how - * the content has been changed. - */ - contents: ISaleArticleComment.IContent[]; - - /** - * Creation time. - */ - created_at: string; -} - -export namespace ISaleArticleComment { - /** - * Store info. - */ - export interface IStore { - /** - * Body of the content. - */ - body: string; - - /** - * Extension, content type (format). - */ - extension: "html" | "md" | "txt"; - - /** - * Whether to hide the writer name or not. - */ - annonymous: boolean; - } - - /** - * Content info. - */ - export interface IContent { - /** - * Primary Key. - */ - id: string; - - /** - * Body of the content. - */ - body: string; - - /** - * Creation time. - */ - created_at: string; - } -} diff --git a/packages/sdk/demo/safe/src/controllers/ConsumerSaleArticleCommentsController.ts b/packages/sdk/demo/safe/src/controllers/ConsumerSaleArticleCommentsController.ts deleted file mode 100644 index 803a4b6d6..000000000 --- a/packages/sdk/demo/safe/src/controllers/ConsumerSaleArticleCommentsController.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { TypedBody, TypedRoute } from "@nestia/core"; -import { Controller, Param, Request } from "@nestjs/common"; -import express from "express"; -import { v4 } from "uuid"; - -import { ISaleArticleComment } from "../api/structures/ISaleArticleComment"; - -const CODE_REGEX = "[0-9a-f]{7}"; -const UUID_REGEX = - "[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}"; - -@Controller( - `consumers/:section(${CODE_REGEX})/sales/:saleId(${UUID_REGEX})/articles/:articleId(${UUID_REGEX})/comments`, -) -export class ConsumerSaleArticleCommentsController { - /** - * Store a new comment. - * - * Write a comment on a sale article. If you configure the comment to be - * `anonymous`, only administrator, you and seller of the sale can read - * the content. - * - * @param request Instance of the Express.Request - * @param sectionCode Code of the target section - * @param saleId ID of the target sale - * @param articleId ID of the target article - * @param input Content to write - * @return Newly archived comment - * - * @throw 400 bad request error when type of the input data is not valid - * @throw 401 unauthorized error when you've not logged in yet - * @throw 403 forbidden error when you're a seller and the sale is not yours - * @throw 404 not found error when unable to find the matched record - */ - @TypedRoute.Post() - public async store( - @Request() request: express.Request, - @Param("section") sectionCode: string, - @Param("saleId") saleId: string, - @Param("articleId") articleId: string, - @TypedBody() input: ISaleArticleComment.IStore, - ): Promise { - request; - sectionCode; - saleId; - articleId; - - return { - id: 0, - parent_id: null, - writer_type: "consumer", - writer_name: input.annonymous ? null : "someone", - created_at: new Date().toString(), - contents: [ - { - id: v4(), - body: input.body, - created_at: new Date().toString(), - }, - ], - }; - } -} diff --git a/packages/sdk/demo/safe/src/test/features/test_comment_store.ts b/packages/sdk/demo/safe/src/test/features/test_comment_store.ts deleted file mode 100644 index 5deeae832..000000000 --- a/packages/sdk/demo/safe/src/test/features/test_comment_store.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { v4 } from "uuid"; - -import typia from "typia"; - -import api from "../../api"; -import { ISaleArticleComment } from "../../api/structures/ISaleArticleComment"; - -export async function test_comment_store( - connection: api.IConnection, -): Promise { - const comment: ISaleArticleComment = - await api.functional.consumers.sales.articles.comments.store( - connection, - "abcdef0", - v4(), - v4(), - { - body: "content-body", - extension: "md", - annonymous: true, - }, - ); - typia.assert(comment); -} diff --git a/packages/sdk/demo/safe/src/test/index.ts b/packages/sdk/demo/safe/src/test/index.ts deleted file mode 100644 index 9a9c90c94..000000000 --- a/packages/sdk/demo/safe/src/test/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { Backend } from "../Backend"; -import { Configuration } from "../Configuration"; -import api from "../api"; -import { DynamicImportIterator } from "./internal/DynamicImportIterator"; - -async function main(): Promise { - const server: Backend = new Backend(); - await server.open(); - - const connection: api.IConnection = { - host: `http://127.0.0.1:${Configuration.PORT}`, - encryption: Configuration.ENCRYPTION_PASSWORD, - }; - await DynamicImportIterator.main(__dirname, { - prefix: "test", - parameters: () => [connection], - }); - - await server.close(); -} -main().catch((exp) => { - console.log(exp); - process.exit(-1); -}); diff --git a/packages/sdk/demo/safe/src/test/internal/DynamicImportIterator.ts b/packages/sdk/demo/safe/src/test/internal/DynamicImportIterator.ts deleted file mode 100644 index 4a12a8b47..000000000 --- a/packages/sdk/demo/safe/src/test/internal/DynamicImportIterator.ts +++ /dev/null @@ -1,109 +0,0 @@ -import cli from "cli"; -import fs from "fs"; -import { IPointer } from "tstl/functional/IPointer"; - -import { StopWatch } from "./StopWatch"; - -const EXTENSION = __filename.substr(-2); - -interface ICommand { - include?: string; - exclude?: string; -} - -export namespace DynamicImportIterator { - export type Closure = ( - ...args: Arguments - ) => Promise; - type Module = { - [key: string]: Closure; - }; - - export interface IOptions { - prefix: string; - parameters: () => Parameters; - wrapper?: (name: string, output: any) => Promise; - counter?: IPointer; - showElapsedTime?: boolean; - } - - export async function main( - path: string, - options: IOptions, - ): Promise { - const command: ICommand = cli.parse(); - await iterate(options, command, path); - } - - export async function force( - path: string, - options: IOptions, - ): Promise { - const command: ICommand = cli.parse(); - const exceptions: Error[] = []; - - await iterate(options, command, path, exceptions); - return exceptions; - } - - async function iterate( - options: IOptions, - command: ICommand, - path: string, - exceptions?: Error[], - ): Promise { - const directory: string[] = await fs.promises.readdir(path); - for (const file of directory) { - const current: string = `${path}/${file}`; - const stats: fs.Stats = await fs.promises.lstat(current); - - if (stats.isDirectory() === true) { - await iterate(options, command, current, exceptions); - continue; - } else if (file.substr(-3) !== `.${EXTENSION}`) continue; - - const external: Module = await import(current); - await execute(options, command, external, exceptions); - } - } - - async function execute( - options: IOptions, - command: ICommand, - external: Module, - exceptions?: Error[], - ): Promise { - for (const key in external) { - if (command.exclude && key.indexOf(command.exclude) !== -1) - continue; - else if (command.include && key.indexOf(command.include) === -1) - continue; - else if (key.substr(0, options.prefix.length) !== options.prefix) - continue; - else if (external[key] instanceof Function) { - const closure: Closure = external[key]; - const func = async () => { - const output = await closure(...options.parameters()); - if (options.wrapper) await options.wrapper(key, output); - }; - - try { - if (options.counter) ++options.counter.value; - if (options.showElapsedTime === false) { - await func(); - console.log(` - ${key}`); - } else { - const time: number = await StopWatch.measure(func); - console.log(` - ${key}: ${time.toLocaleString()} ms`); - } - } catch (exp) { - if (!(exp instanceof Error)) return; - - console.log(` - ${key} -> ${exp.name}`); - if (exceptions !== undefined) exceptions.push(exp); - else throw exp; - } - } - } - } -} diff --git a/packages/sdk/demo/safe/src/test/internal/StopWatch.ts b/packages/sdk/demo/safe/src/test/internal/StopWatch.ts deleted file mode 100644 index 862caf8c8..000000000 --- a/packages/sdk/demo/safe/src/test/internal/StopWatch.ts +++ /dev/null @@ -1,15 +0,0 @@ -export namespace StopWatch { - export type Task = () => Promise; - - export async function measure(task: Task): Promise { - const time: number = Date.now(); - await task(); - return Date.now() - time; - } - - export async function trace(title: string, task: Task): Promise { - process.stdout.write(title); - const time: number = await measure(task); - console.log(`: ${time.toLocaleString()} ms`); - } -} diff --git a/packages/sdk/demo/safe/swagger.json b/packages/sdk/demo/safe/swagger.json deleted file mode 100644 index f6ac4fe35..000000000 --- a/packages/sdk/demo/safe/swagger.json +++ /dev/null @@ -1,378 +0,0 @@ -{ - "openapi": "3.0.1", - "servers": [ - { - "url": "https://github.com/samchon/nestia", - "description": "insert your server url" - } - ], - "info": { - "version": "0.1.0", - "title": "Generated by nestia - https://github.com/samchon/nestia" - }, - "paths": { - "/consumers/{section}/sales/{saleId}/articles/{articleId}/comments": { - "post": { - "tags": [], - "parameters": [ - { - "name": "section", - "in": "path", - "description": "Code of the target section", - "schema": { - "type": "string", - "nullable": false - }, - "required": true - }, - { - "name": "saleId", - "in": "path", - "description": "ID of the target sale", - "schema": { - "type": "string", - "nullable": false - }, - "required": true - }, - { - "name": "articleId", - "in": "path", - "description": "ID of the target article", - "schema": { - "type": "string", - "nullable": false - }, - "required": true - } - ], - "requestBody": { - "description": "Content to write", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ISaleArticleComment.IStore" - } - } - }, - "required": true, - "x-nestia-encrypted": false - }, - "responses": { - "201": { - "description": "Newly archived comment", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ISaleArticleComment" - } - } - }, - "x-nestia-encrypted": false - }, - "400": { - "description": "bad request error when type of the input data is not valid" - }, - "401": { - "description": "unauthorized error when you've not logged in yet" - }, - "403": { - "description": "forbidden error when you're a seller and the sale is not yours" - }, - "404": { - "description": "not found error when unable to find the matched record" - } - }, - "summary": "Store a new comment", - "description": "Store a new comment.\n\nWrite a comment on a sale article. If you configure the comment to be\n`anonymous`, only administrator, you and seller of the sale can read\nthe content.", - "x-nestia-namespace": "consumers.sales.articles.comments.store", - "x-nestia-jsDocTags": [ - { - "name": "param", - "text": [ - { - "text": "request", - "kind": "parameterName" - }, - { - "text": " ", - "kind": "space" - }, - { - "text": "Instance of the Express.Request", - "kind": "text" - } - ] - }, - { - "name": "param", - "text": [ - { - "text": "sectionCode", - "kind": "parameterName" - }, - { - "text": " ", - "kind": "space" - }, - { - "text": "Code of the target section", - "kind": "text" - } - ] - }, - { - "name": "param", - "text": [ - { - "text": "saleId", - "kind": "parameterName" - }, - { - "text": " ", - "kind": "space" - }, - { - "text": "ID of the target sale", - "kind": "text" - } - ] - }, - { - "name": "param", - "text": [ - { - "text": "articleId", - "kind": "parameterName" - }, - { - "text": " ", - "kind": "space" - }, - { - "text": "ID of the target article", - "kind": "text" - } - ] - }, - { - "name": "param", - "text": [ - { - "text": "input", - "kind": "parameterName" - }, - { - "text": " ", - "kind": "space" - }, - { - "text": "Content to write", - "kind": "text" - } - ] - }, - { - "name": "return", - "text": [ - { - "text": "Newly archived comment", - "kind": "text" - } - ] - }, - { - "name": "throw", - "text": [ - { - "text": "400 bad request error when type of the input data is not valid", - "kind": "text" - } - ] - }, - { - "name": "throw", - "text": [ - { - "text": "401 unauthorized error when you've not logged in yet", - "kind": "text" - } - ] - }, - { - "name": "throw", - "text": [ - { - "text": "403 forbidden error when you're a seller and the sale is not yours", - "kind": "text" - } - ] - }, - { - "name": "throw", - "text": [ - { - "text": "404 not found error when unable to find the matched record", - "kind": "text" - } - ] - } - ] - } - } - }, - "components": { - "schemas": { - "ISaleArticleComment.IStore": { - "type": "object", - "properties": { - "body": { - "type": "string", - "nullable": false, - "description": "Body of the content.", - "x-typia-required": true - }, - "extension": { - "type": "string", - "enum": [ - "html", - "md", - "txt" - ], - "nullable": false, - "description": "Extension, content type (format).", - "x-typia-required": true - }, - "annonymous": { - "type": "boolean", - "nullable": false, - "description": "Whether to hide the writer name or not.", - "x-typia-required": true - } - }, - "nullable": false, - "required": [ - "body", - "extension", - "annonymous" - ], - "description": "Store info.", - "x-typia-jsDocTags": [] - }, - "ISaleArticleComment": { - "type": "object", - "properties": { - "id": { - "type": "number", - "nullable": false, - "description": "Primary Key.", - "x-typia-required": true - }, - "parent_id": { - "type": "number", - "nullable": true, - "description": "Parent comment ID.\n\nOnly When this comment has been written as a reply.", - "x-typia-required": true - }, - "writer_type": { - "type": "string", - "enum": [ - "seller", - "consumer" - ], - "nullable": false, - "description": "Type of the writer.", - "x-typia-required": true - }, - "writer_name": { - "type": "string", - "nullable": true, - "description": "Name of the writer.\n\nWhen this is a type of anonymous comment, writer name would be hidden.", - "x-typia-required": true - }, - "contents": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ISaleArticleComment.IContent", - "description": "Contents of the comments.\n\nWhen the comment writer tries to modify content, it would not modify the comment\ncontent but would be accumulated. Therefore, all of the people can read how\nthe content has been changed.", - "x-typia-required": true - }, - "nullable": false, - "description": "Contents of the comments.\n\nWhen the comment writer tries to modify content, it would not modify the comment\ncontent but would be accumulated. Therefore, all of the people can read how\nthe content has been changed.", - "x-typia-required": true - }, - "created_at": { - "type": "string", - "nullable": false, - "description": "Creation time.", - "x-typia-required": true - } - }, - "nullable": false, - "required": [ - "id", - "parent_id", - "writer_type", - "writer_name", - "contents", - "created_at" - ], - "description": "Comment wrote on a sale related article.\n\nWhen an article of a sale has been enrolled, all of the participants like consumers and\nsellers can write a comment on that article. However, when the writer is a consumer, the\nconsumer can hide its name through the annoymous option.\n\nAlso, writing a reply comment for a specific comment is possible and in that case, the\n{@link ISaleArticleComment.parent_id} property would be activated.", - "x-typia-jsDocTags": [ - { - "name": "author", - "text": [ - { - "text": "Jeongho Nam - https://github.com/samchon", - "kind": "text" - } - ] - } - ] - }, - "ISaleArticleComment.IContent": { - "type": "object", - "properties": { - "id": { - "type": "string", - "nullable": false, - "description": "Primary Key.", - "x-typia-required": true - }, - "body": { - "type": "string", - "nullable": false, - "description": "Body of the content.", - "x-typia-required": true - }, - "created_at": { - "type": "string", - "nullable": false, - "description": "Creation time.", - "x-typia-required": true - } - }, - "nullable": false, - "required": [ - "id", - "body", - "created_at" - ], - "description": "Content info.", - "x-typia-jsDocTags": [] - } - }, - "securitySchemes": { - "bearer": { - "type": "apiKey", - "in": "header", - "name": "Authorization" - } - } - }, - "security": [ - { - "bearer": [] - } - ] -} \ No newline at end of file diff --git a/packages/sdk/demo/safe/tsconfig.json b/packages/sdk/demo/safe/tsconfig.json deleted file mode 100644 index 8e8705b08..000000000 --- a/packages/sdk/demo/safe/tsconfig.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": "../tsconfig.base.json", -} \ No newline at end of file diff --git a/packages/sdk/demo/status/nestia.config.ts b/packages/sdk/demo/status/nestia.config.ts deleted file mode 100644 index eff9881d2..000000000 --- a/packages/sdk/demo/status/nestia.config.ts +++ /dev/null @@ -1,9 +0,0 @@ -const config = { - input: ["src/controllers"], - output: "src/api", - swagger: { - output: "swagger.json", - }, - primitive: false, -}; -export default config; diff --git a/packages/sdk/demo/status/src/Backend.ts b/packages/sdk/demo/status/src/Backend.ts deleted file mode 100644 index 4507166f0..000000000 --- a/packages/sdk/demo/status/src/Backend.ts +++ /dev/null @@ -1,28 +0,0 @@ -import helper from "@nestia/core"; -import * as nest from "@nestjs/common"; -import { NestFactory } from "@nestjs/core"; - -import { Configuration } from "./Configuration"; - -export class Backend { - private application_?: nest.INestApplication; - - public async open(): Promise { - this.application_ = await NestFactory.create( - await helper.EncryptedModule.dynamic( - __dirname + "/controllers", - Configuration.ENCRYPTION_PASSWORD, - ), - { logger: false }, - ); - await this.application_.listen(Configuration.PORT); - } - - public async close(): Promise { - if (this.application_ === undefined) return; - - const app = this.application_; - delete this.application_; - await app.close(); - } -} diff --git a/packages/sdk/demo/status/src/Configuration.ts b/packages/sdk/demo/status/src/Configuration.ts deleted file mode 100644 index 01a3f1f12..000000000 --- a/packages/sdk/demo/status/src/Configuration.ts +++ /dev/null @@ -1,7 +0,0 @@ -export namespace Configuration { - export const PORT = 12345; - export const ENCRYPTION_PASSWORD = { - key: "a".repeat(32), - iv: "b".repeat(16), - }; -} diff --git a/packages/sdk/demo/status/src/api/index.ts b/packages/sdk/demo/status/src/api/index.ts deleted file mode 100644 index 541bef45a..000000000 --- a/packages/sdk/demo/status/src/api/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -import * as api from "./module"; - -/** - * @packageDocumentation - * @module api - */ -//================================================================ -export * from "./module"; - -export default api; diff --git a/packages/sdk/demo/status/src/api/module.ts b/packages/sdk/demo/status/src/api/module.ts deleted file mode 100644 index b731ce60c..000000000 --- a/packages/sdk/demo/status/src/api/module.ts +++ /dev/null @@ -1,10 +0,0 @@ -/** - * @packageDocumentation - * @module api - */ -//================================================================ -export * from "./IConnection"; -export * from "./Primitive"; -export * from "./HttpError"; - -export * as functional from "./functional"; diff --git a/packages/sdk/demo/status/src/controllers/StatusController.ts b/packages/sdk/demo/status/src/controllers/StatusController.ts deleted file mode 100644 index 94c11facc..000000000 --- a/packages/sdk/demo/status/src/controllers/StatusController.ts +++ /dev/null @@ -1,11 +0,0 @@ -import core from "@nestia/core"; -import * as nest from "@nestjs/common"; - -@nest.Controller() -export class StatusController { - @nest.HttpCode(300) - @core.TypedRoute.Get("status") - public status(): number { - return 300; - } -} diff --git a/packages/sdk/demo/status/src/test/features/test_status.ts b/packages/sdk/demo/status/src/test/features/test_status.ts deleted file mode 100644 index fc0acebb5..000000000 --- a/packages/sdk/demo/status/src/test/features/test_status.ts +++ /dev/null @@ -1,8 +0,0 @@ -import typia from "typia"; - -import api from "../../api"; - -export async function test_status(connection: api.IConnection): Promise { - const status = await api.functional.status(connection); - typia.assert(status); -} diff --git a/packages/sdk/demo/status/src/test/index.ts b/packages/sdk/demo/status/src/test/index.ts deleted file mode 100644 index 9a9c90c94..000000000 --- a/packages/sdk/demo/status/src/test/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { Backend } from "../Backend"; -import { Configuration } from "../Configuration"; -import api from "../api"; -import { DynamicImportIterator } from "./internal/DynamicImportIterator"; - -async function main(): Promise { - const server: Backend = new Backend(); - await server.open(); - - const connection: api.IConnection = { - host: `http://127.0.0.1:${Configuration.PORT}`, - encryption: Configuration.ENCRYPTION_PASSWORD, - }; - await DynamicImportIterator.main(__dirname, { - prefix: "test", - parameters: () => [connection], - }); - - await server.close(); -} -main().catch((exp) => { - console.log(exp); - process.exit(-1); -}); diff --git a/packages/sdk/demo/status/src/test/internal/DynamicImportIterator.ts b/packages/sdk/demo/status/src/test/internal/DynamicImportIterator.ts deleted file mode 100644 index 4a12a8b47..000000000 --- a/packages/sdk/demo/status/src/test/internal/DynamicImportIterator.ts +++ /dev/null @@ -1,109 +0,0 @@ -import cli from "cli"; -import fs from "fs"; -import { IPointer } from "tstl/functional/IPointer"; - -import { StopWatch } from "./StopWatch"; - -const EXTENSION = __filename.substr(-2); - -interface ICommand { - include?: string; - exclude?: string; -} - -export namespace DynamicImportIterator { - export type Closure = ( - ...args: Arguments - ) => Promise; - type Module = { - [key: string]: Closure; - }; - - export interface IOptions { - prefix: string; - parameters: () => Parameters; - wrapper?: (name: string, output: any) => Promise; - counter?: IPointer; - showElapsedTime?: boolean; - } - - export async function main( - path: string, - options: IOptions, - ): Promise { - const command: ICommand = cli.parse(); - await iterate(options, command, path); - } - - export async function force( - path: string, - options: IOptions, - ): Promise { - const command: ICommand = cli.parse(); - const exceptions: Error[] = []; - - await iterate(options, command, path, exceptions); - return exceptions; - } - - async function iterate( - options: IOptions, - command: ICommand, - path: string, - exceptions?: Error[], - ): Promise { - const directory: string[] = await fs.promises.readdir(path); - for (const file of directory) { - const current: string = `${path}/${file}`; - const stats: fs.Stats = await fs.promises.lstat(current); - - if (stats.isDirectory() === true) { - await iterate(options, command, current, exceptions); - continue; - } else if (file.substr(-3) !== `.${EXTENSION}`) continue; - - const external: Module = await import(current); - await execute(options, command, external, exceptions); - } - } - - async function execute( - options: IOptions, - command: ICommand, - external: Module, - exceptions?: Error[], - ): Promise { - for (const key in external) { - if (command.exclude && key.indexOf(command.exclude) !== -1) - continue; - else if (command.include && key.indexOf(command.include) === -1) - continue; - else if (key.substr(0, options.prefix.length) !== options.prefix) - continue; - else if (external[key] instanceof Function) { - const closure: Closure = external[key]; - const func = async () => { - const output = await closure(...options.parameters()); - if (options.wrapper) await options.wrapper(key, output); - }; - - try { - if (options.counter) ++options.counter.value; - if (options.showElapsedTime === false) { - await func(); - console.log(` - ${key}`); - } else { - const time: number = await StopWatch.measure(func); - console.log(` - ${key}: ${time.toLocaleString()} ms`); - } - } catch (exp) { - if (!(exp instanceof Error)) return; - - console.log(` - ${key} -> ${exp.name}`); - if (exceptions !== undefined) exceptions.push(exp); - else throw exp; - } - } - } - } -} diff --git a/packages/sdk/demo/status/src/test/internal/StopWatch.ts b/packages/sdk/demo/status/src/test/internal/StopWatch.ts deleted file mode 100644 index 862caf8c8..000000000 --- a/packages/sdk/demo/status/src/test/internal/StopWatch.ts +++ /dev/null @@ -1,15 +0,0 @@ -export namespace StopWatch { - export type Task = () => Promise; - - export async function measure(task: Task): Promise { - const time: number = Date.now(); - await task(); - return Date.now() - time; - } - - export async function trace(title: string, task: Task): Promise { - process.stdout.write(title); - const time: number = await measure(task); - console.log(`: ${time.toLocaleString()} ms`); - } -} diff --git a/packages/sdk/demo/status/swagger.json b/packages/sdk/demo/status/swagger.json deleted file mode 100644 index 902109b15..000000000 --- a/packages/sdk/demo/status/swagger.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "openapi": "3.0.1", - "servers": [ - { - "url": "https://github.com/samchon/nestia", - "description": "insert your server url" - } - ], - "info": { - "version": "0.1.0", - "title": "Generated by nestia - https://github.com/samchon/nestia" - }, - "paths": { - "/status": { - "get": { - "tags": [], - "parameters": [], - "responses": { - "300": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "number", - "nullable": false - } - } - }, - "x-nestia-encrypted": false - } - }, - "description": "", - "x-nestia-namespace": "status.status", - "x-nestia-jsDocTags": [] - } - } - }, - "components": { - "schemas": {} - } -} \ No newline at end of file diff --git a/packages/sdk/demo/status/tsconfig.json b/packages/sdk/demo/status/tsconfig.json deleted file mode 100644 index 8e8705b08..000000000 --- a/packages/sdk/demo/status/tsconfig.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": "../tsconfig.base.json", -} \ No newline at end of file diff --git a/packages/sdk/demo/tsconfig.base.json b/packages/sdk/demo/tsconfig.base.json deleted file mode 100644 index 4e65c91b7..000000000 --- a/packages/sdk/demo/tsconfig.base.json +++ /dev/null @@ -1,70 +0,0 @@ -{ - "compilerOptions": { - /* Visit https://aka.ms/tsconfig.json to read more about this file */ - /* Basic Options */ - // "incremental": true, /* Enable incremental compilation */ - "target": "ES5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ - "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ - "lib": [ - "DOM", - "ES2015" - ], /* Specify library files to be included in the compilation. */// "allowJs": true, /* Allow javascript files to be compiled. */ - // "checkJs": true, /* Report errors in .js files. */ - // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ - // "declaration": true, /* Generates corresponding '.d.ts' file. */ - // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ - // "sourceMap": true, /* Generates corresponding '.map' file. */ - // "outFile": "./", /* Concatenate and emit output to single file. */ - // "outDir": "./lib", /* Redirect output structure to the directory. */ - // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ - // "composite": true, /* Enable project compilation */ - // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ - // "removeComments": true, /* Do not emit comments to output. */ - "noEmit": true, /* Do not emit outputs. */ - // "importHelpers": true, /* Import emit helpers from 'tslib'. */ - "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ - /* Strict Type-Checking Options */ - "strict": true, /* Enable all strict type-checking options. */ - // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ - // "strictNullChecks": true, /* Enable strict null checks. */ - // "strictFunctionTypes": true, /* Enable strict checking of function types. */ - // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ - // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ - // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ - // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ - /* Additional Checks */ - "noUnusedLocals": true, /* Report errors on unused locals. */ - "noUnusedParameters": true, /* Report errors on unused parameters. */ - "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ - "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ - // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ - /* Module Resolution Options */ - // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ - // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ - // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ - // "typeRoots": [], /* List of folders to include type definitions from. */ - "types": [ - "node", - "reflect-metadata" - ], /* Type declaration files to be included in compilation. */// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ - "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ - // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ - /* Source Map Options */ - // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ - // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ - // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ - // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ - /* Experimental Options */ - "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ - "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ - "stripInternal": true, - /* Advanced Options */ - "skipLibCheck": true, /* Skip type checking of declaration files. */ - "forceConsistentCasingInFileNames": true, /* Disallow inconsistently-cased references to the same file. */ - "plugins": [ - { "transform": "@nestia/core/lib/transform" }, - { "transform": "typia/lib/transform" }, - { "transform": "typescript-transform-paths" } - ] - }, -} \ No newline at end of file diff --git a/packages/sdk/demo/union/nestia.config.ts b/packages/sdk/demo/union/nestia.config.ts deleted file mode 100644 index eff9881d2..000000000 --- a/packages/sdk/demo/union/nestia.config.ts +++ /dev/null @@ -1,9 +0,0 @@ -const config = { - input: ["src/controllers"], - output: "src/api", - swagger: { - output: "swagger.json", - }, - primitive: false, -}; -export default config; diff --git a/packages/sdk/demo/union/src/Backend.ts b/packages/sdk/demo/union/src/Backend.ts deleted file mode 100644 index 4507166f0..000000000 --- a/packages/sdk/demo/union/src/Backend.ts +++ /dev/null @@ -1,28 +0,0 @@ -import helper from "@nestia/core"; -import * as nest from "@nestjs/common"; -import { NestFactory } from "@nestjs/core"; - -import { Configuration } from "./Configuration"; - -export class Backend { - private application_?: nest.INestApplication; - - public async open(): Promise { - this.application_ = await NestFactory.create( - await helper.EncryptedModule.dynamic( - __dirname + "/controllers", - Configuration.ENCRYPTION_PASSWORD, - ), - { logger: false }, - ); - await this.application_.listen(Configuration.PORT); - } - - public async close(): Promise { - if (this.application_ === undefined) return; - - const app = this.application_; - delete this.application_; - await app.close(); - } -} diff --git a/packages/sdk/demo/union/src/Configuration.ts b/packages/sdk/demo/union/src/Configuration.ts deleted file mode 100644 index 01a3f1f12..000000000 --- a/packages/sdk/demo/union/src/Configuration.ts +++ /dev/null @@ -1,7 +0,0 @@ -export namespace Configuration { - export const PORT = 12345; - export const ENCRYPTION_PASSWORD = { - key: "a".repeat(32), - iv: "b".repeat(16), - }; -} diff --git a/packages/sdk/demo/union/src/api/functional/consumers/index.ts b/packages/sdk/demo/union/src/api/functional/consumers/index.ts deleted file mode 100644 index 3ba654cad..000000000 --- a/packages/sdk/demo/union/src/api/functional/consumers/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -/** - * @packageDocumentation - * @module api.functional.consumers - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -//================================================================ -export * as sales from "./sales"; \ No newline at end of file diff --git a/packages/sdk/demo/union/src/api/functional/consumers/sales/entire_articles/index.ts b/packages/sdk/demo/union/src/api/functional/consumers/sales/entire_articles/index.ts deleted file mode 100644 index 21f906c7f..000000000 --- a/packages/sdk/demo/union/src/api/functional/consumers/sales/entire_articles/index.ts +++ /dev/null @@ -1,130 +0,0 @@ -/** - * @packageDocumentation - * @module api.functional.consumers.sales.entire_articles - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -//================================================================ -import { Fetcher } from "@nestia/fetcher"; -import type { IConnection } from "@nestia/fetcher"; - -import type { ISaleInquiry } from "./../../../../structures/ISaleInquiry"; -import type { ISaleReview } from "./../../../../structures/ISaleReview"; -import type { IPage } from "./../../../../structures/IPage"; -import type { ISaleEntireArtcle } from "./../../../../structures/ISaleEntireArticle"; - -/** - * List up entire sale articles. - * - * @param connection connection Information of the remote HTTP(s) server with headers (+encryption password) - * @param request Instance of the Express.Request - * @param section Code of the target section - * @param saleId ID of the target sale - * @param ipAddr IP Address of the client - * @param href `window.location.href` - * @param query More query parameters - * @param input Page request info - * @returns Paged the entire articles - * - * @controller ConsumerSaleEntireArticlesController.index() - * @path PATCH /consumers/:section/sales/:saleId/entire_articles - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -export function index - ( - connection: IConnection, - section: string, - saleId: number, - input: ISaleInquiry.IRequest, - query: ISaleReview.IQuery, - ipAddr: undefined | string, - href?: undefined | string - ): Promise -{ - return Fetcher.fetch - ( - connection, - index.ENCRYPTED, - index.METHOD, - index.path(section, saleId, ipAddr, href, query), - input - ); -} -export namespace index -{ - export type Query = ISaleReview.IQuery; - export type Input = ISaleInquiry.IRequest; - export type Output = IPage; - - export const METHOD = "PATCH" as const; - export const PATH: string = "/consumers/:section/sales/:saleId/entire_articles"; - export const ENCRYPTED: Fetcher.IEncrypted = { - request: false, - response: false, - }; - - export function path(section: string, saleId: number, ipAddr: undefined | string, href: undefined | string, query: ISaleReview.IQuery): string - { - const variables: Record = - { - ...query, - ip: ipAddr, - "location.href": href, - } as any; - const search: URLSearchParams = new URLSearchParams(); - for (const [key, value] of Object.entries(variables)) - if (value === undefined) continue; - else if (Array.isArray(value)) - value.forEach((elem) => search.append(key, String(elem))); - else - search.set(key, String(value)); - const encoded: string = search.toString(); - return `/consumers/${encodeURIComponent(section)}/sales/${encodeURIComponent(saleId)}/entire_articles${encoded.length ? `?${encoded}` : ""}`;; - } -} - -/** - * Get detailed sale article record. - * - * @param connection connection Information of the remote HTTP(s) server with headers (+encryption password) - * @param request Instance of the Express.Request - * @param section Code of the target section - * @param saleId ID of the target sale - * @param id ID of the target article - * @returns The detailed article record - * - * @controller ConsumerSaleEntireArticlesController.at() - * @path GET /consumers/:section/sales/:saleId/entire_articles/:id - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -export function at - ( - connection: IConnection, - section: string, - saleId: number, - id: number - ): Promise -{ - return Fetcher.fetch - ( - connection, - at.ENCRYPTED, - at.METHOD, - at.path(section, saleId, id) - ); -} -export namespace at -{ - export type Output = ISaleEntireArtcle; - - export const METHOD = "GET" as const; - export const PATH: string = "/consumers/:section/sales/:saleId/entire_articles/:id"; - export const ENCRYPTED: Fetcher.IEncrypted = { - request: false, - response: false, - }; - - export function path(section: string, saleId: number, id: number): string - { - return `/consumers/${encodeURIComponent(section)}/sales/${encodeURIComponent(saleId)}/entire_articles/${encodeURIComponent(id)}`; - } -} \ No newline at end of file diff --git a/packages/sdk/demo/union/src/api/functional/consumers/sales/index.ts b/packages/sdk/demo/union/src/api/functional/consumers/sales/index.ts deleted file mode 100644 index bb48d4673..000000000 --- a/packages/sdk/demo/union/src/api/functional/consumers/sales/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -/** - * @packageDocumentation - * @module api.functional.consumers.sales - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -//================================================================ -export * as entire_articles from "./entire_articles"; -export * as questions from "./questions"; -export * as reviews from "./reviews"; \ No newline at end of file diff --git a/packages/sdk/demo/union/src/api/functional/consumers/sales/questions/index.ts b/packages/sdk/demo/union/src/api/functional/consumers/sales/questions/index.ts deleted file mode 100644 index ec38ab493..000000000 --- a/packages/sdk/demo/union/src/api/functional/consumers/sales/questions/index.ts +++ /dev/null @@ -1,66 +0,0 @@ -/** - * @packageDocumentation - * @module api.functional.consumers.sales.questions - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -//================================================================ -import { Fetcher } from "@nestia/fetcher"; -import type { IConnection } from "@nestia/fetcher"; - -import type { ISaleInquiry } from "./../../../../structures/ISaleInquiry"; -import type { IPage } from "./../../../../structures/IPage"; - -/** - * @controller ConsumerSaleQuestionsController.index() - * @path PATCH /consumers/:section/sales/:saleId/questions - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -export function index - ( - connection: IConnection, - section: string, - saleId: number, - input: ISaleInquiry.IRequest, - ipAddr?: undefined | string, - href?: undefined | string - ): Promise -{ - return Fetcher.fetch - ( - connection, - index.ENCRYPTED, - index.METHOD, - index.path(section, saleId, ipAddr, href), - input - ); -} -export namespace index -{ - export type Input = ISaleInquiry.IRequest; - export type Output = IPage; - - export const METHOD = "PATCH" as const; - export const PATH: string = "/consumers/:section/sales/:saleId/questions"; - export const ENCRYPTED: Fetcher.IEncrypted = { - request: false, - response: false, - }; - - export function path(section: string, saleId: number, ipAddr: undefined | string, href: undefined | string): string - { - const variables: Record = - { - ip: ipAddr, - "location.href": href - } as any; - const search: URLSearchParams = new URLSearchParams(); - for (const [key, value] of Object.entries(variables)) - if (value === undefined) continue; - else if (Array.isArray(value)) - value.forEach((elem) => search.append(key, String(elem))); - else - search.set(key, String(value)); - const encoded: string = search.toString(); - return `/consumers/${encodeURIComponent(section)}/sales/${encodeURIComponent(saleId)}/questions${encoded.length ? `?${encoded}` : ""}`;; - } -} \ No newline at end of file diff --git a/packages/sdk/demo/union/src/api/functional/index.ts b/packages/sdk/demo/union/src/api/functional/index.ts deleted file mode 100644 index 828f7e075..000000000 --- a/packages/sdk/demo/union/src/api/functional/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -/** - * @packageDocumentation - * @module api.functional - * @nestia Generated by Nestia - https://github.com/samchon/nestia - */ -//================================================================ -export * as consumers from "./consumers"; \ No newline at end of file diff --git a/packages/sdk/demo/union/src/api/index.ts b/packages/sdk/demo/union/src/api/index.ts deleted file mode 100644 index 541bef45a..000000000 --- a/packages/sdk/demo/union/src/api/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -import * as api from "./module"; - -/** - * @packageDocumentation - * @module api - */ -//================================================================ -export * from "./module"; - -export default api; diff --git a/packages/sdk/demo/union/src/api/module.ts b/packages/sdk/demo/union/src/api/module.ts deleted file mode 100644 index b731ce60c..000000000 --- a/packages/sdk/demo/union/src/api/module.ts +++ /dev/null @@ -1,10 +0,0 @@ -/** - * @packageDocumentation - * @module api - */ -//================================================================ -export * from "./IConnection"; -export * from "./Primitive"; -export * from "./HttpError"; - -export * as functional from "./functional"; diff --git a/packages/sdk/demo/union/src/api/structures/IAttachmentFile.ts b/packages/sdk/demo/union/src/api/structures/IAttachmentFile.ts deleted file mode 100644 index 12bcdfdd8..000000000 --- a/packages/sdk/demo/union/src/api/structures/IAttachmentFile.ts +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Attachemd (physical) file info. - * - * @author Jeongho Nam - https://github.com/samchon - */ -export interface IAttachmentFile { - /** - * Primary Key. - */ - id: number; - - /** - * Name of the file. - */ - name: string; - - /** - * Extension of the file, but ommitable. - */ - extension: string | null; - - /** - * Full URL path of the file. - */ - url: string; -} diff --git a/packages/sdk/demo/union/src/api/structures/IPage.ts b/packages/sdk/demo/union/src/api/structures/IPage.ts deleted file mode 100644 index 09678b988..000000000 --- a/packages/sdk/demo/union/src/api/structures/IPage.ts +++ /dev/null @@ -1,80 +0,0 @@ -/** - * Paginated records. - * - * @author Jeongho Nam - https://github.com/samchon - */ -export interface IPage { - /** - * Pagination info. - */ - pagination: IPage.IPagination; - - /** - * List of the records. - */ - data: T[]; -} -export namespace IPage { - /** - * Pagenation info. - */ - export interface IPagination { - /** - * Current page number. - */ - page: number; - - /** - * Maximum number of records per a page. - * - * @default 100 - */ - limit: number; - - /** - * Number of entire records. - */ - total_count: number; - - /** - * Number of total pages. - */ - total_pages: number; - } - - /** - * Page request info. - */ - export interface IRequest { - /** - * Page number. - */ - page?: number; - - /** - * Maximum number of records per a page. - * - * @default 100 - */ - limit?: number; - - /** - * Search field(s). - */ - search_fields?: Field[]; - - /** - * Search value. - */ - search_value?: string; - - /** - * Standard of sorting, list up fields with symbols. - * - * - Only field name (`id`): ASC - * - Plus symbol (`+id`): ASC - * - Minus symbol (`-id`): DESC - */ - sort?: string; - } -} diff --git a/packages/sdk/demo/union/src/api/structures/ISaleArticle.ts b/packages/sdk/demo/union/src/api/structures/ISaleArticle.ts deleted file mode 100644 index c2f7b8561..000000000 --- a/packages/sdk/demo/union/src/api/structures/ISaleArticle.ts +++ /dev/null @@ -1,107 +0,0 @@ -import { IAttachmentFile } from "./IAttachmentFile"; -import { IPage } from "./IPage"; - -/** - * Article about a sale. - * - * The `ISaleArticle` is a super type interface. Many sub-type articles would be - * designed by extending this super type interface `ISaleArticle`. - * - * @template Content Content type. - * @author Jeongho Nam - https://github.com/samchon - */ -export interface ISaleArticle { - /** - * Primary Key. - */ - id: number; - - /** - * Hit count. - * - * How many consumers had read. - */ - hit: number; - - /** - * List of contents. - * - * When the article writer tries to modify content, it would not modify the article - * content but would be accumulated. Therefore, all of the people can read how - * the content has been changed. - */ - contents: Content[]; - - /** - * Creation time. - */ - created_at: string; -} -export namespace ISaleArticle { - /** - * Page request info. - */ - export type IRequest = IPage.IRequest<"title" | "content">; - - /** - * Summarized info of the article. - */ - export interface ISummary { - /** - * Primary Key. - */ - id: number; - - /** - * Title of the article. - */ - title: string; - - /** - * Hit count. - * - * How many consumers had read. - */ - hit: number; - - /** - * Creaiton time. - */ - created_at: string; - - /** - * Updated time. - */ - updated_at: string; - } - - /** - * Content info. - */ - export interface IContent { - /** - * Primary Key - */ - id: string; - - /** - * Title of the content. - */ - title: string; - - /** - * Body of the content. - */ - body: string; - - /** - * Attached files. - */ - files: IAttachmentFile[]; - - /** - * Creation time. - */ - created_at: string; - } -} diff --git a/packages/sdk/demo/union/src/api/structures/ISaleEntireArticle.ts b/packages/sdk/demo/union/src/api/structures/ISaleEntireArticle.ts deleted file mode 100644 index d38274aa2..000000000 --- a/packages/sdk/demo/union/src/api/structures/ISaleEntireArticle.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { ISaleQuestion } from "./ISaleQuestion"; -import { ISaleReview } from "./ISaleReview"; - -/** - * Union type of the entire sub-type articles. - * - * @author Jeongho Nam - https://github.com/samchon - */ -export type ISaleEntireArtcle = ISaleQuestion | ISaleReview; -export namespace ISaleEntireArtcle { - /** - * Summarized union type of the entire sub-type articles. - */ - export type ISummary = ISaleQuestion.ISummary | ISaleReview.ISummary; - - /** - * Page request union type of the entire sub-type articles. - */ - export type IRequest = ISaleQuestion.IRequest | ISaleReview.IRequest; - - export type IQuery = ISaleReview.IQuery; -} diff --git a/packages/sdk/demo/union/src/api/structures/ISaleInquiry.ts b/packages/sdk/demo/union/src/api/structures/ISaleInquiry.ts deleted file mode 100644 index cf6950077..000000000 --- a/packages/sdk/demo/union/src/api/structures/ISaleInquiry.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { IPage } from "./IPage"; -import { ISaleArticle } from "./ISaleArticle"; -import { ISaleInquiryAnswer } from "./ISaleInquiryAnswer"; - -/** - * Inquiry article. - * - * Sub-type of article and super-type of question and answer. - * - * @template Content Content type - * @author Jeongho Nam - https://github.com/samchon - */ -export interface ISaleInquiry - extends ISaleArticle { - /** - * Name of the writer. - */ - writer: string; - - /** - * Formal answer from the seller. - */ - answer: ISaleInquiryAnswer | null; -} -export namespace ISaleInquiry { - /** - * Page request info. - */ - export interface IRequest - extends IPage.IRequest<"writer" | "title" | "content"> { - /** - * Whether being answer by seller or not. - */ - answered?: boolean; - } - - /** - * Summarized info of the inquiry article. - */ - export interface ISummary extends ISaleArticle.ISummary { - /** - * Name of the writer. - */ - writer: string; - - /** - * Whether being answer by seller or not. - */ - answered: boolean; - } - - /** - * Content type of the inquiry article. - */ - export type IContent = ISaleArticle.IContent; -} diff --git a/packages/sdk/demo/union/src/api/structures/ISaleInquiryAnswer.ts b/packages/sdk/demo/union/src/api/structures/ISaleInquiryAnswer.ts deleted file mode 100644 index 361d98b2b..000000000 --- a/packages/sdk/demo/union/src/api/structures/ISaleInquiryAnswer.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { ISaleArticle } from "./ISaleArticle"; - -/** - * Formal answer from the seller. - * - * When a consumer writes an inquiry about a sale, the seller can write a formal - * answer article. This `ISaleInquiryAnswer` has been designed to represent such - * formal answer article from the seller. - * - * @author Jeongho Nam - https://github.com/samchon - */ -export type ISaleInquiryAnswer = ISaleArticle; -export namespace ISaleInquiryAnswer { - /** - * Content type of the answer. - */ - export type IContent = ISaleArticle.IContent; - - /** - * Store info of the answer. - */ - export type IStore = ISaleArticle.IContent; -} diff --git a/packages/sdk/demo/union/src/api/structures/ISaleQuestion.ts b/packages/sdk/demo/union/src/api/structures/ISaleQuestion.ts deleted file mode 100644 index 037423459..000000000 --- a/packages/sdk/demo/union/src/api/structures/ISaleQuestion.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { ISaleInquiry } from "./ISaleInquiry"; - -/** - * Question article. - * - * The `ISaleQuestion` is a type of question article wrriten by a consumer - * who has something to ask about the sale. - * - * @author Jeongho Nam - https://github.com/samchon - */ -export type ISaleQuestion = ISaleInquiry; -export namespace ISaleQuestion { - /** - * Page request info of the question. - */ - export type IRequest = ISaleInquiry.IRequest; - - /** - * Summarized info of the question. - */ - export type ISummary = ISaleInquiry.ISummary; - - /** - * Content info of the question. - */ - export type IContent = ISaleInquiry.IContent; -} diff --git a/packages/sdk/demo/union/src/api/structures/ISaleReview.ts b/packages/sdk/demo/union/src/api/structures/ISaleReview.ts deleted file mode 100644 index 51b74759a..000000000 --- a/packages/sdk/demo/union/src/api/structures/ISaleReview.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { ISaleInquiry } from "./ISaleInquiry"; - -/** - * Review article. - * - * The `ISaleReview` is a type of review article written by a consumer who've bought - * the sale good with the estimation score. - * - * @author Jeongho Nam - https://github.com/samchon - */ -export type ISaleReview = ISaleInquiry; -export namespace ISaleReview { - /** - * Page request info of the review. - */ - export type IRequest = ISaleInquiry.IRequest; - - /** - * Summarized info of the review. - */ - export interface ISummary extends ISaleInquiry.ISummary { - /** - * Estimation score. - */ - score: number; - } - - /** - * Content info of the review. - */ - export interface IContent extends ISaleInquiry.IContent { - /** - * Estimation score. - */ - score: number; - } - - export interface IQuery { - code: string; - referrer: string; - alive: boolean; - signal: number; - } -} diff --git a/packages/sdk/demo/union/src/controllers/ConsumerSaleEntireArticlesController.ts b/packages/sdk/demo/union/src/controllers/ConsumerSaleEntireArticlesController.ts deleted file mode 100644 index 1c56c8452..000000000 --- a/packages/sdk/demo/union/src/controllers/ConsumerSaleEntireArticlesController.ts +++ /dev/null @@ -1,109 +0,0 @@ -import core from "@nestia/core"; -import * as nest from "@nestjs/common"; -import * as express from "express"; - -import { IPage } from "../api/structures/IPage"; -import { ISaleEntireArtcle } from "../api/structures/ISaleEntireArticle"; - -@nest.Controller("consumers/:section/sales/:saleId/entire_articles") -export class ConsumerSaleEntireArticlesController { - /** - * List up entire sale articles. - * - * @param request Instance of the Express.Request - * @param section Code of the target section - * @param saleId ID of the target sale - * @param ipAddr IP Address of the client - * @param href `window.location.href` - * @param query More query parameters - * @param input Page request info - * @returns Paged the entire articles - */ - @nest.Patch() - public async index( - @nest.Request() request: express.Request, - @core.TypedParam("section", "string") section: string, - @core.TypedParam("saleId", "number") saleId: number, - @nest.Body() input: ISaleEntireArtcle.IRequest, - @core.TypedQuery() query: ISaleEntireArtcle.IQuery, - @nest.Query("ip") ipAddr: string | undefined, - @nest.Query("location.href") href?: string, - ): Promise> { - request; - section; - saleId; - href; - ipAddr; - query; - - return { - pagination: { - page: 1, - limit: input.limit || 100, - total_count: 2, - total_pages: 1, - }, - data: [ - { - writer: "someone", - answered: false, - id: 1, - title: "some-title", - hit: 0, - created_at: new Date().toString(), - updated_at: new Date().toString(), - }, - { - writer: "someone", - answered: false, - id: 2, - title: "some-title", - hit: 0, - created_at: new Date().toString(), - updated_at: new Date().toString(), - score: 100, - }, - ], - }; - } - - /** - * Get detailed sale article record. - * - * @param request Instance of the Express.Request - * @param section Code of the target section - * @param saleId ID of the target sale - * @param id ID of the target article - * @returns The detailed article record - */ - @nest.Get(":id") - public async at( - @nest.Request() request: express.Request, - @core.TypedParam("section", "string") section: string, - @core.TypedParam("saleId", "number") saleId: number, - @core.TypedParam("id", "number") id: number, - ): Promise { - request; - section; - saleId; - id; - - return { - id: 0, - hit: 0, - writer: "someone", - answer: null, - created_at: new Date().toString(), - contents: [ - { - id: "some-content-id", - title: "some-title", - body: "some-body-content", - files: [], - created_at: new Date().toString(), - score: Math.random() < 0.5 ? 100 : undefined!, - }, - ], - }; - } -} diff --git a/packages/sdk/demo/union/src/controllers/ConsumerSaleQuestionsController.ts b/packages/sdk/demo/union/src/controllers/ConsumerSaleQuestionsController.ts deleted file mode 100644 index 358e80676..000000000 --- a/packages/sdk/demo/union/src/controllers/ConsumerSaleQuestionsController.ts +++ /dev/null @@ -1,45 +0,0 @@ -import core from "@nestia/core"; -import * as nest from "@nestjs/common"; -import * as express from "express"; - -import { IPage } from "../api/structures/IPage"; -import { ISaleQuestion } from "../api/structures/ISaleQuestion"; - -@nest.Controller("consumers/:section/sales/:saleId/questions") -export class ConsumerSaleQuestionsController { - @nest.Patch() - public async index( - @nest.Request() request: express.Request, - @core.TypedParam("section", "string") section: string, - @core.TypedParam("saleId", "number") saleId: number, - @nest.Body() input: ISaleQuestion.IRequest, - @nest.Query("ip") ipAddr?: string, - @nest.Query("location.href") href?: string, - ): Promise> { - request; - section; - saleId; - href; - ipAddr; - - return { - pagination: { - page: 1, - limit: input.limit || 100, - total_count: 1, - total_pages: 1, - }, - data: [ - { - writer: "someone", - answered: false, - id: 1, - title: "some-title", - hit: 0, - created_at: new Date().toString(), - updated_at: new Date().toString(), - }, - ], - }; - } -} diff --git a/packages/sdk/demo/union/src/controllers/ConsumerSaleReviewsController.ts b/packages/sdk/demo/union/src/controllers/ConsumerSaleReviewsController.ts deleted file mode 100644 index 2181deb89..000000000 --- a/packages/sdk/demo/union/src/controllers/ConsumerSaleReviewsController.ts +++ /dev/null @@ -1,44 +0,0 @@ -import core from "@nestia/core"; -import * as nest from "@nestjs/common"; -import * as express from "express"; - -import { IPage } from "../api/structures/IPage"; -import { ISaleReview } from "../api/structures/ISaleReview"; - -@nest.Controller("consumers/:section/sales/:saleId/reviews") -export class ConsumerSaleQuestionsController { - @nest.Patch() - public async index( - @nest.Request() request: express.Request, - @core.TypedParam("section", "string") section: string, - @core.TypedParam("saleId", "number") saleId: number, - @nest.Query() query: ISaleReview.IQuery, - @nest.Body() input: ISaleReview.IRequest, - ): Promise> { - request; - section; - saleId; - query; - - return { - pagination: { - page: 1, - limit: input.limit || 100, - total_count: 1, - total_pages: 1, - }, - data: [ - { - writer: "someone", - answered: false, - id: 2, - title: "some-title", - hit: 0, - created_at: new Date().toString(), - updated_at: new Date().toString(), - score: 100, - }, - ], - }; - } -} diff --git a/packages/sdk/demo/union/src/test/features/test_sale_entire_articles_at.ts b/packages/sdk/demo/union/src/test/features/test_sale_entire_articles_at.ts deleted file mode 100644 index 1f786a37c..000000000 --- a/packages/sdk/demo/union/src/test/features/test_sale_entire_articles_at.ts +++ /dev/null @@ -1,17 +0,0 @@ -import typia from "typia"; - -import api from "../../api"; -import { ISaleEntireArtcle } from "../../api/structures/ISaleEntireArticle"; - -export async function test_sale_entire_articles_at( - connection: api.IConnection, -): Promise { - const article: ISaleEntireArtcle = - await api.functional.consumers.sales.entire_articles.at( - connection, - "general", - 0, - 0, - ); - typia.assert(article); -} diff --git a/packages/sdk/demo/union/src/test/features/test_sale_entire_articles_index.ts b/packages/sdk/demo/union/src/test/features/test_sale_entire_articles_index.ts deleted file mode 100644 index 3a0d394a6..000000000 --- a/packages/sdk/demo/union/src/test/features/test_sale_entire_articles_index.ts +++ /dev/null @@ -1,29 +0,0 @@ -import typia from "typia"; - -import api from "../../api"; -import { IPage } from "../../api/structures/IPage"; -import { ISaleEntireArtcle } from "../../api/structures/ISaleEntireArticle"; - -export async function test_sale_entire_articles_index( - connection: api.IConnection, -): Promise { - const page: IPage = - await api.functional.consumers.sales.entire_articles.index( - connection, - "general", - 0, - { - limit: 10, - page: 3, - }, - { - referrer: "NodeJS", - code: "some-code", - signal: 0, - alive: true, - }, - "127.0.0.1", - __filename, - ); - typia.assert(page); -} diff --git a/packages/sdk/demo/union/src/test/index.ts b/packages/sdk/demo/union/src/test/index.ts deleted file mode 100644 index 9a9c90c94..000000000 --- a/packages/sdk/demo/union/src/test/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { Backend } from "../Backend"; -import { Configuration } from "../Configuration"; -import api from "../api"; -import { DynamicImportIterator } from "./internal/DynamicImportIterator"; - -async function main(): Promise { - const server: Backend = new Backend(); - await server.open(); - - const connection: api.IConnection = { - host: `http://127.0.0.1:${Configuration.PORT}`, - encryption: Configuration.ENCRYPTION_PASSWORD, - }; - await DynamicImportIterator.main(__dirname, { - prefix: "test", - parameters: () => [connection], - }); - - await server.close(); -} -main().catch((exp) => { - console.log(exp); - process.exit(-1); -}); diff --git a/packages/sdk/demo/union/src/test/internal/DynamicImportIterator.ts b/packages/sdk/demo/union/src/test/internal/DynamicImportIterator.ts deleted file mode 100644 index 4a12a8b47..000000000 --- a/packages/sdk/demo/union/src/test/internal/DynamicImportIterator.ts +++ /dev/null @@ -1,109 +0,0 @@ -import cli from "cli"; -import fs from "fs"; -import { IPointer } from "tstl/functional/IPointer"; - -import { StopWatch } from "./StopWatch"; - -const EXTENSION = __filename.substr(-2); - -interface ICommand { - include?: string; - exclude?: string; -} - -export namespace DynamicImportIterator { - export type Closure = ( - ...args: Arguments - ) => Promise; - type Module = { - [key: string]: Closure; - }; - - export interface IOptions { - prefix: string; - parameters: () => Parameters; - wrapper?: (name: string, output: any) => Promise; - counter?: IPointer; - showElapsedTime?: boolean; - } - - export async function main( - path: string, - options: IOptions, - ): Promise { - const command: ICommand = cli.parse(); - await iterate(options, command, path); - } - - export async function force( - path: string, - options: IOptions, - ): Promise { - const command: ICommand = cli.parse(); - const exceptions: Error[] = []; - - await iterate(options, command, path, exceptions); - return exceptions; - } - - async function iterate( - options: IOptions, - command: ICommand, - path: string, - exceptions?: Error[], - ): Promise { - const directory: string[] = await fs.promises.readdir(path); - for (const file of directory) { - const current: string = `${path}/${file}`; - const stats: fs.Stats = await fs.promises.lstat(current); - - if (stats.isDirectory() === true) { - await iterate(options, command, current, exceptions); - continue; - } else if (file.substr(-3) !== `.${EXTENSION}`) continue; - - const external: Module = await import(current); - await execute(options, command, external, exceptions); - } - } - - async function execute( - options: IOptions, - command: ICommand, - external: Module, - exceptions?: Error[], - ): Promise { - for (const key in external) { - if (command.exclude && key.indexOf(command.exclude) !== -1) - continue; - else if (command.include && key.indexOf(command.include) === -1) - continue; - else if (key.substr(0, options.prefix.length) !== options.prefix) - continue; - else if (external[key] instanceof Function) { - const closure: Closure = external[key]; - const func = async () => { - const output = await closure(...options.parameters()); - if (options.wrapper) await options.wrapper(key, output); - }; - - try { - if (options.counter) ++options.counter.value; - if (options.showElapsedTime === false) { - await func(); - console.log(` - ${key}`); - } else { - const time: number = await StopWatch.measure(func); - console.log(` - ${key}: ${time.toLocaleString()} ms`); - } - } catch (exp) { - if (!(exp instanceof Error)) return; - - console.log(` - ${key} -> ${exp.name}`); - if (exceptions !== undefined) exceptions.push(exp); - else throw exp; - } - } - } - } -} diff --git a/packages/sdk/demo/union/src/test/internal/StopWatch.ts b/packages/sdk/demo/union/src/test/internal/StopWatch.ts deleted file mode 100644 index 862caf8c8..000000000 --- a/packages/sdk/demo/union/src/test/internal/StopWatch.ts +++ /dev/null @@ -1,15 +0,0 @@ -export namespace StopWatch { - export type Task = () => Promise; - - export async function measure(task: Task): Promise { - const time: number = Date.now(); - await task(); - return Date.now() - time; - } - - export async function trace(title: string, task: Task): Promise { - process.stdout.write(title); - const time: number = await measure(task); - console.log(`: ${time.toLocaleString()} ms`); - } -} diff --git a/packages/sdk/demo/union/swagger.json b/packages/sdk/demo/union/swagger.json deleted file mode 100644 index 627f8aefd..000000000 --- a/packages/sdk/demo/union/swagger.json +++ /dev/null @@ -1,1302 +0,0 @@ -{ - "openapi": "3.0.1", - "servers": [ - { - "url": "https://github.com/samchon/nestia", - "description": "insert your server url" - } - ], - "info": { - "version": "0.1.0", - "title": "Generated by nestia - https://github.com/samchon/nestia" - }, - "paths": { - "/consumers/{section}/sales/{saleId}/entire_articles": { - "patch": { - "tags": [], - "parameters": [ - { - "name": "section", - "in": "path", - "description": "Code of the target section", - "schema": { - "type": "string", - "nullable": false - }, - "required": true - }, - { - "name": "saleId", - "in": "path", - "description": "ID of the target sale", - "schema": { - "type": "number", - "nullable": false - }, - "required": true - }, - { - "name": "query", - "in": "query", - "description": "More query parameters", - "schema": { - "$ref": "#/components/schemas/ISaleReview.IQuery" - }, - "required": true - }, - { - "name": "ip", - "in": "query", - "description": "IP Address of the client", - "schema": { - "type": "string", - "nullable": false - }, - "required": false - }, - { - "name": "location.href", - "in": "query", - "description": "`window.location.href`", - "schema": { - "type": "string", - "nullable": false - }, - "required": false - } - ], - "requestBody": { - "description": "Page request info", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ISaleInquiry.IRequest" - } - } - }, - "required": true, - "x-nestia-encrypted": false - }, - "responses": { - "201": { - "description": "Paged the entire articles", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/IPage_lt_ISaleEntireArtcle.ISummary_gt_" - } - } - }, - "x-nestia-encrypted": false - } - }, - "summary": "List up entire sale articles", - "description": "List up entire sale articles.", - "x-nestia-namespace": "consumers.sales.entire_articles.index", - "x-nestia-jsDocTags": [ - { - "name": "param", - "text": [ - { - "text": "request", - "kind": "parameterName" - }, - { - "text": " ", - "kind": "space" - }, - { - "text": "Instance of the Express.Request", - "kind": "text" - } - ] - }, - { - "name": "param", - "text": [ - { - "text": "section", - "kind": "parameterName" - }, - { - "text": " ", - "kind": "space" - }, - { - "text": "Code of the target section", - "kind": "text" - } - ] - }, - { - "name": "param", - "text": [ - { - "text": "saleId", - "kind": "parameterName" - }, - { - "text": " ", - "kind": "space" - }, - { - "text": "ID of the target sale", - "kind": "text" - } - ] - }, - { - "name": "param", - "text": [ - { - "text": "ipAddr", - "kind": "parameterName" - }, - { - "text": " ", - "kind": "space" - }, - { - "text": "IP Address of the client", - "kind": "text" - } - ] - }, - { - "name": "param", - "text": [ - { - "text": "href", - "kind": "parameterName" - }, - { - "text": " ", - "kind": "space" - }, - { - "text": "`window.location.href`", - "kind": "text" - } - ] - }, - { - "name": "param", - "text": [ - { - "text": "query", - "kind": "parameterName" - }, - { - "text": " ", - "kind": "space" - }, - { - "text": "More query parameters", - "kind": "text" - } - ] - }, - { - "name": "param", - "text": [ - { - "text": "input", - "kind": "parameterName" - }, - { - "text": " ", - "kind": "space" - }, - { - "text": "Page request info", - "kind": "text" - } - ] - }, - { - "name": "returns", - "text": [ - { - "text": "Paged the entire articles", - "kind": "text" - } - ] - } - ] - } - }, - "/consumers/{section}/sales/{saleId}/entire_articles/{id}": { - "get": { - "tags": [], - "parameters": [ - { - "name": "section", - "in": "path", - "description": "Code of the target section", - "schema": { - "type": "string", - "nullable": false - }, - "required": true - }, - { - "name": "saleId", - "in": "path", - "description": "ID of the target sale", - "schema": { - "type": "number", - "nullable": false - }, - "required": true - }, - { - "name": "id", - "in": "path", - "description": "ID of the target article", - "schema": { - "type": "number", - "nullable": false - }, - "required": true - } - ], - "responses": { - "200": { - "description": "The detailed article record", - "content": { - "application/json": { - "schema": { - "oneOf": [ - { - "$ref": "#/components/schemas/ISaleQuestion" - }, - { - "$ref": "#/components/schemas/ISaleReview" - } - ] - } - } - }, - "x-nestia-encrypted": false - } - }, - "summary": "Get detailed sale article record", - "description": "Get detailed sale article record.", - "x-nestia-namespace": "consumers.sales.entire_articles.at", - "x-nestia-jsDocTags": [ - { - "name": "param", - "text": [ - { - "text": "request", - "kind": "parameterName" - }, - { - "text": " ", - "kind": "space" - }, - { - "text": "Instance of the Express.Request", - "kind": "text" - } - ] - }, - { - "name": "param", - "text": [ - { - "text": "section", - "kind": "parameterName" - }, - { - "text": " ", - "kind": "space" - }, - { - "text": "Code of the target section", - "kind": "text" - } - ] - }, - { - "name": "param", - "text": [ - { - "text": "saleId", - "kind": "parameterName" - }, - { - "text": " ", - "kind": "space" - }, - { - "text": "ID of the target sale", - "kind": "text" - } - ] - }, - { - "name": "param", - "text": [ - { - "text": "id", - "kind": "parameterName" - }, - { - "text": " ", - "kind": "space" - }, - { - "text": "ID of the target article", - "kind": "text" - } - ] - }, - { - "name": "returns", - "text": [ - { - "text": "The detailed article record", - "kind": "text" - } - ] - } - ] - } - }, - "/consumers/{section}/sales/{saleId}/questions": { - "patch": { - "tags": [], - "parameters": [ - { - "name": "section", - "in": "path", - "description": "", - "schema": { - "type": "string", - "nullable": false - }, - "required": true - }, - { - "name": "saleId", - "in": "path", - "description": "", - "schema": { - "type": "number", - "nullable": false - }, - "required": true - }, - { - "name": "ip", - "in": "query", - "description": "", - "schema": { - "type": "string", - "nullable": false - }, - "required": false - }, - { - "name": "location.href", - "in": "query", - "description": "", - "schema": { - "type": "string", - "nullable": false - }, - "required": false - } - ], - "requestBody": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ISaleInquiry.IRequest" - } - } - }, - "required": true, - "x-nestia-encrypted": false - }, - "responses": { - "201": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/IPage_lt_ISaleInquiry.ISummary_gt_" - } - } - }, - "x-nestia-encrypted": false - } - }, - "description": "", - "x-nestia-namespace": "consumers.sales.questions.index", - "x-nestia-jsDocTags": [] - } - }, - "/consumers/{section}/sales/{saleId}/reviews": { - "patch": { - "tags": [], - "parameters": [ - { - "name": "section", - "in": "path", - "description": "", - "schema": { - "type": "string", - "nullable": false - }, - "required": true - }, - { - "name": "saleId", - "in": "path", - "description": "", - "schema": { - "type": "number", - "nullable": false - }, - "required": true - }, - { - "name": "query", - "in": "query", - "description": "", - "schema": { - "$ref": "#/components/schemas/ISaleReview.IQuery" - }, - "required": true - } - ], - "requestBody": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ISaleInquiry.IRequest" - } - } - }, - "required": true, - "x-nestia-encrypted": false - }, - "responses": { - "201": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/IPage_lt_ISaleReview.ISummary_gt_" - } - } - }, - "x-nestia-encrypted": false - } - }, - "description": "", - "x-nestia-namespace": "consumers.sales.reviews.index", - "x-nestia-jsDocTags": [] - } - } - }, - "components": { - "schemas": { - "ISaleReview.IQuery": { - "type": "object", - "properties": { - "code": { - "type": "string", - "nullable": false, - "x-typia-required": true - }, - "referrer": { - "type": "string", - "nullable": false, - "x-typia-required": true - }, - "alive": { - "type": "boolean", - "nullable": false, - "x-typia-required": true - }, - "signal": { - "type": "number", - "nullable": false, - "x-typia-required": true - } - }, - "nullable": false, - "required": [ - "code", - "referrer", - "alive", - "signal" - ], - "x-typia-jsDocTags": [] - }, - "ISaleInquiry.IRequest": { - "type": "object", - "properties": { - "answered": { - "type": "boolean", - "nullable": false, - "description": "Whether being answer by seller or not.", - "x-typia-required": false - }, - "page": { - "type": "number", - "nullable": false, - "description": "Page number.", - "x-typia-required": false - }, - "limit": { - "type": "number", - "nullable": false, - "description": "Maximum number of records per a page.", - "x-typia-jsDocTags": [ - { - "name": "default", - "text": [ - { - "text": "100", - "kind": "text" - } - ] - } - ], - "x-typia-required": false, - "default": 100 - }, - "search_fields": { - "type": "array", - "items": { - "type": "string", - "enum": [ - "writer", - "title", - "content" - ], - "nullable": false, - "description": "Search field(s).", - "x-typia-required": false - }, - "nullable": false, - "description": "Search field(s).", - "x-typia-required": false - }, - "search_value": { - "type": "string", - "nullable": false, - "description": "Search value.", - "x-typia-required": false - }, - "sort": { - "type": "string", - "nullable": false, - "description": "Standard of sorting, list up fields with symbols.\n\n - Only field name (`id`): ASC\n - Plus symbol (`+id`): ASC\n - Minus symbol (`-id`): DESC", - "x-typia-required": false - } - }, - "nullable": false, - "description": "Page request info.", - "x-typia-jsDocTags": [] - }, - "IPage_lt_ISaleEntireArtcle.ISummary_gt_": { - "type": "object", - "properties": { - "pagination": { - "$ref": "#/components/schemas/IPage.IPagination", - "description": "Pagination info.", - "x-typia-required": true - }, - "data": { - "type": "array", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ISaleInquiry.ISummary", - "description": "List of the records.", - "x-typia-required": true - }, - { - "$ref": "#/components/schemas/ISaleReview.ISummary", - "description": "List of the records.", - "x-typia-required": true - } - ], - "description": "List of the records.", - "x-typia-required": true - }, - "nullable": false, - "description": "List of the records.", - "x-typia-required": true - } - }, - "nullable": false, - "required": [ - "pagination", - "data" - ], - "description": "Paginated records.", - "x-typia-jsDocTags": [ - { - "name": "author", - "text": [ - { - "text": "Jeongho Nam - https://github.com/samchon", - "kind": "text" - } - ] - } - ] - }, - "IPage.IPagination": { - "type": "object", - "properties": { - "page": { - "type": "number", - "nullable": false, - "description": "Current page number.", - "x-typia-required": true - }, - "limit": { - "type": "number", - "nullable": false, - "description": "Maximum number of records per a page.", - "x-typia-jsDocTags": [ - { - "name": "default", - "text": [ - { - "text": "100", - "kind": "text" - } - ] - } - ], - "x-typia-required": true, - "default": 100 - }, - "total_count": { - "type": "number", - "nullable": false, - "description": "Number of entire records.", - "x-typia-required": true - }, - "total_pages": { - "type": "number", - "nullable": false, - "description": "Number of total pages.", - "x-typia-required": true - } - }, - "nullable": false, - "required": [ - "page", - "limit", - "total_count", - "total_pages" - ], - "description": "Pagenation info.", - "x-typia-jsDocTags": [] - }, - "ISaleInquiry.ISummary": { - "type": "object", - "properties": { - "writer": { - "type": "string", - "nullable": false, - "description": "Name of the writer.", - "x-typia-required": true - }, - "answered": { - "type": "boolean", - "nullable": false, - "description": "Whether being answer by seller or not.", - "x-typia-required": true - }, - "id": { - "type": "number", - "nullable": false, - "description": "Primary Key.", - "x-typia-required": true - }, - "title": { - "type": "string", - "nullable": false, - "description": "Title of the article.", - "x-typia-required": true - }, - "hit": { - "type": "number", - "nullable": false, - "description": "Hit count.\n\nHow many consumers had read.", - "x-typia-required": true - }, - "created_at": { - "type": "string", - "nullable": false, - "description": "Creaiton time.", - "x-typia-required": true - }, - "updated_at": { - "type": "string", - "nullable": false, - "description": "Updated time.", - "x-typia-required": true - } - }, - "nullable": false, - "required": [ - "writer", - "answered", - "id", - "title", - "hit", - "created_at", - "updated_at" - ], - "description": "Summarized info of the inquiry article.", - "x-typia-jsDocTags": [] - }, - "ISaleReview.ISummary": { - "type": "object", - "properties": { - "score": { - "type": "number", - "nullable": false, - "description": "Estimation score.", - "x-typia-required": true - }, - "writer": { - "type": "string", - "nullable": false, - "description": "Name of the writer.", - "x-typia-required": true - }, - "answered": { - "type": "boolean", - "nullable": false, - "description": "Whether being answer by seller or not.", - "x-typia-required": true - }, - "id": { - "type": "number", - "nullable": false, - "description": "Primary Key.", - "x-typia-required": true - }, - "title": { - "type": "string", - "nullable": false, - "description": "Title of the article.", - "x-typia-required": true - }, - "hit": { - "type": "number", - "nullable": false, - "description": "Hit count.\n\nHow many consumers had read.", - "x-typia-required": true - }, - "created_at": { - "type": "string", - "nullable": false, - "description": "Creaiton time.", - "x-typia-required": true - }, - "updated_at": { - "type": "string", - "nullable": false, - "description": "Updated time.", - "x-typia-required": true - } - }, - "nullable": false, - "required": [ - "score", - "writer", - "answered", - "id", - "title", - "hit", - "created_at", - "updated_at" - ], - "description": "Summarized info of the review.", - "x-typia-jsDocTags": [] - }, - "ISaleQuestion": { - "type": "object", - "properties": { - "writer": { - "type": "string", - "nullable": false, - "description": "Name of the writer.", - "x-typia-required": true - }, - "answer": { - "$ref": "#/components/schemas/ISaleInquiryAnswer.Nullable", - "description": "Formal answer from the seller.", - "x-typia-required": true - }, - "id": { - "type": "number", - "nullable": false, - "description": "Primary Key.", - "x-typia-required": true - }, - "hit": { - "type": "number", - "nullable": false, - "description": "Hit count.\n\nHow many consumers had read.", - "x-typia-required": true - }, - "contents": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ISaleArticle.IContent", - "description": "List of contents.\n\nWhen the article writer tries to modify content, it would not modify the article\ncontent but would be accumulated. Therefore, all of the people can read how\nthe content has been changed.", - "x-typia-required": true - }, - "nullable": false, - "description": "List of contents.\n\nWhen the article writer tries to modify content, it would not modify the article\ncontent but would be accumulated. Therefore, all of the people can read how\nthe content has been changed.", - "x-typia-required": true - }, - "created_at": { - "type": "string", - "nullable": false, - "description": "Creation time.", - "x-typia-required": true - } - }, - "nullable": false, - "required": [ - "writer", - "answer", - "id", - "hit", - "contents", - "created_at" - ], - "description": "Inquiry article.\n\nSub-type of article and super-type of question and answer.", - "x-typia-jsDocTags": [ - { - "name": "template", - "text": [ - { - "text": "Content", - "kind": "typeParameterName" - }, - { - "text": " ", - "kind": "space" - }, - { - "text": "Content type", - "kind": "text" - } - ] - }, - { - "name": "author", - "text": [ - { - "text": "Jeongho Nam - https://github.com/samchon", - "kind": "text" - } - ] - } - ] - }, - "ISaleInquiryAnswer.Nullable": { - "type": "object", - "properties": { - "id": { - "type": "number", - "nullable": false, - "description": "Primary Key.", - "x-typia-required": true - }, - "hit": { - "type": "number", - "nullable": false, - "description": "Hit count.\n\nHow many consumers had read.", - "x-typia-required": true - }, - "contents": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ISaleArticle.IContent", - "description": "List of contents.\n\nWhen the article writer tries to modify content, it would not modify the article\ncontent but would be accumulated. Therefore, all of the people can read how\nthe content has been changed.", - "x-typia-required": true - }, - "nullable": false, - "description": "List of contents.\n\nWhen the article writer tries to modify content, it would not modify the article\ncontent but would be accumulated. Therefore, all of the people can read how\nthe content has been changed.", - "x-typia-required": true - }, - "created_at": { - "type": "string", - "nullable": false, - "description": "Creation time.", - "x-typia-required": true - } - }, - "nullable": true, - "required": [ - "id", - "hit", - "contents", - "created_at" - ], - "description": "Article about a sale.\n\nThe `ISaleArticle` is a super type interface. Many sub-type articles would be\ndesigned by extending this super type interface `ISaleArticle`.", - "x-typia-jsDocTags": [ - { - "name": "template", - "text": [ - { - "text": "Content", - "kind": "typeParameterName" - }, - { - "text": " ", - "kind": "space" - }, - { - "text": "Content type.", - "kind": "text" - } - ] - }, - { - "name": "author", - "text": [ - { - "text": "Jeongho Nam - https://github.com/samchon", - "kind": "text" - } - ] - } - ] - }, - "ISaleArticle.IContent": { - "type": "object", - "properties": { - "id": { - "type": "string", - "nullable": false, - "description": "Primary Key", - "x-typia-required": true - }, - "title": { - "type": "string", - "nullable": false, - "description": "Title of the content.", - "x-typia-required": true - }, - "body": { - "type": "string", - "nullable": false, - "description": "Body of the content.", - "x-typia-required": true - }, - "files": { - "type": "array", - "items": { - "$ref": "#/components/schemas/IAttachmentFile", - "description": "Attached files.", - "x-typia-required": true - }, - "nullable": false, - "description": "Attached files.", - "x-typia-required": true - }, - "created_at": { - "type": "string", - "nullable": false, - "description": "Creation time.", - "x-typia-required": true - } - }, - "nullable": false, - "required": [ - "id", - "title", - "body", - "files", - "created_at" - ], - "description": "Content info.", - "x-typia-jsDocTags": [] - }, - "IAttachmentFile": { - "type": "object", - "properties": { - "id": { - "type": "number", - "nullable": false, - "description": "Primary Key.", - "x-typia-required": true - }, - "name": { - "type": "string", - "nullable": false, - "description": "Name of the file.", - "x-typia-required": true - }, - "extension": { - "type": "string", - "nullable": true, - "description": "Extension of the file, but ommitable.", - "x-typia-required": true - }, - "url": { - "type": "string", - "nullable": false, - "description": "Full URL path of the file.", - "x-typia-required": true - } - }, - "nullable": false, - "required": [ - "id", - "name", - "extension", - "url" - ], - "description": "Attachemd (physical) file info.", - "x-typia-jsDocTags": [ - { - "name": "author", - "text": [ - { - "text": "Jeongho Nam - https://github.com/samchon", - "kind": "text" - } - ] - } - ] - }, - "ISaleReview": { - "type": "object", - "properties": { - "writer": { - "type": "string", - "nullable": false, - "description": "Name of the writer.", - "x-typia-required": true - }, - "answer": { - "$ref": "#/components/schemas/ISaleInquiryAnswer.Nullable", - "description": "Formal answer from the seller.", - "x-typia-required": true - }, - "id": { - "type": "number", - "nullable": false, - "description": "Primary Key.", - "x-typia-required": true - }, - "hit": { - "type": "number", - "nullable": false, - "description": "Hit count.\n\nHow many consumers had read.", - "x-typia-required": true - }, - "contents": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ISaleReview.IContent", - "description": "List of contents.\n\nWhen the article writer tries to modify content, it would not modify the article\ncontent but would be accumulated. Therefore, all of the people can read how\nthe content has been changed.", - "x-typia-required": true - }, - "nullable": false, - "description": "List of contents.\n\nWhen the article writer tries to modify content, it would not modify the article\ncontent but would be accumulated. Therefore, all of the people can read how\nthe content has been changed.", - "x-typia-required": true - }, - "created_at": { - "type": "string", - "nullable": false, - "description": "Creation time.", - "x-typia-required": true - } - }, - "nullable": false, - "required": [ - "writer", - "answer", - "id", - "hit", - "contents", - "created_at" - ], - "description": "Inquiry article.\n\nSub-type of article and super-type of question and answer.", - "x-typia-jsDocTags": [ - { - "name": "template", - "text": [ - { - "text": "Content", - "kind": "typeParameterName" - }, - { - "text": " ", - "kind": "space" - }, - { - "text": "Content type", - "kind": "text" - } - ] - }, - { - "name": "author", - "text": [ - { - "text": "Jeongho Nam - https://github.com/samchon", - "kind": "text" - } - ] - } - ] - }, - "ISaleReview.IContent": { - "type": "object", - "properties": { - "score": { - "type": "number", - "nullable": false, - "description": "Estimation score.", - "x-typia-required": true - }, - "id": { - "type": "string", - "nullable": false, - "description": "Primary Key", - "x-typia-required": true - }, - "title": { - "type": "string", - "nullable": false, - "description": "Title of the content.", - "x-typia-required": true - }, - "body": { - "type": "string", - "nullable": false, - "description": "Body of the content.", - "x-typia-required": true - }, - "files": { - "type": "array", - "items": { - "$ref": "#/components/schemas/IAttachmentFile", - "description": "Attached files.", - "x-typia-required": true - }, - "nullable": false, - "description": "Attached files.", - "x-typia-required": true - }, - "created_at": { - "type": "string", - "nullable": false, - "description": "Creation time.", - "x-typia-required": true - } - }, - "nullable": false, - "required": [ - "score", - "id", - "title", - "body", - "files", - "created_at" - ], - "description": "Content info of the review.", - "x-typia-jsDocTags": [] - }, - "IPage_lt_ISaleInquiry.ISummary_gt_": { - "type": "object", - "properties": { - "pagination": { - "$ref": "#/components/schemas/IPage.IPagination", - "description": "Pagination info.", - "x-typia-required": true - }, - "data": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ISaleInquiry.ISummary", - "description": "List of the records.", - "x-typia-required": true - }, - "nullable": false, - "description": "List of the records.", - "x-typia-required": true - } - }, - "nullable": false, - "required": [ - "pagination", - "data" - ], - "description": "Paginated records.", - "x-typia-jsDocTags": [ - { - "name": "author", - "text": [ - { - "text": "Jeongho Nam - https://github.com/samchon", - "kind": "text" - } - ] - } - ] - }, - "IPage_lt_ISaleReview.ISummary_gt_": { - "type": "object", - "properties": { - "pagination": { - "$ref": "#/components/schemas/IPage.IPagination", - "description": "Pagination info.", - "x-typia-required": true - }, - "data": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ISaleReview.ISummary", - "description": "List of the records.", - "x-typia-required": true - }, - "nullable": false, - "description": "List of the records.", - "x-typia-required": true - } - }, - "nullable": false, - "required": [ - "pagination", - "data" - ], - "description": "Paginated records.", - "x-typia-jsDocTags": [ - { - "name": "author", - "text": [ - { - "text": "Jeongho Nam - https://github.com/samchon", - "kind": "text" - } - ] - } - ] - } - } - } -} \ No newline at end of file diff --git a/packages/sdk/demo/union/tsconfig.json b/packages/sdk/demo/union/tsconfig.json deleted file mode 100644 index 8e8705b08..000000000 --- a/packages/sdk/demo/union/tsconfig.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": "../tsconfig.base.json", -} \ No newline at end of file diff --git a/packages/sdk/package.json b/packages/sdk/package.json index 678159be8..1a5a47669 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -1,6 +1,6 @@ { "name": "@nestia/sdk", - "version": "1.1.0", + "version": "1.1.1", "description": "Nestia SDK and Swagger generator", "main": "lib/index.js", "typings": "lib/index.d.ts", @@ -11,11 +11,10 @@ "build": "rimraf lib && tsc", "dev": "rimraf lib && tsc --watch", "eslint": "eslint ./**/*.ts", - "package:latest": "npm run build && npm run test && npm publish --access public", + "package:latest": "npm run build && npm publish --access public", "package:next": "npm run package:latest -- --tag next", "prepare": "ts-patch install", - "prettier": "prettier --write ./**/*.ts", - "test": "node lib/test" + "prettier": "prettier --write ./**/*.ts" }, "repository": { "type": "git", @@ -69,8 +68,8 @@ "prettier": "^2.8.1", "rimraf": "^3.0.2", "ts-node": "^10.9.1", - "ts-patch": "3.0.0-beta3", - "typescript": "^5.0.4", + "ts-patch": "v2.1.0", + "typescript": "^4.9.5", "typescript-transform-paths": "^3.4.4", "uuid": "^9.0.0" }, @@ -78,8 +77,6 @@ "assets", "lib", "src", - "!lib/test", - "!src/test", "README.md", "LICENSE", "package.json" diff --git a/packages/sdk/src/analyses/ReflectAnalyzer.ts b/packages/sdk/src/analyses/ReflectAnalyzer.ts index ffbd67a2e..6cde6ad38 100644 --- a/packages/sdk/src/analyses/ReflectAnalyzer.ts +++ b/packages/sdk/src/analyses/ReflectAnalyzer.ts @@ -6,6 +6,8 @@ import { ParamCategory } from "../structures/ParamCategory"; import { ArrayUtil } from "../utils/ArrayUtil"; import { PathAnalyzer } from "./PathAnalyzer"; +declare const Reflect: any; + type IModule = { [key: string]: any; }; diff --git a/packages/sdk/src/executable/internal/NestiaSdkCommand.ts b/packages/sdk/src/executable/internal/NestiaSdkCommand.ts index b74fcdeb3..9c3cc7939 100644 --- a/packages/sdk/src/executable/internal/NestiaSdkCommand.ts +++ b/packages/sdk/src/executable/internal/NestiaSdkCommand.ts @@ -138,7 +138,7 @@ export namespace NestiaSdkCommand { validate: (config: INestiaConfig) => boolean, ): Promise { const connector = new WorkerConnector(null, null, "process"); - await connector.connect(`${__dirname}/nestia.config.getter.js`); + await connector.connect(`${__dirname}/nestia.config.getter.${__filename.substr(-2)}`); const driver = await connector.getDriver(); const config: INestiaConfig | null = await driver.get(); diff --git a/packages/sdk/src/generates/FunctionGenerator.ts b/packages/sdk/src/generates/FunctionGenerator.ts index e2a63fc53..65dcd77a7 100644 --- a/packages/sdk/src/generates/FunctionGenerator.ts +++ b/packages/sdk/src/generates/FunctionGenerator.ts @@ -283,7 +283,7 @@ export namespace FunctionGenerator { if (param.category === "param") path = path.replace( `:${param.field}`, - `\${encodeURIComponent(${param.name})}`, + `\${encodeURIComponent(${param.name} ?? "null")}`, ); // NO QUERY PARAMETER diff --git a/packages/sdk/src/test/TestBuilder.ts b/packages/sdk/src/test/TestBuilder.ts deleted file mode 100644 index 35da7fe56..000000000 --- a/packages/sdk/src/test/TestBuilder.ts +++ /dev/null @@ -1,52 +0,0 @@ -import cp from "child_process"; -import fs from "fs"; - -import { NestiaSdkCommand } from "../executable/internal/NestiaSdkCommand"; - -export namespace TestBuilder { - export async function generate( - name: string, - job: "sdk" | "swagger", - argv: string[], - ): Promise { - const task = - job === "sdk" - ? { - generate: NestiaSdkCommand.sdk, - file: "src/api/functional/index.ts", - } - : { - generate: NestiaSdkCommand.swagger, - file: "swagger.json", - }; - - process.chdir(`${PATH}/../../demo/${name}`); - if (fs.existsSync(task.file)) await fs.promises.unlink(task.file); - - try { - await task.generate(argv, false); - if (fs.existsSync(task.file) === false) - throw new Error( - `Bug on NestiaCommand.${job}(): failed to generate file(s).`, - ); - } catch (exp) { - console.log(exp); - throw exp; - } - } - - export async function test(name: string): Promise { - process.chdir(`${PATH}/../../demo/${name}`); - - try { - cp.execSync("npx ts-node src/test", { - stdio: "inherit", - }); - } catch (exp) { - console.log(exp); - throw exp; - } - } - - const PATH = __dirname; -} diff --git a/packages/sdk/src/test/index.ts b/packages/sdk/src/test/index.ts deleted file mode 100644 index e635b4f09..000000000 --- a/packages/sdk/src/test/index.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { WorkerConnector } from "tgrid/protocols/workers/WorkerConnector"; - -import { TestBuilder } from "./TestBuilder"; - -async function execute( - name: string, - job: "sdk" | "swagger" | "test", - elements: string[], -): Promise { - if (job === "test") console.log(`${name} -> npx ts-node src/test`); - else console.log(`${name} -> npx nestia ${job} ${elements.join(" ")}`); - - const worker = new WorkerConnector(null, null, "process"); - await worker.connect(`${__dirname}/test.builder.executor.js`); - - try { - const driver = worker.getDriver(); - if (job === "test") await driver.test(name); - else await driver.generate(name, job, elements); - await worker.close(); - } catch (exp) { - await worker.close(); - process.exit(-1); - } -} - -function get_arguments( - target: "directory" | "pattern", - job: "sdk" | "swagger" | "test", - specialize: boolean = false, -): string[] { - return [ - target === "directory" ? "src/controllers" : "src/**/*.controller.ts", - "--out", - job === "sdk" ? "src/api" : specialize ? "swagger.json" : "./", - ]; -} - -async function main(): Promise { - console.log("Build Demonstration Projects"); - for (const job of ["swagger", "sdk", "test"] as const) { - console.log( - "---------------------------------------------------------", - ); - await execute("176", job, get_arguments("directory", job)); - await execute("296", job, get_arguments("directory", job)); - await execute("encrypted", job, get_arguments("directory", job)); - await execute("generic", job, get_arguments("directory", job)); - await execute("recursive", job, get_arguments("pattern", job)); - await execute("safe", job, get_arguments("directory", job)); - await execute("union", job, get_arguments("directory", job)); - await execute("multiple-paths", job, get_arguments("directory", job)); - await execute("status", job, get_arguments("directory", job)); - } -} -main().catch((exp) => { - console.log(exp); - process.exit(-1); -}); diff --git a/packages/sdk/src/test/test.builder.executor.ts b/packages/sdk/src/test/test.builder.executor.ts deleted file mode 100644 index 1c72e9594..000000000 --- a/packages/sdk/src/test/test.builder.executor.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { WorkerServer } from "tgrid/protocols/workers/WorkerServer"; - -import { TestBuilder } from "./TestBuilder"; - -async function main(): Promise { - const worker = new WorkerServer(); - await worker.open(TestBuilder); -} -main().catch((exp) => { - console.log(exp); - process.exit(-1); -}); diff --git a/prettier.config.js b/prettier.config.js new file mode 100644 index 000000000..aa2c2336c --- /dev/null +++ b/prettier.config.js @@ -0,0 +1,16 @@ +module.exports = { + parser: "typescript", + printWidth: 80, + semi: true, + tabWidth: 4, + trailingComma: "all", + importOrder: [ + "", + "@nestia(.*)$", + "@api(.*)$", + "^[./]", + ], + importOrderSeparation: true, + importOrderSortSpecifiers: true, + importOrderParserPlugins: ["decorators-legacy", "typescript"], +}; \ No newline at end of file diff --git a/test/.prettierignore b/test/.prettierignore new file mode 100644 index 000000000..a7b69bac4 --- /dev/null +++ b/test/.prettierignore @@ -0,0 +1,2 @@ +api/functional +node_modules \ No newline at end of file diff --git a/test/.vscode/settings.json b/test/.vscode/settings.json new file mode 100644 index 000000000..fbdc2f18e --- /dev/null +++ b/test/.vscode/settings.json @@ -0,0 +1,17 @@ +{ + "editor.tabSize": 4, + "[typescript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true, + "editor.codeActionsOnSave": { + "source.fixAll.eslint": true + }, + }, + "[javascript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true, + "editor.codeActionsOnSave": { + "source.fixAll.eslint": true + }, + } +} \ No newline at end of file diff --git a/test/executable/generate.js b/test/executable/generate.js new file mode 100644 index 000000000..04236e7aa --- /dev/null +++ b/test/executable/generate.js @@ -0,0 +1,30 @@ +const fs = require("fs"); + +const directory = (name) => `${__dirname}/../features/${name}`; + +const copy = + (src) => + async (dest) => { + const stats = await fs.promises.lstat(src); + if (stats.isDirectory()) { + await fs.promises.mkdir(dest); + for (const file of await fs.promises.readdir(src)) + await copy(`${src}/${file}`)(`${dest}/${file}`); + } else await fs.promises.copyFile(src, dest); + }; + +const main = async () => { + const name = process.argv[2]; + if (name === undefined) + throw new Error("No name specified. (e.g. npm run generate route-error-generic"); + + const type = name.includes("error") ? "error" : "success"; + if (fs.existsSync(directory(name))) + throw new Error("duplicated name exists."); + await copy(`${__dirname}/../template/${type}`)(directory(name)); +}; + +main().catch((exp) => { + console.error(exp); + process.exit(-1); +}); diff --git a/test/executable/setup.js b/test/executable/setup.js new file mode 100644 index 000000000..bb57f7cb2 --- /dev/null +++ b/test/executable/setup.js @@ -0,0 +1,47 @@ +const cp = require("child_process"); +const fs = require("fs"); + +const main = async () => { + const directory = (name) => `${__dirname}/../../packages/${name}`; + const devDependencies = []; + + for (const modulo of await fs.promises.readdir(directory(""))) { + const content = JSON.parse( + await fs.promises.readFile( + `${directory(modulo)}/package.json`, + "utf8", + ), + ); + for (const dependencies of [ + content.dependencies, + content.devDependencies, + ]) + for (const [name, version] of Object.entries(dependencies ?? {})) { + if (name.includes("@nestia")) continue; + devDependencies.push([name, version]); + } + } + devDependencies.sort((a, b) => a[0].localeCompare(b[0])); + + const content = JSON.parse( + await fs.promises.readFile(`${__dirname}/../package.json`, "utf8"), + ); + content.devDependencies = {}; + for (const [name, version] of devDependencies) + content.devDependencies[name] = version; + + await fs.promises.writeFile( + `${__dirname}/../package.json`, + JSON.stringify(content, null, 2), + "utf8", + ); + + await fs.promises.rm(`${__dirname}/../node_modules`, { recursive: true }); + await fs.promises.rm(`${__dirname}/../package-lock.json`); + cp.execSync("npm install", { cwd: `${__dirname}/..`, stdio: "inherit" }); +}; + +main().catch((exp) => { + console.error(exp); + process.exit(-1); +}); diff --git a/test/executable/start.js b/test/executable/start.js new file mode 100644 index 000000000..a3c48b826 --- /dev/null +++ b/test/executable/start.js @@ -0,0 +1,90 @@ +const cp = require("child_process"); +const fs = require("fs"); + +const library = (name) => `${__dirname}/../../packages/${name}`; +const feature = (name) => `${__dirname}/../features/${name}`; + +const build = async (name) => { + process.chdir(library(name)); + + process.stdout.write(` - @nestia/${name}`); + cp.execSync("npm install", { stdio: "ignore" }); + cp.execSync("npm run build", { stdio: "ignore" }); + + const pack = JSON.parse( + await fs.promises.readFile("package.json", "utf8"), + ); + if (pack.scripts.test !== undefined) + cp.execSync("npm run test", { stdio: "ignore" }); +}; + +const execute = (name) => { + // MOVE TO THE DIRECTORY + process.chdir(feature(name)); + process.stdout.write(` - ${name}`); + + // COMPILE + const compile = () => cp.execSync("npx tsc"); + if (name.includes("error")) { + try { + TestValidator.error("compile error")(compile); + throw new Error("compile error must be occured."); + } + catch { + return; + } + } + + // GENERATE SWAGGER & SDK + const configured = fs.existsSync( + `${feature(name)}/nestia.config.ts`, + ); + const input = configured + ? null + : fs.existsSync("src/controllers") + ? "src/controllers" + : "src/**/*.controller.ts"; + + const generate = (type) => { + const argv = input !== null + ? type === "swagger" + ? `${type} ${input} --out swagger.json` + : `${type} ${input} --out src/api` + : type; + const command = `node ${library("sdk")}/lib/executable/sdk`; + cp.execSync(`${command} ${argv}`, { stdio: "ignore" }); + }; + generate("swagger"); + generate("sdk"); + compile(); + + // RUN TEST AUTOMATION PROGRAM + if (fs.existsSync("src/test")) + cp.execSync("npx ts-node src/test", { stdio: "ignore" }); +}; + +const main = async () => { + const measure = (title) => async (task) => { + const time = Date.now(); + await task(); + const elapsed = Date.now() - time; + console.log(`${title}: ${elapsed.toLocaleString()} ms`); + } + + await measure("\nTotal Elapsed Time")(async () => { + if (!process.argv.find((str) => str === "--skipBuild")) { + console.log("Build Packages"); + for (const name of await fs.promises.readdir(library(""))) + await measure("")(() => build(name)); + } + + console.log("\nTest Features"); + for (const name of await fs.promises.readdir(feature(""))) + await measure("")(async () => execute(name)); + }); +}; + +main().catch((exp) => { + console.error(exp); + process.exit(-1); +}); diff --git a/packages/sdk/demo/safe/nestia.config.ts b/test/features/body-error-generic/nestia.config.ts similarity index 70% rename from packages/sdk/demo/safe/nestia.config.ts rename to test/features/body-error-generic/nestia.config.ts index f064b1adb..2594a40d0 100644 --- a/packages/sdk/demo/safe/nestia.config.ts +++ b/test/features/body-error-generic/nestia.config.ts @@ -1,4 +1,4 @@ -import { INestiaConfig } from "../../src/INestiaConfig"; +import { INestiaConfig } from "@nestia/sdk"; export const NESTIA_CONFIG: INestiaConfig = { input: ["src/controllers"], @@ -11,8 +11,5 @@ export const NESTIA_CONFIG: INestiaConfig = { }, }, }, - compilerOptions: { - noUnusedParameters: false, - }, }; export default NESTIA_CONFIG; diff --git a/test/features/body-error-generic/src/controllers/HealthController.ts b/test/features/body-error-generic/src/controllers/HealthController.ts new file mode 100644 index 000000000..a9ce3563b --- /dev/null +++ b/test/features/body-error-generic/src/controllers/HealthController.ts @@ -0,0 +1,9 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +@Controller("health") +export class HealthController { + @core.TypedRoute.Get() + public get(): void {} +} diff --git a/test/features/body-error-generic/src/controllers/TypedBodyController.ts b/test/features/body-error-generic/src/controllers/TypedBodyController.ts new file mode 100644 index 000000000..7df596139 --- /dev/null +++ b/test/features/body-error-generic/src/controllers/TypedBodyController.ts @@ -0,0 +1,17 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +@Controller("body") +export class TypedBodyController { + @core.TypedRoute.Get("generic") + public async generic( + @core.TypedBody() input: ISomething, + ): Promise> { + return input; + } +} + +interface ISomething { + value: T; +} diff --git a/test/features/body-error-generic/tsconfig.json b/test/features/body-error-generic/tsconfig.json new file mode 100644 index 000000000..e74060a2d --- /dev/null +++ b/test/features/body-error-generic/tsconfig.json @@ -0,0 +1,101 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + /* Language and Environment */ + "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + /* Modules */ + "module": "commonjs", /* Specify what module code is generated. */// "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + "paths": { + "@nestia/core": ["../../../packages/core/src"], + "@nestia/e2e": ["../../../packages/e2e/src"], + "@nestia/fetcher": ["../../../packages/fetcher/src"], + "@nestia/sdk": ["../../../packages/sdk/src"], + "@nestia/sdk/lib/*": ["../../../packages/sdk/src/*"], + }, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. *//* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true, /* Skip type checking all .d.ts files. */ + "plugins": [ + { "transform": "typescript-transform-paths" }, + { "transform": "typia/lib/transform" }, + { "transform": "../../../packages/core/src/transform.ts" }, + ], + } + } \ No newline at end of file diff --git a/packages/sdk/demo/296/nestia.config.ts b/test/features/body-manual-assert/nestia.config.ts similarity index 70% rename from packages/sdk/demo/296/nestia.config.ts rename to test/features/body-manual-assert/nestia.config.ts index f064b1adb..2594a40d0 100644 --- a/packages/sdk/demo/296/nestia.config.ts +++ b/test/features/body-manual-assert/nestia.config.ts @@ -1,4 +1,4 @@ -import { INestiaConfig } from "../../src/INestiaConfig"; +import { INestiaConfig } from "@nestia/sdk"; export const NESTIA_CONFIG: INestiaConfig = { input: ["src/controllers"], @@ -11,8 +11,5 @@ export const NESTIA_CONFIG: INestiaConfig = { }, }, }, - compilerOptions: { - noUnusedParameters: false, - }, }; export default NESTIA_CONFIG; diff --git a/packages/sdk/demo/recursive/src/Backend.ts b/test/features/body-manual-assert/src/Backend.ts similarity index 52% rename from packages/sdk/demo/recursive/src/Backend.ts rename to test/features/body-manual-assert/src/Backend.ts index 5d000a8ed..8ab51b70f 100644 --- a/packages/sdk/demo/recursive/src/Backend.ts +++ b/test/features/body-manual-assert/src/Backend.ts @@ -1,28 +1,28 @@ -import helper from "@nestia/core"; -import * as nest from "@nestjs/common"; +import { INestApplication } from "@nestjs/common"; import { NestFactory } from "@nestjs/core"; -import { Configuration } from "./Configuration"; +import core from "@nestia/core"; export class Backend { - private application_?: nest.INestApplication; + private application_?: INestApplication; public async open(): Promise { this.application_ = await NestFactory.create( - await helper.EncryptedModule.dynamic( - __dirname, - Configuration.ENCRYPTION_PASSWORD, - ), + await core.EncryptedModule.dynamic(__dirname + "/controllers", { + key: "A".repeat(32), + iv: "B".repeat(16), + }), { logger: false }, ); - await this.application_.listen(Configuration.PORT); + await this.application_.listen(37_000); } public async close(): Promise { if (this.application_ === undefined) return; const app = this.application_; - delete this.application_; await app.close(); + + delete this.application_; } } diff --git a/packages/core/test/api/HttpError.ts b/test/features/body-manual-assert/src/api/HttpError.ts similarity index 100% rename from packages/core/test/api/HttpError.ts rename to test/features/body-manual-assert/src/api/HttpError.ts diff --git a/packages/core/test/api/IConnection.ts b/test/features/body-manual-assert/src/api/IConnection.ts similarity index 100% rename from packages/core/test/api/IConnection.ts rename to test/features/body-manual-assert/src/api/IConnection.ts diff --git a/packages/core/test/api/Primitive.ts b/test/features/body-manual-assert/src/api/Primitive.ts similarity index 100% rename from packages/core/test/api/Primitive.ts rename to test/features/body-manual-assert/src/api/Primitive.ts diff --git a/test/features/body-manual-assert/src/api/functional/body/index.ts b/test/features/body-manual-assert/src/api/functional/body/index.ts new file mode 100644 index 000000000..f28ef0e87 --- /dev/null +++ b/test/features/body-manual-assert/src/api/functional/body/index.ts @@ -0,0 +1,48 @@ +/** + * @packageDocumentation + * @module api.functional.body + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +import { Fetcher, Primitive } from "@nestia/fetcher"; +import type { IConnection } from "@nestia/fetcher"; + +import type { IBbsArticle } from "./../../structures/IBbsArticle"; + +/** + * @controller TypedBodyController.store() + * @path POST /body + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export function store + ( + connection: IConnection, + input: Primitive + ): Promise +{ + return Fetcher.fetch + ( + connection, + store.ENCRYPTED, + store.METHOD, + store.path(), + input + ); +} +export namespace store +{ + export type Input = Primitive; + export type Output = Primitive; + + export const METHOD = "POST" as const; + export const PATH: string = "/body"; + export const ENCRYPTED: Fetcher.IEncrypted = { + request: false, + response: false, + }; + + export function path(): string + { + return `/body`; + } +} \ No newline at end of file diff --git a/packages/sdk/demo/multiple-paths/src/api/functional/health/index.ts b/test/features/body-manual-assert/src/api/functional/health/index.ts similarity index 70% rename from packages/sdk/demo/multiple-paths/src/api/functional/health/index.ts rename to test/features/body-manual-assert/src/api/functional/health/index.ts index 427c34979..619581f93 100644 --- a/packages/sdk/demo/multiple-paths/src/api/functional/health/index.ts +++ b/test/features/body-manual-assert/src/api/functional/health/index.ts @@ -7,14 +7,12 @@ import { Fetcher } from "@nestia/fetcher"; import type { IConnection } from "@nestia/fetcher"; -export * as alive from "./alive"; - /** - * @controller HealthController.check() - * @path GET /health/check + * @controller HealthController.get() + * @path GET /health * @nestia Generated by Nestia - https://github.com/samchon/nestia */ -export function check +export function get ( connection: IConnection ): Promise @@ -22,16 +20,16 @@ export function check return Fetcher.fetch ( connection, - check.ENCRYPTED, - check.METHOD, - check.path() + get.ENCRYPTED, + get.METHOD, + get.path() ); } -export namespace check +export namespace get { export const METHOD = "GET" as const; - export const PATH: string = "/health/check"; + export const PATH: string = "/health"; export const ENCRYPTED: Fetcher.IEncrypted = { request: false, response: false, @@ -39,6 +37,6 @@ export namespace check export function path(): string { - return `/health/check`; + return `/health`; } } \ No newline at end of file diff --git a/test/features/body-manual-assert/src/api/functional/index.ts b/test/features/body-manual-assert/src/api/functional/index.ts new file mode 100644 index 000000000..c668415f8 --- /dev/null +++ b/test/features/body-manual-assert/src/api/functional/index.ts @@ -0,0 +1,9 @@ +/** + * @packageDocumentation + * @module api.functional + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +export * as health from "./health"; +export * as performance from "./performance"; +export * as body from "./body"; \ No newline at end of file diff --git a/test/features/body-manual-assert/src/api/functional/performance/index.ts b/test/features/body-manual-assert/src/api/functional/performance/index.ts new file mode 100644 index 000000000..9e402a44a --- /dev/null +++ b/test/features/body-manual-assert/src/api/functional/performance/index.ts @@ -0,0 +1,45 @@ +/** + * @packageDocumentation + * @module api.functional.performance + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +import { Fetcher, Primitive } from "@nestia/fetcher"; +import type { IConnection } from "@nestia/fetcher"; + +import type { IPerformance } from "./../../structures/IPerformance"; + +/** + * @controller PerformanceController.get() + * @path GET /performance + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export function get + ( + connection: IConnection + ): Promise +{ + return Fetcher.fetch + ( + connection, + get.ENCRYPTED, + get.METHOD, + get.path() + ); +} +export namespace get +{ + export type Output = Primitive; + + export const METHOD = "GET" as const; + export const PATH: string = "/performance"; + export const ENCRYPTED: Fetcher.IEncrypted = { + request: false, + response: false, + }; + + export function path(): string + { + return `/performance`; + } +} \ No newline at end of file diff --git a/packages/core/test/api/index.ts b/test/features/body-manual-assert/src/api/index.ts similarity index 100% rename from packages/core/test/api/index.ts rename to test/features/body-manual-assert/src/api/index.ts diff --git a/packages/core/test/api/module.ts b/test/features/body-manual-assert/src/api/module.ts similarity index 100% rename from packages/core/test/api/module.ts rename to test/features/body-manual-assert/src/api/module.ts diff --git a/test/features/body-manual-assert/src/api/structures/IBbsArticle.ts b/test/features/body-manual-assert/src/api/structures/IBbsArticle.ts new file mode 100644 index 000000000..aa8085b02 --- /dev/null +++ b/test/features/body-manual-assert/src/api/structures/IBbsArticle.ts @@ -0,0 +1,41 @@ +export interface IBbsArticle extends IBbsArticle.IStore { + /** + * @format uuid + */ + id: string; + + /** + * @format date-time + */ + created_at: string; +} +export namespace IBbsArticle { + export interface IStore { + /** + * @minLength 3 + * @maxLength 50 + */ + title: string; + body: string; + files: IAttachmentFile[]; + } +} + +export interface IAttachmentFile { + /** + * @minLengt 1 + * @maxLength 255 + */ + name: string | null; + + /** + * @minLength 1 + * @maxLength 8 + */ + extension: string | null; + + /** + * @format url + */ + url: string; +} diff --git a/test/features/body-manual-assert/src/api/structures/IPerformance.ts b/test/features/body-manual-assert/src/api/structures/IPerformance.ts new file mode 100644 index 000000000..a9e9336e1 --- /dev/null +++ b/test/features/body-manual-assert/src/api/structures/IPerformance.ts @@ -0,0 +1,10 @@ +/** + * Performance info. + * + * @author Samchon + */ +export interface IPerformance { + cpu: NodeJS.CpuUsage; + memory: NodeJS.MemoryUsage; + resource: NodeJS.ResourceUsage; +} diff --git a/packages/core/test/api/structures/ISystem.ts b/test/features/body-manual-assert/src/api/structures/ISystem.ts similarity index 78% rename from packages/core/test/api/structures/ISystem.ts rename to test/features/body-manual-assert/src/api/structures/ISystem.ts index 98e55cbe7..68f05ca92 100644 --- a/packages/core/test/api/structures/ISystem.ts +++ b/test/features/body-manual-assert/src/api/structures/ISystem.ts @@ -1,8 +1,3 @@ -/** - * @packageDocumentation - * @module api.structures.monitors - */ -//================================================================ /** * System Information. * @@ -20,23 +15,24 @@ export interface ISystem { arguments: string[]; /** - * Git commit information. + * Git commit info. */ commit: ISystem.ICommit; /** - * `package.json` */ + * `package.json` + */ package: ISystem.IPackage; /** - * Creation time of this system. + * Creation time of this server. */ created_at: string; } export namespace ISystem { /** - * Git commit information. + * Git commit info. */ export interface ICommit { shortHash: string; @@ -54,7 +50,7 @@ export namespace ISystem { } export namespace ICommit { /** - * Git user information. + * Git user account info. */ export interface IUser { name: string; @@ -63,23 +59,23 @@ export namespace ISystem { } /** - * NPM package information. + * NPM package info. */ export interface IPackage { name: string; version: string; description: string; + main?: string; + typings?: string; scripts: Record; repository: { type: "git"; url: string }; author: string; license: string; bugs: { url: string }; homepage: string; - devDependencies: Record; + devDependencies?: Record; dependencies: Record; publishConfig?: { registry: string }; - main?: string; - typings?: string; files?: string[]; } } diff --git a/test/features/body-manual-assert/src/controllers/HealthController.ts b/test/features/body-manual-assert/src/controllers/HealthController.ts new file mode 100644 index 000000000..a9ce3563b --- /dev/null +++ b/test/features/body-manual-assert/src/controllers/HealthController.ts @@ -0,0 +1,9 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +@Controller("health") +export class HealthController { + @core.TypedRoute.Get() + public get(): void {} +} diff --git a/test/features/body-manual-assert/src/controllers/PerformanceController.ts b/test/features/body-manual-assert/src/controllers/PerformanceController.ts new file mode 100644 index 000000000..798d64fae --- /dev/null +++ b/test/features/body-manual-assert/src/controllers/PerformanceController.ts @@ -0,0 +1,17 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +import { IPerformance } from "@api/lib/structures/IPerformance"; + +@Controller("performance") +export class PerformanceController { + @core.TypedRoute.Get() + public async get(): Promise { + return { + cpu: process.cpuUsage(), + memory: process.memoryUsage(), + resource: process.resourceUsage(), + }; + } +} diff --git a/test/features/body-manual-assert/src/controllers/TypedBodyController.ts b/test/features/body-manual-assert/src/controllers/TypedBodyController.ts new file mode 100644 index 000000000..a964ef603 --- /dev/null +++ b/test/features/body-manual-assert/src/controllers/TypedBodyController.ts @@ -0,0 +1,23 @@ +import { Controller } from "@nestjs/common"; +import typia from "typia"; + +import core from "@nestia/core"; + +import { IBbsArticle } from "@api/lib/structures/IBbsArticle"; + +@Controller("body") +export class TypedBodyController { + @core.TypedRoute.Post() + public async store( + @core.TypedBody({ + type: "assert", + assert: typia.createAssert(), + }) + input: IBbsArticle.IStore, + ): Promise { + return { + ...typia.random(), + ...input, + }; + } +} diff --git a/test/features/body-manual-assert/src/test/features/test_api_body.ts b/test/features/body-manual-assert/src/test/features/test_api_body.ts new file mode 100644 index 000000000..e22640324 --- /dev/null +++ b/test/features/body-manual-assert/src/test/features/test_api_body.ts @@ -0,0 +1,14 @@ +import typia from "typia"; + +import api from "@api"; +import { IBbsArticle } from "@api/lib/structures/IBbsArticle"; + +export const test_api_body = async ( + connection: api.IConnection, +): Promise => { + const article: IBbsArticle = await api.functional.body.store( + connection, + typia.random(), + ); + typia.assertEquals(article); +}; diff --git a/test/features/body-manual-assert/src/test/features/test_api_health_check.ts b/test/features/body-manual-assert/src/test/features/test_api_health_check.ts new file mode 100644 index 000000000..c34703c71 --- /dev/null +++ b/test/features/body-manual-assert/src/test/features/test_api_health_check.ts @@ -0,0 +1,5 @@ +import api from "@api"; + +export const test_api_monitor_health_check = ( + connection: api.IConnection, +): Promise => api.functional.health.get(connection); diff --git a/test/features/body-manual-assert/src/test/features/test_api_performance.ts b/test/features/body-manual-assert/src/test/features/test_api_performance.ts new file mode 100644 index 000000000..55b6d2ca7 --- /dev/null +++ b/test/features/body-manual-assert/src/test/features/test_api_performance.ts @@ -0,0 +1,13 @@ +import typia from "typia"; + +import api from "@api"; +import { IPerformance } from "@api/lib/structures/IPerformance"; + +export const test_api_monitor_performance = async ( + connection: api.IConnection, +): Promise => { + const performance: IPerformance = await api.functional.performance.get( + connection, + ); + typia.assert(performance); +}; diff --git a/test/features/body-manual-assert/src/test/index.ts b/test/features/body-manual-assert/src/test/index.ts new file mode 100644 index 000000000..e89842739 --- /dev/null +++ b/test/features/body-manual-assert/src/test/index.ts @@ -0,0 +1,39 @@ +import { DynamicExecutor } from "@nestia/e2e"; + +import { Backend } from "../Backend"; + +async function main(): Promise { + const server: Backend = new Backend(); + await server.open(); + + const report: DynamicExecutor.IReport = await DynamicExecutor.validate({ + prefix: "test", + parameters: () => [ + { + host: "http://127.0.0.1:37000", + encryption: { + key: "A".repeat(32), + iv: "B".repeat(16), + }, + }, + ], + })(`${__dirname}/features`); + await server.close(); + + const exceptions: Error[] = report.executions + .filter((exec) => exec.error !== null) + .map((exec) => exec.error!); + if (exceptions.length === 0) { + console.log("Success"); + console.log("Elapsed time", report.time.toLocaleString(), `ms`); + } else { + // for (const exp of exceptions) console.log(exp); + console.log("Failed"); + console.log("Elapsed time", report.time.toLocaleString(), `ms`); + process.exit(-1); + } +} +main().catch((exp) => { + console.log(exp); + process.exit(-1); +}); diff --git a/test/features/body-manual-assert/swagger.json b/test/features/body-manual-assert/swagger.json new file mode 100644 index 000000000..22afde432 --- /dev/null +++ b/test/features/body-manual-assert/swagger.json @@ -0,0 +1,619 @@ +{ + "openapi": "3.0.1", + "servers": [ + { + "url": "https://github.com/samchon/nestia", + "description": "insert your server url" + } + ], + "info": { + "version": "0.1.0", + "title": "Generated by nestia - https://github.com/samchon/nestia" + }, + "paths": { + "/health": { + "get": { + "tags": [], + "parameters": [], + "responses": { + "200": { + "description": "", + "x-nestia-encrypted": false + } + }, + "description": "", + "x-nestia-namespace": "health.get", + "x-nestia-jsDocTags": [] + } + }, + "/performance": { + "get": { + "tags": [], + "parameters": [], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IPerformance" + } + } + }, + "x-nestia-encrypted": false + } + }, + "description": "", + "x-nestia-namespace": "performance.get", + "x-nestia-jsDocTags": [] + } + }, + "/body": { + "post": { + "tags": [], + "parameters": [], + "requestBody": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IBbsArticle.IStore" + } + } + }, + "required": true, + "x-nestia-encrypted": false + }, + "responses": { + "201": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IBbsArticle" + } + } + }, + "x-nestia-encrypted": false + } + }, + "description": "", + "x-nestia-namespace": "body.store", + "x-nestia-jsDocTags": [] + } + } + }, + "components": { + "schemas": { + "IPerformance": { + "type": "object", + "properties": { + "cpu": { + "$ref": "#/components/schemas/_singlequote_process_singlequote_.global.NodeJS.CpuUsage", + "x-typia-required": true, + "x-typia-optional": false + }, + "memory": { + "$ref": "#/components/schemas/_singlequote_process_singlequote_.global.NodeJS.MemoryUsage", + "x-typia-required": true, + "x-typia-optional": false + }, + "resource": { + "$ref": "#/components/schemas/_singlequote_process_singlequote_.global.NodeJS.ResourceUsage", + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "cpu", + "memory", + "resource" + ], + "description": "Performance info.", + "x-typia-jsDocTags": [ + { + "name": "author", + "text": [ + { + "text": "Samchon", + "kind": "text" + } + ] + } + ] + }, + "_singlequote_process_singlequote_.global.NodeJS.CpuUsage": { + "type": "object", + "properties": { + "user": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "system": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "user", + "system" + ], + "x-typia-jsDocTags": [] + }, + "_singlequote_process_singlequote_.global.NodeJS.MemoryUsage": { + "type": "object", + "properties": { + "rss": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "heapTotal": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "heapUsed": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "external": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "arrayBuffers": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "rss", + "heapTotal", + "heapUsed", + "external", + "arrayBuffers" + ], + "x-typia-jsDocTags": [] + }, + "_singlequote_process_singlequote_.global.NodeJS.ResourceUsage": { + "type": "object", + "properties": { + "fsRead": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "fsWrite": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "involuntaryContextSwitches": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "ipcReceived": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "ipcSent": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "majorPageFault": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "maxRSS": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "minorPageFault": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "sharedMemorySize": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "signalsCount": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "swappedOut": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "systemCPUTime": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "unsharedDataSize": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "unsharedStackSize": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "userCPUTime": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "voluntaryContextSwitches": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "fsRead", + "fsWrite", + "involuntaryContextSwitches", + "ipcReceived", + "ipcSent", + "majorPageFault", + "maxRSS", + "minorPageFault", + "sharedMemorySize", + "signalsCount", + "swappedOut", + "systemCPUTime", + "unsharedDataSize", + "unsharedStackSize", + "userCPUTime", + "voluntaryContextSwitches" + ], + "x-typia-jsDocTags": [] + }, + "IBbsArticle.IStore": { + "type": "object", + "properties": { + "title": { + "type": "string", + "nullable": false, + "x-typia-metaTags": [ + { + "kind": "minLength", + "value": 3 + }, + { + "kind": "maxLength", + "value": 50 + } + ], + "x-typia-jsDocTags": [ + { + "name": "minLength", + "text": [ + { + "text": "3", + "kind": "text" + } + ] + }, + { + "name": "maxLength", + "text": [ + { + "text": "50", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "minLength": 3, + "maxLength": 50 + }, + "body": { + "type": "string", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "files": { + "type": "array", + "items": { + "$ref": "#/components/schemas/IAttachmentFile", + "x-typia-required": true, + "x-typia-optional": false + }, + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "title", + "body", + "files" + ], + "x-typia-jsDocTags": [] + }, + "IAttachmentFile": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "x-typia-metaTags": [ + { + "kind": "maxLength", + "value": 255 + } + ], + "x-typia-jsDocTags": [ + { + "name": "minLengt", + "text": [ + { + "text": "1", + "kind": "text" + } + ] + }, + { + "name": "maxLength", + "text": [ + { + "text": "255", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "maxLength": 255 + }, + "extension": { + "type": "string", + "nullable": true, + "x-typia-metaTags": [ + { + "kind": "minLength", + "value": 1 + }, + { + "kind": "maxLength", + "value": 8 + } + ], + "x-typia-jsDocTags": [ + { + "name": "minLength", + "text": [ + { + "text": "1", + "kind": "text" + } + ] + }, + { + "name": "maxLength", + "text": [ + { + "text": "8", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "minLength": 1, + "maxLength": 8 + }, + "url": { + "type": "string", + "nullable": false, + "x-typia-metaTags": [ + { + "kind": "format", + "value": "url" + } + ], + "x-typia-jsDocTags": [ + { + "name": "format", + "text": [ + { + "text": "url", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "format": "url" + } + }, + "nullable": false, + "required": [ + "name", + "extension", + "url" + ], + "x-typia-jsDocTags": [] + }, + "IBbsArticle": { + "type": "object", + "properties": { + "id": { + "type": "string", + "nullable": false, + "x-typia-metaTags": [ + { + "kind": "format", + "value": "uuid" + } + ], + "x-typia-jsDocTags": [ + { + "name": "format", + "text": [ + { + "text": "uuid", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "format": "uuid" + }, + "created_at": { + "type": "string", + "nullable": false, + "x-typia-metaTags": [ + { + "kind": "format", + "value": "datetime" + } + ], + "x-typia-jsDocTags": [ + { + "name": "format", + "text": [ + { + "text": "date-time", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "format": "date-time" + }, + "title": { + "type": "string", + "nullable": false, + "x-typia-metaTags": [ + { + "kind": "minLength", + "value": 3 + }, + { + "kind": "maxLength", + "value": 50 + } + ], + "x-typia-jsDocTags": [ + { + "name": "minLength", + "text": [ + { + "text": "3", + "kind": "text" + } + ] + }, + { + "name": "maxLength", + "text": [ + { + "text": "50", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "minLength": 3, + "maxLength": 50 + }, + "body": { + "type": "string", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "files": { + "type": "array", + "items": { + "$ref": "#/components/schemas/IAttachmentFile", + "x-typia-required": true, + "x-typia-optional": false + }, + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "id", + "created_at", + "title", + "body", + "files" + ], + "x-typia-jsDocTags": [] + } + }, + "securitySchemes": { + "bearer": { + "type": "apiKey", + "in": "header", + "name": "Authorization" + } + } + }, + "security": [ + { + "bearer": [] + } + ] +} \ No newline at end of file diff --git a/test/features/body-manual-assert/tsconfig.json b/test/features/body-manual-assert/tsconfig.json new file mode 100644 index 000000000..e5fe47a95 --- /dev/null +++ b/test/features/body-manual-assert/tsconfig.json @@ -0,0 +1,103 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + /* Language and Environment */ + "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + /* Modules */ + "module": "commonjs", /* Specify what module code is generated. */// "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + "paths": { + "@nestia/core": ["../../../packages/core/src"], + "@nestia/e2e": ["../../../packages/e2e/src"], + "@nestia/fetcher": ["../../../packages/fetcher/src"], + "@nestia/sdk": ["../../../packages/sdk/src"], + "@nestia/sdk/lib/*": ["../../../packages/sdk/src/*"], + "@api": ["./src/api"], + "@api/lib/*": ["./src/api/*"], + }, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. *//* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true, /* Skip type checking all .d.ts files. */ + "plugins": [ + { "transform": "typescript-transform-paths" }, + { "transform": "typia/lib/transform" }, + { "transform": "../../../packages/core/src/transform.ts" }, + ], + } + } \ No newline at end of file diff --git a/test/features/body-manual-is/nestia.config.ts b/test/features/body-manual-is/nestia.config.ts new file mode 100644 index 000000000..2594a40d0 --- /dev/null +++ b/test/features/body-manual-is/nestia.config.ts @@ -0,0 +1,15 @@ +import { INestiaConfig } from "@nestia/sdk"; + +export const NESTIA_CONFIG: INestiaConfig = { + input: ["src/controllers"], + output: "src/api", + swagger: { + output: "swagger.json", + security: { + bearer: { + type: "apiKey", + }, + }, + }, +}; +export default NESTIA_CONFIG; diff --git a/packages/sdk/demo/176/src/Backend.ts b/test/features/body-manual-is/src/Backend.ts similarity index 51% rename from packages/sdk/demo/176/src/Backend.ts rename to test/features/body-manual-is/src/Backend.ts index 4507166f0..8ab51b70f 100644 --- a/packages/sdk/demo/176/src/Backend.ts +++ b/test/features/body-manual-is/src/Backend.ts @@ -1,28 +1,28 @@ -import helper from "@nestia/core"; -import * as nest from "@nestjs/common"; +import { INestApplication } from "@nestjs/common"; import { NestFactory } from "@nestjs/core"; -import { Configuration } from "./Configuration"; +import core from "@nestia/core"; export class Backend { - private application_?: nest.INestApplication; + private application_?: INestApplication; public async open(): Promise { this.application_ = await NestFactory.create( - await helper.EncryptedModule.dynamic( - __dirname + "/controllers", - Configuration.ENCRYPTION_PASSWORD, - ), + await core.EncryptedModule.dynamic(__dirname + "/controllers", { + key: "A".repeat(32), + iv: "B".repeat(16), + }), { logger: false }, ); - await this.application_.listen(Configuration.PORT); + await this.application_.listen(37_000); } public async close(): Promise { if (this.application_ === undefined) return; const app = this.application_; - delete this.application_; await app.close(); + + delete this.application_; } } diff --git a/packages/sdk/demo/176/src/api/HttpError.ts b/test/features/body-manual-is/src/api/HttpError.ts similarity index 100% rename from packages/sdk/demo/176/src/api/HttpError.ts rename to test/features/body-manual-is/src/api/HttpError.ts diff --git a/packages/sdk/demo/176/src/api/IConnection.ts b/test/features/body-manual-is/src/api/IConnection.ts similarity index 100% rename from packages/sdk/demo/176/src/api/IConnection.ts rename to test/features/body-manual-is/src/api/IConnection.ts diff --git a/packages/sdk/demo/176/src/api/Primitive.ts b/test/features/body-manual-is/src/api/Primitive.ts similarity index 100% rename from packages/sdk/demo/176/src/api/Primitive.ts rename to test/features/body-manual-is/src/api/Primitive.ts diff --git a/test/features/body-manual-is/src/api/functional/body/index.ts b/test/features/body-manual-is/src/api/functional/body/index.ts new file mode 100644 index 000000000..f28ef0e87 --- /dev/null +++ b/test/features/body-manual-is/src/api/functional/body/index.ts @@ -0,0 +1,48 @@ +/** + * @packageDocumentation + * @module api.functional.body + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +import { Fetcher, Primitive } from "@nestia/fetcher"; +import type { IConnection } from "@nestia/fetcher"; + +import type { IBbsArticle } from "./../../structures/IBbsArticle"; + +/** + * @controller TypedBodyController.store() + * @path POST /body + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export function store + ( + connection: IConnection, + input: Primitive + ): Promise +{ + return Fetcher.fetch + ( + connection, + store.ENCRYPTED, + store.METHOD, + store.path(), + input + ); +} +export namespace store +{ + export type Input = Primitive; + export type Output = Primitive; + + export const METHOD = "POST" as const; + export const PATH: string = "/body"; + export const ENCRYPTED: Fetcher.IEncrypted = { + request: false, + response: false, + }; + + export function path(): string + { + return `/body`; + } +} \ No newline at end of file diff --git a/packages/sdk/demo/multiple-paths/src/api/functional/health/alive/index.ts b/test/features/body-manual-is/src/api/functional/health/index.ts similarity index 68% rename from packages/sdk/demo/multiple-paths/src/api/functional/health/alive/index.ts rename to test/features/body-manual-is/src/api/functional/health/index.ts index 7f3646f84..619581f93 100644 --- a/packages/sdk/demo/multiple-paths/src/api/functional/health/alive/index.ts +++ b/test/features/body-manual-is/src/api/functional/health/index.ts @@ -1,6 +1,6 @@ /** * @packageDocumentation - * @module api.functional.health.alive + * @module api.functional.health * @nestia Generated by Nestia - https://github.com/samchon/nestia */ //================================================================ @@ -8,11 +8,11 @@ import { Fetcher } from "@nestia/fetcher"; import type { IConnection } from "@nestia/fetcher"; /** - * @controller HealthController.check() - * @path GET /health/alive + * @controller HealthController.get() + * @path GET /health * @nestia Generated by Nestia - https://github.com/samchon/nestia */ -export function check +export function get ( connection: IConnection ): Promise @@ -20,16 +20,16 @@ export function check return Fetcher.fetch ( connection, - check.ENCRYPTED, - check.METHOD, - check.path() + get.ENCRYPTED, + get.METHOD, + get.path() ); } -export namespace check +export namespace get { export const METHOD = "GET" as const; - export const PATH: string = "/health/alive"; + export const PATH: string = "/health"; export const ENCRYPTED: Fetcher.IEncrypted = { request: false, response: false, @@ -37,6 +37,6 @@ export namespace check export function path(): string { - return `/health/alive`; + return `/health`; } } \ No newline at end of file diff --git a/test/features/body-manual-is/src/api/functional/index.ts b/test/features/body-manual-is/src/api/functional/index.ts new file mode 100644 index 000000000..c668415f8 --- /dev/null +++ b/test/features/body-manual-is/src/api/functional/index.ts @@ -0,0 +1,9 @@ +/** + * @packageDocumentation + * @module api.functional + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +export * as health from "./health"; +export * as performance from "./performance"; +export * as body from "./body"; \ No newline at end of file diff --git a/test/features/body-manual-is/src/api/functional/performance/index.ts b/test/features/body-manual-is/src/api/functional/performance/index.ts new file mode 100644 index 000000000..9e402a44a --- /dev/null +++ b/test/features/body-manual-is/src/api/functional/performance/index.ts @@ -0,0 +1,45 @@ +/** + * @packageDocumentation + * @module api.functional.performance + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +import { Fetcher, Primitive } from "@nestia/fetcher"; +import type { IConnection } from "@nestia/fetcher"; + +import type { IPerformance } from "./../../structures/IPerformance"; + +/** + * @controller PerformanceController.get() + * @path GET /performance + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export function get + ( + connection: IConnection + ): Promise +{ + return Fetcher.fetch + ( + connection, + get.ENCRYPTED, + get.METHOD, + get.path() + ); +} +export namespace get +{ + export type Output = Primitive; + + export const METHOD = "GET" as const; + export const PATH: string = "/performance"; + export const ENCRYPTED: Fetcher.IEncrypted = { + request: false, + response: false, + }; + + export function path(): string + { + return `/performance`; + } +} \ No newline at end of file diff --git a/test/features/body-manual-is/src/api/index.ts b/test/features/body-manual-is/src/api/index.ts new file mode 100644 index 000000000..1896c4fbd --- /dev/null +++ b/test/features/body-manual-is/src/api/index.ts @@ -0,0 +1,5 @@ +import * as api from "./module"; + +export * from "./module"; + +export default api; diff --git a/packages/sdk/demo/296/src/api/module.ts b/test/features/body-manual-is/src/api/module.ts similarity index 53% rename from packages/sdk/demo/296/src/api/module.ts rename to test/features/body-manual-is/src/api/module.ts index b731ce60c..00239fb3b 100644 --- a/packages/sdk/demo/296/src/api/module.ts +++ b/test/features/body-manual-is/src/api/module.ts @@ -1,8 +1,3 @@ -/** - * @packageDocumentation - * @module api - */ -//================================================================ export * from "./IConnection"; export * from "./Primitive"; export * from "./HttpError"; diff --git a/test/features/body-manual-is/src/api/structures/IBbsArticle.ts b/test/features/body-manual-is/src/api/structures/IBbsArticle.ts new file mode 100644 index 000000000..aa8085b02 --- /dev/null +++ b/test/features/body-manual-is/src/api/structures/IBbsArticle.ts @@ -0,0 +1,41 @@ +export interface IBbsArticle extends IBbsArticle.IStore { + /** + * @format uuid + */ + id: string; + + /** + * @format date-time + */ + created_at: string; +} +export namespace IBbsArticle { + export interface IStore { + /** + * @minLength 3 + * @maxLength 50 + */ + title: string; + body: string; + files: IAttachmentFile[]; + } +} + +export interface IAttachmentFile { + /** + * @minLengt 1 + * @maxLength 255 + */ + name: string | null; + + /** + * @minLength 1 + * @maxLength 8 + */ + extension: string | null; + + /** + * @format url + */ + url: string; +} diff --git a/test/features/body-manual-is/src/api/structures/IPerformance.ts b/test/features/body-manual-is/src/api/structures/IPerformance.ts new file mode 100644 index 000000000..a9e9336e1 --- /dev/null +++ b/test/features/body-manual-is/src/api/structures/IPerformance.ts @@ -0,0 +1,10 @@ +/** + * Performance info. + * + * @author Samchon + */ +export interface IPerformance { + cpu: NodeJS.CpuUsage; + memory: NodeJS.MemoryUsage; + resource: NodeJS.ResourceUsage; +} diff --git a/test/features/body-manual-is/src/api/structures/ISystem.ts b/test/features/body-manual-is/src/api/structures/ISystem.ts new file mode 100644 index 000000000..68f05ca92 --- /dev/null +++ b/test/features/body-manual-is/src/api/structures/ISystem.ts @@ -0,0 +1,81 @@ +/** + * System Information. + * + * @author Jeongho Nam + */ +export interface ISystem { + /** + * Random Unique ID. + */ + uid: number; + + /** + * `process.argv` + */ + arguments: string[]; + + /** + * Git commit info. + */ + commit: ISystem.ICommit; + + /** + * `package.json` + */ + package: ISystem.IPackage; + + /** + * Creation time of this server. + */ + created_at: string; +} + +export namespace ISystem { + /** + * Git commit info. + */ + export interface ICommit { + shortHash: string; + branch: string; + hash: string; + subject: string; + sanitizedSubject: string; + body: string; + author: ICommit.IUser; + committer: ICommit.IUser; + authored_at: string; + commited_at: string; + notes?: string; + tags: string[]; + } + export namespace ICommit { + /** + * Git user account info. + */ + export interface IUser { + name: string; + email: string; + } + } + + /** + * NPM package info. + */ + export interface IPackage { + name: string; + version: string; + description: string; + main?: string; + typings?: string; + scripts: Record; + repository: { type: "git"; url: string }; + author: string; + license: string; + bugs: { url: string }; + homepage: string; + devDependencies?: Record; + dependencies: Record; + publishConfig?: { registry: string }; + files?: string[]; + } +} diff --git a/test/features/body-manual-is/src/controllers/HealthController.ts b/test/features/body-manual-is/src/controllers/HealthController.ts new file mode 100644 index 000000000..a9ce3563b --- /dev/null +++ b/test/features/body-manual-is/src/controllers/HealthController.ts @@ -0,0 +1,9 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +@Controller("health") +export class HealthController { + @core.TypedRoute.Get() + public get(): void {} +} diff --git a/test/features/body-manual-is/src/controllers/PerformanceController.ts b/test/features/body-manual-is/src/controllers/PerformanceController.ts new file mode 100644 index 000000000..798d64fae --- /dev/null +++ b/test/features/body-manual-is/src/controllers/PerformanceController.ts @@ -0,0 +1,17 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +import { IPerformance } from "@api/lib/structures/IPerformance"; + +@Controller("performance") +export class PerformanceController { + @core.TypedRoute.Get() + public async get(): Promise { + return { + cpu: process.cpuUsage(), + memory: process.memoryUsage(), + resource: process.resourceUsage(), + }; + } +} diff --git a/test/features/body-manual-is/src/controllers/TypedBodyController.ts b/test/features/body-manual-is/src/controllers/TypedBodyController.ts new file mode 100644 index 000000000..655d241bb --- /dev/null +++ b/test/features/body-manual-is/src/controllers/TypedBodyController.ts @@ -0,0 +1,23 @@ +import { Controller } from "@nestjs/common"; +import typia from "typia"; + +import core from "@nestia/core"; + +import { IBbsArticle } from "@api/lib/structures/IBbsArticle"; + +@Controller("body") +export class TypedBodyController { + @core.TypedRoute.Post() + public async store( + @core.TypedBody({ + type: "is", + is: typia.createIs(), + }) + input: IBbsArticle.IStore, + ): Promise { + return { + ...typia.random(), + ...input, + }; + } +} diff --git a/test/features/body-manual-is/src/test/features/test_api_body.ts b/test/features/body-manual-is/src/test/features/test_api_body.ts new file mode 100644 index 000000000..e22640324 --- /dev/null +++ b/test/features/body-manual-is/src/test/features/test_api_body.ts @@ -0,0 +1,14 @@ +import typia from "typia"; + +import api from "@api"; +import { IBbsArticle } from "@api/lib/structures/IBbsArticle"; + +export const test_api_body = async ( + connection: api.IConnection, +): Promise => { + const article: IBbsArticle = await api.functional.body.store( + connection, + typia.random(), + ); + typia.assertEquals(article); +}; diff --git a/test/features/body-manual-is/src/test/features/test_api_health_check.ts b/test/features/body-manual-is/src/test/features/test_api_health_check.ts new file mode 100644 index 000000000..c34703c71 --- /dev/null +++ b/test/features/body-manual-is/src/test/features/test_api_health_check.ts @@ -0,0 +1,5 @@ +import api from "@api"; + +export const test_api_monitor_health_check = ( + connection: api.IConnection, +): Promise => api.functional.health.get(connection); diff --git a/test/features/body-manual-is/src/test/features/test_api_performance.ts b/test/features/body-manual-is/src/test/features/test_api_performance.ts new file mode 100644 index 000000000..55b6d2ca7 --- /dev/null +++ b/test/features/body-manual-is/src/test/features/test_api_performance.ts @@ -0,0 +1,13 @@ +import typia from "typia"; + +import api from "@api"; +import { IPerformance } from "@api/lib/structures/IPerformance"; + +export const test_api_monitor_performance = async ( + connection: api.IConnection, +): Promise => { + const performance: IPerformance = await api.functional.performance.get( + connection, + ); + typia.assert(performance); +}; diff --git a/test/features/body-manual-is/src/test/index.ts b/test/features/body-manual-is/src/test/index.ts new file mode 100644 index 000000000..e89842739 --- /dev/null +++ b/test/features/body-manual-is/src/test/index.ts @@ -0,0 +1,39 @@ +import { DynamicExecutor } from "@nestia/e2e"; + +import { Backend } from "../Backend"; + +async function main(): Promise { + const server: Backend = new Backend(); + await server.open(); + + const report: DynamicExecutor.IReport = await DynamicExecutor.validate({ + prefix: "test", + parameters: () => [ + { + host: "http://127.0.0.1:37000", + encryption: { + key: "A".repeat(32), + iv: "B".repeat(16), + }, + }, + ], + })(`${__dirname}/features`); + await server.close(); + + const exceptions: Error[] = report.executions + .filter((exec) => exec.error !== null) + .map((exec) => exec.error!); + if (exceptions.length === 0) { + console.log("Success"); + console.log("Elapsed time", report.time.toLocaleString(), `ms`); + } else { + // for (const exp of exceptions) console.log(exp); + console.log("Failed"); + console.log("Elapsed time", report.time.toLocaleString(), `ms`); + process.exit(-1); + } +} +main().catch((exp) => { + console.log(exp); + process.exit(-1); +}); diff --git a/test/features/body-manual-is/swagger.json b/test/features/body-manual-is/swagger.json new file mode 100644 index 000000000..22afde432 --- /dev/null +++ b/test/features/body-manual-is/swagger.json @@ -0,0 +1,619 @@ +{ + "openapi": "3.0.1", + "servers": [ + { + "url": "https://github.com/samchon/nestia", + "description": "insert your server url" + } + ], + "info": { + "version": "0.1.0", + "title": "Generated by nestia - https://github.com/samchon/nestia" + }, + "paths": { + "/health": { + "get": { + "tags": [], + "parameters": [], + "responses": { + "200": { + "description": "", + "x-nestia-encrypted": false + } + }, + "description": "", + "x-nestia-namespace": "health.get", + "x-nestia-jsDocTags": [] + } + }, + "/performance": { + "get": { + "tags": [], + "parameters": [], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IPerformance" + } + } + }, + "x-nestia-encrypted": false + } + }, + "description": "", + "x-nestia-namespace": "performance.get", + "x-nestia-jsDocTags": [] + } + }, + "/body": { + "post": { + "tags": [], + "parameters": [], + "requestBody": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IBbsArticle.IStore" + } + } + }, + "required": true, + "x-nestia-encrypted": false + }, + "responses": { + "201": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IBbsArticle" + } + } + }, + "x-nestia-encrypted": false + } + }, + "description": "", + "x-nestia-namespace": "body.store", + "x-nestia-jsDocTags": [] + } + } + }, + "components": { + "schemas": { + "IPerformance": { + "type": "object", + "properties": { + "cpu": { + "$ref": "#/components/schemas/_singlequote_process_singlequote_.global.NodeJS.CpuUsage", + "x-typia-required": true, + "x-typia-optional": false + }, + "memory": { + "$ref": "#/components/schemas/_singlequote_process_singlequote_.global.NodeJS.MemoryUsage", + "x-typia-required": true, + "x-typia-optional": false + }, + "resource": { + "$ref": "#/components/schemas/_singlequote_process_singlequote_.global.NodeJS.ResourceUsage", + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "cpu", + "memory", + "resource" + ], + "description": "Performance info.", + "x-typia-jsDocTags": [ + { + "name": "author", + "text": [ + { + "text": "Samchon", + "kind": "text" + } + ] + } + ] + }, + "_singlequote_process_singlequote_.global.NodeJS.CpuUsage": { + "type": "object", + "properties": { + "user": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "system": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "user", + "system" + ], + "x-typia-jsDocTags": [] + }, + "_singlequote_process_singlequote_.global.NodeJS.MemoryUsage": { + "type": "object", + "properties": { + "rss": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "heapTotal": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "heapUsed": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "external": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "arrayBuffers": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "rss", + "heapTotal", + "heapUsed", + "external", + "arrayBuffers" + ], + "x-typia-jsDocTags": [] + }, + "_singlequote_process_singlequote_.global.NodeJS.ResourceUsage": { + "type": "object", + "properties": { + "fsRead": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "fsWrite": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "involuntaryContextSwitches": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "ipcReceived": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "ipcSent": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "majorPageFault": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "maxRSS": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "minorPageFault": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "sharedMemorySize": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "signalsCount": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "swappedOut": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "systemCPUTime": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "unsharedDataSize": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "unsharedStackSize": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "userCPUTime": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "voluntaryContextSwitches": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "fsRead", + "fsWrite", + "involuntaryContextSwitches", + "ipcReceived", + "ipcSent", + "majorPageFault", + "maxRSS", + "minorPageFault", + "sharedMemorySize", + "signalsCount", + "swappedOut", + "systemCPUTime", + "unsharedDataSize", + "unsharedStackSize", + "userCPUTime", + "voluntaryContextSwitches" + ], + "x-typia-jsDocTags": [] + }, + "IBbsArticle.IStore": { + "type": "object", + "properties": { + "title": { + "type": "string", + "nullable": false, + "x-typia-metaTags": [ + { + "kind": "minLength", + "value": 3 + }, + { + "kind": "maxLength", + "value": 50 + } + ], + "x-typia-jsDocTags": [ + { + "name": "minLength", + "text": [ + { + "text": "3", + "kind": "text" + } + ] + }, + { + "name": "maxLength", + "text": [ + { + "text": "50", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "minLength": 3, + "maxLength": 50 + }, + "body": { + "type": "string", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "files": { + "type": "array", + "items": { + "$ref": "#/components/schemas/IAttachmentFile", + "x-typia-required": true, + "x-typia-optional": false + }, + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "title", + "body", + "files" + ], + "x-typia-jsDocTags": [] + }, + "IAttachmentFile": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "x-typia-metaTags": [ + { + "kind": "maxLength", + "value": 255 + } + ], + "x-typia-jsDocTags": [ + { + "name": "minLengt", + "text": [ + { + "text": "1", + "kind": "text" + } + ] + }, + { + "name": "maxLength", + "text": [ + { + "text": "255", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "maxLength": 255 + }, + "extension": { + "type": "string", + "nullable": true, + "x-typia-metaTags": [ + { + "kind": "minLength", + "value": 1 + }, + { + "kind": "maxLength", + "value": 8 + } + ], + "x-typia-jsDocTags": [ + { + "name": "minLength", + "text": [ + { + "text": "1", + "kind": "text" + } + ] + }, + { + "name": "maxLength", + "text": [ + { + "text": "8", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "minLength": 1, + "maxLength": 8 + }, + "url": { + "type": "string", + "nullable": false, + "x-typia-metaTags": [ + { + "kind": "format", + "value": "url" + } + ], + "x-typia-jsDocTags": [ + { + "name": "format", + "text": [ + { + "text": "url", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "format": "url" + } + }, + "nullable": false, + "required": [ + "name", + "extension", + "url" + ], + "x-typia-jsDocTags": [] + }, + "IBbsArticle": { + "type": "object", + "properties": { + "id": { + "type": "string", + "nullable": false, + "x-typia-metaTags": [ + { + "kind": "format", + "value": "uuid" + } + ], + "x-typia-jsDocTags": [ + { + "name": "format", + "text": [ + { + "text": "uuid", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "format": "uuid" + }, + "created_at": { + "type": "string", + "nullable": false, + "x-typia-metaTags": [ + { + "kind": "format", + "value": "datetime" + } + ], + "x-typia-jsDocTags": [ + { + "name": "format", + "text": [ + { + "text": "date-time", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "format": "date-time" + }, + "title": { + "type": "string", + "nullable": false, + "x-typia-metaTags": [ + { + "kind": "minLength", + "value": 3 + }, + { + "kind": "maxLength", + "value": 50 + } + ], + "x-typia-jsDocTags": [ + { + "name": "minLength", + "text": [ + { + "text": "3", + "kind": "text" + } + ] + }, + { + "name": "maxLength", + "text": [ + { + "text": "50", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "minLength": 3, + "maxLength": 50 + }, + "body": { + "type": "string", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "files": { + "type": "array", + "items": { + "$ref": "#/components/schemas/IAttachmentFile", + "x-typia-required": true, + "x-typia-optional": false + }, + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "id", + "created_at", + "title", + "body", + "files" + ], + "x-typia-jsDocTags": [] + } + }, + "securitySchemes": { + "bearer": { + "type": "apiKey", + "in": "header", + "name": "Authorization" + } + } + }, + "security": [ + { + "bearer": [] + } + ] +} \ No newline at end of file diff --git a/test/features/body-manual-is/tsconfig.json b/test/features/body-manual-is/tsconfig.json new file mode 100644 index 000000000..e5fe47a95 --- /dev/null +++ b/test/features/body-manual-is/tsconfig.json @@ -0,0 +1,103 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + /* Language and Environment */ + "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + /* Modules */ + "module": "commonjs", /* Specify what module code is generated. */// "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + "paths": { + "@nestia/core": ["../../../packages/core/src"], + "@nestia/e2e": ["../../../packages/e2e/src"], + "@nestia/fetcher": ["../../../packages/fetcher/src"], + "@nestia/sdk": ["../../../packages/sdk/src"], + "@nestia/sdk/lib/*": ["../../../packages/sdk/src/*"], + "@api": ["./src/api"], + "@api/lib/*": ["./src/api/*"], + }, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. *//* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true, /* Skip type checking all .d.ts files. */ + "plugins": [ + { "transform": "typescript-transform-paths" }, + { "transform": "typia/lib/transform" }, + { "transform": "../../../packages/core/src/transform.ts" }, + ], + } + } \ No newline at end of file diff --git a/test/features/body-manual-validate/nestia.config.ts b/test/features/body-manual-validate/nestia.config.ts new file mode 100644 index 000000000..2594a40d0 --- /dev/null +++ b/test/features/body-manual-validate/nestia.config.ts @@ -0,0 +1,15 @@ +import { INestiaConfig } from "@nestia/sdk"; + +export const NESTIA_CONFIG: INestiaConfig = { + input: ["src/controllers"], + output: "src/api", + swagger: { + output: "swagger.json", + security: { + bearer: { + type: "apiKey", + }, + }, + }, +}; +export default NESTIA_CONFIG; diff --git a/packages/sdk/demo/296/src/Backend.ts b/test/features/body-manual-validate/src/Backend.ts similarity index 51% rename from packages/sdk/demo/296/src/Backend.ts rename to test/features/body-manual-validate/src/Backend.ts index 4507166f0..8ab51b70f 100644 --- a/packages/sdk/demo/296/src/Backend.ts +++ b/test/features/body-manual-validate/src/Backend.ts @@ -1,28 +1,28 @@ -import helper from "@nestia/core"; -import * as nest from "@nestjs/common"; +import { INestApplication } from "@nestjs/common"; import { NestFactory } from "@nestjs/core"; -import { Configuration } from "./Configuration"; +import core from "@nestia/core"; export class Backend { - private application_?: nest.INestApplication; + private application_?: INestApplication; public async open(): Promise { this.application_ = await NestFactory.create( - await helper.EncryptedModule.dynamic( - __dirname + "/controllers", - Configuration.ENCRYPTION_PASSWORD, - ), + await core.EncryptedModule.dynamic(__dirname + "/controllers", { + key: "A".repeat(32), + iv: "B".repeat(16), + }), { logger: false }, ); - await this.application_.listen(Configuration.PORT); + await this.application_.listen(37_000); } public async close(): Promise { if (this.application_ === undefined) return; const app = this.application_; - delete this.application_; await app.close(); + + delete this.application_; } } diff --git a/packages/sdk/demo/296/src/api/HttpError.ts b/test/features/body-manual-validate/src/api/HttpError.ts similarity index 100% rename from packages/sdk/demo/296/src/api/HttpError.ts rename to test/features/body-manual-validate/src/api/HttpError.ts diff --git a/packages/sdk/demo/296/src/api/IConnection.ts b/test/features/body-manual-validate/src/api/IConnection.ts similarity index 100% rename from packages/sdk/demo/296/src/api/IConnection.ts rename to test/features/body-manual-validate/src/api/IConnection.ts diff --git a/packages/sdk/demo/296/src/api/Primitive.ts b/test/features/body-manual-validate/src/api/Primitive.ts similarity index 100% rename from packages/sdk/demo/296/src/api/Primitive.ts rename to test/features/body-manual-validate/src/api/Primitive.ts diff --git a/test/features/body-manual-validate/src/api/functional/body/index.ts b/test/features/body-manual-validate/src/api/functional/body/index.ts new file mode 100644 index 000000000..f28ef0e87 --- /dev/null +++ b/test/features/body-manual-validate/src/api/functional/body/index.ts @@ -0,0 +1,48 @@ +/** + * @packageDocumentation + * @module api.functional.body + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +import { Fetcher, Primitive } from "@nestia/fetcher"; +import type { IConnection } from "@nestia/fetcher"; + +import type { IBbsArticle } from "./../../structures/IBbsArticle"; + +/** + * @controller TypedBodyController.store() + * @path POST /body + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export function store + ( + connection: IConnection, + input: Primitive + ): Promise +{ + return Fetcher.fetch + ( + connection, + store.ENCRYPTED, + store.METHOD, + store.path(), + input + ); +} +export namespace store +{ + export type Input = Primitive; + export type Output = Primitive; + + export const METHOD = "POST" as const; + export const PATH: string = "/body"; + export const ENCRYPTED: Fetcher.IEncrypted = { + request: false, + response: false, + }; + + export function path(): string + { + return `/body`; + } +} \ No newline at end of file diff --git a/packages/sdk/demo/multiple-paths/src/api/functional/healthy/alive/index.ts b/test/features/body-manual-validate/src/api/functional/health/index.ts similarity index 68% rename from packages/sdk/demo/multiple-paths/src/api/functional/healthy/alive/index.ts rename to test/features/body-manual-validate/src/api/functional/health/index.ts index 201f9cd76..619581f93 100644 --- a/packages/sdk/demo/multiple-paths/src/api/functional/healthy/alive/index.ts +++ b/test/features/body-manual-validate/src/api/functional/health/index.ts @@ -1,6 +1,6 @@ /** * @packageDocumentation - * @module api.functional.healthy.alive + * @module api.functional.health * @nestia Generated by Nestia - https://github.com/samchon/nestia */ //================================================================ @@ -8,11 +8,11 @@ import { Fetcher } from "@nestia/fetcher"; import type { IConnection } from "@nestia/fetcher"; /** - * @controller HealthController.check() - * @path GET /healthy/alive + * @controller HealthController.get() + * @path GET /health * @nestia Generated by Nestia - https://github.com/samchon/nestia */ -export function check +export function get ( connection: IConnection ): Promise @@ -20,16 +20,16 @@ export function check return Fetcher.fetch ( connection, - check.ENCRYPTED, - check.METHOD, - check.path() + get.ENCRYPTED, + get.METHOD, + get.path() ); } -export namespace check +export namespace get { export const METHOD = "GET" as const; - export const PATH: string = "/healthy/alive"; + export const PATH: string = "/health"; export const ENCRYPTED: Fetcher.IEncrypted = { request: false, response: false, @@ -37,6 +37,6 @@ export namespace check export function path(): string { - return `/healthy/alive`; + return `/health`; } } \ No newline at end of file diff --git a/test/features/body-manual-validate/src/api/functional/index.ts b/test/features/body-manual-validate/src/api/functional/index.ts new file mode 100644 index 000000000..c668415f8 --- /dev/null +++ b/test/features/body-manual-validate/src/api/functional/index.ts @@ -0,0 +1,9 @@ +/** + * @packageDocumentation + * @module api.functional + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +export * as health from "./health"; +export * as performance from "./performance"; +export * as body from "./body"; \ No newline at end of file diff --git a/test/features/body-manual-validate/src/api/functional/performance/index.ts b/test/features/body-manual-validate/src/api/functional/performance/index.ts new file mode 100644 index 000000000..9e402a44a --- /dev/null +++ b/test/features/body-manual-validate/src/api/functional/performance/index.ts @@ -0,0 +1,45 @@ +/** + * @packageDocumentation + * @module api.functional.performance + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +import { Fetcher, Primitive } from "@nestia/fetcher"; +import type { IConnection } from "@nestia/fetcher"; + +import type { IPerformance } from "./../../structures/IPerformance"; + +/** + * @controller PerformanceController.get() + * @path GET /performance + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export function get + ( + connection: IConnection + ): Promise +{ + return Fetcher.fetch + ( + connection, + get.ENCRYPTED, + get.METHOD, + get.path() + ); +} +export namespace get +{ + export type Output = Primitive; + + export const METHOD = "GET" as const; + export const PATH: string = "/performance"; + export const ENCRYPTED: Fetcher.IEncrypted = { + request: false, + response: false, + }; + + export function path(): string + { + return `/performance`; + } +} \ No newline at end of file diff --git a/test/features/body-manual-validate/src/api/index.ts b/test/features/body-manual-validate/src/api/index.ts new file mode 100644 index 000000000..1896c4fbd --- /dev/null +++ b/test/features/body-manual-validate/src/api/index.ts @@ -0,0 +1,5 @@ +import * as api from "./module"; + +export * from "./module"; + +export default api; diff --git a/packages/sdk/demo/176/src/api/module.ts b/test/features/body-manual-validate/src/api/module.ts similarity index 53% rename from packages/sdk/demo/176/src/api/module.ts rename to test/features/body-manual-validate/src/api/module.ts index b731ce60c..00239fb3b 100644 --- a/packages/sdk/demo/176/src/api/module.ts +++ b/test/features/body-manual-validate/src/api/module.ts @@ -1,8 +1,3 @@ -/** - * @packageDocumentation - * @module api - */ -//================================================================ export * from "./IConnection"; export * from "./Primitive"; export * from "./HttpError"; diff --git a/test/features/body-manual-validate/src/api/structures/IBbsArticle.ts b/test/features/body-manual-validate/src/api/structures/IBbsArticle.ts new file mode 100644 index 000000000..aa8085b02 --- /dev/null +++ b/test/features/body-manual-validate/src/api/structures/IBbsArticle.ts @@ -0,0 +1,41 @@ +export interface IBbsArticle extends IBbsArticle.IStore { + /** + * @format uuid + */ + id: string; + + /** + * @format date-time + */ + created_at: string; +} +export namespace IBbsArticle { + export interface IStore { + /** + * @minLength 3 + * @maxLength 50 + */ + title: string; + body: string; + files: IAttachmentFile[]; + } +} + +export interface IAttachmentFile { + /** + * @minLengt 1 + * @maxLength 255 + */ + name: string | null; + + /** + * @minLength 1 + * @maxLength 8 + */ + extension: string | null; + + /** + * @format url + */ + url: string; +} diff --git a/test/features/body-manual-validate/src/api/structures/IPerformance.ts b/test/features/body-manual-validate/src/api/structures/IPerformance.ts new file mode 100644 index 000000000..a9e9336e1 --- /dev/null +++ b/test/features/body-manual-validate/src/api/structures/IPerformance.ts @@ -0,0 +1,10 @@ +/** + * Performance info. + * + * @author Samchon + */ +export interface IPerformance { + cpu: NodeJS.CpuUsage; + memory: NodeJS.MemoryUsage; + resource: NodeJS.ResourceUsage; +} diff --git a/test/features/body-manual-validate/src/api/structures/ISystem.ts b/test/features/body-manual-validate/src/api/structures/ISystem.ts new file mode 100644 index 000000000..68f05ca92 --- /dev/null +++ b/test/features/body-manual-validate/src/api/structures/ISystem.ts @@ -0,0 +1,81 @@ +/** + * System Information. + * + * @author Jeongho Nam + */ +export interface ISystem { + /** + * Random Unique ID. + */ + uid: number; + + /** + * `process.argv` + */ + arguments: string[]; + + /** + * Git commit info. + */ + commit: ISystem.ICommit; + + /** + * `package.json` + */ + package: ISystem.IPackage; + + /** + * Creation time of this server. + */ + created_at: string; +} + +export namespace ISystem { + /** + * Git commit info. + */ + export interface ICommit { + shortHash: string; + branch: string; + hash: string; + subject: string; + sanitizedSubject: string; + body: string; + author: ICommit.IUser; + committer: ICommit.IUser; + authored_at: string; + commited_at: string; + notes?: string; + tags: string[]; + } + export namespace ICommit { + /** + * Git user account info. + */ + export interface IUser { + name: string; + email: string; + } + } + + /** + * NPM package info. + */ + export interface IPackage { + name: string; + version: string; + description: string; + main?: string; + typings?: string; + scripts: Record; + repository: { type: "git"; url: string }; + author: string; + license: string; + bugs: { url: string }; + homepage: string; + devDependencies?: Record; + dependencies: Record; + publishConfig?: { registry: string }; + files?: string[]; + } +} diff --git a/test/features/body-manual-validate/src/controllers/HealthController.ts b/test/features/body-manual-validate/src/controllers/HealthController.ts new file mode 100644 index 000000000..a9ce3563b --- /dev/null +++ b/test/features/body-manual-validate/src/controllers/HealthController.ts @@ -0,0 +1,9 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +@Controller("health") +export class HealthController { + @core.TypedRoute.Get() + public get(): void {} +} diff --git a/test/features/body-manual-validate/src/controllers/PerformanceController.ts b/test/features/body-manual-validate/src/controllers/PerformanceController.ts new file mode 100644 index 000000000..798d64fae --- /dev/null +++ b/test/features/body-manual-validate/src/controllers/PerformanceController.ts @@ -0,0 +1,17 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +import { IPerformance } from "@api/lib/structures/IPerformance"; + +@Controller("performance") +export class PerformanceController { + @core.TypedRoute.Get() + public async get(): Promise { + return { + cpu: process.cpuUsage(), + memory: process.memoryUsage(), + resource: process.resourceUsage(), + }; + } +} diff --git a/test/features/body-manual-validate/src/controllers/TypedBodyController.ts b/test/features/body-manual-validate/src/controllers/TypedBodyController.ts new file mode 100644 index 000000000..5a776944a --- /dev/null +++ b/test/features/body-manual-validate/src/controllers/TypedBodyController.ts @@ -0,0 +1,23 @@ +import { Controller } from "@nestjs/common"; +import typia from "typia"; + +import core from "@nestia/core"; + +import { IBbsArticle } from "@api/lib/structures/IBbsArticle"; + +@Controller("body") +export class TypedBodyController { + @core.TypedRoute.Post() + public async store( + @core.TypedBody({ + type: "validate", + validate: typia.createValidate(), + }) + input: IBbsArticle.IStore, + ): Promise { + return { + ...typia.random(), + ...input, + }; + } +} diff --git a/test/features/body-manual-validate/src/test/features/test_api_body.ts b/test/features/body-manual-validate/src/test/features/test_api_body.ts new file mode 100644 index 000000000..e22640324 --- /dev/null +++ b/test/features/body-manual-validate/src/test/features/test_api_body.ts @@ -0,0 +1,14 @@ +import typia from "typia"; + +import api from "@api"; +import { IBbsArticle } from "@api/lib/structures/IBbsArticle"; + +export const test_api_body = async ( + connection: api.IConnection, +): Promise => { + const article: IBbsArticle = await api.functional.body.store( + connection, + typia.random(), + ); + typia.assertEquals(article); +}; diff --git a/test/features/body-manual-validate/src/test/features/test_api_health_check.ts b/test/features/body-manual-validate/src/test/features/test_api_health_check.ts new file mode 100644 index 000000000..c34703c71 --- /dev/null +++ b/test/features/body-manual-validate/src/test/features/test_api_health_check.ts @@ -0,0 +1,5 @@ +import api from "@api"; + +export const test_api_monitor_health_check = ( + connection: api.IConnection, +): Promise => api.functional.health.get(connection); diff --git a/test/features/body-manual-validate/src/test/features/test_api_performance.ts b/test/features/body-manual-validate/src/test/features/test_api_performance.ts new file mode 100644 index 000000000..55b6d2ca7 --- /dev/null +++ b/test/features/body-manual-validate/src/test/features/test_api_performance.ts @@ -0,0 +1,13 @@ +import typia from "typia"; + +import api from "@api"; +import { IPerformance } from "@api/lib/structures/IPerformance"; + +export const test_api_monitor_performance = async ( + connection: api.IConnection, +): Promise => { + const performance: IPerformance = await api.functional.performance.get( + connection, + ); + typia.assert(performance); +}; diff --git a/test/features/body-manual-validate/src/test/index.ts b/test/features/body-manual-validate/src/test/index.ts new file mode 100644 index 000000000..e89842739 --- /dev/null +++ b/test/features/body-manual-validate/src/test/index.ts @@ -0,0 +1,39 @@ +import { DynamicExecutor } from "@nestia/e2e"; + +import { Backend } from "../Backend"; + +async function main(): Promise { + const server: Backend = new Backend(); + await server.open(); + + const report: DynamicExecutor.IReport = await DynamicExecutor.validate({ + prefix: "test", + parameters: () => [ + { + host: "http://127.0.0.1:37000", + encryption: { + key: "A".repeat(32), + iv: "B".repeat(16), + }, + }, + ], + })(`${__dirname}/features`); + await server.close(); + + const exceptions: Error[] = report.executions + .filter((exec) => exec.error !== null) + .map((exec) => exec.error!); + if (exceptions.length === 0) { + console.log("Success"); + console.log("Elapsed time", report.time.toLocaleString(), `ms`); + } else { + // for (const exp of exceptions) console.log(exp); + console.log("Failed"); + console.log("Elapsed time", report.time.toLocaleString(), `ms`); + process.exit(-1); + } +} +main().catch((exp) => { + console.log(exp); + process.exit(-1); +}); diff --git a/test/features/body-manual-validate/swagger.json b/test/features/body-manual-validate/swagger.json new file mode 100644 index 000000000..22afde432 --- /dev/null +++ b/test/features/body-manual-validate/swagger.json @@ -0,0 +1,619 @@ +{ + "openapi": "3.0.1", + "servers": [ + { + "url": "https://github.com/samchon/nestia", + "description": "insert your server url" + } + ], + "info": { + "version": "0.1.0", + "title": "Generated by nestia - https://github.com/samchon/nestia" + }, + "paths": { + "/health": { + "get": { + "tags": [], + "parameters": [], + "responses": { + "200": { + "description": "", + "x-nestia-encrypted": false + } + }, + "description": "", + "x-nestia-namespace": "health.get", + "x-nestia-jsDocTags": [] + } + }, + "/performance": { + "get": { + "tags": [], + "parameters": [], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IPerformance" + } + } + }, + "x-nestia-encrypted": false + } + }, + "description": "", + "x-nestia-namespace": "performance.get", + "x-nestia-jsDocTags": [] + } + }, + "/body": { + "post": { + "tags": [], + "parameters": [], + "requestBody": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IBbsArticle.IStore" + } + } + }, + "required": true, + "x-nestia-encrypted": false + }, + "responses": { + "201": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IBbsArticle" + } + } + }, + "x-nestia-encrypted": false + } + }, + "description": "", + "x-nestia-namespace": "body.store", + "x-nestia-jsDocTags": [] + } + } + }, + "components": { + "schemas": { + "IPerformance": { + "type": "object", + "properties": { + "cpu": { + "$ref": "#/components/schemas/_singlequote_process_singlequote_.global.NodeJS.CpuUsage", + "x-typia-required": true, + "x-typia-optional": false + }, + "memory": { + "$ref": "#/components/schemas/_singlequote_process_singlequote_.global.NodeJS.MemoryUsage", + "x-typia-required": true, + "x-typia-optional": false + }, + "resource": { + "$ref": "#/components/schemas/_singlequote_process_singlequote_.global.NodeJS.ResourceUsage", + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "cpu", + "memory", + "resource" + ], + "description": "Performance info.", + "x-typia-jsDocTags": [ + { + "name": "author", + "text": [ + { + "text": "Samchon", + "kind": "text" + } + ] + } + ] + }, + "_singlequote_process_singlequote_.global.NodeJS.CpuUsage": { + "type": "object", + "properties": { + "user": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "system": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "user", + "system" + ], + "x-typia-jsDocTags": [] + }, + "_singlequote_process_singlequote_.global.NodeJS.MemoryUsage": { + "type": "object", + "properties": { + "rss": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "heapTotal": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "heapUsed": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "external": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "arrayBuffers": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "rss", + "heapTotal", + "heapUsed", + "external", + "arrayBuffers" + ], + "x-typia-jsDocTags": [] + }, + "_singlequote_process_singlequote_.global.NodeJS.ResourceUsage": { + "type": "object", + "properties": { + "fsRead": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "fsWrite": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "involuntaryContextSwitches": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "ipcReceived": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "ipcSent": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "majorPageFault": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "maxRSS": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "minorPageFault": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "sharedMemorySize": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "signalsCount": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "swappedOut": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "systemCPUTime": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "unsharedDataSize": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "unsharedStackSize": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "userCPUTime": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "voluntaryContextSwitches": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "fsRead", + "fsWrite", + "involuntaryContextSwitches", + "ipcReceived", + "ipcSent", + "majorPageFault", + "maxRSS", + "minorPageFault", + "sharedMemorySize", + "signalsCount", + "swappedOut", + "systemCPUTime", + "unsharedDataSize", + "unsharedStackSize", + "userCPUTime", + "voluntaryContextSwitches" + ], + "x-typia-jsDocTags": [] + }, + "IBbsArticle.IStore": { + "type": "object", + "properties": { + "title": { + "type": "string", + "nullable": false, + "x-typia-metaTags": [ + { + "kind": "minLength", + "value": 3 + }, + { + "kind": "maxLength", + "value": 50 + } + ], + "x-typia-jsDocTags": [ + { + "name": "minLength", + "text": [ + { + "text": "3", + "kind": "text" + } + ] + }, + { + "name": "maxLength", + "text": [ + { + "text": "50", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "minLength": 3, + "maxLength": 50 + }, + "body": { + "type": "string", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "files": { + "type": "array", + "items": { + "$ref": "#/components/schemas/IAttachmentFile", + "x-typia-required": true, + "x-typia-optional": false + }, + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "title", + "body", + "files" + ], + "x-typia-jsDocTags": [] + }, + "IAttachmentFile": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "x-typia-metaTags": [ + { + "kind": "maxLength", + "value": 255 + } + ], + "x-typia-jsDocTags": [ + { + "name": "minLengt", + "text": [ + { + "text": "1", + "kind": "text" + } + ] + }, + { + "name": "maxLength", + "text": [ + { + "text": "255", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "maxLength": 255 + }, + "extension": { + "type": "string", + "nullable": true, + "x-typia-metaTags": [ + { + "kind": "minLength", + "value": 1 + }, + { + "kind": "maxLength", + "value": 8 + } + ], + "x-typia-jsDocTags": [ + { + "name": "minLength", + "text": [ + { + "text": "1", + "kind": "text" + } + ] + }, + { + "name": "maxLength", + "text": [ + { + "text": "8", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "minLength": 1, + "maxLength": 8 + }, + "url": { + "type": "string", + "nullable": false, + "x-typia-metaTags": [ + { + "kind": "format", + "value": "url" + } + ], + "x-typia-jsDocTags": [ + { + "name": "format", + "text": [ + { + "text": "url", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "format": "url" + } + }, + "nullable": false, + "required": [ + "name", + "extension", + "url" + ], + "x-typia-jsDocTags": [] + }, + "IBbsArticle": { + "type": "object", + "properties": { + "id": { + "type": "string", + "nullable": false, + "x-typia-metaTags": [ + { + "kind": "format", + "value": "uuid" + } + ], + "x-typia-jsDocTags": [ + { + "name": "format", + "text": [ + { + "text": "uuid", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "format": "uuid" + }, + "created_at": { + "type": "string", + "nullable": false, + "x-typia-metaTags": [ + { + "kind": "format", + "value": "datetime" + } + ], + "x-typia-jsDocTags": [ + { + "name": "format", + "text": [ + { + "text": "date-time", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "format": "date-time" + }, + "title": { + "type": "string", + "nullable": false, + "x-typia-metaTags": [ + { + "kind": "minLength", + "value": 3 + }, + { + "kind": "maxLength", + "value": 50 + } + ], + "x-typia-jsDocTags": [ + { + "name": "minLength", + "text": [ + { + "text": "3", + "kind": "text" + } + ] + }, + { + "name": "maxLength", + "text": [ + { + "text": "50", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "minLength": 3, + "maxLength": 50 + }, + "body": { + "type": "string", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "files": { + "type": "array", + "items": { + "$ref": "#/components/schemas/IAttachmentFile", + "x-typia-required": true, + "x-typia-optional": false + }, + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "id", + "created_at", + "title", + "body", + "files" + ], + "x-typia-jsDocTags": [] + } + }, + "securitySchemes": { + "bearer": { + "type": "apiKey", + "in": "header", + "name": "Authorization" + } + } + }, + "security": [ + { + "bearer": [] + } + ] +} \ No newline at end of file diff --git a/test/features/body-manual-validate/tsconfig.json b/test/features/body-manual-validate/tsconfig.json new file mode 100644 index 000000000..e5fe47a95 --- /dev/null +++ b/test/features/body-manual-validate/tsconfig.json @@ -0,0 +1,103 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + /* Language and Environment */ + "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + /* Modules */ + "module": "commonjs", /* Specify what module code is generated. */// "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + "paths": { + "@nestia/core": ["../../../packages/core/src"], + "@nestia/e2e": ["../../../packages/e2e/src"], + "@nestia/fetcher": ["../../../packages/fetcher/src"], + "@nestia/sdk": ["../../../packages/sdk/src"], + "@nestia/sdk/lib/*": ["../../../packages/sdk/src/*"], + "@api": ["./src/api"], + "@api/lib/*": ["./src/api/*"], + }, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. *//* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true, /* Skip type checking all .d.ts files. */ + "plugins": [ + { "transform": "typescript-transform-paths" }, + { "transform": "typia/lib/transform" }, + { "transform": "../../../packages/core/src/transform.ts" }, + ], + } + } \ No newline at end of file diff --git a/test/features/body/nestia.config.ts b/test/features/body/nestia.config.ts new file mode 100644 index 000000000..2594a40d0 --- /dev/null +++ b/test/features/body/nestia.config.ts @@ -0,0 +1,15 @@ +import { INestiaConfig } from "@nestia/sdk"; + +export const NESTIA_CONFIG: INestiaConfig = { + input: ["src/controllers"], + output: "src/api", + swagger: { + output: "swagger.json", + security: { + bearer: { + type: "apiKey", + }, + }, + }, +}; +export default NESTIA_CONFIG; diff --git a/packages/sdk/demo/generic/src/Backend.ts b/test/features/body/src/Backend.ts similarity index 51% rename from packages/sdk/demo/generic/src/Backend.ts rename to test/features/body/src/Backend.ts index 4507166f0..8ab51b70f 100644 --- a/packages/sdk/demo/generic/src/Backend.ts +++ b/test/features/body/src/Backend.ts @@ -1,28 +1,28 @@ -import helper from "@nestia/core"; -import * as nest from "@nestjs/common"; +import { INestApplication } from "@nestjs/common"; import { NestFactory } from "@nestjs/core"; -import { Configuration } from "./Configuration"; +import core from "@nestia/core"; export class Backend { - private application_?: nest.INestApplication; + private application_?: INestApplication; public async open(): Promise { this.application_ = await NestFactory.create( - await helper.EncryptedModule.dynamic( - __dirname + "/controllers", - Configuration.ENCRYPTION_PASSWORD, - ), + await core.EncryptedModule.dynamic(__dirname + "/controllers", { + key: "A".repeat(32), + iv: "B".repeat(16), + }), { logger: false }, ); - await this.application_.listen(Configuration.PORT); + await this.application_.listen(37_000); } public async close(): Promise { if (this.application_ === undefined) return; const app = this.application_; - delete this.application_; await app.close(); + + delete this.application_; } } diff --git a/packages/sdk/demo/encrypted/src/api/HttpError.ts b/test/features/body/src/api/HttpError.ts similarity index 100% rename from packages/sdk/demo/encrypted/src/api/HttpError.ts rename to test/features/body/src/api/HttpError.ts diff --git a/packages/sdk/demo/encrypted/src/api/IConnection.ts b/test/features/body/src/api/IConnection.ts similarity index 100% rename from packages/sdk/demo/encrypted/src/api/IConnection.ts rename to test/features/body/src/api/IConnection.ts diff --git a/packages/sdk/demo/encrypted/src/api/Primitive.ts b/test/features/body/src/api/Primitive.ts similarity index 100% rename from packages/sdk/demo/encrypted/src/api/Primitive.ts rename to test/features/body/src/api/Primitive.ts diff --git a/test/features/body/src/api/functional/body/index.ts b/test/features/body/src/api/functional/body/index.ts new file mode 100644 index 000000000..f28ef0e87 --- /dev/null +++ b/test/features/body/src/api/functional/body/index.ts @@ -0,0 +1,48 @@ +/** + * @packageDocumentation + * @module api.functional.body + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +import { Fetcher, Primitive } from "@nestia/fetcher"; +import type { IConnection } from "@nestia/fetcher"; + +import type { IBbsArticle } from "./../../structures/IBbsArticle"; + +/** + * @controller TypedBodyController.store() + * @path POST /body + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export function store + ( + connection: IConnection, + input: Primitive + ): Promise +{ + return Fetcher.fetch + ( + connection, + store.ENCRYPTED, + store.METHOD, + store.path(), + input + ); +} +export namespace store +{ + export type Input = Primitive; + export type Output = Primitive; + + export const METHOD = "POST" as const; + export const PATH: string = "/body"; + export const ENCRYPTED: Fetcher.IEncrypted = { + request: false, + response: false, + }; + + export function path(): string + { + return `/body`; + } +} \ No newline at end of file diff --git a/packages/sdk/demo/multiple-paths/src/api/functional/healthy/index.ts b/test/features/body/src/api/functional/health/index.ts similarity index 66% rename from packages/sdk/demo/multiple-paths/src/api/functional/healthy/index.ts rename to test/features/body/src/api/functional/health/index.ts index 4fd46575a..619581f93 100644 --- a/packages/sdk/demo/multiple-paths/src/api/functional/healthy/index.ts +++ b/test/features/body/src/api/functional/health/index.ts @@ -1,20 +1,18 @@ /** * @packageDocumentation - * @module api.functional.healthy + * @module api.functional.health * @nestia Generated by Nestia - https://github.com/samchon/nestia */ //================================================================ import { Fetcher } from "@nestia/fetcher"; import type { IConnection } from "@nestia/fetcher"; -export * as alive from "./alive"; - /** - * @controller HealthController.check() - * @path GET /healthy/check + * @controller HealthController.get() + * @path GET /health * @nestia Generated by Nestia - https://github.com/samchon/nestia */ -export function check +export function get ( connection: IConnection ): Promise @@ -22,16 +20,16 @@ export function check return Fetcher.fetch ( connection, - check.ENCRYPTED, - check.METHOD, - check.path() + get.ENCRYPTED, + get.METHOD, + get.path() ); } -export namespace check +export namespace get { export const METHOD = "GET" as const; - export const PATH: string = "/healthy/check"; + export const PATH: string = "/health"; export const ENCRYPTED: Fetcher.IEncrypted = { request: false, response: false, @@ -39,6 +37,6 @@ export namespace check export function path(): string { - return `/healthy/check`; + return `/health`; } } \ No newline at end of file diff --git a/test/features/body/src/api/functional/index.ts b/test/features/body/src/api/functional/index.ts new file mode 100644 index 000000000..c668415f8 --- /dev/null +++ b/test/features/body/src/api/functional/index.ts @@ -0,0 +1,9 @@ +/** + * @packageDocumentation + * @module api.functional + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +export * as health from "./health"; +export * as performance from "./performance"; +export * as body from "./body"; \ No newline at end of file diff --git a/test/features/body/src/api/functional/performance/index.ts b/test/features/body/src/api/functional/performance/index.ts new file mode 100644 index 000000000..9e402a44a --- /dev/null +++ b/test/features/body/src/api/functional/performance/index.ts @@ -0,0 +1,45 @@ +/** + * @packageDocumentation + * @module api.functional.performance + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +import { Fetcher, Primitive } from "@nestia/fetcher"; +import type { IConnection } from "@nestia/fetcher"; + +import type { IPerformance } from "./../../structures/IPerformance"; + +/** + * @controller PerformanceController.get() + * @path GET /performance + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export function get + ( + connection: IConnection + ): Promise +{ + return Fetcher.fetch + ( + connection, + get.ENCRYPTED, + get.METHOD, + get.path() + ); +} +export namespace get +{ + export type Output = Primitive; + + export const METHOD = "GET" as const; + export const PATH: string = "/performance"; + export const ENCRYPTED: Fetcher.IEncrypted = { + request: false, + response: false, + }; + + export function path(): string + { + return `/performance`; + } +} \ No newline at end of file diff --git a/test/features/body/src/api/index.ts b/test/features/body/src/api/index.ts new file mode 100644 index 000000000..1896c4fbd --- /dev/null +++ b/test/features/body/src/api/index.ts @@ -0,0 +1,5 @@ +import * as api from "./module"; + +export * from "./module"; + +export default api; diff --git a/packages/sdk/demo/encrypted/src/api/module.ts b/test/features/body/src/api/module.ts similarity index 53% rename from packages/sdk/demo/encrypted/src/api/module.ts rename to test/features/body/src/api/module.ts index b731ce60c..00239fb3b 100644 --- a/packages/sdk/demo/encrypted/src/api/module.ts +++ b/test/features/body/src/api/module.ts @@ -1,8 +1,3 @@ -/** - * @packageDocumentation - * @module api - */ -//================================================================ export * from "./IConnection"; export * from "./Primitive"; export * from "./HttpError"; diff --git a/test/features/body/src/api/structures/IBbsArticle.ts b/test/features/body/src/api/structures/IBbsArticle.ts new file mode 100644 index 000000000..aa8085b02 --- /dev/null +++ b/test/features/body/src/api/structures/IBbsArticle.ts @@ -0,0 +1,41 @@ +export interface IBbsArticle extends IBbsArticle.IStore { + /** + * @format uuid + */ + id: string; + + /** + * @format date-time + */ + created_at: string; +} +export namespace IBbsArticle { + export interface IStore { + /** + * @minLength 3 + * @maxLength 50 + */ + title: string; + body: string; + files: IAttachmentFile[]; + } +} + +export interface IAttachmentFile { + /** + * @minLengt 1 + * @maxLength 255 + */ + name: string | null; + + /** + * @minLength 1 + * @maxLength 8 + */ + extension: string | null; + + /** + * @format url + */ + url: string; +} diff --git a/test/features/body/src/api/structures/IPerformance.ts b/test/features/body/src/api/structures/IPerformance.ts new file mode 100644 index 000000000..a9e9336e1 --- /dev/null +++ b/test/features/body/src/api/structures/IPerformance.ts @@ -0,0 +1,10 @@ +/** + * Performance info. + * + * @author Samchon + */ +export interface IPerformance { + cpu: NodeJS.CpuUsage; + memory: NodeJS.MemoryUsage; + resource: NodeJS.ResourceUsage; +} diff --git a/test/features/body/src/api/structures/ISystem.ts b/test/features/body/src/api/structures/ISystem.ts new file mode 100644 index 000000000..68f05ca92 --- /dev/null +++ b/test/features/body/src/api/structures/ISystem.ts @@ -0,0 +1,81 @@ +/** + * System Information. + * + * @author Jeongho Nam + */ +export interface ISystem { + /** + * Random Unique ID. + */ + uid: number; + + /** + * `process.argv` + */ + arguments: string[]; + + /** + * Git commit info. + */ + commit: ISystem.ICommit; + + /** + * `package.json` + */ + package: ISystem.IPackage; + + /** + * Creation time of this server. + */ + created_at: string; +} + +export namespace ISystem { + /** + * Git commit info. + */ + export interface ICommit { + shortHash: string; + branch: string; + hash: string; + subject: string; + sanitizedSubject: string; + body: string; + author: ICommit.IUser; + committer: ICommit.IUser; + authored_at: string; + commited_at: string; + notes?: string; + tags: string[]; + } + export namespace ICommit { + /** + * Git user account info. + */ + export interface IUser { + name: string; + email: string; + } + } + + /** + * NPM package info. + */ + export interface IPackage { + name: string; + version: string; + description: string; + main?: string; + typings?: string; + scripts: Record; + repository: { type: "git"; url: string }; + author: string; + license: string; + bugs: { url: string }; + homepage: string; + devDependencies?: Record; + dependencies: Record; + publishConfig?: { registry: string }; + files?: string[]; + } +} diff --git a/test/features/body/src/controllers/HealthController.ts b/test/features/body/src/controllers/HealthController.ts new file mode 100644 index 000000000..a9ce3563b --- /dev/null +++ b/test/features/body/src/controllers/HealthController.ts @@ -0,0 +1,9 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +@Controller("health") +export class HealthController { + @core.TypedRoute.Get() + public get(): void {} +} diff --git a/test/features/body/src/controllers/PerformanceController.ts b/test/features/body/src/controllers/PerformanceController.ts new file mode 100644 index 000000000..798d64fae --- /dev/null +++ b/test/features/body/src/controllers/PerformanceController.ts @@ -0,0 +1,17 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +import { IPerformance } from "@api/lib/structures/IPerformance"; + +@Controller("performance") +export class PerformanceController { + @core.TypedRoute.Get() + public async get(): Promise { + return { + cpu: process.cpuUsage(), + memory: process.memoryUsage(), + resource: process.resourceUsage(), + }; + } +} diff --git a/test/features/body/src/controllers/TypedBodyController.ts b/test/features/body/src/controllers/TypedBodyController.ts new file mode 100644 index 000000000..1c0b33e69 --- /dev/null +++ b/test/features/body/src/controllers/TypedBodyController.ts @@ -0,0 +1,19 @@ +import { Controller } from "@nestjs/common"; +import typia from "typia"; + +import core from "@nestia/core"; + +import { IBbsArticle } from "@api/lib/structures/IBbsArticle"; + +@Controller("body") +export class TypedBodyController { + @core.TypedRoute.Post() + public async store( + @core.TypedBody() input: IBbsArticle.IStore, + ): Promise { + return { + ...typia.random(), + ...input, + }; + } +} diff --git a/test/features/body/src/test/features/test_api_body.ts b/test/features/body/src/test/features/test_api_body.ts new file mode 100644 index 000000000..e22640324 --- /dev/null +++ b/test/features/body/src/test/features/test_api_body.ts @@ -0,0 +1,14 @@ +import typia from "typia"; + +import api from "@api"; +import { IBbsArticle } from "@api/lib/structures/IBbsArticle"; + +export const test_api_body = async ( + connection: api.IConnection, +): Promise => { + const article: IBbsArticle = await api.functional.body.store( + connection, + typia.random(), + ); + typia.assertEquals(article); +}; diff --git a/test/features/body/src/test/features/test_api_body_invalid.ts b/test/features/body/src/test/features/test_api_body_invalid.ts new file mode 100644 index 000000000..ff3037dbd --- /dev/null +++ b/test/features/body/src/test/features/test_api_body_invalid.ts @@ -0,0 +1,17 @@ +import typia from "typia"; + +import api from "@api"; +import { IBbsArticle } from "@api/lib/structures/IBbsArticle"; + +import { TestValidator } from "../../../../../../packages/e2e/src/TestValidator"; + +export const test_api_body = async ( + connection: api.IConnection, +): Promise => { + await TestValidator.error("invalid")(() => + api.functional.body.store(connection, { + ...typia.random(), + title: null!, + }), + ); +}; diff --git a/test/features/body/src/test/features/test_api_health_check.ts b/test/features/body/src/test/features/test_api_health_check.ts new file mode 100644 index 000000000..c34703c71 --- /dev/null +++ b/test/features/body/src/test/features/test_api_health_check.ts @@ -0,0 +1,5 @@ +import api from "@api"; + +export const test_api_monitor_health_check = ( + connection: api.IConnection, +): Promise => api.functional.health.get(connection); diff --git a/test/features/body/src/test/features/test_api_performance.ts b/test/features/body/src/test/features/test_api_performance.ts new file mode 100644 index 000000000..55b6d2ca7 --- /dev/null +++ b/test/features/body/src/test/features/test_api_performance.ts @@ -0,0 +1,13 @@ +import typia from "typia"; + +import api from "@api"; +import { IPerformance } from "@api/lib/structures/IPerformance"; + +export const test_api_monitor_performance = async ( + connection: api.IConnection, +): Promise => { + const performance: IPerformance = await api.functional.performance.get( + connection, + ); + typia.assert(performance); +}; diff --git a/test/features/body/src/test/index.ts b/test/features/body/src/test/index.ts new file mode 100644 index 000000000..e89842739 --- /dev/null +++ b/test/features/body/src/test/index.ts @@ -0,0 +1,39 @@ +import { DynamicExecutor } from "@nestia/e2e"; + +import { Backend } from "../Backend"; + +async function main(): Promise { + const server: Backend = new Backend(); + await server.open(); + + const report: DynamicExecutor.IReport = await DynamicExecutor.validate({ + prefix: "test", + parameters: () => [ + { + host: "http://127.0.0.1:37000", + encryption: { + key: "A".repeat(32), + iv: "B".repeat(16), + }, + }, + ], + })(`${__dirname}/features`); + await server.close(); + + const exceptions: Error[] = report.executions + .filter((exec) => exec.error !== null) + .map((exec) => exec.error!); + if (exceptions.length === 0) { + console.log("Success"); + console.log("Elapsed time", report.time.toLocaleString(), `ms`); + } else { + // for (const exp of exceptions) console.log(exp); + console.log("Failed"); + console.log("Elapsed time", report.time.toLocaleString(), `ms`); + process.exit(-1); + } +} +main().catch((exp) => { + console.log(exp); + process.exit(-1); +}); diff --git a/test/features/body/swagger.json b/test/features/body/swagger.json new file mode 100644 index 000000000..22afde432 --- /dev/null +++ b/test/features/body/swagger.json @@ -0,0 +1,619 @@ +{ + "openapi": "3.0.1", + "servers": [ + { + "url": "https://github.com/samchon/nestia", + "description": "insert your server url" + } + ], + "info": { + "version": "0.1.0", + "title": "Generated by nestia - https://github.com/samchon/nestia" + }, + "paths": { + "/health": { + "get": { + "tags": [], + "parameters": [], + "responses": { + "200": { + "description": "", + "x-nestia-encrypted": false + } + }, + "description": "", + "x-nestia-namespace": "health.get", + "x-nestia-jsDocTags": [] + } + }, + "/performance": { + "get": { + "tags": [], + "parameters": [], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IPerformance" + } + } + }, + "x-nestia-encrypted": false + } + }, + "description": "", + "x-nestia-namespace": "performance.get", + "x-nestia-jsDocTags": [] + } + }, + "/body": { + "post": { + "tags": [], + "parameters": [], + "requestBody": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IBbsArticle.IStore" + } + } + }, + "required": true, + "x-nestia-encrypted": false + }, + "responses": { + "201": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IBbsArticle" + } + } + }, + "x-nestia-encrypted": false + } + }, + "description": "", + "x-nestia-namespace": "body.store", + "x-nestia-jsDocTags": [] + } + } + }, + "components": { + "schemas": { + "IPerformance": { + "type": "object", + "properties": { + "cpu": { + "$ref": "#/components/schemas/_singlequote_process_singlequote_.global.NodeJS.CpuUsage", + "x-typia-required": true, + "x-typia-optional": false + }, + "memory": { + "$ref": "#/components/schemas/_singlequote_process_singlequote_.global.NodeJS.MemoryUsage", + "x-typia-required": true, + "x-typia-optional": false + }, + "resource": { + "$ref": "#/components/schemas/_singlequote_process_singlequote_.global.NodeJS.ResourceUsage", + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "cpu", + "memory", + "resource" + ], + "description": "Performance info.", + "x-typia-jsDocTags": [ + { + "name": "author", + "text": [ + { + "text": "Samchon", + "kind": "text" + } + ] + } + ] + }, + "_singlequote_process_singlequote_.global.NodeJS.CpuUsage": { + "type": "object", + "properties": { + "user": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "system": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "user", + "system" + ], + "x-typia-jsDocTags": [] + }, + "_singlequote_process_singlequote_.global.NodeJS.MemoryUsage": { + "type": "object", + "properties": { + "rss": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "heapTotal": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "heapUsed": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "external": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "arrayBuffers": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "rss", + "heapTotal", + "heapUsed", + "external", + "arrayBuffers" + ], + "x-typia-jsDocTags": [] + }, + "_singlequote_process_singlequote_.global.NodeJS.ResourceUsage": { + "type": "object", + "properties": { + "fsRead": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "fsWrite": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "involuntaryContextSwitches": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "ipcReceived": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "ipcSent": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "majorPageFault": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "maxRSS": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "minorPageFault": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "sharedMemorySize": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "signalsCount": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "swappedOut": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "systemCPUTime": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "unsharedDataSize": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "unsharedStackSize": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "userCPUTime": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "voluntaryContextSwitches": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "fsRead", + "fsWrite", + "involuntaryContextSwitches", + "ipcReceived", + "ipcSent", + "majorPageFault", + "maxRSS", + "minorPageFault", + "sharedMemorySize", + "signalsCount", + "swappedOut", + "systemCPUTime", + "unsharedDataSize", + "unsharedStackSize", + "userCPUTime", + "voluntaryContextSwitches" + ], + "x-typia-jsDocTags": [] + }, + "IBbsArticle.IStore": { + "type": "object", + "properties": { + "title": { + "type": "string", + "nullable": false, + "x-typia-metaTags": [ + { + "kind": "minLength", + "value": 3 + }, + { + "kind": "maxLength", + "value": 50 + } + ], + "x-typia-jsDocTags": [ + { + "name": "minLength", + "text": [ + { + "text": "3", + "kind": "text" + } + ] + }, + { + "name": "maxLength", + "text": [ + { + "text": "50", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "minLength": 3, + "maxLength": 50 + }, + "body": { + "type": "string", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "files": { + "type": "array", + "items": { + "$ref": "#/components/schemas/IAttachmentFile", + "x-typia-required": true, + "x-typia-optional": false + }, + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "title", + "body", + "files" + ], + "x-typia-jsDocTags": [] + }, + "IAttachmentFile": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "x-typia-metaTags": [ + { + "kind": "maxLength", + "value": 255 + } + ], + "x-typia-jsDocTags": [ + { + "name": "minLengt", + "text": [ + { + "text": "1", + "kind": "text" + } + ] + }, + { + "name": "maxLength", + "text": [ + { + "text": "255", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "maxLength": 255 + }, + "extension": { + "type": "string", + "nullable": true, + "x-typia-metaTags": [ + { + "kind": "minLength", + "value": 1 + }, + { + "kind": "maxLength", + "value": 8 + } + ], + "x-typia-jsDocTags": [ + { + "name": "minLength", + "text": [ + { + "text": "1", + "kind": "text" + } + ] + }, + { + "name": "maxLength", + "text": [ + { + "text": "8", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "minLength": 1, + "maxLength": 8 + }, + "url": { + "type": "string", + "nullable": false, + "x-typia-metaTags": [ + { + "kind": "format", + "value": "url" + } + ], + "x-typia-jsDocTags": [ + { + "name": "format", + "text": [ + { + "text": "url", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "format": "url" + } + }, + "nullable": false, + "required": [ + "name", + "extension", + "url" + ], + "x-typia-jsDocTags": [] + }, + "IBbsArticle": { + "type": "object", + "properties": { + "id": { + "type": "string", + "nullable": false, + "x-typia-metaTags": [ + { + "kind": "format", + "value": "uuid" + } + ], + "x-typia-jsDocTags": [ + { + "name": "format", + "text": [ + { + "text": "uuid", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "format": "uuid" + }, + "created_at": { + "type": "string", + "nullable": false, + "x-typia-metaTags": [ + { + "kind": "format", + "value": "datetime" + } + ], + "x-typia-jsDocTags": [ + { + "name": "format", + "text": [ + { + "text": "date-time", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "format": "date-time" + }, + "title": { + "type": "string", + "nullable": false, + "x-typia-metaTags": [ + { + "kind": "minLength", + "value": 3 + }, + { + "kind": "maxLength", + "value": 50 + } + ], + "x-typia-jsDocTags": [ + { + "name": "minLength", + "text": [ + { + "text": "3", + "kind": "text" + } + ] + }, + { + "name": "maxLength", + "text": [ + { + "text": "50", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "minLength": 3, + "maxLength": 50 + }, + "body": { + "type": "string", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "files": { + "type": "array", + "items": { + "$ref": "#/components/schemas/IAttachmentFile", + "x-typia-required": true, + "x-typia-optional": false + }, + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "id", + "created_at", + "title", + "body", + "files" + ], + "x-typia-jsDocTags": [] + } + }, + "securitySchemes": { + "bearer": { + "type": "apiKey", + "in": "header", + "name": "Authorization" + } + } + }, + "security": [ + { + "bearer": [] + } + ] +} \ No newline at end of file diff --git a/test/features/body/tsconfig.json b/test/features/body/tsconfig.json new file mode 100644 index 000000000..e5fe47a95 --- /dev/null +++ b/test/features/body/tsconfig.json @@ -0,0 +1,103 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + /* Language and Environment */ + "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + /* Modules */ + "module": "commonjs", /* Specify what module code is generated. */// "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + "paths": { + "@nestia/core": ["../../../packages/core/src"], + "@nestia/e2e": ["../../../packages/e2e/src"], + "@nestia/fetcher": ["../../../packages/fetcher/src"], + "@nestia/sdk": ["../../../packages/sdk/src"], + "@nestia/sdk/lib/*": ["../../../packages/sdk/src/*"], + "@api": ["./src/api"], + "@api/lib/*": ["./src/api/*"], + }, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. *//* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true, /* Skip type checking all .d.ts files. */ + "plugins": [ + { "transform": "typescript-transform-paths" }, + { "transform": "typia/lib/transform" }, + { "transform": "../../../packages/core/src/transform.ts" }, + ], + } + } \ No newline at end of file diff --git a/test/features/cli-directory/src/Backend.ts b/test/features/cli-directory/src/Backend.ts new file mode 100644 index 000000000..8ab51b70f --- /dev/null +++ b/test/features/cli-directory/src/Backend.ts @@ -0,0 +1,28 @@ +import { INestApplication } from "@nestjs/common"; +import { NestFactory } from "@nestjs/core"; + +import core from "@nestia/core"; + +export class Backend { + private application_?: INestApplication; + + public async open(): Promise { + this.application_ = await NestFactory.create( + await core.EncryptedModule.dynamic(__dirname + "/controllers", { + key: "A".repeat(32), + iv: "B".repeat(16), + }), + { logger: false }, + ); + await this.application_.listen(37_000); + } + + public async close(): Promise { + if (this.application_ === undefined) return; + + const app = this.application_; + await app.close(); + + delete this.application_; + } +} diff --git a/packages/sdk/demo/generic/src/api/HttpError.ts b/test/features/cli-directory/src/api/HttpError.ts similarity index 100% rename from packages/sdk/demo/generic/src/api/HttpError.ts rename to test/features/cli-directory/src/api/HttpError.ts diff --git a/packages/sdk/demo/generic/src/api/IConnection.ts b/test/features/cli-directory/src/api/IConnection.ts similarity index 100% rename from packages/sdk/demo/generic/src/api/IConnection.ts rename to test/features/cli-directory/src/api/IConnection.ts diff --git a/packages/sdk/demo/generic/src/api/Primitive.ts b/test/features/cli-directory/src/api/Primitive.ts similarity index 100% rename from packages/sdk/demo/generic/src/api/Primitive.ts rename to test/features/cli-directory/src/api/Primitive.ts diff --git a/test/features/cli-directory/src/api/functional/health/index.ts b/test/features/cli-directory/src/api/functional/health/index.ts new file mode 100644 index 000000000..619581f93 --- /dev/null +++ b/test/features/cli-directory/src/api/functional/health/index.ts @@ -0,0 +1,42 @@ +/** + * @packageDocumentation + * @module api.functional.health + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +import { Fetcher } from "@nestia/fetcher"; +import type { IConnection } from "@nestia/fetcher"; + +/** + * @controller HealthController.get() + * @path GET /health + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export function get + ( + connection: IConnection + ): Promise +{ + return Fetcher.fetch + ( + connection, + get.ENCRYPTED, + get.METHOD, + get.path() + ); +} +export namespace get +{ + + export const METHOD = "GET" as const; + export const PATH: string = "/health"; + export const ENCRYPTED: Fetcher.IEncrypted = { + request: false, + response: false, + }; + + export function path(): string + { + return `/health`; + } +} \ No newline at end of file diff --git a/packages/sdk/demo/176/src/api/functional/index.ts b/test/features/cli-directory/src/api/functional/index.ts similarity index 70% rename from packages/sdk/demo/176/src/api/functional/index.ts rename to test/features/cli-directory/src/api/functional/index.ts index 0bbf5121e..bc823f38c 100644 --- a/packages/sdk/demo/176/src/api/functional/index.ts +++ b/test/features/cli-directory/src/api/functional/index.ts @@ -4,4 +4,5 @@ * @nestia Generated by Nestia - https://github.com/samchon/nestia */ //================================================================ -export * as userspace from "./userspace"; \ No newline at end of file +export * as health from "./health"; +export * as performance from "./performance"; \ No newline at end of file diff --git a/test/features/cli-directory/src/api/functional/performance/index.ts b/test/features/cli-directory/src/api/functional/performance/index.ts new file mode 100644 index 000000000..9e402a44a --- /dev/null +++ b/test/features/cli-directory/src/api/functional/performance/index.ts @@ -0,0 +1,45 @@ +/** + * @packageDocumentation + * @module api.functional.performance + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +import { Fetcher, Primitive } from "@nestia/fetcher"; +import type { IConnection } from "@nestia/fetcher"; + +import type { IPerformance } from "./../../structures/IPerformance"; + +/** + * @controller PerformanceController.get() + * @path GET /performance + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export function get + ( + connection: IConnection + ): Promise +{ + return Fetcher.fetch + ( + connection, + get.ENCRYPTED, + get.METHOD, + get.path() + ); +} +export namespace get +{ + export type Output = Primitive; + + export const METHOD = "GET" as const; + export const PATH: string = "/performance"; + export const ENCRYPTED: Fetcher.IEncrypted = { + request: false, + response: false, + }; + + export function path(): string + { + return `/performance`; + } +} \ No newline at end of file diff --git a/test/features/cli-directory/src/api/index.ts b/test/features/cli-directory/src/api/index.ts new file mode 100644 index 000000000..1896c4fbd --- /dev/null +++ b/test/features/cli-directory/src/api/index.ts @@ -0,0 +1,5 @@ +import * as api from "./module"; + +export * from "./module"; + +export default api; diff --git a/packages/sdk/demo/generic/src/api/module.ts b/test/features/cli-directory/src/api/module.ts similarity index 53% rename from packages/sdk/demo/generic/src/api/module.ts rename to test/features/cli-directory/src/api/module.ts index b731ce60c..00239fb3b 100644 --- a/packages/sdk/demo/generic/src/api/module.ts +++ b/test/features/cli-directory/src/api/module.ts @@ -1,8 +1,3 @@ -/** - * @packageDocumentation - * @module api - */ -//================================================================ export * from "./IConnection"; export * from "./Primitive"; export * from "./HttpError"; diff --git a/test/features/cli-directory/src/api/structures/IPerformance.ts b/test/features/cli-directory/src/api/structures/IPerformance.ts new file mode 100644 index 000000000..a9e9336e1 --- /dev/null +++ b/test/features/cli-directory/src/api/structures/IPerformance.ts @@ -0,0 +1,10 @@ +/** + * Performance info. + * + * @author Samchon + */ +export interface IPerformance { + cpu: NodeJS.CpuUsage; + memory: NodeJS.MemoryUsage; + resource: NodeJS.ResourceUsage; +} diff --git a/test/features/cli-directory/src/api/structures/ISystem.ts b/test/features/cli-directory/src/api/structures/ISystem.ts new file mode 100644 index 000000000..68f05ca92 --- /dev/null +++ b/test/features/cli-directory/src/api/structures/ISystem.ts @@ -0,0 +1,81 @@ +/** + * System Information. + * + * @author Jeongho Nam + */ +export interface ISystem { + /** + * Random Unique ID. + */ + uid: number; + + /** + * `process.argv` + */ + arguments: string[]; + + /** + * Git commit info. + */ + commit: ISystem.ICommit; + + /** + * `package.json` + */ + package: ISystem.IPackage; + + /** + * Creation time of this server. + */ + created_at: string; +} + +export namespace ISystem { + /** + * Git commit info. + */ + export interface ICommit { + shortHash: string; + branch: string; + hash: string; + subject: string; + sanitizedSubject: string; + body: string; + author: ICommit.IUser; + committer: ICommit.IUser; + authored_at: string; + commited_at: string; + notes?: string; + tags: string[]; + } + export namespace ICommit { + /** + * Git user account info. + */ + export interface IUser { + name: string; + email: string; + } + } + + /** + * NPM package info. + */ + export interface IPackage { + name: string; + version: string; + description: string; + main?: string; + typings?: string; + scripts: Record; + repository: { type: "git"; url: string }; + author: string; + license: string; + bugs: { url: string }; + homepage: string; + devDependencies?: Record; + dependencies: Record; + publishConfig?: { registry: string }; + files?: string[]; + } +} diff --git a/test/features/cli-directory/src/controllers/HealthController.ts b/test/features/cli-directory/src/controllers/HealthController.ts new file mode 100644 index 000000000..a9ce3563b --- /dev/null +++ b/test/features/cli-directory/src/controllers/HealthController.ts @@ -0,0 +1,9 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +@Controller("health") +export class HealthController { + @core.TypedRoute.Get() + public get(): void {} +} diff --git a/test/features/cli-directory/src/controllers/PerformanceController.ts b/test/features/cli-directory/src/controllers/PerformanceController.ts new file mode 100644 index 000000000..798d64fae --- /dev/null +++ b/test/features/cli-directory/src/controllers/PerformanceController.ts @@ -0,0 +1,17 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +import { IPerformance } from "@api/lib/structures/IPerformance"; + +@Controller("performance") +export class PerformanceController { + @core.TypedRoute.Get() + public async get(): Promise { + return { + cpu: process.cpuUsage(), + memory: process.memoryUsage(), + resource: process.resourceUsage(), + }; + } +} diff --git a/test/features/cli-directory/src/test/features/test_api_health_check.ts b/test/features/cli-directory/src/test/features/test_api_health_check.ts new file mode 100644 index 000000000..c34703c71 --- /dev/null +++ b/test/features/cli-directory/src/test/features/test_api_health_check.ts @@ -0,0 +1,5 @@ +import api from "@api"; + +export const test_api_monitor_health_check = ( + connection: api.IConnection, +): Promise => api.functional.health.get(connection); diff --git a/test/features/cli-directory/src/test/features/test_api_performance.ts b/test/features/cli-directory/src/test/features/test_api_performance.ts new file mode 100644 index 000000000..55b6d2ca7 --- /dev/null +++ b/test/features/cli-directory/src/test/features/test_api_performance.ts @@ -0,0 +1,13 @@ +import typia from "typia"; + +import api from "@api"; +import { IPerformance } from "@api/lib/structures/IPerformance"; + +export const test_api_monitor_performance = async ( + connection: api.IConnection, +): Promise => { + const performance: IPerformance = await api.functional.performance.get( + connection, + ); + typia.assert(performance); +}; diff --git a/test/features/cli-directory/src/test/index.ts b/test/features/cli-directory/src/test/index.ts new file mode 100644 index 000000000..e89842739 --- /dev/null +++ b/test/features/cli-directory/src/test/index.ts @@ -0,0 +1,39 @@ +import { DynamicExecutor } from "@nestia/e2e"; + +import { Backend } from "../Backend"; + +async function main(): Promise { + const server: Backend = new Backend(); + await server.open(); + + const report: DynamicExecutor.IReport = await DynamicExecutor.validate({ + prefix: "test", + parameters: () => [ + { + host: "http://127.0.0.1:37000", + encryption: { + key: "A".repeat(32), + iv: "B".repeat(16), + }, + }, + ], + })(`${__dirname}/features`); + await server.close(); + + const exceptions: Error[] = report.executions + .filter((exec) => exec.error !== null) + .map((exec) => exec.error!); + if (exceptions.length === 0) { + console.log("Success"); + console.log("Elapsed time", report.time.toLocaleString(), `ms`); + } else { + // for (const exp of exceptions) console.log(exp); + console.log("Failed"); + console.log("Elapsed time", report.time.toLocaleString(), `ms`); + process.exit(-1); + } +} +main().catch((exp) => { + console.log(exp); + process.exit(-1); +}); diff --git a/test/features/cli-directory/swagger.json b/test/features/cli-directory/swagger.json new file mode 100644 index 000000000..238a06e7a --- /dev/null +++ b/test/features/cli-directory/swagger.json @@ -0,0 +1,282 @@ +{ + "openapi": "3.0.1", + "servers": [ + { + "url": "https://github.com/samchon/nestia", + "description": "insert your server url" + } + ], + "info": { + "version": "0.1.0", + "title": "Generated by nestia - https://github.com/samchon/nestia" + }, + "paths": { + "/health": { + "get": { + "tags": [], + "parameters": [], + "responses": { + "200": { + "description": "", + "x-nestia-encrypted": false + } + }, + "description": "", + "x-nestia-namespace": "health.get", + "x-nestia-jsDocTags": [] + } + }, + "/performance": { + "get": { + "tags": [], + "parameters": [], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IPerformance" + } + } + }, + "x-nestia-encrypted": false + } + }, + "description": "", + "x-nestia-namespace": "performance.get", + "x-nestia-jsDocTags": [] + } + } + }, + "components": { + "schemas": { + "IPerformance": { + "type": "object", + "properties": { + "cpu": { + "$ref": "#/components/schemas/_singlequote_process_singlequote_.global.NodeJS.CpuUsage", + "x-typia-required": true, + "x-typia-optional": false + }, + "memory": { + "$ref": "#/components/schemas/_singlequote_process_singlequote_.global.NodeJS.MemoryUsage", + "x-typia-required": true, + "x-typia-optional": false + }, + "resource": { + "$ref": "#/components/schemas/_singlequote_process_singlequote_.global.NodeJS.ResourceUsage", + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "cpu", + "memory", + "resource" + ], + "description": "Performance info.", + "x-typia-jsDocTags": [ + { + "name": "author", + "text": [ + { + "text": "Samchon", + "kind": "text" + } + ] + } + ] + }, + "_singlequote_process_singlequote_.global.NodeJS.CpuUsage": { + "type": "object", + "properties": { + "user": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "system": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "user", + "system" + ], + "x-typia-jsDocTags": [] + }, + "_singlequote_process_singlequote_.global.NodeJS.MemoryUsage": { + "type": "object", + "properties": { + "rss": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "heapTotal": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "heapUsed": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "external": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "arrayBuffers": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "rss", + "heapTotal", + "heapUsed", + "external", + "arrayBuffers" + ], + "x-typia-jsDocTags": [] + }, + "_singlequote_process_singlequote_.global.NodeJS.ResourceUsage": { + "type": "object", + "properties": { + "fsRead": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "fsWrite": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "involuntaryContextSwitches": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "ipcReceived": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "ipcSent": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "majorPageFault": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "maxRSS": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "minorPageFault": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "sharedMemorySize": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "signalsCount": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "swappedOut": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "systemCPUTime": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "unsharedDataSize": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "unsharedStackSize": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "userCPUTime": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "voluntaryContextSwitches": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "fsRead", + "fsWrite", + "involuntaryContextSwitches", + "ipcReceived", + "ipcSent", + "majorPageFault", + "maxRSS", + "minorPageFault", + "sharedMemorySize", + "signalsCount", + "swappedOut", + "systemCPUTime", + "unsharedDataSize", + "unsharedStackSize", + "userCPUTime", + "voluntaryContextSwitches" + ], + "x-typia-jsDocTags": [] + } + } + } +} \ No newline at end of file diff --git a/test/features/cli-directory/tsconfig.json b/test/features/cli-directory/tsconfig.json new file mode 100644 index 000000000..e5fe47a95 --- /dev/null +++ b/test/features/cli-directory/tsconfig.json @@ -0,0 +1,103 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + /* Language and Environment */ + "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + /* Modules */ + "module": "commonjs", /* Specify what module code is generated. */// "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + "paths": { + "@nestia/core": ["../../../packages/core/src"], + "@nestia/e2e": ["../../../packages/e2e/src"], + "@nestia/fetcher": ["../../../packages/fetcher/src"], + "@nestia/sdk": ["../../../packages/sdk/src"], + "@nestia/sdk/lib/*": ["../../../packages/sdk/src/*"], + "@api": ["./src/api"], + "@api/lib/*": ["./src/api/*"], + }, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. *//* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true, /* Skip type checking all .d.ts files. */ + "plugins": [ + { "transform": "typescript-transform-paths" }, + { "transform": "typia/lib/transform" }, + { "transform": "../../../packages/core/src/transform.ts" }, + ], + } + } \ No newline at end of file diff --git a/test/features/cli-pattern/src/Backend.ts b/test/features/cli-pattern/src/Backend.ts new file mode 100644 index 000000000..8d6de8b1b --- /dev/null +++ b/test/features/cli-pattern/src/Backend.ts @@ -0,0 +1,28 @@ +import { INestApplication } from "@nestjs/common"; +import { NestFactory } from "@nestjs/core"; + +import core from "@nestia/core"; + +export class Backend { + private application_?: INestApplication; + + public async open(): Promise { + this.application_ = await NestFactory.create( + await core.EncryptedModule.dynamic(__dirname + "/routes", { + key: "A".repeat(32), + iv: "B".repeat(16), + }), + { logger: false }, + ); + await this.application_.listen(37_000); + } + + public async close(): Promise { + if (this.application_ === undefined) return; + + const app = this.application_; + await app.close(); + + delete this.application_; + } +} diff --git a/packages/sdk/demo/multiple-paths/src/api/HttpError.ts b/test/features/cli-pattern/src/api/HttpError.ts similarity index 100% rename from packages/sdk/demo/multiple-paths/src/api/HttpError.ts rename to test/features/cli-pattern/src/api/HttpError.ts diff --git a/packages/sdk/demo/multiple-paths/src/api/IConnection.ts b/test/features/cli-pattern/src/api/IConnection.ts similarity index 100% rename from packages/sdk/demo/multiple-paths/src/api/IConnection.ts rename to test/features/cli-pattern/src/api/IConnection.ts diff --git a/packages/sdk/demo/multiple-paths/src/api/Primitive.ts b/test/features/cli-pattern/src/api/Primitive.ts similarity index 100% rename from packages/sdk/demo/multiple-paths/src/api/Primitive.ts rename to test/features/cli-pattern/src/api/Primitive.ts diff --git a/test/features/cli-pattern/src/api/functional/health/index.ts b/test/features/cli-pattern/src/api/functional/health/index.ts new file mode 100644 index 000000000..619581f93 --- /dev/null +++ b/test/features/cli-pattern/src/api/functional/health/index.ts @@ -0,0 +1,42 @@ +/** + * @packageDocumentation + * @module api.functional.health + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +import { Fetcher } from "@nestia/fetcher"; +import type { IConnection } from "@nestia/fetcher"; + +/** + * @controller HealthController.get() + * @path GET /health + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export function get + ( + connection: IConnection + ): Promise +{ + return Fetcher.fetch + ( + connection, + get.ENCRYPTED, + get.METHOD, + get.path() + ); +} +export namespace get +{ + + export const METHOD = "GET" as const; + export const PATH: string = "/health"; + export const ENCRYPTED: Fetcher.IEncrypted = { + request: false, + response: false, + }; + + export function path(): string + { + return `/health`; + } +} \ No newline at end of file diff --git a/packages/sdk/demo/296/src/api/functional/index.ts b/test/features/cli-pattern/src/api/functional/index.ts similarity index 70% rename from packages/sdk/demo/296/src/api/functional/index.ts rename to test/features/cli-pattern/src/api/functional/index.ts index 3d0f601fa..bc823f38c 100644 --- a/packages/sdk/demo/296/src/api/functional/index.ts +++ b/test/features/cli-pattern/src/api/functional/index.ts @@ -4,4 +4,5 @@ * @nestia Generated by Nestia - https://github.com/samchon/nestia */ //================================================================ -export * as user from "./user"; \ No newline at end of file +export * as health from "./health"; +export * as performance from "./performance"; \ No newline at end of file diff --git a/test/features/cli-pattern/src/api/functional/performance/index.ts b/test/features/cli-pattern/src/api/functional/performance/index.ts new file mode 100644 index 000000000..9e402a44a --- /dev/null +++ b/test/features/cli-pattern/src/api/functional/performance/index.ts @@ -0,0 +1,45 @@ +/** + * @packageDocumentation + * @module api.functional.performance + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +import { Fetcher, Primitive } from "@nestia/fetcher"; +import type { IConnection } from "@nestia/fetcher"; + +import type { IPerformance } from "./../../structures/IPerformance"; + +/** + * @controller PerformanceController.get() + * @path GET /performance + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export function get + ( + connection: IConnection + ): Promise +{ + return Fetcher.fetch + ( + connection, + get.ENCRYPTED, + get.METHOD, + get.path() + ); +} +export namespace get +{ + export type Output = Primitive; + + export const METHOD = "GET" as const; + export const PATH: string = "/performance"; + export const ENCRYPTED: Fetcher.IEncrypted = { + request: false, + response: false, + }; + + export function path(): string + { + return `/performance`; + } +} \ No newline at end of file diff --git a/test/features/cli-pattern/src/api/index.ts b/test/features/cli-pattern/src/api/index.ts new file mode 100644 index 000000000..1896c4fbd --- /dev/null +++ b/test/features/cli-pattern/src/api/index.ts @@ -0,0 +1,5 @@ +import * as api from "./module"; + +export * from "./module"; + +export default api; diff --git a/test/features/cli-pattern/src/api/module.ts b/test/features/cli-pattern/src/api/module.ts new file mode 100644 index 000000000..00239fb3b --- /dev/null +++ b/test/features/cli-pattern/src/api/module.ts @@ -0,0 +1,5 @@ +export * from "./IConnection"; +export * from "./Primitive"; +export * from "./HttpError"; + +export * as functional from "./functional"; diff --git a/test/features/cli-pattern/src/api/structures/IPerformance.ts b/test/features/cli-pattern/src/api/structures/IPerformance.ts new file mode 100644 index 000000000..a9e9336e1 --- /dev/null +++ b/test/features/cli-pattern/src/api/structures/IPerformance.ts @@ -0,0 +1,10 @@ +/** + * Performance info. + * + * @author Samchon + */ +export interface IPerformance { + cpu: NodeJS.CpuUsage; + memory: NodeJS.MemoryUsage; + resource: NodeJS.ResourceUsage; +} diff --git a/test/features/cli-pattern/src/api/structures/ISystem.ts b/test/features/cli-pattern/src/api/structures/ISystem.ts new file mode 100644 index 000000000..68f05ca92 --- /dev/null +++ b/test/features/cli-pattern/src/api/structures/ISystem.ts @@ -0,0 +1,81 @@ +/** + * System Information. + * + * @author Jeongho Nam + */ +export interface ISystem { + /** + * Random Unique ID. + */ + uid: number; + + /** + * `process.argv` + */ + arguments: string[]; + + /** + * Git commit info. + */ + commit: ISystem.ICommit; + + /** + * `package.json` + */ + package: ISystem.IPackage; + + /** + * Creation time of this server. + */ + created_at: string; +} + +export namespace ISystem { + /** + * Git commit info. + */ + export interface ICommit { + shortHash: string; + branch: string; + hash: string; + subject: string; + sanitizedSubject: string; + body: string; + author: ICommit.IUser; + committer: ICommit.IUser; + authored_at: string; + commited_at: string; + notes?: string; + tags: string[]; + } + export namespace ICommit { + /** + * Git user account info. + */ + export interface IUser { + name: string; + email: string; + } + } + + /** + * NPM package info. + */ + export interface IPackage { + name: string; + version: string; + description: string; + main?: string; + typings?: string; + scripts: Record; + repository: { type: "git"; url: string }; + author: string; + license: string; + bugs: { url: string }; + homepage: string; + devDependencies?: Record; + dependencies: Record; + publishConfig?: { registry: string }; + files?: string[]; + } +} diff --git a/test/features/cli-pattern/src/routes/health/health.controller.ts b/test/features/cli-pattern/src/routes/health/health.controller.ts new file mode 100644 index 000000000..a9ce3563b --- /dev/null +++ b/test/features/cli-pattern/src/routes/health/health.controller.ts @@ -0,0 +1,9 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +@Controller("health") +export class HealthController { + @core.TypedRoute.Get() + public get(): void {} +} diff --git a/test/features/cli-pattern/src/routes/performance/performance.controller.ts b/test/features/cli-pattern/src/routes/performance/performance.controller.ts new file mode 100644 index 000000000..798d64fae --- /dev/null +++ b/test/features/cli-pattern/src/routes/performance/performance.controller.ts @@ -0,0 +1,17 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +import { IPerformance } from "@api/lib/structures/IPerformance"; + +@Controller("performance") +export class PerformanceController { + @core.TypedRoute.Get() + public async get(): Promise { + return { + cpu: process.cpuUsage(), + memory: process.memoryUsage(), + resource: process.resourceUsage(), + }; + } +} diff --git a/test/features/cli-pattern/src/test/features/test_api_health_check.ts b/test/features/cli-pattern/src/test/features/test_api_health_check.ts new file mode 100644 index 000000000..c34703c71 --- /dev/null +++ b/test/features/cli-pattern/src/test/features/test_api_health_check.ts @@ -0,0 +1,5 @@ +import api from "@api"; + +export const test_api_monitor_health_check = ( + connection: api.IConnection, +): Promise => api.functional.health.get(connection); diff --git a/test/features/cli-pattern/src/test/features/test_api_performance.ts b/test/features/cli-pattern/src/test/features/test_api_performance.ts new file mode 100644 index 000000000..55b6d2ca7 --- /dev/null +++ b/test/features/cli-pattern/src/test/features/test_api_performance.ts @@ -0,0 +1,13 @@ +import typia from "typia"; + +import api from "@api"; +import { IPerformance } from "@api/lib/structures/IPerformance"; + +export const test_api_monitor_performance = async ( + connection: api.IConnection, +): Promise => { + const performance: IPerformance = await api.functional.performance.get( + connection, + ); + typia.assert(performance); +}; diff --git a/test/features/cli-pattern/src/test/index.ts b/test/features/cli-pattern/src/test/index.ts new file mode 100644 index 000000000..e89842739 --- /dev/null +++ b/test/features/cli-pattern/src/test/index.ts @@ -0,0 +1,39 @@ +import { DynamicExecutor } from "@nestia/e2e"; + +import { Backend } from "../Backend"; + +async function main(): Promise { + const server: Backend = new Backend(); + await server.open(); + + const report: DynamicExecutor.IReport = await DynamicExecutor.validate({ + prefix: "test", + parameters: () => [ + { + host: "http://127.0.0.1:37000", + encryption: { + key: "A".repeat(32), + iv: "B".repeat(16), + }, + }, + ], + })(`${__dirname}/features`); + await server.close(); + + const exceptions: Error[] = report.executions + .filter((exec) => exec.error !== null) + .map((exec) => exec.error!); + if (exceptions.length === 0) { + console.log("Success"); + console.log("Elapsed time", report.time.toLocaleString(), `ms`); + } else { + // for (const exp of exceptions) console.log(exp); + console.log("Failed"); + console.log("Elapsed time", report.time.toLocaleString(), `ms`); + process.exit(-1); + } +} +main().catch((exp) => { + console.log(exp); + process.exit(-1); +}); diff --git a/test/features/cli-pattern/swagger.json b/test/features/cli-pattern/swagger.json new file mode 100644 index 000000000..0ff2d8727 --- /dev/null +++ b/test/features/cli-pattern/swagger.json @@ -0,0 +1,294 @@ +{ + "openapi": "3.0.1", + "servers": [ + { + "url": "https://github.com/samchon/nestia", + "description": "insert your server url" + } + ], + "info": { + "version": "0.1.0", + "title": "Generated by nestia - https://github.com/samchon/nestia" + }, + "paths": { + "/health": { + "get": { + "tags": [], + "parameters": [], + "responses": { + "200": { + "description": "", + "x-nestia-encrypted": false + } + }, + "description": "", + "x-nestia-namespace": "health.get", + "x-nestia-jsDocTags": [] + } + }, + "/performance": { + "get": { + "tags": [], + "parameters": [], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IPerformance" + } + } + }, + "x-nestia-encrypted": false + } + }, + "description": "", + "x-nestia-namespace": "performance.get", + "x-nestia-jsDocTags": [] + } + } + }, + "components": { + "schemas": { + "IPerformance": { + "type": "object", + "properties": { + "cpu": { + "$ref": "#/components/schemas/_singlequote_process_singlequote_.global.NodeJS.CpuUsage", + "x-typia-required": true, + "x-typia-optional": false + }, + "memory": { + "$ref": "#/components/schemas/_singlequote_process_singlequote_.global.NodeJS.MemoryUsage", + "x-typia-required": true, + "x-typia-optional": false + }, + "resource": { + "$ref": "#/components/schemas/_singlequote_process_singlequote_.global.NodeJS.ResourceUsage", + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "cpu", + "memory", + "resource" + ], + "description": "Performance info.", + "x-typia-jsDocTags": [ + { + "name": "author", + "text": [ + { + "text": "Samchon", + "kind": "text" + } + ] + } + ] + }, + "_singlequote_process_singlequote_.global.NodeJS.CpuUsage": { + "type": "object", + "properties": { + "user": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "system": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "user", + "system" + ], + "x-typia-jsDocTags": [] + }, + "_singlequote_process_singlequote_.global.NodeJS.MemoryUsage": { + "type": "object", + "properties": { + "rss": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "heapTotal": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "heapUsed": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "external": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "arrayBuffers": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "rss", + "heapTotal", + "heapUsed", + "external", + "arrayBuffers" + ], + "x-typia-jsDocTags": [] + }, + "_singlequote_process_singlequote_.global.NodeJS.ResourceUsage": { + "type": "object", + "properties": { + "fsRead": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "fsWrite": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "involuntaryContextSwitches": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "ipcReceived": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "ipcSent": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "majorPageFault": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "maxRSS": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "minorPageFault": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "sharedMemorySize": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "signalsCount": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "swappedOut": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "systemCPUTime": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "unsharedDataSize": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "unsharedStackSize": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "userCPUTime": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "voluntaryContextSwitches": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "fsRead", + "fsWrite", + "involuntaryContextSwitches", + "ipcReceived", + "ipcSent", + "majorPageFault", + "maxRSS", + "minorPageFault", + "sharedMemorySize", + "signalsCount", + "swappedOut", + "systemCPUTime", + "unsharedDataSize", + "unsharedStackSize", + "userCPUTime", + "voluntaryContextSwitches" + ], + "x-typia-jsDocTags": [] + } + }, + "securitySchemes": { + "bearer": { + "type": "apiKey", + "in": "header", + "name": "Authorization" + } + } + }, + "security": [ + { + "bearer": [] + } + ] +} \ No newline at end of file diff --git a/test/features/cli-pattern/tsconfig.json b/test/features/cli-pattern/tsconfig.json new file mode 100644 index 000000000..e5fe47a95 --- /dev/null +++ b/test/features/cli-pattern/tsconfig.json @@ -0,0 +1,103 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + /* Language and Environment */ + "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + /* Modules */ + "module": "commonjs", /* Specify what module code is generated. */// "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + "paths": { + "@nestia/core": ["../../../packages/core/src"], + "@nestia/e2e": ["../../../packages/e2e/src"], + "@nestia/fetcher": ["../../../packages/fetcher/src"], + "@nestia/sdk": ["../../../packages/sdk/src"], + "@nestia/sdk/lib/*": ["../../../packages/sdk/src/*"], + "@api": ["./src/api"], + "@api/lib/*": ["./src/api/*"], + }, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. *//* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true, /* Skip type checking all .d.ts files. */ + "plugins": [ + { "transform": "typescript-transform-paths" }, + { "transform": "typia/lib/transform" }, + { "transform": "../../../packages/core/src/transform.ts" }, + ], + } + } \ No newline at end of file diff --git a/test/features/config-pattern/nestia.config.ts b/test/features/config-pattern/nestia.config.ts new file mode 100644 index 000000000..24322ff6e --- /dev/null +++ b/test/features/config-pattern/nestia.config.ts @@ -0,0 +1,15 @@ +import { INestiaConfig } from "@nestia/sdk"; + +export const NESTIA_CONFIG: INestiaConfig = { + input: ["src/**/*.controller.ts"], + output: "src/api", + swagger: { + output: "swagger.json", + security: { + bearer: { + type: "apiKey", + }, + }, + }, +}; +export default NESTIA_CONFIG; diff --git a/test/features/config-pattern/src/Backend.ts b/test/features/config-pattern/src/Backend.ts new file mode 100644 index 000000000..8d6de8b1b --- /dev/null +++ b/test/features/config-pattern/src/Backend.ts @@ -0,0 +1,28 @@ +import { INestApplication } from "@nestjs/common"; +import { NestFactory } from "@nestjs/core"; + +import core from "@nestia/core"; + +export class Backend { + private application_?: INestApplication; + + public async open(): Promise { + this.application_ = await NestFactory.create( + await core.EncryptedModule.dynamic(__dirname + "/routes", { + key: "A".repeat(32), + iv: "B".repeat(16), + }), + { logger: false }, + ); + await this.application_.listen(37_000); + } + + public async close(): Promise { + if (this.application_ === undefined) return; + + const app = this.application_; + await app.close(); + + delete this.application_; + } +} diff --git a/packages/sdk/demo/recursive/src/api/HttpError.ts b/test/features/config-pattern/src/api/HttpError.ts similarity index 100% rename from packages/sdk/demo/recursive/src/api/HttpError.ts rename to test/features/config-pattern/src/api/HttpError.ts diff --git a/packages/sdk/demo/recursive/src/api/IConnection.ts b/test/features/config-pattern/src/api/IConnection.ts similarity index 100% rename from packages/sdk/demo/recursive/src/api/IConnection.ts rename to test/features/config-pattern/src/api/IConnection.ts diff --git a/packages/sdk/demo/recursive/src/api/Primitive.ts b/test/features/config-pattern/src/api/Primitive.ts similarity index 100% rename from packages/sdk/demo/recursive/src/api/Primitive.ts rename to test/features/config-pattern/src/api/Primitive.ts diff --git a/test/features/config-pattern/src/api/functional/health/index.ts b/test/features/config-pattern/src/api/functional/health/index.ts new file mode 100644 index 000000000..619581f93 --- /dev/null +++ b/test/features/config-pattern/src/api/functional/health/index.ts @@ -0,0 +1,42 @@ +/** + * @packageDocumentation + * @module api.functional.health + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +import { Fetcher } from "@nestia/fetcher"; +import type { IConnection } from "@nestia/fetcher"; + +/** + * @controller HealthController.get() + * @path GET /health + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export function get + ( + connection: IConnection + ): Promise +{ + return Fetcher.fetch + ( + connection, + get.ENCRYPTED, + get.METHOD, + get.path() + ); +} +export namespace get +{ + + export const METHOD = "GET" as const; + export const PATH: string = "/health"; + export const ENCRYPTED: Fetcher.IEncrypted = { + request: false, + response: false, + }; + + export function path(): string + { + return `/health`; + } +} \ No newline at end of file diff --git a/packages/sdk/demo/encrypted/src/api/functional/index.ts b/test/features/config-pattern/src/api/functional/index.ts similarity index 70% rename from packages/sdk/demo/encrypted/src/api/functional/index.ts rename to test/features/config-pattern/src/api/functional/index.ts index 4331542bf..bc823f38c 100644 --- a/packages/sdk/demo/encrypted/src/api/functional/index.ts +++ b/test/features/config-pattern/src/api/functional/index.ts @@ -4,4 +4,5 @@ * @nestia Generated by Nestia - https://github.com/samchon/nestia */ //================================================================ -export * as sellers from "./sellers"; \ No newline at end of file +export * as health from "./health"; +export * as performance from "./performance"; \ No newline at end of file diff --git a/test/features/config-pattern/src/api/functional/performance/index.ts b/test/features/config-pattern/src/api/functional/performance/index.ts new file mode 100644 index 000000000..9e402a44a --- /dev/null +++ b/test/features/config-pattern/src/api/functional/performance/index.ts @@ -0,0 +1,45 @@ +/** + * @packageDocumentation + * @module api.functional.performance + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +import { Fetcher, Primitive } from "@nestia/fetcher"; +import type { IConnection } from "@nestia/fetcher"; + +import type { IPerformance } from "./../../structures/IPerformance"; + +/** + * @controller PerformanceController.get() + * @path GET /performance + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export function get + ( + connection: IConnection + ): Promise +{ + return Fetcher.fetch + ( + connection, + get.ENCRYPTED, + get.METHOD, + get.path() + ); +} +export namespace get +{ + export type Output = Primitive; + + export const METHOD = "GET" as const; + export const PATH: string = "/performance"; + export const ENCRYPTED: Fetcher.IEncrypted = { + request: false, + response: false, + }; + + export function path(): string + { + return `/performance`; + } +} \ No newline at end of file diff --git a/test/features/config-pattern/src/api/index.ts b/test/features/config-pattern/src/api/index.ts new file mode 100644 index 000000000..1896c4fbd --- /dev/null +++ b/test/features/config-pattern/src/api/index.ts @@ -0,0 +1,5 @@ +import * as api from "./module"; + +export * from "./module"; + +export default api; diff --git a/test/features/config-pattern/src/api/module.ts b/test/features/config-pattern/src/api/module.ts new file mode 100644 index 000000000..00239fb3b --- /dev/null +++ b/test/features/config-pattern/src/api/module.ts @@ -0,0 +1,5 @@ +export * from "./IConnection"; +export * from "./Primitive"; +export * from "./HttpError"; + +export * as functional from "./functional"; diff --git a/test/features/config-pattern/src/api/structures/IPerformance.ts b/test/features/config-pattern/src/api/structures/IPerformance.ts new file mode 100644 index 000000000..a9e9336e1 --- /dev/null +++ b/test/features/config-pattern/src/api/structures/IPerformance.ts @@ -0,0 +1,10 @@ +/** + * Performance info. + * + * @author Samchon + */ +export interface IPerformance { + cpu: NodeJS.CpuUsage; + memory: NodeJS.MemoryUsage; + resource: NodeJS.ResourceUsage; +} diff --git a/test/features/config-pattern/src/api/structures/ISystem.ts b/test/features/config-pattern/src/api/structures/ISystem.ts new file mode 100644 index 000000000..68f05ca92 --- /dev/null +++ b/test/features/config-pattern/src/api/structures/ISystem.ts @@ -0,0 +1,81 @@ +/** + * System Information. + * + * @author Jeongho Nam + */ +export interface ISystem { + /** + * Random Unique ID. + */ + uid: number; + + /** + * `process.argv` + */ + arguments: string[]; + + /** + * Git commit info. + */ + commit: ISystem.ICommit; + + /** + * `package.json` + */ + package: ISystem.IPackage; + + /** + * Creation time of this server. + */ + created_at: string; +} + +export namespace ISystem { + /** + * Git commit info. + */ + export interface ICommit { + shortHash: string; + branch: string; + hash: string; + subject: string; + sanitizedSubject: string; + body: string; + author: ICommit.IUser; + committer: ICommit.IUser; + authored_at: string; + commited_at: string; + notes?: string; + tags: string[]; + } + export namespace ICommit { + /** + * Git user account info. + */ + export interface IUser { + name: string; + email: string; + } + } + + /** + * NPM package info. + */ + export interface IPackage { + name: string; + version: string; + description: string; + main?: string; + typings?: string; + scripts: Record; + repository: { type: "git"; url: string }; + author: string; + license: string; + bugs: { url: string }; + homepage: string; + devDependencies?: Record; + dependencies: Record; + publishConfig?: { registry: string }; + files?: string[]; + } +} diff --git a/test/features/config-pattern/src/routes/health/health.controller.ts b/test/features/config-pattern/src/routes/health/health.controller.ts new file mode 100644 index 000000000..a9ce3563b --- /dev/null +++ b/test/features/config-pattern/src/routes/health/health.controller.ts @@ -0,0 +1,9 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +@Controller("health") +export class HealthController { + @core.TypedRoute.Get() + public get(): void {} +} diff --git a/test/features/config-pattern/src/routes/performance/performance.controller.ts b/test/features/config-pattern/src/routes/performance/performance.controller.ts new file mode 100644 index 000000000..798d64fae --- /dev/null +++ b/test/features/config-pattern/src/routes/performance/performance.controller.ts @@ -0,0 +1,17 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +import { IPerformance } from "@api/lib/structures/IPerformance"; + +@Controller("performance") +export class PerformanceController { + @core.TypedRoute.Get() + public async get(): Promise { + return { + cpu: process.cpuUsage(), + memory: process.memoryUsage(), + resource: process.resourceUsage(), + }; + } +} diff --git a/test/features/config-pattern/src/test/features/test_api_health_check.ts b/test/features/config-pattern/src/test/features/test_api_health_check.ts new file mode 100644 index 000000000..c34703c71 --- /dev/null +++ b/test/features/config-pattern/src/test/features/test_api_health_check.ts @@ -0,0 +1,5 @@ +import api from "@api"; + +export const test_api_monitor_health_check = ( + connection: api.IConnection, +): Promise => api.functional.health.get(connection); diff --git a/test/features/config-pattern/src/test/features/test_api_performance.ts b/test/features/config-pattern/src/test/features/test_api_performance.ts new file mode 100644 index 000000000..55b6d2ca7 --- /dev/null +++ b/test/features/config-pattern/src/test/features/test_api_performance.ts @@ -0,0 +1,13 @@ +import typia from "typia"; + +import api from "@api"; +import { IPerformance } from "@api/lib/structures/IPerformance"; + +export const test_api_monitor_performance = async ( + connection: api.IConnection, +): Promise => { + const performance: IPerformance = await api.functional.performance.get( + connection, + ); + typia.assert(performance); +}; diff --git a/test/features/config-pattern/src/test/index.ts b/test/features/config-pattern/src/test/index.ts new file mode 100644 index 000000000..e89842739 --- /dev/null +++ b/test/features/config-pattern/src/test/index.ts @@ -0,0 +1,39 @@ +import { DynamicExecutor } from "@nestia/e2e"; + +import { Backend } from "../Backend"; + +async function main(): Promise { + const server: Backend = new Backend(); + await server.open(); + + const report: DynamicExecutor.IReport = await DynamicExecutor.validate({ + prefix: "test", + parameters: () => [ + { + host: "http://127.0.0.1:37000", + encryption: { + key: "A".repeat(32), + iv: "B".repeat(16), + }, + }, + ], + })(`${__dirname}/features`); + await server.close(); + + const exceptions: Error[] = report.executions + .filter((exec) => exec.error !== null) + .map((exec) => exec.error!); + if (exceptions.length === 0) { + console.log("Success"); + console.log("Elapsed time", report.time.toLocaleString(), `ms`); + } else { + // for (const exp of exceptions) console.log(exp); + console.log("Failed"); + console.log("Elapsed time", report.time.toLocaleString(), `ms`); + process.exit(-1); + } +} +main().catch((exp) => { + console.log(exp); + process.exit(-1); +}); diff --git a/test/features/config-pattern/swagger.json b/test/features/config-pattern/swagger.json new file mode 100644 index 000000000..0ff2d8727 --- /dev/null +++ b/test/features/config-pattern/swagger.json @@ -0,0 +1,294 @@ +{ + "openapi": "3.0.1", + "servers": [ + { + "url": "https://github.com/samchon/nestia", + "description": "insert your server url" + } + ], + "info": { + "version": "0.1.0", + "title": "Generated by nestia - https://github.com/samchon/nestia" + }, + "paths": { + "/health": { + "get": { + "tags": [], + "parameters": [], + "responses": { + "200": { + "description": "", + "x-nestia-encrypted": false + } + }, + "description": "", + "x-nestia-namespace": "health.get", + "x-nestia-jsDocTags": [] + } + }, + "/performance": { + "get": { + "tags": [], + "parameters": [], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IPerformance" + } + } + }, + "x-nestia-encrypted": false + } + }, + "description": "", + "x-nestia-namespace": "performance.get", + "x-nestia-jsDocTags": [] + } + } + }, + "components": { + "schemas": { + "IPerformance": { + "type": "object", + "properties": { + "cpu": { + "$ref": "#/components/schemas/_singlequote_process_singlequote_.global.NodeJS.CpuUsage", + "x-typia-required": true, + "x-typia-optional": false + }, + "memory": { + "$ref": "#/components/schemas/_singlequote_process_singlequote_.global.NodeJS.MemoryUsage", + "x-typia-required": true, + "x-typia-optional": false + }, + "resource": { + "$ref": "#/components/schemas/_singlequote_process_singlequote_.global.NodeJS.ResourceUsage", + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "cpu", + "memory", + "resource" + ], + "description": "Performance info.", + "x-typia-jsDocTags": [ + { + "name": "author", + "text": [ + { + "text": "Samchon", + "kind": "text" + } + ] + } + ] + }, + "_singlequote_process_singlequote_.global.NodeJS.CpuUsage": { + "type": "object", + "properties": { + "user": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "system": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "user", + "system" + ], + "x-typia-jsDocTags": [] + }, + "_singlequote_process_singlequote_.global.NodeJS.MemoryUsage": { + "type": "object", + "properties": { + "rss": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "heapTotal": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "heapUsed": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "external": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "arrayBuffers": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "rss", + "heapTotal", + "heapUsed", + "external", + "arrayBuffers" + ], + "x-typia-jsDocTags": [] + }, + "_singlequote_process_singlequote_.global.NodeJS.ResourceUsage": { + "type": "object", + "properties": { + "fsRead": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "fsWrite": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "involuntaryContextSwitches": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "ipcReceived": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "ipcSent": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "majorPageFault": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "maxRSS": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "minorPageFault": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "sharedMemorySize": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "signalsCount": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "swappedOut": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "systemCPUTime": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "unsharedDataSize": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "unsharedStackSize": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "userCPUTime": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "voluntaryContextSwitches": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "fsRead", + "fsWrite", + "involuntaryContextSwitches", + "ipcReceived", + "ipcSent", + "majorPageFault", + "maxRSS", + "minorPageFault", + "sharedMemorySize", + "signalsCount", + "swappedOut", + "systemCPUTime", + "unsharedDataSize", + "unsharedStackSize", + "userCPUTime", + "voluntaryContextSwitches" + ], + "x-typia-jsDocTags": [] + } + }, + "securitySchemes": { + "bearer": { + "type": "apiKey", + "in": "header", + "name": "Authorization" + } + } + }, + "security": [ + { + "bearer": [] + } + ] +} \ No newline at end of file diff --git a/test/features/config-pattern/tsconfig.json b/test/features/config-pattern/tsconfig.json new file mode 100644 index 000000000..e5fe47a95 --- /dev/null +++ b/test/features/config-pattern/tsconfig.json @@ -0,0 +1,103 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + /* Language and Environment */ + "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + /* Modules */ + "module": "commonjs", /* Specify what module code is generated. */// "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + "paths": { + "@nestia/core": ["../../../packages/core/src"], + "@nestia/e2e": ["../../../packages/e2e/src"], + "@nestia/fetcher": ["../../../packages/fetcher/src"], + "@nestia/sdk": ["../../../packages/sdk/src"], + "@nestia/sdk/lib/*": ["../../../packages/sdk/src/*"], + "@api": ["./src/api"], + "@api/lib/*": ["./src/api/*"], + }, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. *//* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true, /* Skip type checking all .d.ts files. */ + "plugins": [ + { "transform": "typescript-transform-paths" }, + { "transform": "typia/lib/transform" }, + { "transform": "../../../packages/core/src/transform.ts" }, + ], + } + } \ No newline at end of file diff --git a/test/features/duplicated/nestia.config.ts b/test/features/duplicated/nestia.config.ts new file mode 100644 index 000000000..2594a40d0 --- /dev/null +++ b/test/features/duplicated/nestia.config.ts @@ -0,0 +1,15 @@ +import { INestiaConfig } from "@nestia/sdk"; + +export const NESTIA_CONFIG: INestiaConfig = { + input: ["src/controllers"], + output: "src/api", + swagger: { + output: "swagger.json", + security: { + bearer: { + type: "apiKey", + }, + }, + }, +}; +export default NESTIA_CONFIG; diff --git a/test/features/duplicated/src/Backend.ts b/test/features/duplicated/src/Backend.ts new file mode 100644 index 000000000..8ab51b70f --- /dev/null +++ b/test/features/duplicated/src/Backend.ts @@ -0,0 +1,28 @@ +import { INestApplication } from "@nestjs/common"; +import { NestFactory } from "@nestjs/core"; + +import core from "@nestia/core"; + +export class Backend { + private application_?: INestApplication; + + public async open(): Promise { + this.application_ = await NestFactory.create( + await core.EncryptedModule.dynamic(__dirname + "/controllers", { + key: "A".repeat(32), + iv: "B".repeat(16), + }), + { logger: false }, + ); + await this.application_.listen(37_000); + } + + public async close(): Promise { + if (this.application_ === undefined) return; + + const app = this.application_; + await app.close(); + + delete this.application_; + } +} diff --git a/packages/sdk/demo/safe/src/api/HttpError.ts b/test/features/duplicated/src/api/HttpError.ts similarity index 100% rename from packages/sdk/demo/safe/src/api/HttpError.ts rename to test/features/duplicated/src/api/HttpError.ts diff --git a/packages/sdk/demo/safe/src/api/IConnection.ts b/test/features/duplicated/src/api/IConnection.ts similarity index 100% rename from packages/sdk/demo/safe/src/api/IConnection.ts rename to test/features/duplicated/src/api/IConnection.ts diff --git a/packages/sdk/demo/safe/src/api/Primitive.ts b/test/features/duplicated/src/api/Primitive.ts similarity index 100% rename from packages/sdk/demo/safe/src/api/Primitive.ts rename to test/features/duplicated/src/api/Primitive.ts diff --git a/test/features/duplicated/src/api/functional/duplicated/get/index.ts b/test/features/duplicated/src/api/functional/duplicated/get/index.ts new file mode 100644 index 000000000..9284d9855 --- /dev/null +++ b/test/features/duplicated/src/api/functional/duplicated/get/index.ts @@ -0,0 +1,45 @@ +/** + * @packageDocumentation + * @module api.functional.duplicated.get + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +import { Fetcher, Primitive } from "@nestia/fetcher"; +import type { IConnection } from "@nestia/fetcher"; + +import type { IBbsArticle } from "./../../../structures/IBbsArticle"; + +/** + * @controller DuplicatedController.at() + * @path GET /duplicated/get + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export function at + ( + connection: IConnection + ): Promise +{ + return Fetcher.fetch + ( + connection, + at.ENCRYPTED, + at.METHOD, + at.path() + ); +} +export namespace at +{ + export type Output = Primitive; + + export const METHOD = "GET" as const; + export const PATH: string = "/duplicated/get"; + export const ENCRYPTED: Fetcher.IEncrypted = { + request: false, + response: false, + }; + + export function path(): string + { + return `/duplicated/get`; + } +} \ No newline at end of file diff --git a/test/features/duplicated/src/api/functional/duplicated/index.ts b/test/features/duplicated/src/api/functional/duplicated/index.ts new file mode 100644 index 000000000..b67bf0545 --- /dev/null +++ b/test/features/duplicated/src/api/functional/duplicated/index.ts @@ -0,0 +1,45 @@ +/** + * @packageDocumentation + * @module api.functional.duplicated + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +import { Fetcher, Primitive } from "@nestia/fetcher"; +import type { IConnection } from "@nestia/fetcher"; + +import type { IBbsArticle } from "./../../structures/IBbsArticle"; + +/** + * @controller DuplicatedController.at() + * @path GET /duplicated/at + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export function at + ( + connection: IConnection + ): Promise +{ + return Fetcher.fetch + ( + connection, + at.ENCRYPTED, + at.METHOD, + at.path() + ); +} +export namespace at +{ + export type Output = Primitive; + + export const METHOD = "GET" as const; + export const PATH: string = "/duplicated/at"; + export const ENCRYPTED: Fetcher.IEncrypted = { + request: false, + response: false, + }; + + export function path(): string + { + return `/duplicated/at`; + } +} \ No newline at end of file diff --git a/test/features/duplicated/src/api/functional/health/index.ts b/test/features/duplicated/src/api/functional/health/index.ts new file mode 100644 index 000000000..619581f93 --- /dev/null +++ b/test/features/duplicated/src/api/functional/health/index.ts @@ -0,0 +1,42 @@ +/** + * @packageDocumentation + * @module api.functional.health + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +import { Fetcher } from "@nestia/fetcher"; +import type { IConnection } from "@nestia/fetcher"; + +/** + * @controller HealthController.get() + * @path GET /health + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export function get + ( + connection: IConnection + ): Promise +{ + return Fetcher.fetch + ( + connection, + get.ENCRYPTED, + get.METHOD, + get.path() + ); +} +export namespace get +{ + + export const METHOD = "GET" as const; + export const PATH: string = "/health"; + export const ENCRYPTED: Fetcher.IEncrypted = { + request: false, + response: false, + }; + + export function path(): string + { + return `/health`; + } +} \ No newline at end of file diff --git a/test/features/duplicated/src/api/functional/index.ts b/test/features/duplicated/src/api/functional/index.ts new file mode 100644 index 000000000..335719ace --- /dev/null +++ b/test/features/duplicated/src/api/functional/index.ts @@ -0,0 +1,10 @@ +/** + * @packageDocumentation + * @module api.functional + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +export * as duplicated from "./duplicated"; +export * as multiple from "./multiple"; +export * as health from "./health"; +export * as performance from "./performance"; \ No newline at end of file diff --git a/test/features/duplicated/src/api/functional/multiple/get/index.ts b/test/features/duplicated/src/api/functional/multiple/get/index.ts new file mode 100644 index 000000000..c3a37d8ac --- /dev/null +++ b/test/features/duplicated/src/api/functional/multiple/get/index.ts @@ -0,0 +1,45 @@ +/** + * @packageDocumentation + * @module api.functional.multiple.get + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +import { Fetcher, Primitive } from "@nestia/fetcher"; +import type { IConnection } from "@nestia/fetcher"; + +import type { IBbsArticle } from "./../../../structures/IBbsArticle"; + +/** + * @controller DuplicatedController.at() + * @path GET /multiple/get + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export function at + ( + connection: IConnection + ): Promise +{ + return Fetcher.fetch + ( + connection, + at.ENCRYPTED, + at.METHOD, + at.path() + ); +} +export namespace at +{ + export type Output = Primitive; + + export const METHOD = "GET" as const; + export const PATH: string = "/multiple/get"; + export const ENCRYPTED: Fetcher.IEncrypted = { + request: false, + response: false, + }; + + export function path(): string + { + return `/multiple/get`; + } +} \ No newline at end of file diff --git a/test/features/duplicated/src/api/functional/multiple/index.ts b/test/features/duplicated/src/api/functional/multiple/index.ts new file mode 100644 index 000000000..fb2d1a1ec --- /dev/null +++ b/test/features/duplicated/src/api/functional/multiple/index.ts @@ -0,0 +1,45 @@ +/** + * @packageDocumentation + * @module api.functional.multiple + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +import { Fetcher, Primitive } from "@nestia/fetcher"; +import type { IConnection } from "@nestia/fetcher"; + +import type { IBbsArticle } from "./../../structures/IBbsArticle"; + +/** + * @controller DuplicatedController.at() + * @path GET /multiple/at + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export function at + ( + connection: IConnection + ): Promise +{ + return Fetcher.fetch + ( + connection, + at.ENCRYPTED, + at.METHOD, + at.path() + ); +} +export namespace at +{ + export type Output = Primitive; + + export const METHOD = "GET" as const; + export const PATH: string = "/multiple/at"; + export const ENCRYPTED: Fetcher.IEncrypted = { + request: false, + response: false, + }; + + export function path(): string + { + return `/multiple/at`; + } +} \ No newline at end of file diff --git a/test/features/duplicated/src/api/functional/performance/index.ts b/test/features/duplicated/src/api/functional/performance/index.ts new file mode 100644 index 000000000..9e402a44a --- /dev/null +++ b/test/features/duplicated/src/api/functional/performance/index.ts @@ -0,0 +1,45 @@ +/** + * @packageDocumentation + * @module api.functional.performance + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +import { Fetcher, Primitive } from "@nestia/fetcher"; +import type { IConnection } from "@nestia/fetcher"; + +import type { IPerformance } from "./../../structures/IPerformance"; + +/** + * @controller PerformanceController.get() + * @path GET /performance + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export function get + ( + connection: IConnection + ): Promise +{ + return Fetcher.fetch + ( + connection, + get.ENCRYPTED, + get.METHOD, + get.path() + ); +} +export namespace get +{ + export type Output = Primitive; + + export const METHOD = "GET" as const; + export const PATH: string = "/performance"; + export const ENCRYPTED: Fetcher.IEncrypted = { + request: false, + response: false, + }; + + export function path(): string + { + return `/performance`; + } +} \ No newline at end of file diff --git a/test/features/duplicated/src/api/index.ts b/test/features/duplicated/src/api/index.ts new file mode 100644 index 000000000..1896c4fbd --- /dev/null +++ b/test/features/duplicated/src/api/index.ts @@ -0,0 +1,5 @@ +import * as api from "./module"; + +export * from "./module"; + +export default api; diff --git a/test/features/duplicated/src/api/module.ts b/test/features/duplicated/src/api/module.ts new file mode 100644 index 000000000..00239fb3b --- /dev/null +++ b/test/features/duplicated/src/api/module.ts @@ -0,0 +1,5 @@ +export * from "./IConnection"; +export * from "./Primitive"; +export * from "./HttpError"; + +export * as functional from "./functional"; diff --git a/test/features/duplicated/src/api/structures/IBbsArticle.ts b/test/features/duplicated/src/api/structures/IBbsArticle.ts new file mode 100644 index 000000000..a5188f20c --- /dev/null +++ b/test/features/duplicated/src/api/structures/IBbsArticle.ts @@ -0,0 +1,40 @@ +export interface IBbsArticle { + /** + * @format uuid + */ + id: string; + + /** + * @minLength 3 + * @maxLength 50 + */ + title: string; + + body: string; + + files: IAttachmentFile[]; + + /** + * @format date-time + */ + created_at: string; +} + +export interface IAttachmentFile { + /** + * @minLengt 1 + * @maxLength 255 + */ + name: string | null; + + /** + * @minLength 1 + * @maxLength 8 + */ + extension: string | null; + + /** + * @format url + */ + url: string; +} diff --git a/test/features/duplicated/src/api/structures/IPerformance.ts b/test/features/duplicated/src/api/structures/IPerformance.ts new file mode 100644 index 000000000..a9e9336e1 --- /dev/null +++ b/test/features/duplicated/src/api/structures/IPerformance.ts @@ -0,0 +1,10 @@ +/** + * Performance info. + * + * @author Samchon + */ +export interface IPerformance { + cpu: NodeJS.CpuUsage; + memory: NodeJS.MemoryUsage; + resource: NodeJS.ResourceUsage; +} diff --git a/test/features/duplicated/src/api/structures/ISystem.ts b/test/features/duplicated/src/api/structures/ISystem.ts new file mode 100644 index 000000000..68f05ca92 --- /dev/null +++ b/test/features/duplicated/src/api/structures/ISystem.ts @@ -0,0 +1,81 @@ +/** + * System Information. + * + * @author Jeongho Nam + */ +export interface ISystem { + /** + * Random Unique ID. + */ + uid: number; + + /** + * `process.argv` + */ + arguments: string[]; + + /** + * Git commit info. + */ + commit: ISystem.ICommit; + + /** + * `package.json` + */ + package: ISystem.IPackage; + + /** + * Creation time of this server. + */ + created_at: string; +} + +export namespace ISystem { + /** + * Git commit info. + */ + export interface ICommit { + shortHash: string; + branch: string; + hash: string; + subject: string; + sanitizedSubject: string; + body: string; + author: ICommit.IUser; + committer: ICommit.IUser; + authored_at: string; + commited_at: string; + notes?: string; + tags: string[]; + } + export namespace ICommit { + /** + * Git user account info. + */ + export interface IUser { + name: string; + email: string; + } + } + + /** + * NPM package info. + */ + export interface IPackage { + name: string; + version: string; + description: string; + main?: string; + typings?: string; + scripts: Record; + repository: { type: "git"; url: string }; + author: string; + license: string; + bugs: { url: string }; + homepage: string; + devDependencies?: Record; + dependencies: Record; + publishConfig?: { registry: string }; + files?: string[]; + } +} diff --git a/test/features/duplicated/src/controllers/DuplicatedController.ts b/test/features/duplicated/src/controllers/DuplicatedController.ts new file mode 100644 index 000000000..961639bb6 --- /dev/null +++ b/test/features/duplicated/src/controllers/DuplicatedController.ts @@ -0,0 +1,16 @@ +import { Controller } from "@nestjs/common"; +import typia from "typia"; + +import core from "@nestia/core"; + +import { IBbsArticle } from "@api/lib/structures/IBbsArticle"; + +@Controller(["duplicated", "multiple"]) +export class DuplicatedController { + @core.TypedRoute.Get("at") + public async at(): Promise { + return article; + } +} + +const article: IBbsArticle = typia.random(); diff --git a/test/features/duplicated/src/controllers/HealthController.ts b/test/features/duplicated/src/controllers/HealthController.ts new file mode 100644 index 000000000..a9ce3563b --- /dev/null +++ b/test/features/duplicated/src/controllers/HealthController.ts @@ -0,0 +1,9 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +@Controller("health") +export class HealthController { + @core.TypedRoute.Get() + public get(): void {} +} diff --git a/test/features/duplicated/src/controllers/PerformanceController.ts b/test/features/duplicated/src/controllers/PerformanceController.ts new file mode 100644 index 000000000..798d64fae --- /dev/null +++ b/test/features/duplicated/src/controllers/PerformanceController.ts @@ -0,0 +1,17 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +import { IPerformance } from "@api/lib/structures/IPerformance"; + +@Controller("performance") +export class PerformanceController { + @core.TypedRoute.Get() + public async get(): Promise { + return { + cpu: process.cpuUsage(), + memory: process.memoryUsage(), + resource: process.resourceUsage(), + }; + } +} diff --git a/test/features/duplicated/src/test/features/test_api_duplicated.ts b/test/features/duplicated/src/test/features/test_api_duplicated.ts new file mode 100644 index 000000000..47bc4403e --- /dev/null +++ b/test/features/duplicated/src/test/features/test_api_duplicated.ts @@ -0,0 +1,18 @@ +import typia from "typia"; + +import api from "@api"; +import { IBbsArticle } from "@api/lib/structures/IBbsArticle"; + +import { TestValidator } from "../../../../../../packages/e2e/src/TestValidator"; + +export const test_api_duplicated = async ( + connection: api.IConnection, +): Promise => { + const [x, y]: [IBbsArticle, IBbsArticle] = [ + await api.functional.duplicated.at(connection), + await api.functional.multiple.at(connection), + ]; + typia.assertEquals([x, y]); + + TestValidator.equals("duplicated")(x)(y); +}; diff --git a/test/features/duplicated/src/test/features/test_api_health_check.ts b/test/features/duplicated/src/test/features/test_api_health_check.ts new file mode 100644 index 000000000..c34703c71 --- /dev/null +++ b/test/features/duplicated/src/test/features/test_api_health_check.ts @@ -0,0 +1,5 @@ +import api from "@api"; + +export const test_api_monitor_health_check = ( + connection: api.IConnection, +): Promise => api.functional.health.get(connection); diff --git a/test/features/duplicated/src/test/features/test_api_performance.ts b/test/features/duplicated/src/test/features/test_api_performance.ts new file mode 100644 index 000000000..55b6d2ca7 --- /dev/null +++ b/test/features/duplicated/src/test/features/test_api_performance.ts @@ -0,0 +1,13 @@ +import typia from "typia"; + +import api from "@api"; +import { IPerformance } from "@api/lib/structures/IPerformance"; + +export const test_api_monitor_performance = async ( + connection: api.IConnection, +): Promise => { + const performance: IPerformance = await api.functional.performance.get( + connection, + ); + typia.assert(performance); +}; diff --git a/test/features/duplicated/src/test/index.ts b/test/features/duplicated/src/test/index.ts new file mode 100644 index 000000000..e89842739 --- /dev/null +++ b/test/features/duplicated/src/test/index.ts @@ -0,0 +1,39 @@ +import { DynamicExecutor } from "@nestia/e2e"; + +import { Backend } from "../Backend"; + +async function main(): Promise { + const server: Backend = new Backend(); + await server.open(); + + const report: DynamicExecutor.IReport = await DynamicExecutor.validate({ + prefix: "test", + parameters: () => [ + { + host: "http://127.0.0.1:37000", + encryption: { + key: "A".repeat(32), + iv: "B".repeat(16), + }, + }, + ], + })(`${__dirname}/features`); + await server.close(); + + const exceptions: Error[] = report.executions + .filter((exec) => exec.error !== null) + .map((exec) => exec.error!); + if (exceptions.length === 0) { + console.log("Success"); + console.log("Elapsed time", report.time.toLocaleString(), `ms`); + } else { + // for (const exp of exceptions) console.log(exp); + console.log("Failed"); + console.log("Elapsed time", report.time.toLocaleString(), `ms`); + process.exit(-1); + } +} +main().catch((exp) => { + console.log(exp); + process.exit(-1); +}); diff --git a/test/features/duplicated/swagger.json b/test/features/duplicated/swagger.json new file mode 100644 index 000000000..3fde69231 --- /dev/null +++ b/test/features/duplicated/swagger.json @@ -0,0 +1,562 @@ +{ + "openapi": "3.0.1", + "servers": [ + { + "url": "https://github.com/samchon/nestia", + "description": "insert your server url" + } + ], + "info": { + "version": "0.1.0", + "title": "Generated by nestia - https://github.com/samchon/nestia" + }, + "paths": { + "/duplicated/at": { + "get": { + "tags": [], + "parameters": [], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IBbsArticle" + } + } + }, + "x-nestia-encrypted": false + } + }, + "description": "", + "x-nestia-namespace": "duplicated.at.at", + "x-nestia-jsDocTags": [] + } + }, + "/multiple/at": { + "get": { + "tags": [], + "parameters": [], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IBbsArticle" + } + } + }, + "x-nestia-encrypted": false + } + }, + "description": "", + "x-nestia-namespace": "multiple.at.at", + "x-nestia-jsDocTags": [] + } + }, + "/health": { + "get": { + "tags": [], + "parameters": [], + "responses": { + "200": { + "description": "", + "x-nestia-encrypted": false + } + }, + "description": "", + "x-nestia-namespace": "health.get", + "x-nestia-jsDocTags": [] + } + }, + "/performance": { + "get": { + "tags": [], + "parameters": [], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IPerformance" + } + } + }, + "x-nestia-encrypted": false + } + }, + "description": "", + "x-nestia-namespace": "performance.get", + "x-nestia-jsDocTags": [] + } + } + }, + "components": { + "schemas": { + "IBbsArticle": { + "type": "object", + "properties": { + "id": { + "type": "string", + "nullable": false, + "x-typia-metaTags": [ + { + "kind": "format", + "value": "uuid" + } + ], + "x-typia-jsDocTags": [ + { + "name": "format", + "text": [ + { + "text": "uuid", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "format": "uuid" + }, + "title": { + "type": "string", + "nullable": false, + "x-typia-metaTags": [ + { + "kind": "minLength", + "value": 3 + }, + { + "kind": "maxLength", + "value": 50 + } + ], + "x-typia-jsDocTags": [ + { + "name": "minLength", + "text": [ + { + "text": "3", + "kind": "text" + } + ] + }, + { + "name": "maxLength", + "text": [ + { + "text": "50", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "minLength": 3, + "maxLength": 50 + }, + "body": { + "type": "string", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "files": { + "type": "array", + "items": { + "$ref": "#/components/schemas/IAttachmentFile", + "x-typia-required": true, + "x-typia-optional": false + }, + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "created_at": { + "type": "string", + "nullable": false, + "x-typia-metaTags": [ + { + "kind": "format", + "value": "datetime" + } + ], + "x-typia-jsDocTags": [ + { + "name": "format", + "text": [ + { + "text": "date-time", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "format": "date-time" + } + }, + "nullable": false, + "required": [ + "id", + "title", + "body", + "files", + "created_at" + ], + "x-typia-jsDocTags": [] + }, + "IAttachmentFile": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "x-typia-metaTags": [ + { + "kind": "maxLength", + "value": 255 + } + ], + "x-typia-jsDocTags": [ + { + "name": "minLengt", + "text": [ + { + "text": "1", + "kind": "text" + } + ] + }, + { + "name": "maxLength", + "text": [ + { + "text": "255", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "maxLength": 255 + }, + "extension": { + "type": "string", + "nullable": true, + "x-typia-metaTags": [ + { + "kind": "minLength", + "value": 1 + }, + { + "kind": "maxLength", + "value": 8 + } + ], + "x-typia-jsDocTags": [ + { + "name": "minLength", + "text": [ + { + "text": "1", + "kind": "text" + } + ] + }, + { + "name": "maxLength", + "text": [ + { + "text": "8", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "minLength": 1, + "maxLength": 8 + }, + "url": { + "type": "string", + "nullable": false, + "x-typia-metaTags": [ + { + "kind": "format", + "value": "url" + } + ], + "x-typia-jsDocTags": [ + { + "name": "format", + "text": [ + { + "text": "url", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "format": "url" + } + }, + "nullable": false, + "required": [ + "name", + "extension", + "url" + ], + "x-typia-jsDocTags": [] + }, + "IPerformance": { + "type": "object", + "properties": { + "cpu": { + "$ref": "#/components/schemas/_singlequote_process_singlequote_.global.NodeJS.CpuUsage", + "x-typia-required": true, + "x-typia-optional": false + }, + "memory": { + "$ref": "#/components/schemas/_singlequote_process_singlequote_.global.NodeJS.MemoryUsage", + "x-typia-required": true, + "x-typia-optional": false + }, + "resource": { + "$ref": "#/components/schemas/_singlequote_process_singlequote_.global.NodeJS.ResourceUsage", + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "cpu", + "memory", + "resource" + ], + "description": "Performance info.", + "x-typia-jsDocTags": [ + { + "name": "author", + "text": [ + { + "text": "Samchon", + "kind": "text" + } + ] + } + ] + }, + "_singlequote_process_singlequote_.global.NodeJS.CpuUsage": { + "type": "object", + "properties": { + "user": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "system": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "user", + "system" + ], + "x-typia-jsDocTags": [] + }, + "_singlequote_process_singlequote_.global.NodeJS.MemoryUsage": { + "type": "object", + "properties": { + "rss": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "heapTotal": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "heapUsed": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "external": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "arrayBuffers": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "rss", + "heapTotal", + "heapUsed", + "external", + "arrayBuffers" + ], + "x-typia-jsDocTags": [] + }, + "_singlequote_process_singlequote_.global.NodeJS.ResourceUsage": { + "type": "object", + "properties": { + "fsRead": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "fsWrite": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "involuntaryContextSwitches": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "ipcReceived": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "ipcSent": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "majorPageFault": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "maxRSS": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "minorPageFault": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "sharedMemorySize": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "signalsCount": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "swappedOut": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "systemCPUTime": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "unsharedDataSize": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "unsharedStackSize": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "userCPUTime": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "voluntaryContextSwitches": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "fsRead", + "fsWrite", + "involuntaryContextSwitches", + "ipcReceived", + "ipcSent", + "majorPageFault", + "maxRSS", + "minorPageFault", + "sharedMemorySize", + "signalsCount", + "swappedOut", + "systemCPUTime", + "unsharedDataSize", + "unsharedStackSize", + "userCPUTime", + "voluntaryContextSwitches" + ], + "x-typia-jsDocTags": [] + } + }, + "securitySchemes": { + "bearer": { + "type": "apiKey", + "in": "header", + "name": "Authorization" + } + } + }, + "security": [ + { + "bearer": [] + } + ] +} \ No newline at end of file diff --git a/test/features/duplicated/tsconfig.json b/test/features/duplicated/tsconfig.json new file mode 100644 index 000000000..e5fe47a95 --- /dev/null +++ b/test/features/duplicated/tsconfig.json @@ -0,0 +1,103 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + /* Language and Environment */ + "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + /* Modules */ + "module": "commonjs", /* Specify what module code is generated. */// "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + "paths": { + "@nestia/core": ["../../../packages/core/src"], + "@nestia/e2e": ["../../../packages/e2e/src"], + "@nestia/fetcher": ["../../../packages/fetcher/src"], + "@nestia/sdk": ["../../../packages/sdk/src"], + "@nestia/sdk/lib/*": ["../../../packages/sdk/src/*"], + "@api": ["./src/api"], + "@api/lib/*": ["./src/api/*"], + }, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. *//* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true, /* Skip type checking all .d.ts files. */ + "plugins": [ + { "transform": "typescript-transform-paths" }, + { "transform": "typia/lib/transform" }, + { "transform": "../../../packages/core/src/transform.ts" }, + ], + } + } \ No newline at end of file diff --git a/test/features/encrypted/nestia.config.ts b/test/features/encrypted/nestia.config.ts new file mode 100644 index 000000000..2594a40d0 --- /dev/null +++ b/test/features/encrypted/nestia.config.ts @@ -0,0 +1,15 @@ +import { INestiaConfig } from "@nestia/sdk"; + +export const NESTIA_CONFIG: INestiaConfig = { + input: ["src/controllers"], + output: "src/api", + swagger: { + output: "swagger.json", + security: { + bearer: { + type: "apiKey", + }, + }, + }, +}; +export default NESTIA_CONFIG; diff --git a/test/features/encrypted/src/Backend.ts b/test/features/encrypted/src/Backend.ts new file mode 100644 index 000000000..8ab51b70f --- /dev/null +++ b/test/features/encrypted/src/Backend.ts @@ -0,0 +1,28 @@ +import { INestApplication } from "@nestjs/common"; +import { NestFactory } from "@nestjs/core"; + +import core from "@nestia/core"; + +export class Backend { + private application_?: INestApplication; + + public async open(): Promise { + this.application_ = await NestFactory.create( + await core.EncryptedModule.dynamic(__dirname + "/controllers", { + key: "A".repeat(32), + iv: "B".repeat(16), + }), + { logger: false }, + ); + await this.application_.listen(37_000); + } + + public async close(): Promise { + if (this.application_ === undefined) return; + + const app = this.application_; + await app.close(); + + delete this.application_; + } +} diff --git a/packages/sdk/demo/status/src/api/HttpError.ts b/test/features/encrypted/src/api/HttpError.ts similarity index 100% rename from packages/sdk/demo/status/src/api/HttpError.ts rename to test/features/encrypted/src/api/HttpError.ts diff --git a/packages/sdk/demo/status/src/api/IConnection.ts b/test/features/encrypted/src/api/IConnection.ts similarity index 100% rename from packages/sdk/demo/status/src/api/IConnection.ts rename to test/features/encrypted/src/api/IConnection.ts diff --git a/packages/sdk/demo/status/src/api/Primitive.ts b/test/features/encrypted/src/api/Primitive.ts similarity index 100% rename from packages/sdk/demo/status/src/api/Primitive.ts rename to test/features/encrypted/src/api/Primitive.ts diff --git a/test/features/encrypted/src/api/functional/health/index.ts b/test/features/encrypted/src/api/functional/health/index.ts new file mode 100644 index 000000000..619581f93 --- /dev/null +++ b/test/features/encrypted/src/api/functional/health/index.ts @@ -0,0 +1,42 @@ +/** + * @packageDocumentation + * @module api.functional.health + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +import { Fetcher } from "@nestia/fetcher"; +import type { IConnection } from "@nestia/fetcher"; + +/** + * @controller HealthController.get() + * @path GET /health + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export function get + ( + connection: IConnection + ): Promise +{ + return Fetcher.fetch + ( + connection, + get.ENCRYPTED, + get.METHOD, + get.path() + ); +} +export namespace get +{ + + export const METHOD = "GET" as const; + export const PATH: string = "/health"; + export const ENCRYPTED: Fetcher.IEncrypted = { + request: false, + response: false, + }; + + export function path(): string + { + return `/health`; + } +} \ No newline at end of file diff --git a/packages/sdk/demo/multiple-paths/src/api/functional/index.ts b/test/features/encrypted/src/api/functional/index.ts similarity index 76% rename from packages/sdk/demo/multiple-paths/src/api/functional/index.ts rename to test/features/encrypted/src/api/functional/index.ts index a2ce92c14..96ce9465b 100644 --- a/packages/sdk/demo/multiple-paths/src/api/functional/index.ts +++ b/test/features/encrypted/src/api/functional/index.ts @@ -5,6 +5,5 @@ */ //================================================================ export * as health from "./health"; -export * as healthy from "./healthy"; -export * as consumers from "./consumers"; +export * as performance from "./performance"; export * as sellers from "./sellers"; \ No newline at end of file diff --git a/test/features/encrypted/src/api/functional/performance/index.ts b/test/features/encrypted/src/api/functional/performance/index.ts new file mode 100644 index 000000000..9e402a44a --- /dev/null +++ b/test/features/encrypted/src/api/functional/performance/index.ts @@ -0,0 +1,45 @@ +/** + * @packageDocumentation + * @module api.functional.performance + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +import { Fetcher, Primitive } from "@nestia/fetcher"; +import type { IConnection } from "@nestia/fetcher"; + +import type { IPerformance } from "./../../structures/IPerformance"; + +/** + * @controller PerformanceController.get() + * @path GET /performance + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export function get + ( + connection: IConnection + ): Promise +{ + return Fetcher.fetch + ( + connection, + get.ENCRYPTED, + get.METHOD, + get.path() + ); +} +export namespace get +{ + export type Output = Primitive; + + export const METHOD = "GET" as const; + export const PATH: string = "/performance"; + export const ENCRYPTED: Fetcher.IEncrypted = { + request: false, + response: false, + }; + + export function path(): string + { + return `/performance`; + } +} \ No newline at end of file diff --git a/packages/sdk/demo/encrypted/src/api/functional/sellers/authenticate/index.ts b/test/features/encrypted/src/api/functional/sellers/authenticate/index.ts similarity index 100% rename from packages/sdk/demo/encrypted/src/api/functional/sellers/authenticate/index.ts rename to test/features/encrypted/src/api/functional/sellers/authenticate/index.ts diff --git a/packages/sdk/demo/encrypted/src/api/functional/sellers/authenticate/password/index.ts b/test/features/encrypted/src/api/functional/sellers/authenticate/password/index.ts similarity index 100% rename from packages/sdk/demo/encrypted/src/api/functional/sellers/authenticate/password/index.ts rename to test/features/encrypted/src/api/functional/sellers/authenticate/password/index.ts diff --git a/packages/sdk/demo/encrypted/src/api/functional/sellers/index.ts b/test/features/encrypted/src/api/functional/sellers/index.ts similarity index 100% rename from packages/sdk/demo/encrypted/src/api/functional/sellers/index.ts rename to test/features/encrypted/src/api/functional/sellers/index.ts diff --git a/test/features/encrypted/src/api/index.ts b/test/features/encrypted/src/api/index.ts new file mode 100644 index 000000000..1896c4fbd --- /dev/null +++ b/test/features/encrypted/src/api/index.ts @@ -0,0 +1,5 @@ +import * as api from "./module"; + +export * from "./module"; + +export default api; diff --git a/test/features/encrypted/src/api/module.ts b/test/features/encrypted/src/api/module.ts new file mode 100644 index 000000000..00239fb3b --- /dev/null +++ b/test/features/encrypted/src/api/module.ts @@ -0,0 +1,5 @@ +export * from "./IConnection"; +export * from "./Primitive"; +export * from "./HttpError"; + +export * as functional from "./functional"; diff --git a/test/features/encrypted/src/api/structures/IPerformance.ts b/test/features/encrypted/src/api/structures/IPerformance.ts new file mode 100644 index 000000000..a9e9336e1 --- /dev/null +++ b/test/features/encrypted/src/api/structures/IPerformance.ts @@ -0,0 +1,10 @@ +/** + * Performance info. + * + * @author Samchon + */ +export interface IPerformance { + cpu: NodeJS.CpuUsage; + memory: NodeJS.MemoryUsage; + resource: NodeJS.ResourceUsage; +} diff --git a/packages/sdk/demo/encrypted/src/api/structures/ISeller.ts b/test/features/encrypted/src/api/structures/ISeller.ts similarity index 100% rename from packages/sdk/demo/encrypted/src/api/structures/ISeller.ts rename to test/features/encrypted/src/api/structures/ISeller.ts diff --git a/test/features/encrypted/src/api/structures/ISystem.ts b/test/features/encrypted/src/api/structures/ISystem.ts new file mode 100644 index 000000000..68f05ca92 --- /dev/null +++ b/test/features/encrypted/src/api/structures/ISystem.ts @@ -0,0 +1,81 @@ +/** + * System Information. + * + * @author Jeongho Nam + */ +export interface ISystem { + /** + * Random Unique ID. + */ + uid: number; + + /** + * `process.argv` + */ + arguments: string[]; + + /** + * Git commit info. + */ + commit: ISystem.ICommit; + + /** + * `package.json` + */ + package: ISystem.IPackage; + + /** + * Creation time of this server. + */ + created_at: string; +} + +export namespace ISystem { + /** + * Git commit info. + */ + export interface ICommit { + shortHash: string; + branch: string; + hash: string; + subject: string; + sanitizedSubject: string; + body: string; + author: ICommit.IUser; + committer: ICommit.IUser; + authored_at: string; + commited_at: string; + notes?: string; + tags: string[]; + } + export namespace ICommit { + /** + * Git user account info. + */ + export interface IUser { + name: string; + email: string; + } + } + + /** + * NPM package info. + */ + export interface IPackage { + name: string; + version: string; + description: string; + main?: string; + typings?: string; + scripts: Record; + repository: { type: "git"; url: string }; + author: string; + license: string; + bugs: { url: string }; + homepage: string; + devDependencies?: Record; + dependencies: Record; + publishConfig?: { registry: string }; + files?: string[]; + } +} diff --git a/test/features/encrypted/src/controllers/HealthController.ts b/test/features/encrypted/src/controllers/HealthController.ts new file mode 100644 index 000000000..a9ce3563b --- /dev/null +++ b/test/features/encrypted/src/controllers/HealthController.ts @@ -0,0 +1,9 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +@Controller("health") +export class HealthController { + @core.TypedRoute.Get() + public get(): void {} +} diff --git a/test/features/encrypted/src/controllers/PerformanceController.ts b/test/features/encrypted/src/controllers/PerformanceController.ts new file mode 100644 index 000000000..798d64fae --- /dev/null +++ b/test/features/encrypted/src/controllers/PerformanceController.ts @@ -0,0 +1,17 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +import { IPerformance } from "@api/lib/structures/IPerformance"; + +@Controller("performance") +export class PerformanceController { + @core.TypedRoute.Get() + public async get(): Promise { + return { + cpu: process.cpuUsage(), + memory: process.memoryUsage(), + resource: process.resourceUsage(), + }; + } +} diff --git a/packages/sdk/demo/encrypted/src/controllers/SellerAuthenticateController.ts b/test/features/encrypted/src/controllers/SellerAuthenticateController.ts similarity index 66% rename from packages/sdk/demo/encrypted/src/controllers/SellerAuthenticateController.ts rename to test/features/encrypted/src/controllers/SellerAuthenticateController.ts index 20e5b57a4..175a8134a 100644 --- a/packages/sdk/demo/encrypted/src/controllers/SellerAuthenticateController.ts +++ b/test/features/encrypted/src/controllers/SellerAuthenticateController.ts @@ -1,8 +1,9 @@ -import core from "@nestia/core"; import * as nest from "@nestjs/common"; -import type express from "express"; +import typia from "typia"; + +import core from "@nestia/core"; -import { ISeller } from "../api/structures/ISeller"; +import { ISeller } from "@api/lib/structures/ISeller"; @nest.Controller("sellers/authenticate") export class SellerAuthenticateController { @@ -18,16 +19,11 @@ export class SellerAuthenticateController { @core.EncryptedBody() input: ISeller.IJoin, ): Promise { return { - id: 0, + ...typia.random(), email: input.email, name: input.name, mobile: input.mobile, company: input.company, - created_at: new Date().toString(), - authorization: { - token: "token", - expires_at: new Date().toString(), - }, }; } @@ -43,16 +39,8 @@ export class SellerAuthenticateController { @core.EncryptedBody() input: ISeller.ILogin, ): Promise { return { - id: 0, + ...typia.random(), email: input.email, - mobile: "01012345678", - name: "John Doe", - company: "ABC Company", - created_at: new Date().toString(), - authorization: { - token: "token", - expires_at: new Date().toString(), - }, }; } @@ -64,7 +52,6 @@ export class SellerAuthenticateController { */ @nest.Patch("password/change") public async change( - @nest.Request() _httpReq: express.Request, @core.EncryptedBody() input: ISeller.IChangePassword, ): Promise { input; @@ -74,7 +61,5 @@ export class SellerAuthenticateController { * Erase the seller by itself. */ @nest.Delete("exit") - public async exit( - @nest.Request() _httpReq: express.Request, - ): Promise {} + public async exit(): Promise {} } diff --git a/test/features/encrypted/src/test/features/test_api_health_check.ts b/test/features/encrypted/src/test/features/test_api_health_check.ts new file mode 100644 index 000000000..c34703c71 --- /dev/null +++ b/test/features/encrypted/src/test/features/test_api_health_check.ts @@ -0,0 +1,5 @@ +import api from "@api"; + +export const test_api_monitor_health_check = ( + connection: api.IConnection, +): Promise => api.functional.health.get(connection); diff --git a/test/features/encrypted/src/test/features/test_api_performance.ts b/test/features/encrypted/src/test/features/test_api_performance.ts new file mode 100644 index 000000000..55b6d2ca7 --- /dev/null +++ b/test/features/encrypted/src/test/features/test_api_performance.ts @@ -0,0 +1,13 @@ +import typia from "typia"; + +import api from "@api"; +import { IPerformance } from "@api/lib/structures/IPerformance"; + +export const test_api_monitor_performance = async ( + connection: api.IConnection, +): Promise => { + const performance: IPerformance = await api.functional.performance.get( + connection, + ); + typia.assert(performance); +}; diff --git a/packages/sdk/demo/encrypted/src/test/features/test_seller_exit.ts b/test/features/encrypted/src/test/features/test_api_seller_exit.ts similarity index 75% rename from packages/sdk/demo/encrypted/src/test/features/test_seller_exit.ts rename to test/features/encrypted/src/test/features/test_api_seller_exit.ts index fd356de4a..4f00dea52 100644 --- a/packages/sdk/demo/encrypted/src/test/features/test_seller_exit.ts +++ b/test/features/encrypted/src/test/features/test_api_seller_exit.ts @@ -1,9 +1,9 @@ import typia from "typia"; -import api from "../../api"; -import { ISeller } from "../../api/structures/ISeller"; +import api from "@api"; +import { ISeller } from "@api/lib/structures/ISeller"; -export async function test_seller_exit( +export async function test_api_seller_exit( connection: api.IConnection, ): Promise { const seller: ISeller = await api.functional.sellers.authenticate.login( diff --git a/packages/sdk/demo/encrypted/src/test/features/test_seller_join.ts b/test/features/encrypted/src/test/features/test_api_seller_join.ts similarity index 76% rename from packages/sdk/demo/encrypted/src/test/features/test_seller_join.ts rename to test/features/encrypted/src/test/features/test_api_seller_join.ts index 39786baea..aa4510152 100644 --- a/packages/sdk/demo/encrypted/src/test/features/test_seller_join.ts +++ b/test/features/encrypted/src/test/features/test_api_seller_join.ts @@ -1,9 +1,9 @@ import typia from "typia"; -import api from "../../api"; -import { ISeller } from "../../api/structures/ISeller"; +import api from "@api"; +import { ISeller } from "@api/lib/structures/ISeller"; -export async function test_seller_join( +export async function test_api_seller_join( connection: api.IConnection, ): Promise { const seller: ISeller = await api.functional.sellers.authenticate.join( diff --git a/packages/sdk/demo/encrypted/src/test/features/test_seller_login.ts b/test/features/encrypted/src/test/features/test_api_seller_login.ts similarity index 71% rename from packages/sdk/demo/encrypted/src/test/features/test_seller_login.ts rename to test/features/encrypted/src/test/features/test_api_seller_login.ts index 9c8a54e82..41bc60158 100644 --- a/packages/sdk/demo/encrypted/src/test/features/test_seller_login.ts +++ b/test/features/encrypted/src/test/features/test_api_seller_login.ts @@ -1,9 +1,9 @@ import typia from "typia"; -import api from "../../api"; -import { ISeller } from "../../api/structures/ISeller"; +import api from "@api"; +import { ISeller } from "@api/lib/structures/ISeller"; -export async function test_seller_login( +export async function test_api_seller_login( connection: api.IConnection, ): Promise { const seller: ISeller = await api.functional.sellers.authenticate.login( diff --git a/packages/sdk/demo/encrypted/src/test/features/test_seller_password_change.ts b/test/features/encrypted/src/test/features/test_api_seller_password_change.ts similarity index 73% rename from packages/sdk/demo/encrypted/src/test/features/test_seller_password_change.ts rename to test/features/encrypted/src/test/features/test_api_seller_password_change.ts index 1eddcad42..c4b5a68f8 100644 --- a/packages/sdk/demo/encrypted/src/test/features/test_seller_password_change.ts +++ b/test/features/encrypted/src/test/features/test_api_seller_password_change.ts @@ -1,9 +1,9 @@ import typia from "typia"; -import api from "../../api"; -import { ISeller } from "../../api/structures/ISeller"; +import api from "@api"; +import { ISeller } from "@api/lib/structures/ISeller"; -export async function test_seller_password_change( +export async function test_api_seller_password_change( connection: api.IConnection, ): Promise { const seller: ISeller = await api.functional.sellers.authenticate.login( diff --git a/test/features/encrypted/src/test/index.ts b/test/features/encrypted/src/test/index.ts new file mode 100644 index 000000000..e89842739 --- /dev/null +++ b/test/features/encrypted/src/test/index.ts @@ -0,0 +1,39 @@ +import { DynamicExecutor } from "@nestia/e2e"; + +import { Backend } from "../Backend"; + +async function main(): Promise { + const server: Backend = new Backend(); + await server.open(); + + const report: DynamicExecutor.IReport = await DynamicExecutor.validate({ + prefix: "test", + parameters: () => [ + { + host: "http://127.0.0.1:37000", + encryption: { + key: "A".repeat(32), + iv: "B".repeat(16), + }, + }, + ], + })(`${__dirname}/features`); + await server.close(); + + const exceptions: Error[] = report.executions + .filter((exec) => exec.error !== null) + .map((exec) => exec.error!); + if (exceptions.length === 0) { + console.log("Success"); + console.log("Elapsed time", report.time.toLocaleString(), `ms`); + } else { + // for (const exp of exceptions) console.log(exp); + console.log("Failed"); + console.log("Elapsed time", report.time.toLocaleString(), `ms`); + process.exit(-1); + } +} +main().catch((exp) => { + console.log(exp); + process.exit(-1); +}); diff --git a/packages/sdk/demo/encrypted/swagger.json b/test/features/encrypted/swagger.json similarity index 56% rename from packages/sdk/demo/encrypted/swagger.json rename to test/features/encrypted/swagger.json index f963e0623..c54fdbcd3 100644 --- a/packages/sdk/demo/encrypted/swagger.json +++ b/test/features/encrypted/swagger.json @@ -11,6 +11,43 @@ "title": "Generated by nestia - https://github.com/samchon/nestia" }, "paths": { + "/health": { + "get": { + "tags": [], + "parameters": [], + "responses": { + "200": { + "description": "", + "x-nestia-encrypted": false + } + }, + "description": "", + "x-nestia-namespace": "health.get", + "x-nestia-jsDocTags": [] + } + }, + "/performance": { + "get": { + "tags": [], + "parameters": [], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IPerformance" + } + } + }, + "x-nestia-encrypted": false + } + }, + "description": "", + "x-nestia-namespace": "performance.get", + "x-nestia-jsDocTags": [] + } + }, "/sellers/authenticate/join": { "post": { "tags": [], @@ -227,33 +264,264 @@ }, "components": { "schemas": { + "IPerformance": { + "type": "object", + "properties": { + "cpu": { + "$ref": "#/components/schemas/_singlequote_process_singlequote_.global.NodeJS.CpuUsage", + "x-typia-required": true, + "x-typia-optional": false + }, + "memory": { + "$ref": "#/components/schemas/_singlequote_process_singlequote_.global.NodeJS.MemoryUsage", + "x-typia-required": true, + "x-typia-optional": false + }, + "resource": { + "$ref": "#/components/schemas/_singlequote_process_singlequote_.global.NodeJS.ResourceUsage", + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "cpu", + "memory", + "resource" + ], + "description": "Performance info.", + "x-typia-jsDocTags": [ + { + "name": "author", + "text": [ + { + "text": "Samchon", + "kind": "text" + } + ] + } + ] + }, + "_singlequote_process_singlequote_.global.NodeJS.CpuUsage": { + "type": "object", + "properties": { + "user": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "system": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "user", + "system" + ], + "x-typia-jsDocTags": [] + }, + "_singlequote_process_singlequote_.global.NodeJS.MemoryUsage": { + "type": "object", + "properties": { + "rss": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "heapTotal": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "heapUsed": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "external": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "arrayBuffers": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "rss", + "heapTotal", + "heapUsed", + "external", + "arrayBuffers" + ], + "x-typia-jsDocTags": [] + }, + "_singlequote_process_singlequote_.global.NodeJS.ResourceUsage": { + "type": "object", + "properties": { + "fsRead": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "fsWrite": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "involuntaryContextSwitches": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "ipcReceived": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "ipcSent": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "majorPageFault": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "maxRSS": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "minorPageFault": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "sharedMemorySize": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "signalsCount": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "swappedOut": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "systemCPUTime": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "unsharedDataSize": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "unsharedStackSize": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "userCPUTime": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "voluntaryContextSwitches": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "fsRead", + "fsWrite", + "involuntaryContextSwitches", + "ipcReceived", + "ipcSent", + "majorPageFault", + "maxRSS", + "minorPageFault", + "sharedMemorySize", + "signalsCount", + "swappedOut", + "systemCPUTime", + "unsharedDataSize", + "unsharedStackSize", + "userCPUTime", + "voluntaryContextSwitches" + ], + "x-typia-jsDocTags": [] + }, "ISeller.IJoin": { "type": "object", "properties": { "email": { "type": "string", "nullable": false, - "x-typia-required": true + "x-typia-required": true, + "x-typia-optional": false }, "password": { "type": "string", "nullable": false, - "x-typia-required": true + "x-typia-required": true, + "x-typia-optional": false }, "name": { "type": "string", "nullable": false, - "x-typia-required": true + "x-typia-required": true, + "x-typia-optional": false }, "mobile": { "type": "string", "nullable": false, - "x-typia-required": true + "x-typia-required": true, + "x-typia-optional": false }, "company": { "type": "string", "nullable": false, - "x-typia-required": true + "x-typia-required": true, + "x-typia-optional": false } }, "nullable": false, @@ -271,43 +539,50 @@ "properties": { "authorization": { "$ref": "#/components/schemas/__type", - "x-typia-required": true + "x-typia-required": true, + "x-typia-optional": false }, "id": { "type": "number", "nullable": false, "description": "Primary key.", - "x-typia-required": true + "x-typia-required": true, + "x-typia-optional": false }, "email": { "type": "string", "nullable": false, "description": "Email address.", - "x-typia-required": true + "x-typia-required": true, + "x-typia-optional": false }, "name": { "type": "string", "nullable": false, "description": "Name of the seller.", - "x-typia-required": true + "x-typia-required": true, + "x-typia-optional": false }, "mobile": { "type": "string", "nullable": false, "description": "Mobile number of the seller.", - "x-typia-required": true + "x-typia-required": true, + "x-typia-optional": false }, "company": { "type": "string", "nullable": false, "description": "Belonged company name.", - "x-typia-required": true + "x-typia-required": true, + "x-typia-optional": false }, "created_at": { "type": "string", "nullable": false, "description": "Joined time.", - "x-typia-required": true + "x-typia-required": true, + "x-typia-optional": false } }, "nullable": false, @@ -328,12 +603,14 @@ "token": { "type": "string", "nullable": false, - "x-typia-required": true + "x-typia-required": true, + "x-typia-optional": false }, "expires_at": { "type": "string", "nullable": false, - "x-typia-required": true + "x-typia-required": true, + "x-typia-optional": false } }, "nullable": false, @@ -349,12 +626,14 @@ "email": { "type": "string", "nullable": false, - "x-typia-required": true + "x-typia-required": true, + "x-typia-optional": false }, "password": { "type": "string", "nullable": false, - "x-typia-required": true + "x-typia-required": true, + "x-typia-optional": false } }, "nullable": false, @@ -370,12 +649,14 @@ "old_password": { "type": "string", "nullable": false, - "x-typia-required": true + "x-typia-required": true, + "x-typia-optional": false }, "new_password": { "type": "string", "nullable": false, - "x-typia-required": true + "x-typia-required": true, + "x-typia-optional": false } }, "nullable": false, @@ -385,6 +666,18 @@ ], "x-typia-jsDocTags": [] } + }, + "securitySchemes": { + "bearer": { + "type": "apiKey", + "in": "header", + "name": "Authorization" + } + } + }, + "security": [ + { + "bearer": [] } - } + ] } \ No newline at end of file diff --git a/test/features/encrypted/tsconfig.json b/test/features/encrypted/tsconfig.json new file mode 100644 index 000000000..e5fe47a95 --- /dev/null +++ b/test/features/encrypted/tsconfig.json @@ -0,0 +1,103 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + /* Language and Environment */ + "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + /* Modules */ + "module": "commonjs", /* Specify what module code is generated. */// "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + "paths": { + "@nestia/core": ["../../../packages/core/src"], + "@nestia/e2e": ["../../../packages/e2e/src"], + "@nestia/fetcher": ["../../../packages/fetcher/src"], + "@nestia/sdk": ["../../../packages/sdk/src"], + "@nestia/sdk/lib/*": ["../../../packages/sdk/src/*"], + "@api": ["./src/api"], + "@api/lib/*": ["./src/api/*"], + }, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. *//* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true, /* Skip type checking all .d.ts files. */ + "plugins": [ + { "transform": "typescript-transform-paths" }, + { "transform": "typia/lib/transform" }, + { "transform": "../../../packages/core/src/transform.ts" }, + ], + } + } \ No newline at end of file diff --git a/test/features/param-error-array/nestia.config.ts b/test/features/param-error-array/nestia.config.ts new file mode 100644 index 000000000..2594a40d0 --- /dev/null +++ b/test/features/param-error-array/nestia.config.ts @@ -0,0 +1,15 @@ +import { INestiaConfig } from "@nestia/sdk"; + +export const NESTIA_CONFIG: INestiaConfig = { + input: ["src/controllers"], + output: "src/api", + swagger: { + output: "swagger.json", + security: { + bearer: { + type: "apiKey", + }, + }, + }, +}; +export default NESTIA_CONFIG; diff --git a/test/features/param-error-array/src/controllers/HealthController.ts b/test/features/param-error-array/src/controllers/HealthController.ts new file mode 100644 index 000000000..a9ce3563b --- /dev/null +++ b/test/features/param-error-array/src/controllers/HealthController.ts @@ -0,0 +1,9 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +@Controller("health") +export class HealthController { + @core.TypedRoute.Get() + public get(): void {} +} diff --git a/test/features/param-error-array/src/controllers/TypedParamController.ts b/test/features/param-error-array/src/controllers/TypedParamController.ts new file mode 100644 index 000000000..a654029d3 --- /dev/null +++ b/test/features/param-error-array/src/controllers/TypedParamController.ts @@ -0,0 +1,11 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +@Controller("param") +export class TypedParamController { + @core.TypedRoute.Get(":value") + public param(@core.TypedParam("value") value: string[]): void { + value; + } +} diff --git a/test/features/param-error-array/tsconfig.json b/test/features/param-error-array/tsconfig.json new file mode 100644 index 000000000..e74060a2d --- /dev/null +++ b/test/features/param-error-array/tsconfig.json @@ -0,0 +1,101 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + /* Language and Environment */ + "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + /* Modules */ + "module": "commonjs", /* Specify what module code is generated. */// "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + "paths": { + "@nestia/core": ["../../../packages/core/src"], + "@nestia/e2e": ["../../../packages/e2e/src"], + "@nestia/fetcher": ["../../../packages/fetcher/src"], + "@nestia/sdk": ["../../../packages/sdk/src"], + "@nestia/sdk/lib/*": ["../../../packages/sdk/src/*"], + }, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. *//* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true, /* Skip type checking all .d.ts files. */ + "plugins": [ + { "transform": "typescript-transform-paths" }, + { "transform": "typia/lib/transform" }, + { "transform": "../../../packages/core/src/transform.ts" }, + ], + } + } \ No newline at end of file diff --git a/test/features/param-error-generic/nestia.config.ts b/test/features/param-error-generic/nestia.config.ts new file mode 100644 index 000000000..2594a40d0 --- /dev/null +++ b/test/features/param-error-generic/nestia.config.ts @@ -0,0 +1,15 @@ +import { INestiaConfig } from "@nestia/sdk"; + +export const NESTIA_CONFIG: INestiaConfig = { + input: ["src/controllers"], + output: "src/api", + swagger: { + output: "swagger.json", + security: { + bearer: { + type: "apiKey", + }, + }, + }, +}; +export default NESTIA_CONFIG; diff --git a/test/features/param-error-generic/src/controllers/HealthController.ts b/test/features/param-error-generic/src/controllers/HealthController.ts new file mode 100644 index 000000000..a9ce3563b --- /dev/null +++ b/test/features/param-error-generic/src/controllers/HealthController.ts @@ -0,0 +1,9 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +@Controller("health") +export class HealthController { + @core.TypedRoute.Get() + public get(): void {} +} diff --git a/test/features/param-error-generic/src/controllers/TypedParamController.ts b/test/features/param-error-generic/src/controllers/TypedParamController.ts new file mode 100644 index 000000000..fc54f0e7e --- /dev/null +++ b/test/features/param-error-generic/src/controllers/TypedParamController.ts @@ -0,0 +1,13 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +@Controller("param") +export class TypedParamController { + @core.TypedRoute.Get(":value") + public param( + @core.TypedParam("value") value: T, + ): void { + value; + } +} diff --git a/test/features/param-error-generic/tsconfig.json b/test/features/param-error-generic/tsconfig.json new file mode 100644 index 000000000..e74060a2d --- /dev/null +++ b/test/features/param-error-generic/tsconfig.json @@ -0,0 +1,101 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + /* Language and Environment */ + "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + /* Modules */ + "module": "commonjs", /* Specify what module code is generated. */// "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + "paths": { + "@nestia/core": ["../../../packages/core/src"], + "@nestia/e2e": ["../../../packages/e2e/src"], + "@nestia/fetcher": ["../../../packages/fetcher/src"], + "@nestia/sdk": ["../../../packages/sdk/src"], + "@nestia/sdk/lib/*": ["../../../packages/sdk/src/*"], + }, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. *//* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true, /* Skip type checking all .d.ts files. */ + "plugins": [ + { "transform": "typescript-transform-paths" }, + { "transform": "typia/lib/transform" }, + { "transform": "../../../packages/core/src/transform.ts" }, + ], + } + } \ No newline at end of file diff --git a/test/features/param-error-native/nestia.config.ts b/test/features/param-error-native/nestia.config.ts new file mode 100644 index 000000000..2594a40d0 --- /dev/null +++ b/test/features/param-error-native/nestia.config.ts @@ -0,0 +1,15 @@ +import { INestiaConfig } from "@nestia/sdk"; + +export const NESTIA_CONFIG: INestiaConfig = { + input: ["src/controllers"], + output: "src/api", + swagger: { + output: "swagger.json", + security: { + bearer: { + type: "apiKey", + }, + }, + }, +}; +export default NESTIA_CONFIG; diff --git a/test/features/param-error-native/src/controllers/HealthController.ts b/test/features/param-error-native/src/controllers/HealthController.ts new file mode 100644 index 000000000..a9ce3563b --- /dev/null +++ b/test/features/param-error-native/src/controllers/HealthController.ts @@ -0,0 +1,9 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +@Controller("health") +export class HealthController { + @core.TypedRoute.Get() + public get(): void {} +} diff --git a/test/features/param-error-native/src/controllers/TypedParamController.ts b/test/features/param-error-native/src/controllers/TypedParamController.ts new file mode 100644 index 000000000..dbb360f5e --- /dev/null +++ b/test/features/param-error-native/src/controllers/TypedParamController.ts @@ -0,0 +1,11 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +@Controller("param") +export class TypedParamController { + @core.TypedRoute.Get(":value") + public param(@core.TypedParam("value") value: Uint8Array): void { + value; + } +} diff --git a/test/features/param-error-native/tsconfig.json b/test/features/param-error-native/tsconfig.json new file mode 100644 index 000000000..e74060a2d --- /dev/null +++ b/test/features/param-error-native/tsconfig.json @@ -0,0 +1,101 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + /* Language and Environment */ + "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + /* Modules */ + "module": "commonjs", /* Specify what module code is generated. */// "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + "paths": { + "@nestia/core": ["../../../packages/core/src"], + "@nestia/e2e": ["../../../packages/e2e/src"], + "@nestia/fetcher": ["../../../packages/fetcher/src"], + "@nestia/sdk": ["../../../packages/sdk/src"], + "@nestia/sdk/lib/*": ["../../../packages/sdk/src/*"], + }, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. *//* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true, /* Skip type checking all .d.ts files. */ + "plugins": [ + { "transform": "typescript-transform-paths" }, + { "transform": "typia/lib/transform" }, + { "transform": "../../../packages/core/src/transform.ts" }, + ], + } + } \ No newline at end of file diff --git a/test/features/param-error-object/nestia.config.ts b/test/features/param-error-object/nestia.config.ts new file mode 100644 index 000000000..2594a40d0 --- /dev/null +++ b/test/features/param-error-object/nestia.config.ts @@ -0,0 +1,15 @@ +import { INestiaConfig } from "@nestia/sdk"; + +export const NESTIA_CONFIG: INestiaConfig = { + input: ["src/controllers"], + output: "src/api", + swagger: { + output: "swagger.json", + security: { + bearer: { + type: "apiKey", + }, + }, + }, +}; +export default NESTIA_CONFIG; diff --git a/test/features/param-error-object/src/controllers/HealthController.ts b/test/features/param-error-object/src/controllers/HealthController.ts new file mode 100644 index 000000000..a9ce3563b --- /dev/null +++ b/test/features/param-error-object/src/controllers/HealthController.ts @@ -0,0 +1,9 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +@Controller("health") +export class HealthController { + @core.TypedRoute.Get() + public get(): void {} +} diff --git a/test/features/param-error-object/src/controllers/TypedParamController.ts b/test/features/param-error-object/src/controllers/TypedParamController.ts new file mode 100644 index 000000000..438edef54 --- /dev/null +++ b/test/features/param-error-object/src/controllers/TypedParamController.ts @@ -0,0 +1,15 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +@Controller("param") +export class TypedParamController { + @core.TypedRoute.Get(":value") + public param(@core.TypedParam("value") value: IParam): void { + value; + } +} + +interface IParam { + value: string; +} diff --git a/test/features/param-error-object/tsconfig.json b/test/features/param-error-object/tsconfig.json new file mode 100644 index 000000000..e74060a2d --- /dev/null +++ b/test/features/param-error-object/tsconfig.json @@ -0,0 +1,101 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + /* Language and Environment */ + "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + /* Modules */ + "module": "commonjs", /* Specify what module code is generated. */// "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + "paths": { + "@nestia/core": ["../../../packages/core/src"], + "@nestia/e2e": ["../../../packages/e2e/src"], + "@nestia/fetcher": ["../../../packages/fetcher/src"], + "@nestia/sdk": ["../../../packages/sdk/src"], + "@nestia/sdk/lib/*": ["../../../packages/sdk/src/*"], + }, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. *//* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true, /* Skip type checking all .d.ts files. */ + "plugins": [ + { "transform": "typescript-transform-paths" }, + { "transform": "typia/lib/transform" }, + { "transform": "../../../packages/core/src/transform.ts" }, + ], + } + } \ No newline at end of file diff --git a/test/features/param-error-undefined/nestia.config.ts b/test/features/param-error-undefined/nestia.config.ts new file mode 100644 index 000000000..2594a40d0 --- /dev/null +++ b/test/features/param-error-undefined/nestia.config.ts @@ -0,0 +1,15 @@ +import { INestiaConfig } from "@nestia/sdk"; + +export const NESTIA_CONFIG: INestiaConfig = { + input: ["src/controllers"], + output: "src/api", + swagger: { + output: "swagger.json", + security: { + bearer: { + type: "apiKey", + }, + }, + }, +}; +export default NESTIA_CONFIG; diff --git a/test/features/param-error-undefined/src/controllers/HealthController.ts b/test/features/param-error-undefined/src/controllers/HealthController.ts new file mode 100644 index 000000000..a9ce3563b --- /dev/null +++ b/test/features/param-error-undefined/src/controllers/HealthController.ts @@ -0,0 +1,9 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +@Controller("health") +export class HealthController { + @core.TypedRoute.Get() + public get(): void {} +} diff --git a/test/features/param-error-undefined/src/controllers/TypedParamController.ts b/test/features/param-error-undefined/src/controllers/TypedParamController.ts new file mode 100644 index 000000000..e57e527d9 --- /dev/null +++ b/test/features/param-error-undefined/src/controllers/TypedParamController.ts @@ -0,0 +1,11 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +@Controller("param") +export class TypedParamController { + @core.TypedRoute.Get(":value") + public param(@core.TypedParam("value") value?: number): void { + value; + } +} diff --git a/test/features/param-error-undefined/tsconfig.json b/test/features/param-error-undefined/tsconfig.json new file mode 100644 index 000000000..e74060a2d --- /dev/null +++ b/test/features/param-error-undefined/tsconfig.json @@ -0,0 +1,101 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + /* Language and Environment */ + "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + /* Modules */ + "module": "commonjs", /* Specify what module code is generated. */// "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + "paths": { + "@nestia/core": ["../../../packages/core/src"], + "@nestia/e2e": ["../../../packages/e2e/src"], + "@nestia/fetcher": ["../../../packages/fetcher/src"], + "@nestia/sdk": ["../../../packages/sdk/src"], + "@nestia/sdk/lib/*": ["../../../packages/sdk/src/*"], + }, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. *//* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true, /* Skip type checking all .d.ts files. */ + "plugins": [ + { "transform": "typescript-transform-paths" }, + { "transform": "typia/lib/transform" }, + { "transform": "../../../packages/core/src/transform.ts" }, + ], + } + } \ No newline at end of file diff --git a/test/features/param-error-union-literal/nestia.config.ts b/test/features/param-error-union-literal/nestia.config.ts new file mode 100644 index 000000000..2594a40d0 --- /dev/null +++ b/test/features/param-error-union-literal/nestia.config.ts @@ -0,0 +1,15 @@ +import { INestiaConfig } from "@nestia/sdk"; + +export const NESTIA_CONFIG: INestiaConfig = { + input: ["src/controllers"], + output: "src/api", + swagger: { + output: "swagger.json", + security: { + bearer: { + type: "apiKey", + }, + }, + }, +}; +export default NESTIA_CONFIG; diff --git a/test/features/param-error-union-literal/src/controllers/HealthController.ts b/test/features/param-error-union-literal/src/controllers/HealthController.ts new file mode 100644 index 000000000..a9ce3563b --- /dev/null +++ b/test/features/param-error-union-literal/src/controllers/HealthController.ts @@ -0,0 +1,9 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +@Controller("health") +export class HealthController { + @core.TypedRoute.Get() + public get(): void {} +} diff --git a/test/features/param-error-union-literal/tsconfig.json b/test/features/param-error-union-literal/tsconfig.json new file mode 100644 index 000000000..e74060a2d --- /dev/null +++ b/test/features/param-error-union-literal/tsconfig.json @@ -0,0 +1,101 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + /* Language and Environment */ + "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + /* Modules */ + "module": "commonjs", /* Specify what module code is generated. */// "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + "paths": { + "@nestia/core": ["../../../packages/core/src"], + "@nestia/e2e": ["../../../packages/e2e/src"], + "@nestia/fetcher": ["../../../packages/fetcher/src"], + "@nestia/sdk": ["../../../packages/sdk/src"], + "@nestia/sdk/lib/*": ["../../../packages/sdk/src/*"], + }, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. *//* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true, /* Skip type checking all .d.ts files. */ + "plugins": [ + { "transform": "typescript-transform-paths" }, + { "transform": "typia/lib/transform" }, + { "transform": "../../../packages/core/src/transform.ts" }, + ], + } + } \ No newline at end of file diff --git a/test/features/param-error-union/nestia.config.ts b/test/features/param-error-union/nestia.config.ts new file mode 100644 index 000000000..2594a40d0 --- /dev/null +++ b/test/features/param-error-union/nestia.config.ts @@ -0,0 +1,15 @@ +import { INestiaConfig } from "@nestia/sdk"; + +export const NESTIA_CONFIG: INestiaConfig = { + input: ["src/controllers"], + output: "src/api", + swagger: { + output: "swagger.json", + security: { + bearer: { + type: "apiKey", + }, + }, + }, +}; +export default NESTIA_CONFIG; diff --git a/test/features/param-error-union/src/controllers/HealthController.ts b/test/features/param-error-union/src/controllers/HealthController.ts new file mode 100644 index 000000000..a9ce3563b --- /dev/null +++ b/test/features/param-error-union/src/controllers/HealthController.ts @@ -0,0 +1,9 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +@Controller("health") +export class HealthController { + @core.TypedRoute.Get() + public get(): void {} +} diff --git a/test/features/param-error-union/src/controllers/TypedParamController.ts b/test/features/param-error-union/src/controllers/TypedParamController.ts new file mode 100644 index 000000000..6ce78a5b4 --- /dev/null +++ b/test/features/param-error-union/src/controllers/TypedParamController.ts @@ -0,0 +1,11 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +@Controller("param") +export class TypedParamController { + @core.TypedRoute.Get(":value") + public param(@core.TypedParam("value") value: string | number): void { + value; + } +} diff --git a/test/features/param-error-union/tsconfig.json b/test/features/param-error-union/tsconfig.json new file mode 100644 index 000000000..e74060a2d --- /dev/null +++ b/test/features/param-error-union/tsconfig.json @@ -0,0 +1,101 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + /* Language and Environment */ + "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + /* Modules */ + "module": "commonjs", /* Specify what module code is generated. */// "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + "paths": { + "@nestia/core": ["../../../packages/core/src"], + "@nestia/e2e": ["../../../packages/e2e/src"], + "@nestia/fetcher": ["../../../packages/fetcher/src"], + "@nestia/sdk": ["../../../packages/sdk/src"], + "@nestia/sdk/lib/*": ["../../../packages/sdk/src/*"], + }, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. *//* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true, /* Skip type checking all .d.ts files. */ + "plugins": [ + { "transform": "typescript-transform-paths" }, + { "transform": "typia/lib/transform" }, + { "transform": "../../../packages/core/src/transform.ts" }, + ], + } + } \ No newline at end of file diff --git a/test/features/param/nestia.config.ts b/test/features/param/nestia.config.ts new file mode 100644 index 000000000..2594a40d0 --- /dev/null +++ b/test/features/param/nestia.config.ts @@ -0,0 +1,15 @@ +import { INestiaConfig } from "@nestia/sdk"; + +export const NESTIA_CONFIG: INestiaConfig = { + input: ["src/controllers"], + output: "src/api", + swagger: { + output: "swagger.json", + security: { + bearer: { + type: "apiKey", + }, + }, + }, +}; +export default NESTIA_CONFIG; diff --git a/test/features/param/src/Backend.ts b/test/features/param/src/Backend.ts new file mode 100644 index 000000000..8ab51b70f --- /dev/null +++ b/test/features/param/src/Backend.ts @@ -0,0 +1,28 @@ +import { INestApplication } from "@nestjs/common"; +import { NestFactory } from "@nestjs/core"; + +import core from "@nestia/core"; + +export class Backend { + private application_?: INestApplication; + + public async open(): Promise { + this.application_ = await NestFactory.create( + await core.EncryptedModule.dynamic(__dirname + "/controllers", { + key: "A".repeat(32), + iv: "B".repeat(16), + }), + { logger: false }, + ); + await this.application_.listen(37_000); + } + + public async close(): Promise { + if (this.application_ === undefined) return; + + const app = this.application_; + await app.close(); + + delete this.application_; + } +} diff --git a/packages/sdk/demo/union/src/api/HttpError.ts b/test/features/param/src/api/HttpError.ts similarity index 100% rename from packages/sdk/demo/union/src/api/HttpError.ts rename to test/features/param/src/api/HttpError.ts diff --git a/packages/sdk/demo/union/src/api/IConnection.ts b/test/features/param/src/api/IConnection.ts similarity index 100% rename from packages/sdk/demo/union/src/api/IConnection.ts rename to test/features/param/src/api/IConnection.ts diff --git a/packages/sdk/demo/union/src/api/Primitive.ts b/test/features/param/src/api/Primitive.ts similarity index 100% rename from packages/sdk/demo/union/src/api/Primitive.ts rename to test/features/param/src/api/Primitive.ts diff --git a/test/features/param/src/api/functional/health/index.ts b/test/features/param/src/api/functional/health/index.ts new file mode 100644 index 000000000..619581f93 --- /dev/null +++ b/test/features/param/src/api/functional/health/index.ts @@ -0,0 +1,42 @@ +/** + * @packageDocumentation + * @module api.functional.health + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +import { Fetcher } from "@nestia/fetcher"; +import type { IConnection } from "@nestia/fetcher"; + +/** + * @controller HealthController.get() + * @path GET /health + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export function get + ( + connection: IConnection + ): Promise +{ + return Fetcher.fetch + ( + connection, + get.ENCRYPTED, + get.METHOD, + get.path() + ); +} +export namespace get +{ + + export const METHOD = "GET" as const; + export const PATH: string = "/health"; + export const ENCRYPTED: Fetcher.IEncrypted = { + request: false, + response: false, + }; + + export function path(): string + { + return `/health`; + } +} \ No newline at end of file diff --git a/test/features/param/src/api/functional/index.ts b/test/features/param/src/api/functional/index.ts new file mode 100644 index 000000000..097cf85b1 --- /dev/null +++ b/test/features/param/src/api/functional/index.ts @@ -0,0 +1,9 @@ +/** + * @packageDocumentation + * @module api.functional + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +export * as health from "./health"; +export * as performance from "./performance"; +export * as param from "./param"; \ No newline at end of file diff --git a/test/features/param/src/api/functional/param/index.ts b/test/features/param/src/api/functional/param/index.ts new file mode 100644 index 000000000..9900d8e79 --- /dev/null +++ b/test/features/param/src/api/functional/param/index.ts @@ -0,0 +1,188 @@ +/** + * @packageDocumentation + * @module api.functional.param + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +import { Fetcher, Primitive } from "@nestia/fetcher"; +import type { IConnection } from "@nestia/fetcher"; + +/** + * @controller TypedParamController.boolean() + * @path GET /param/:value/boolean + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export function boolean + ( + connection: IConnection, + value: false | true + ): Promise +{ + return Fetcher.fetch + ( + connection, + boolean.ENCRYPTED, + boolean.METHOD, + boolean.path(value) + ); +} +export namespace boolean +{ + export type Output = Primitive; + + export const METHOD = "GET" as const; + export const PATH: string = "/param/:value/boolean"; + export const ENCRYPTED: Fetcher.IEncrypted = { + request: false, + response: false, + }; + + export function path(value: false | true): string + { + return `/param/${encodeURIComponent(value ?? "null")}/boolean`; + } +} + +/** + * @controller TypedParamController.number() + * @path GET /param/:value/number + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export function number + ( + connection: IConnection, + value: number + ): Promise +{ + return Fetcher.fetch + ( + connection, + number.ENCRYPTED, + number.METHOD, + number.path(value) + ); +} +export namespace number +{ + export type Output = Primitive; + + export const METHOD = "GET" as const; + export const PATH: string = "/param/:value/number"; + export const ENCRYPTED: Fetcher.IEncrypted = { + request: false, + response: false, + }; + + export function path(value: number): string + { + return `/param/${encodeURIComponent(value ?? "null")}/number`; + } +} + +/** + * @controller TypedParamController.string() + * @path GET /param/:value/string + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export function string + ( + connection: IConnection, + value: string + ): Promise +{ + return Fetcher.fetch + ( + connection, + string.ENCRYPTED, + string.METHOD, + string.path(value) + ); +} +export namespace string +{ + export type Output = Primitive; + + export const METHOD = "GET" as const; + export const PATH: string = "/param/:value/string"; + export const ENCRYPTED: Fetcher.IEncrypted = { + request: false, + response: false, + }; + + export function path(value: string): string + { + return `/param/${encodeURIComponent(value ?? "null")}/string`; + } +} + +/** + * @controller TypedParamController.nullable() + * @path GET /param/:value/nullable + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export function nullable + ( + connection: IConnection, + value: null | string + ): Promise +{ + return Fetcher.fetch + ( + connection, + nullable.ENCRYPTED, + nullable.METHOD, + nullable.path(value) + ); +} +export namespace nullable +{ + export type Output = Primitive; + + export const METHOD = "GET" as const; + export const PATH: string = "/param/:value/nullable"; + export const ENCRYPTED: Fetcher.IEncrypted = { + request: false, + response: false, + }; + + export function path(value: null | string): string + { + return `/param/${encodeURIComponent(value ?? "null")}/nullable`; + } +} + +/** + * @controller TypedParamController.literal() + * @path GET /param/:value/literal + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export function literal + ( + connection: IConnection, + value: "A" | "B" | "C" + ): Promise +{ + return Fetcher.fetch + ( + connection, + literal.ENCRYPTED, + literal.METHOD, + literal.path(value) + ); +} +export namespace literal +{ + export type Output = Primitive<"A" | "B" | "C">; + + export const METHOD = "GET" as const; + export const PATH: string = "/param/:value/literal"; + export const ENCRYPTED: Fetcher.IEncrypted = { + request: false, + response: false, + }; + + export function path(value: "A" | "B" | "C"): string + { + return `/param/${encodeURIComponent(value ?? "null")}/literal`; + } +} \ No newline at end of file diff --git a/test/features/param/src/api/functional/performance/index.ts b/test/features/param/src/api/functional/performance/index.ts new file mode 100644 index 000000000..9e402a44a --- /dev/null +++ b/test/features/param/src/api/functional/performance/index.ts @@ -0,0 +1,45 @@ +/** + * @packageDocumentation + * @module api.functional.performance + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +import { Fetcher, Primitive } from "@nestia/fetcher"; +import type { IConnection } from "@nestia/fetcher"; + +import type { IPerformance } from "./../../structures/IPerformance"; + +/** + * @controller PerformanceController.get() + * @path GET /performance + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export function get + ( + connection: IConnection + ): Promise +{ + return Fetcher.fetch + ( + connection, + get.ENCRYPTED, + get.METHOD, + get.path() + ); +} +export namespace get +{ + export type Output = Primitive; + + export const METHOD = "GET" as const; + export const PATH: string = "/performance"; + export const ENCRYPTED: Fetcher.IEncrypted = { + request: false, + response: false, + }; + + export function path(): string + { + return `/performance`; + } +} \ No newline at end of file diff --git a/test/features/param/src/api/index.ts b/test/features/param/src/api/index.ts new file mode 100644 index 000000000..1896c4fbd --- /dev/null +++ b/test/features/param/src/api/index.ts @@ -0,0 +1,5 @@ +import * as api from "./module"; + +export * from "./module"; + +export default api; diff --git a/test/features/param/src/api/module.ts b/test/features/param/src/api/module.ts new file mode 100644 index 000000000..00239fb3b --- /dev/null +++ b/test/features/param/src/api/module.ts @@ -0,0 +1,5 @@ +export * from "./IConnection"; +export * from "./Primitive"; +export * from "./HttpError"; + +export * as functional from "./functional"; diff --git a/test/features/param/src/api/structures/IPerformance.ts b/test/features/param/src/api/structures/IPerformance.ts new file mode 100644 index 000000000..a9e9336e1 --- /dev/null +++ b/test/features/param/src/api/structures/IPerformance.ts @@ -0,0 +1,10 @@ +/** + * Performance info. + * + * @author Samchon + */ +export interface IPerformance { + cpu: NodeJS.CpuUsage; + memory: NodeJS.MemoryUsage; + resource: NodeJS.ResourceUsage; +} diff --git a/test/features/param/src/api/structures/ISystem.ts b/test/features/param/src/api/structures/ISystem.ts new file mode 100644 index 000000000..68f05ca92 --- /dev/null +++ b/test/features/param/src/api/structures/ISystem.ts @@ -0,0 +1,81 @@ +/** + * System Information. + * + * @author Jeongho Nam + */ +export interface ISystem { + /** + * Random Unique ID. + */ + uid: number; + + /** + * `process.argv` + */ + arguments: string[]; + + /** + * Git commit info. + */ + commit: ISystem.ICommit; + + /** + * `package.json` + */ + package: ISystem.IPackage; + + /** + * Creation time of this server. + */ + created_at: string; +} + +export namespace ISystem { + /** + * Git commit info. + */ + export interface ICommit { + shortHash: string; + branch: string; + hash: string; + subject: string; + sanitizedSubject: string; + body: string; + author: ICommit.IUser; + committer: ICommit.IUser; + authored_at: string; + commited_at: string; + notes?: string; + tags: string[]; + } + export namespace ICommit { + /** + * Git user account info. + */ + export interface IUser { + name: string; + email: string; + } + } + + /** + * NPM package info. + */ + export interface IPackage { + name: string; + version: string; + description: string; + main?: string; + typings?: string; + scripts: Record; + repository: { type: "git"; url: string }; + author: string; + license: string; + bugs: { url: string }; + homepage: string; + devDependencies?: Record; + dependencies: Record; + publishConfig?: { registry: string }; + files?: string[]; + } +} diff --git a/test/features/param/src/controllers/HealthController.ts b/test/features/param/src/controllers/HealthController.ts new file mode 100644 index 000000000..a9ce3563b --- /dev/null +++ b/test/features/param/src/controllers/HealthController.ts @@ -0,0 +1,9 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +@Controller("health") +export class HealthController { + @core.TypedRoute.Get() + public get(): void {} +} diff --git a/test/features/param/src/controllers/PerformanceController.ts b/test/features/param/src/controllers/PerformanceController.ts new file mode 100644 index 000000000..798d64fae --- /dev/null +++ b/test/features/param/src/controllers/PerformanceController.ts @@ -0,0 +1,17 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +import { IPerformance } from "@api/lib/structures/IPerformance"; + +@Controller("performance") +export class PerformanceController { + @core.TypedRoute.Get() + public async get(): Promise { + return { + cpu: process.cpuUsage(), + memory: process.memoryUsage(), + resource: process.resourceUsage(), + }; + } +} diff --git a/test/features/param/src/controllers/TypedParamController.ts b/test/features/param/src/controllers/TypedParamController.ts new file mode 100644 index 000000000..b2dd97912 --- /dev/null +++ b/test/features/param/src/controllers/TypedParamController.ts @@ -0,0 +1,35 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +@Controller("param") +export class TypedParamController { + @core.TypedRoute.Get(":value/boolean") + public boolean(@core.TypedParam("value") value: boolean): boolean { + return value; + } + + @core.TypedRoute.Get(":value/number") + public number(@core.TypedParam("value") value: number): number { + return value; + } + + @core.TypedRoute.Get(":value/string") + public string(@core.TypedParam("value") value: string): string { + return value; + } + + @core.TypedRoute.Get(":value/nullable") + public nullable( + @core.TypedParam("value") value: string | null, + ): string | null { + return value; + } + + @core.TypedRoute.Get(":value/literal") + public literal( + @core.TypedParam("value") value: "A" | "B" | "C", + ): "A" | "B" | "C" { + return value; + } +} diff --git a/test/features/param/src/test/features/test_api_health_check.ts b/test/features/param/src/test/features/test_api_health_check.ts new file mode 100644 index 000000000..c34703c71 --- /dev/null +++ b/test/features/param/src/test/features/test_api_health_check.ts @@ -0,0 +1,5 @@ +import api from "@api"; + +export const test_api_monitor_health_check = ( + connection: api.IConnection, +): Promise => api.functional.health.get(connection); diff --git a/test/features/param/src/test/features/test_api_param_boolean.ts b/test/features/param/src/test/features/test_api_param_boolean.ts new file mode 100644 index 000000000..637fc12ee --- /dev/null +++ b/test/features/param/src/test/features/test_api_param_boolean.ts @@ -0,0 +1,29 @@ +import typia from "typia"; + +import api from "@api"; + +import { TestValidator } from "../../../../../../packages/e2e/src/TestValidator"; + +export const test_api_param_boolean = async ( + connection: api.IConnection, +): Promise => { + const value: boolean = await api.functional.param.boolean( + connection, + false, + ); + typia.assert(value); + + TestValidator.equals("false")(false)( + await api.functional.param.boolean(connection, 0 as any), + ); + TestValidator.equals("true")(true)( + await api.functional.param.boolean(connection, 1 as any), + ); + + await TestValidator.error("number")(() => + api.functional.param.boolean(connection, 2 as any), + ); + await TestValidator.error("string")(() => + api.functional.param.boolean(connection, "string" as any), + ); +}; diff --git a/test/features/param/src/test/features/test_api_param_literal.ts b/test/features/param/src/test/features/test_api_param_literal.ts new file mode 100644 index 000000000..17eef57d7 --- /dev/null +++ b/test/features/param/src/test/features/test_api_param_literal.ts @@ -0,0 +1,22 @@ +import api from "@api"; + +import { TestValidator } from "../../../../../../packages/e2e/src/TestValidator"; + +export const test_api_param_literal = async ( + connection: api.IConnection, +): Promise => { + for (const value of ["A", "B", "C"] as const) { + const result = await api.functional.param.literal(connection, value); + TestValidator.equals("literal")(value)(result); + } + + await TestValidator.error("string")(() => + api.functional.param.literal(connection, "D" as any), + ); + await TestValidator.error("number")(() => + api.functional.param.literal(connection, 1 as any), + ); + await TestValidator.error("boolean")(() => + api.functional.param.literal(connection, true as any), + ); +}; diff --git a/test/features/param/src/test/features/test_api_param_number.ts b/test/features/param/src/test/features/test_api_param_number.ts new file mode 100644 index 000000000..5882f88c2 --- /dev/null +++ b/test/features/param/src/test/features/test_api_param_number.ts @@ -0,0 +1,19 @@ +import typia from "typia"; + +import api from "@api"; + +import { TestValidator } from "../../../../../../packages/e2e/src/TestValidator"; + +export const test_api_param_number = async ( + connection: api.IConnection, +): Promise => { + const value: number = await api.functional.param.number(connection, 1); + typia.assert(value); + + await TestValidator.error("boolean")(() => + api.functional.param.number(connection, true as any), + ); + await TestValidator.error("string")(() => + api.functional.param.number(connection, "string" as any), + ); +}; diff --git a/test/features/param/src/test/features/test_api_param_string.ts b/test/features/param/src/test/features/test_api_param_string.ts new file mode 100644 index 000000000..8e6fda3cf --- /dev/null +++ b/test/features/param/src/test/features/test_api_param_string.ts @@ -0,0 +1,13 @@ +import typia from "typia"; + +import api from "@api"; + +export const test_api_param_string = async ( + connection: api.IConnection, +): Promise => { + const value: string = await api.functional.param.string( + connection, + "string", + ); + typia.assert(value); +}; diff --git a/test/features/param/src/test/features/test_api_performance.ts b/test/features/param/src/test/features/test_api_performance.ts new file mode 100644 index 000000000..55b6d2ca7 --- /dev/null +++ b/test/features/param/src/test/features/test_api_performance.ts @@ -0,0 +1,13 @@ +import typia from "typia"; + +import api from "@api"; +import { IPerformance } from "@api/lib/structures/IPerformance"; + +export const test_api_monitor_performance = async ( + connection: api.IConnection, +): Promise => { + const performance: IPerformance = await api.functional.performance.get( + connection, + ); + typia.assert(performance); +}; diff --git a/test/features/param/src/test/index.ts b/test/features/param/src/test/index.ts new file mode 100644 index 000000000..e89842739 --- /dev/null +++ b/test/features/param/src/test/index.ts @@ -0,0 +1,39 @@ +import { DynamicExecutor } from "@nestia/e2e"; + +import { Backend } from "../Backend"; + +async function main(): Promise { + const server: Backend = new Backend(); + await server.open(); + + const report: DynamicExecutor.IReport = await DynamicExecutor.validate({ + prefix: "test", + parameters: () => [ + { + host: "http://127.0.0.1:37000", + encryption: { + key: "A".repeat(32), + iv: "B".repeat(16), + }, + }, + ], + })(`${__dirname}/features`); + await server.close(); + + const exceptions: Error[] = report.executions + .filter((exec) => exec.error !== null) + .map((exec) => exec.error!); + if (exceptions.length === 0) { + console.log("Success"); + console.log("Elapsed time", report.time.toLocaleString(), `ms`); + } else { + // for (const exp of exceptions) console.log(exp); + console.log("Failed"); + console.log("Elapsed time", report.time.toLocaleString(), `ms`); + process.exit(-1); + } +} +main().catch((exp) => { + console.log(exp); + process.exit(-1); +}); diff --git a/test/features/param/swagger.json b/test/features/param/swagger.json new file mode 100644 index 000000000..2792325f4 --- /dev/null +++ b/test/features/param/swagger.json @@ -0,0 +1,474 @@ +{ + "openapi": "3.0.1", + "servers": [ + { + "url": "https://github.com/samchon/nestia", + "description": "insert your server url" + } + ], + "info": { + "version": "0.1.0", + "title": "Generated by nestia - https://github.com/samchon/nestia" + }, + "paths": { + "/health": { + "get": { + "tags": [], + "parameters": [], + "responses": { + "200": { + "description": "", + "x-nestia-encrypted": false + } + }, + "description": "", + "x-nestia-namespace": "health.get", + "x-nestia-jsDocTags": [] + } + }, + "/performance": { + "get": { + "tags": [], + "parameters": [], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IPerformance" + } + } + }, + "x-nestia-encrypted": false + } + }, + "description": "", + "x-nestia-namespace": "performance.get", + "x-nestia-jsDocTags": [] + } + }, + "/param/{value}/boolean": { + "get": { + "tags": [], + "parameters": [ + { + "name": "value", + "in": "path", + "description": "", + "schema": { + "type": "boolean", + "nullable": false + }, + "required": true + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "boolean", + "nullable": false + } + } + }, + "x-nestia-encrypted": false + } + }, + "description": "", + "x-nestia-namespace": "param.boolean.boolean", + "x-nestia-jsDocTags": [] + } + }, + "/param/{value}/number": { + "get": { + "tags": [], + "parameters": [ + { + "name": "value", + "in": "path", + "description": "", + "schema": { + "type": "number", + "nullable": false + }, + "required": true + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "number", + "nullable": false + } + } + }, + "x-nestia-encrypted": false + } + }, + "description": "", + "x-nestia-namespace": "param.number.number", + "x-nestia-jsDocTags": [] + } + }, + "/param/{value}/string": { + "get": { + "tags": [], + "parameters": [ + { + "name": "value", + "in": "path", + "description": "", + "schema": { + "type": "string", + "nullable": false + }, + "required": true + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "string", + "nullable": false + } + } + }, + "x-nestia-encrypted": false + } + }, + "description": "", + "x-nestia-namespace": "param.string.string", + "x-nestia-jsDocTags": [] + } + }, + "/param/{value}/nullable": { + "get": { + "tags": [], + "parameters": [ + { + "name": "value", + "in": "path", + "description": "", + "schema": { + "type": "string", + "nullable": true + }, + "required": true + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "string", + "nullable": true + } + } + }, + "x-nestia-encrypted": false + } + }, + "description": "", + "x-nestia-namespace": "param.nullable.nullable", + "x-nestia-jsDocTags": [] + } + }, + "/param/{value}/literal": { + "get": { + "tags": [], + "parameters": [ + { + "name": "value", + "in": "path", + "description": "", + "schema": { + "type": "string", + "enum": [ + "A", + "B", + "C" + ], + "nullable": false + }, + "required": true + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "string", + "enum": [ + "A", + "B", + "C" + ], + "nullable": false + } + } + }, + "x-nestia-encrypted": false + } + }, + "description": "", + "x-nestia-namespace": "param.literal.literal", + "x-nestia-jsDocTags": [] + } + } + }, + "components": { + "schemas": { + "IPerformance": { + "type": "object", + "properties": { + "cpu": { + "$ref": "#/components/schemas/_singlequote_process_singlequote_.global.NodeJS.CpuUsage", + "x-typia-required": true, + "x-typia-optional": false + }, + "memory": { + "$ref": "#/components/schemas/_singlequote_process_singlequote_.global.NodeJS.MemoryUsage", + "x-typia-required": true, + "x-typia-optional": false + }, + "resource": { + "$ref": "#/components/schemas/_singlequote_process_singlequote_.global.NodeJS.ResourceUsage", + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "cpu", + "memory", + "resource" + ], + "description": "Performance info.", + "x-typia-jsDocTags": [ + { + "name": "author", + "text": [ + { + "text": "Samchon", + "kind": "text" + } + ] + } + ] + }, + "_singlequote_process_singlequote_.global.NodeJS.CpuUsage": { + "type": "object", + "properties": { + "user": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "system": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "user", + "system" + ], + "x-typia-jsDocTags": [] + }, + "_singlequote_process_singlequote_.global.NodeJS.MemoryUsage": { + "type": "object", + "properties": { + "rss": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "heapTotal": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "heapUsed": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "external": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "arrayBuffers": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "rss", + "heapTotal", + "heapUsed", + "external", + "arrayBuffers" + ], + "x-typia-jsDocTags": [] + }, + "_singlequote_process_singlequote_.global.NodeJS.ResourceUsage": { + "type": "object", + "properties": { + "fsRead": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "fsWrite": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "involuntaryContextSwitches": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "ipcReceived": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "ipcSent": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "majorPageFault": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "maxRSS": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "minorPageFault": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "sharedMemorySize": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "signalsCount": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "swappedOut": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "systemCPUTime": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "unsharedDataSize": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "unsharedStackSize": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "userCPUTime": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "voluntaryContextSwitches": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "fsRead", + "fsWrite", + "involuntaryContextSwitches", + "ipcReceived", + "ipcSent", + "majorPageFault", + "maxRSS", + "minorPageFault", + "sharedMemorySize", + "signalsCount", + "swappedOut", + "systemCPUTime", + "unsharedDataSize", + "unsharedStackSize", + "userCPUTime", + "voluntaryContextSwitches" + ], + "x-typia-jsDocTags": [] + } + }, + "securitySchemes": { + "bearer": { + "type": "apiKey", + "in": "header", + "name": "Authorization" + } + } + }, + "security": [ + { + "bearer": [] + } + ] +} \ No newline at end of file diff --git a/test/features/param/tsconfig.json b/test/features/param/tsconfig.json new file mode 100644 index 000000000..e5fe47a95 --- /dev/null +++ b/test/features/param/tsconfig.json @@ -0,0 +1,103 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + /* Language and Environment */ + "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + /* Modules */ + "module": "commonjs", /* Specify what module code is generated. */// "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + "paths": { + "@nestia/core": ["../../../packages/core/src"], + "@nestia/e2e": ["../../../packages/e2e/src"], + "@nestia/fetcher": ["../../../packages/fetcher/src"], + "@nestia/sdk": ["../../../packages/sdk/src"], + "@nestia/sdk/lib/*": ["../../../packages/sdk/src/*"], + "@api": ["./src/api"], + "@api/lib/*": ["./src/api/*"], + }, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. *//* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true, /* Skip type checking all .d.ts files. */ + "plugins": [ + { "transform": "typescript-transform-paths" }, + { "transform": "typia/lib/transform" }, + { "transform": "../../../packages/core/src/transform.ts" }, + ], + } + } \ No newline at end of file diff --git a/test/features/query-error-array/nestia.config.ts b/test/features/query-error-array/nestia.config.ts new file mode 100644 index 000000000..2594a40d0 --- /dev/null +++ b/test/features/query-error-array/nestia.config.ts @@ -0,0 +1,15 @@ +import { INestiaConfig } from "@nestia/sdk"; + +export const NESTIA_CONFIG: INestiaConfig = { + input: ["src/controllers"], + output: "src/api", + swagger: { + output: "swagger.json", + security: { + bearer: { + type: "apiKey", + }, + }, + }, +}; +export default NESTIA_CONFIG; diff --git a/test/features/query-error-array/src/controllers/HealthController.ts b/test/features/query-error-array/src/controllers/HealthController.ts new file mode 100644 index 000000000..a9ce3563b --- /dev/null +++ b/test/features/query-error-array/src/controllers/HealthController.ts @@ -0,0 +1,9 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +@Controller("health") +export class HealthController { + @core.TypedRoute.Get() + public get(): void {} +} diff --git a/test/features/query-error-array/src/controllers/TypedQueryController.ts b/test/features/query-error-array/src/controllers/TypedQueryController.ts new file mode 100644 index 000000000..b7128e20b --- /dev/null +++ b/test/features/query-error-array/src/controllers/TypedQueryController.ts @@ -0,0 +1,18 @@ +import { Controller } from "@nestjs/common"; + +import { + TypedQuery, + TypedRoute, +} from "../../../../../packages/core/src/module"; + +@Controller("query") +export class TypedQueryController { + @TypedRoute.Get() + public query(@TypedQuery() query: IObject[]): void { + query; + } +} + +interface IObject { + name: string; +} diff --git a/test/features/query-error-array/tsconfig.json b/test/features/query-error-array/tsconfig.json new file mode 100644 index 000000000..e74060a2d --- /dev/null +++ b/test/features/query-error-array/tsconfig.json @@ -0,0 +1,101 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + /* Language and Environment */ + "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + /* Modules */ + "module": "commonjs", /* Specify what module code is generated. */// "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + "paths": { + "@nestia/core": ["../../../packages/core/src"], + "@nestia/e2e": ["../../../packages/e2e/src"], + "@nestia/fetcher": ["../../../packages/fetcher/src"], + "@nestia/sdk": ["../../../packages/sdk/src"], + "@nestia/sdk/lib/*": ["../../../packages/sdk/src/*"], + }, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. *//* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true, /* Skip type checking all .d.ts files. */ + "plugins": [ + { "transform": "typescript-transform-paths" }, + { "transform": "typia/lib/transform" }, + { "transform": "../../../packages/core/src/transform.ts" }, + ], + } + } \ No newline at end of file diff --git a/test/features/query-error-atomic/nestia.config.ts b/test/features/query-error-atomic/nestia.config.ts new file mode 100644 index 000000000..2594a40d0 --- /dev/null +++ b/test/features/query-error-atomic/nestia.config.ts @@ -0,0 +1,15 @@ +import { INestiaConfig } from "@nestia/sdk"; + +export const NESTIA_CONFIG: INestiaConfig = { + input: ["src/controllers"], + output: "src/api", + swagger: { + output: "swagger.json", + security: { + bearer: { + type: "apiKey", + }, + }, + }, +}; +export default NESTIA_CONFIG; diff --git a/test/features/query-error-atomic/src/controllers/HealthController.ts b/test/features/query-error-atomic/src/controllers/HealthController.ts new file mode 100644 index 000000000..a9ce3563b --- /dev/null +++ b/test/features/query-error-atomic/src/controllers/HealthController.ts @@ -0,0 +1,9 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +@Controller("health") +export class HealthController { + @core.TypedRoute.Get() + public get(): void {} +} diff --git a/test/features/query-error-atomic/src/controllers/TypedQueryController.ts b/test/features/query-error-atomic/src/controllers/TypedQueryController.ts new file mode 100644 index 000000000..71fdb870d --- /dev/null +++ b/test/features/query-error-atomic/src/controllers/TypedQueryController.ts @@ -0,0 +1,14 @@ +import { Controller } from "@nestjs/common"; + +import { + TypedQuery, + TypedRoute, +} from "../../../../../packages/core/src/module"; + +@Controller("query") +export class TypedQueryController { + @TypedRoute.Get() + public query(@TypedQuery() query: number): void { + query; + } +} diff --git a/test/features/query-error-atomic/tsconfig.json b/test/features/query-error-atomic/tsconfig.json new file mode 100644 index 000000000..e74060a2d --- /dev/null +++ b/test/features/query-error-atomic/tsconfig.json @@ -0,0 +1,101 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + /* Language and Environment */ + "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + /* Modules */ + "module": "commonjs", /* Specify what module code is generated. */// "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + "paths": { + "@nestia/core": ["../../../packages/core/src"], + "@nestia/e2e": ["../../../packages/e2e/src"], + "@nestia/fetcher": ["../../../packages/fetcher/src"], + "@nestia/sdk": ["../../../packages/sdk/src"], + "@nestia/sdk/lib/*": ["../../../packages/sdk/src/*"], + }, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. *//* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true, /* Skip type checking all .d.ts files. */ + "plugins": [ + { "transform": "typescript-transform-paths" }, + { "transform": "typia/lib/transform" }, + { "transform": "../../../packages/core/src/transform.ts" }, + ], + } + } \ No newline at end of file diff --git a/test/features/query-error-generic/nestia.config.ts b/test/features/query-error-generic/nestia.config.ts new file mode 100644 index 000000000..2594a40d0 --- /dev/null +++ b/test/features/query-error-generic/nestia.config.ts @@ -0,0 +1,15 @@ +import { INestiaConfig } from "@nestia/sdk"; + +export const NESTIA_CONFIG: INestiaConfig = { + input: ["src/controllers"], + output: "src/api", + swagger: { + output: "swagger.json", + security: { + bearer: { + type: "apiKey", + }, + }, + }, +}; +export default NESTIA_CONFIG; diff --git a/test/features/query-error-generic/src/controllers/HealthController.ts b/test/features/query-error-generic/src/controllers/HealthController.ts new file mode 100644 index 000000000..a9ce3563b --- /dev/null +++ b/test/features/query-error-generic/src/controllers/HealthController.ts @@ -0,0 +1,9 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +@Controller("health") +export class HealthController { + @core.TypedRoute.Get() + public get(): void {} +} diff --git a/test/features/query-error-generic/src/controllers/TypedQueryController.ts b/test/features/query-error-generic/src/controllers/TypedQueryController.ts new file mode 100644 index 000000000..e4beb8639 --- /dev/null +++ b/test/features/query-error-generic/src/controllers/TypedQueryController.ts @@ -0,0 +1,18 @@ +import { Controller } from "@nestjs/common"; + +import { + TypedQuery, + TypedRoute, +} from "../../../../../packages/core/src/module"; + +@Controller("query") +export class TypedQueryController { + @TypedRoute.Get() + public query(@TypedQuery() query: IUnionGeneric): void { + query; + } +} + +interface IUnionGeneric { + value: T; +} diff --git a/test/features/query-error-generic/tsconfig.json b/test/features/query-error-generic/tsconfig.json new file mode 100644 index 000000000..e74060a2d --- /dev/null +++ b/test/features/query-error-generic/tsconfig.json @@ -0,0 +1,101 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + /* Language and Environment */ + "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + /* Modules */ + "module": "commonjs", /* Specify what module code is generated. */// "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + "paths": { + "@nestia/core": ["../../../packages/core/src"], + "@nestia/e2e": ["../../../packages/e2e/src"], + "@nestia/fetcher": ["../../../packages/fetcher/src"], + "@nestia/sdk": ["../../../packages/sdk/src"], + "@nestia/sdk/lib/*": ["../../../packages/sdk/src/*"], + }, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. *//* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true, /* Skip type checking all .d.ts files. */ + "plugins": [ + { "transform": "typescript-transform-paths" }, + { "transform": "typia/lib/transform" }, + { "transform": "../../../packages/core/src/transform.ts" }, + ], + } + } \ No newline at end of file diff --git a/test/features/query-error-native/nestia.config.ts b/test/features/query-error-native/nestia.config.ts new file mode 100644 index 000000000..2594a40d0 --- /dev/null +++ b/test/features/query-error-native/nestia.config.ts @@ -0,0 +1,15 @@ +import { INestiaConfig } from "@nestia/sdk"; + +export const NESTIA_CONFIG: INestiaConfig = { + input: ["src/controllers"], + output: "src/api", + swagger: { + output: "swagger.json", + security: { + bearer: { + type: "apiKey", + }, + }, + }, +}; +export default NESTIA_CONFIG; diff --git a/test/features/query-error-native/src/controllers/HealthController.ts b/test/features/query-error-native/src/controllers/HealthController.ts new file mode 100644 index 000000000..a9ce3563b --- /dev/null +++ b/test/features/query-error-native/src/controllers/HealthController.ts @@ -0,0 +1,9 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +@Controller("health") +export class HealthController { + @core.TypedRoute.Get() + public get(): void {} +} diff --git a/test/features/query-error-native/src/controllers/TypedQueryController.ts b/test/features/query-error-native/src/controllers/TypedQueryController.ts new file mode 100644 index 000000000..ab50c8069 --- /dev/null +++ b/test/features/query-error-native/src/controllers/TypedQueryController.ts @@ -0,0 +1,14 @@ +import { Controller } from "@nestjs/common"; + +import { + TypedQuery, + TypedRoute, +} from "../../../../../packages/core/src/module"; + +@Controller("query") +export class TypedQueryController { + @TypedRoute.Get() + public query(@TypedQuery() query: Map): void { + query; + } +} diff --git a/test/features/query-error-native/tsconfig.json b/test/features/query-error-native/tsconfig.json new file mode 100644 index 000000000..e74060a2d --- /dev/null +++ b/test/features/query-error-native/tsconfig.json @@ -0,0 +1,101 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + /* Language and Environment */ + "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + /* Modules */ + "module": "commonjs", /* Specify what module code is generated. */// "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + "paths": { + "@nestia/core": ["../../../packages/core/src"], + "@nestia/e2e": ["../../../packages/e2e/src"], + "@nestia/fetcher": ["../../../packages/fetcher/src"], + "@nestia/sdk": ["../../../packages/sdk/src"], + "@nestia/sdk/lib/*": ["../../../packages/sdk/src/*"], + }, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. *//* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true, /* Skip type checking all .d.ts files. */ + "plugins": [ + { "transform": "typescript-transform-paths" }, + { "transform": "typia/lib/transform" }, + { "transform": "../../../packages/core/src/transform.ts" }, + ], + } + } \ No newline at end of file diff --git a/test/features/query-error-union-array/nestia.config.ts b/test/features/query-error-union-array/nestia.config.ts new file mode 100644 index 000000000..2594a40d0 --- /dev/null +++ b/test/features/query-error-union-array/nestia.config.ts @@ -0,0 +1,15 @@ +import { INestiaConfig } from "@nestia/sdk"; + +export const NESTIA_CONFIG: INestiaConfig = { + input: ["src/controllers"], + output: "src/api", + swagger: { + output: "swagger.json", + security: { + bearer: { + type: "apiKey", + }, + }, + }, +}; +export default NESTIA_CONFIG; diff --git a/test/features/query-error-union-array/src/controllers/HealthController.ts b/test/features/query-error-union-array/src/controllers/HealthController.ts new file mode 100644 index 000000000..a9ce3563b --- /dev/null +++ b/test/features/query-error-union-array/src/controllers/HealthController.ts @@ -0,0 +1,9 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +@Controller("health") +export class HealthController { + @core.TypedRoute.Get() + public get(): void {} +} diff --git a/test/features/query-error-union-array/src/controllers/TypedQueryController.ts b/test/features/query-error-union-array/src/controllers/TypedQueryController.ts new file mode 100644 index 000000000..2cb8f3b54 --- /dev/null +++ b/test/features/query-error-union-array/src/controllers/TypedQueryController.ts @@ -0,0 +1,18 @@ +import { Controller } from "@nestjs/common"; + +import { + TypedQuery, + TypedRoute, +} from "../../../../../packages/core/src/module"; + +@Controller("query") +export class TypedQueryController { + @TypedRoute.Get() + public query(@TypedQuery() query: IUnionArray): void { + query; + } +} + +interface IUnionArray { + array: Array; +} diff --git a/test/features/query-error-union-array/tsconfig.json b/test/features/query-error-union-array/tsconfig.json new file mode 100644 index 000000000..e74060a2d --- /dev/null +++ b/test/features/query-error-union-array/tsconfig.json @@ -0,0 +1,101 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + /* Language and Environment */ + "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + /* Modules */ + "module": "commonjs", /* Specify what module code is generated. */// "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + "paths": { + "@nestia/core": ["../../../packages/core/src"], + "@nestia/e2e": ["../../../packages/e2e/src"], + "@nestia/fetcher": ["../../../packages/fetcher/src"], + "@nestia/sdk": ["../../../packages/sdk/src"], + "@nestia/sdk/lib/*": ["../../../packages/sdk/src/*"], + }, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. *//* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true, /* Skip type checking all .d.ts files. */ + "plugins": [ + { "transform": "typescript-transform-paths" }, + { "transform": "typia/lib/transform" }, + { "transform": "../../../packages/core/src/transform.ts" }, + ], + } + } \ No newline at end of file diff --git a/test/features/query-error-union-literal/nestia.config.ts b/test/features/query-error-union-literal/nestia.config.ts new file mode 100644 index 000000000..2594a40d0 --- /dev/null +++ b/test/features/query-error-union-literal/nestia.config.ts @@ -0,0 +1,15 @@ +import { INestiaConfig } from "@nestia/sdk"; + +export const NESTIA_CONFIG: INestiaConfig = { + input: ["src/controllers"], + output: "src/api", + swagger: { + output: "swagger.json", + security: { + bearer: { + type: "apiKey", + }, + }, + }, +}; +export default NESTIA_CONFIG; diff --git a/test/features/query-error-union-literal/src/controllers/HealthController.ts b/test/features/query-error-union-literal/src/controllers/HealthController.ts new file mode 100644 index 000000000..a9ce3563b --- /dev/null +++ b/test/features/query-error-union-literal/src/controllers/HealthController.ts @@ -0,0 +1,9 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +@Controller("health") +export class HealthController { + @core.TypedRoute.Get() + public get(): void {} +} diff --git a/test/features/query-error-union-literal/src/controllers/TypedQueryController.ts b/test/features/query-error-union-literal/src/controllers/TypedQueryController.ts new file mode 100644 index 000000000..7c5ebcb66 --- /dev/null +++ b/test/features/query-error-union-literal/src/controllers/TypedQueryController.ts @@ -0,0 +1,18 @@ +import { Controller } from "@nestjs/common"; + +import { + TypedQuery, + TypedRoute, +} from "../../../../../packages/core/src/module"; + +@Controller("query") +export class TypedQueryController { + @TypedRoute.Get() + public query(@TypedQuery() query: IUnionLiteralQuery): void { + query; + } +} + +interface IUnionLiteralQuery { + literal: false | 1 | "two"; +} diff --git a/test/features/query-error-union-literal/tsconfig.json b/test/features/query-error-union-literal/tsconfig.json new file mode 100644 index 000000000..e74060a2d --- /dev/null +++ b/test/features/query-error-union-literal/tsconfig.json @@ -0,0 +1,101 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + /* Language and Environment */ + "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + /* Modules */ + "module": "commonjs", /* Specify what module code is generated. */// "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + "paths": { + "@nestia/core": ["../../../packages/core/src"], + "@nestia/e2e": ["../../../packages/e2e/src"], + "@nestia/fetcher": ["../../../packages/fetcher/src"], + "@nestia/sdk": ["../../../packages/sdk/src"], + "@nestia/sdk/lib/*": ["../../../packages/sdk/src/*"], + }, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. *//* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true, /* Skip type checking all .d.ts files. */ + "plugins": [ + { "transform": "typescript-transform-paths" }, + { "transform": "typia/lib/transform" }, + { "transform": "../../../packages/core/src/transform.ts" }, + ], + } + } \ No newline at end of file diff --git a/test/features/query-error-union-object/nestia.config.ts b/test/features/query-error-union-object/nestia.config.ts new file mode 100644 index 000000000..2594a40d0 --- /dev/null +++ b/test/features/query-error-union-object/nestia.config.ts @@ -0,0 +1,15 @@ +import { INestiaConfig } from "@nestia/sdk"; + +export const NESTIA_CONFIG: INestiaConfig = { + input: ["src/controllers"], + output: "src/api", + swagger: { + output: "swagger.json", + security: { + bearer: { + type: "apiKey", + }, + }, + }, +}; +export default NESTIA_CONFIG; diff --git a/test/features/query-error-union-object/src/controllers/HealthController.ts b/test/features/query-error-union-object/src/controllers/HealthController.ts new file mode 100644 index 000000000..a9ce3563b --- /dev/null +++ b/test/features/query-error-union-object/src/controllers/HealthController.ts @@ -0,0 +1,9 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +@Controller("health") +export class HealthController { + @core.TypedRoute.Get() + public get(): void {} +} diff --git a/test/features/query-error-union-object/src/controllers/TypedQueryController.ts b/test/features/query-error-union-object/src/controllers/TypedQueryController.ts new file mode 100644 index 000000000..c3108616d --- /dev/null +++ b/test/features/query-error-union-object/src/controllers/TypedQueryController.ts @@ -0,0 +1,21 @@ +import { Controller } from "@nestjs/common"; + +import { + TypedQuery, + TypedRoute, +} from "../../../../../packages/core/src/module"; + +@Controller("query") +export class TypedQueryController { + @TypedRoute.Get() + public query(@TypedQuery() query: IFirst | ISecond): void { + query; + } +} + +interface IFirst { + first: string; +} +interface ISecond { + second: string; +} diff --git a/test/features/query-error-union-object/tsconfig.json b/test/features/query-error-union-object/tsconfig.json new file mode 100644 index 000000000..e74060a2d --- /dev/null +++ b/test/features/query-error-union-object/tsconfig.json @@ -0,0 +1,101 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + /* Language and Environment */ + "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + /* Modules */ + "module": "commonjs", /* Specify what module code is generated. */// "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + "paths": { + "@nestia/core": ["../../../packages/core/src"], + "@nestia/e2e": ["../../../packages/e2e/src"], + "@nestia/fetcher": ["../../../packages/fetcher/src"], + "@nestia/sdk": ["../../../packages/sdk/src"], + "@nestia/sdk/lib/*": ["../../../packages/sdk/src/*"], + }, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. *//* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true, /* Skip type checking all .d.ts files. */ + "plugins": [ + { "transform": "typescript-transform-paths" }, + { "transform": "typia/lib/transform" }, + { "transform": "../../../packages/core/src/transform.ts" }, + ], + } + } \ No newline at end of file diff --git a/test/features/query-error-union-property/nestia.config.ts b/test/features/query-error-union-property/nestia.config.ts new file mode 100644 index 000000000..2594a40d0 --- /dev/null +++ b/test/features/query-error-union-property/nestia.config.ts @@ -0,0 +1,15 @@ +import { INestiaConfig } from "@nestia/sdk"; + +export const NESTIA_CONFIG: INestiaConfig = { + input: ["src/controllers"], + output: "src/api", + swagger: { + output: "swagger.json", + security: { + bearer: { + type: "apiKey", + }, + }, + }, +}; +export default NESTIA_CONFIG; diff --git a/test/features/query-error-union-property/src/controllers/HealthController.ts b/test/features/query-error-union-property/src/controllers/HealthController.ts new file mode 100644 index 000000000..a9ce3563b --- /dev/null +++ b/test/features/query-error-union-property/src/controllers/HealthController.ts @@ -0,0 +1,9 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +@Controller("health") +export class HealthController { + @core.TypedRoute.Get() + public get(): void {} +} diff --git a/test/features/query-error-union-property/src/controllers/TypedQueryController.ts b/test/features/query-error-union-property/src/controllers/TypedQueryController.ts new file mode 100644 index 000000000..5e87c539a --- /dev/null +++ b/test/features/query-error-union-property/src/controllers/TypedQueryController.ts @@ -0,0 +1,18 @@ +import { Controller } from "@nestjs/common"; + +import { + TypedQuery, + TypedRoute, +} from "../../../../../packages/core/src/module"; + +@Controller("query") +export class TypedQueryController { + @TypedRoute.Get() + public query(@TypedQuery() query: IUnionProperty): void { + query; + } +} + +interface IUnionProperty { + property: string | number; +} diff --git a/test/features/query-error-union-property/tsconfig.json b/test/features/query-error-union-property/tsconfig.json new file mode 100644 index 000000000..e74060a2d --- /dev/null +++ b/test/features/query-error-union-property/tsconfig.json @@ -0,0 +1,101 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + /* Language and Environment */ + "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + /* Modules */ + "module": "commonjs", /* Specify what module code is generated. */// "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + "paths": { + "@nestia/core": ["../../../packages/core/src"], + "@nestia/e2e": ["../../../packages/e2e/src"], + "@nestia/fetcher": ["../../../packages/fetcher/src"], + "@nestia/sdk": ["../../../packages/sdk/src"], + "@nestia/sdk/lib/*": ["../../../packages/sdk/src/*"], + }, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. *//* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true, /* Skip type checking all .d.ts files. */ + "plugins": [ + { "transform": "typescript-transform-paths" }, + { "transform": "typia/lib/transform" }, + { "transform": "../../../packages/core/src/transform.ts" }, + ], + } + } \ No newline at end of file diff --git a/test/features/query/nestia.config.ts b/test/features/query/nestia.config.ts new file mode 100644 index 000000000..2594a40d0 --- /dev/null +++ b/test/features/query/nestia.config.ts @@ -0,0 +1,15 @@ +import { INestiaConfig } from "@nestia/sdk"; + +export const NESTIA_CONFIG: INestiaConfig = { + input: ["src/controllers"], + output: "src/api", + swagger: { + output: "swagger.json", + security: { + bearer: { + type: "apiKey", + }, + }, + }, +}; +export default NESTIA_CONFIG; diff --git a/test/features/query/src/Backend.ts b/test/features/query/src/Backend.ts new file mode 100644 index 000000000..8ab51b70f --- /dev/null +++ b/test/features/query/src/Backend.ts @@ -0,0 +1,28 @@ +import { INestApplication } from "@nestjs/common"; +import { NestFactory } from "@nestjs/core"; + +import core from "@nestia/core"; + +export class Backend { + private application_?: INestApplication; + + public async open(): Promise { + this.application_ = await NestFactory.create( + await core.EncryptedModule.dynamic(__dirname + "/controllers", { + key: "A".repeat(32), + iv: "B".repeat(16), + }), + { logger: false }, + ); + await this.application_.listen(37_000); + } + + public async close(): Promise { + if (this.application_ === undefined) return; + + const app = this.application_; + await app.close(); + + delete this.application_; + } +} diff --git a/test/features/query/src/api/HttpError.ts b/test/features/query/src/api/HttpError.ts new file mode 100644 index 000000000..5df328ae4 --- /dev/null +++ b/test/features/query/src/api/HttpError.ts @@ -0,0 +1 @@ +export { HttpError } from "@nestia/fetcher"; diff --git a/test/features/query/src/api/IConnection.ts b/test/features/query/src/api/IConnection.ts new file mode 100644 index 000000000..92727cfc2 --- /dev/null +++ b/test/features/query/src/api/IConnection.ts @@ -0,0 +1 @@ +export { IConnection } from "@nestia/fetcher"; diff --git a/test/features/query/src/api/Primitive.ts b/test/features/query/src/api/Primitive.ts new file mode 100644 index 000000000..3c1db5a74 --- /dev/null +++ b/test/features/query/src/api/Primitive.ts @@ -0,0 +1 @@ +export { Primitive } from "@nestia/fetcher"; diff --git a/packages/sdk/demo/union/src/api/functional/consumers/sales/reviews/index.ts b/test/features/query/src/api/functional/bbs/articles/index.ts similarity index 50% rename from packages/sdk/demo/union/src/api/functional/consumers/sales/reviews/index.ts rename to test/features/query/src/api/functional/bbs/articles/index.ts index f06ba591b..4e2a1549f 100644 --- a/packages/sdk/demo/union/src/api/functional/consumers/sales/reviews/index.ts +++ b/test/features/query/src/api/functional/bbs/articles/index.ts @@ -1,28 +1,24 @@ /** * @packageDocumentation - * @module api.functional.consumers.sales.reviews + * @module api.functional.bbs.articles * @nestia Generated by Nestia - https://github.com/samchon/nestia */ //================================================================ -import { Fetcher } from "@nestia/fetcher"; +import { Fetcher, Primitive } from "@nestia/fetcher"; import type { IConnection } from "@nestia/fetcher"; -import type { ISaleReview } from "./../../../../structures/ISaleReview"; -import type { ISaleInquiry } from "./../../../../structures/ISaleInquiry"; -import type { IPage } from "./../../../../structures/IPage"; +import type { IPage } from "./../../../structures/IPage"; +import type { IBbsArticle } from "./../../../structures/IBbsArticle"; /** - * @controller ConsumerSaleQuestionsController.index() - * @path PATCH /consumers/:section/sales/:saleId/reviews + * @controller BbsArticlesController.index() + * @path GET /bbs/articles * @nestia Generated by Nestia - https://github.com/samchon/nestia */ export function index ( connection: IConnection, - section: string, - saleId: number, - query: ISaleReview.IQuery, - input: ISaleInquiry.IRequest + query: Primitive ): Promise { return Fetcher.fetch @@ -30,24 +26,22 @@ export function index connection, index.ENCRYPTED, index.METHOD, - index.path(section, saleId, query), - input + index.path(query) ); } export namespace index { - export type Query = ISaleReview.IQuery; - export type Input = ISaleInquiry.IRequest; - export type Output = IPage; + export type Query = Primitive; + export type Output = Primitive>; - export const METHOD = "PATCH" as const; - export const PATH: string = "/consumers/:section/sales/:saleId/reviews"; + export const METHOD = "GET" as const; + export const PATH: string = "/bbs/articles"; export const ENCRYPTED: Fetcher.IEncrypted = { request: false, response: false, }; - export function path(section: string, saleId: number, query: ISaleReview.IQuery): string + export function path(query: IPage.IRequest): string { const variables: Record = query as any; const search: URLSearchParams = new URLSearchParams(); @@ -58,6 +52,6 @@ export namespace index else search.set(key, String(value)); const encoded: string = search.toString(); - return `/consumers/${encodeURIComponent(section)}/sales/${encodeURIComponent(saleId)}/reviews${encoded.length ? `?${encoded}` : ""}`;; + return `/bbs/articles${encoded.length ? `?${encoded}` : ""}`;; } } \ No newline at end of file diff --git a/packages/sdk/demo/multiple-paths/src/api/functional/sellers/sales/index.ts b/test/features/query/src/api/functional/bbs/index.ts similarity index 83% rename from packages/sdk/demo/multiple-paths/src/api/functional/sellers/sales/index.ts rename to test/features/query/src/api/functional/bbs/index.ts index fcaa0832a..efe5ba769 100644 --- a/packages/sdk/demo/multiple-paths/src/api/functional/sellers/sales/index.ts +++ b/test/features/query/src/api/functional/bbs/index.ts @@ -1,6 +1,6 @@ /** * @packageDocumentation - * @module api.functional.sellers.sales + * @module api.functional.bbs * @nestia Generated by Nestia - https://github.com/samchon/nestia */ //================================================================ diff --git a/test/features/query/src/api/functional/health/index.ts b/test/features/query/src/api/functional/health/index.ts new file mode 100644 index 000000000..619581f93 --- /dev/null +++ b/test/features/query/src/api/functional/health/index.ts @@ -0,0 +1,42 @@ +/** + * @packageDocumentation + * @module api.functional.health + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +import { Fetcher } from "@nestia/fetcher"; +import type { IConnection } from "@nestia/fetcher"; + +/** + * @controller HealthController.get() + * @path GET /health + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export function get + ( + connection: IConnection + ): Promise +{ + return Fetcher.fetch + ( + connection, + get.ENCRYPTED, + get.METHOD, + get.path() + ); +} +export namespace get +{ + + export const METHOD = "GET" as const; + export const PATH: string = "/health"; + export const ENCRYPTED: Fetcher.IEncrypted = { + request: false, + response: false, + }; + + export function path(): string + { + return `/health`; + } +} \ No newline at end of file diff --git a/test/features/query/src/api/functional/index.ts b/test/features/query/src/api/functional/index.ts new file mode 100644 index 000000000..0d710aad5 --- /dev/null +++ b/test/features/query/src/api/functional/index.ts @@ -0,0 +1,9 @@ +/** + * @packageDocumentation + * @module api.functional + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +export * as bbs from "./bbs"; +export * as health from "./health"; +export * as performance from "./performance"; \ No newline at end of file diff --git a/test/features/query/src/api/functional/param/index.ts b/test/features/query/src/api/functional/param/index.ts new file mode 100644 index 000000000..339fa3965 --- /dev/null +++ b/test/features/query/src/api/functional/param/index.ts @@ -0,0 +1,148 @@ +/** + * @packageDocumentation + * @module api.functional.param + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +import { Fetcher } from "@nestia/fetcher"; +import type { IConnection } from "@nestia/fetcher"; + +/** + * @controller TypedParamController.boolean() + * @path GET /param/:value/boolean + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export function boolean + ( + connection: IConnection, + value: false | true + ): Promise +{ + return Fetcher.fetch + ( + connection, + boolean.ENCRYPTED, + boolean.METHOD, + boolean.path(value) + ); +} +export namespace boolean +{ + + export const METHOD = "GET" as const; + export const PATH: string = "/param/:value/boolean"; + export const ENCRYPTED: Fetcher.IEncrypted = { + request: false, + response: false, + }; + + export function path(value: false | true): string + { + return `/param/${encodeURIComponent(value)}/boolean`; + } +} + +/** + * @controller TypedParamController.number() + * @path GET /param/:value/number + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export function number + ( + connection: IConnection, + value: number + ): Promise +{ + return Fetcher.fetch + ( + connection, + number.ENCRYPTED, + number.METHOD, + number.path(value) + ); +} +export namespace number +{ + + export const METHOD = "GET" as const; + export const PATH: string = "/param/:value/number"; + export const ENCRYPTED: Fetcher.IEncrypted = { + request: false, + response: false, + }; + + export function path(value: number): string + { + return `/param/${encodeURIComponent(value)}/number`; + } +} + +/** + * @controller TypedParamController.string() + * @path GET /param/:value/string + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export function string + ( + connection: IConnection, + value: string + ): Promise +{ + return Fetcher.fetch + ( + connection, + string.ENCRYPTED, + string.METHOD, + string.path(value) + ); +} +export namespace string +{ + + export const METHOD = "GET" as const; + export const PATH: string = "/param/:value/string"; + export const ENCRYPTED: Fetcher.IEncrypted = { + request: false, + response: false, + }; + + export function path(value: string): string + { + return `/param/${encodeURIComponent(value)}/string`; + } +} + +/** + * @controller TypedParamController.literal() + * @path GET /param/:value/literal + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export function literal + ( + connection: IConnection, + value: "A" | "B" | "C" + ): Promise +{ + return Fetcher.fetch + ( + connection, + literal.ENCRYPTED, + literal.METHOD, + literal.path(value) + ); +} +export namespace literal +{ + + export const METHOD = "GET" as const; + export const PATH: string = "/param/:value/literal"; + export const ENCRYPTED: Fetcher.IEncrypted = { + request: false, + response: false, + }; + + export function path(value: "A" | "B" | "C"): string + { + return `/param/${encodeURIComponent(value)}/literal`; + } +} \ No newline at end of file diff --git a/test/features/query/src/api/functional/performance/index.ts b/test/features/query/src/api/functional/performance/index.ts new file mode 100644 index 000000000..9e402a44a --- /dev/null +++ b/test/features/query/src/api/functional/performance/index.ts @@ -0,0 +1,45 @@ +/** + * @packageDocumentation + * @module api.functional.performance + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +import { Fetcher, Primitive } from "@nestia/fetcher"; +import type { IConnection } from "@nestia/fetcher"; + +import type { IPerformance } from "./../../structures/IPerformance"; + +/** + * @controller PerformanceController.get() + * @path GET /performance + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export function get + ( + connection: IConnection + ): Promise +{ + return Fetcher.fetch + ( + connection, + get.ENCRYPTED, + get.METHOD, + get.path() + ); +} +export namespace get +{ + export type Output = Primitive; + + export const METHOD = "GET" as const; + export const PATH: string = "/performance"; + export const ENCRYPTED: Fetcher.IEncrypted = { + request: false, + response: false, + }; + + export function path(): string + { + return `/performance`; + } +} \ No newline at end of file diff --git a/test/features/query/src/api/index.ts b/test/features/query/src/api/index.ts new file mode 100644 index 000000000..1896c4fbd --- /dev/null +++ b/test/features/query/src/api/index.ts @@ -0,0 +1,5 @@ +import * as api from "./module"; + +export * from "./module"; + +export default api; diff --git a/test/features/query/src/api/module.ts b/test/features/query/src/api/module.ts new file mode 100644 index 000000000..00239fb3b --- /dev/null +++ b/test/features/query/src/api/module.ts @@ -0,0 +1,5 @@ +export * from "./IConnection"; +export * from "./Primitive"; +export * from "./HttpError"; + +export * as functional from "./functional"; diff --git a/test/features/query/src/api/structures/IBbsArticle.ts b/test/features/query/src/api/structures/IBbsArticle.ts new file mode 100644 index 000000000..a870fc850 --- /dev/null +++ b/test/features/query/src/api/structures/IBbsArticle.ts @@ -0,0 +1,21 @@ +export namespace IBbsArticle { + export interface ISummary { + /** + * @format uuid + */ + id: string; + + writer: string; + + /** + * @minLength 3 + * @maxLength 50 + */ + title: string; + + /** + * @format date-time + */ + created_at: string; + } +} diff --git a/test/features/query/src/api/structures/IPage.ts b/test/features/query/src/api/structures/IPage.ts new file mode 100644 index 000000000..c58220e35 --- /dev/null +++ b/test/features/query/src/api/structures/IPage.ts @@ -0,0 +1,45 @@ +export interface IPage { + data: T[]; + pagination: IPage.IPagination; +} +export namespace IPage { + /** + * Page request data + */ + export interface IRequest { + /** + * @type uint + */ + page?: number | null; + + /** + * @type uint + */ + limit?: number | null; + } + + /** + * Page information. + */ + export interface IPagination { + /** + * @type uint + */ + current: number; + + /** + * @type uint + */ + limit: number; + + /** + * @type uint + */ + records: number; + + /** + * @type uint + */ + pages: number; + } +} diff --git a/test/features/query/src/api/structures/IPerformance.ts b/test/features/query/src/api/structures/IPerformance.ts new file mode 100644 index 000000000..a9e9336e1 --- /dev/null +++ b/test/features/query/src/api/structures/IPerformance.ts @@ -0,0 +1,10 @@ +/** + * Performance info. + * + * @author Samchon + */ +export interface IPerformance { + cpu: NodeJS.CpuUsage; + memory: NodeJS.MemoryUsage; + resource: NodeJS.ResourceUsage; +} diff --git a/test/features/query/src/api/structures/ISystem.ts b/test/features/query/src/api/structures/ISystem.ts new file mode 100644 index 000000000..68f05ca92 --- /dev/null +++ b/test/features/query/src/api/structures/ISystem.ts @@ -0,0 +1,81 @@ +/** + * System Information. + * + * @author Jeongho Nam + */ +export interface ISystem { + /** + * Random Unique ID. + */ + uid: number; + + /** + * `process.argv` + */ + arguments: string[]; + + /** + * Git commit info. + */ + commit: ISystem.ICommit; + + /** + * `package.json` + */ + package: ISystem.IPackage; + + /** + * Creation time of this server. + */ + created_at: string; +} + +export namespace ISystem { + /** + * Git commit info. + */ + export interface ICommit { + shortHash: string; + branch: string; + hash: string; + subject: string; + sanitizedSubject: string; + body: string; + author: ICommit.IUser; + committer: ICommit.IUser; + authored_at: string; + commited_at: string; + notes?: string; + tags: string[]; + } + export namespace ICommit { + /** + * Git user account info. + */ + export interface IUser { + name: string; + email: string; + } + } + + /** + * NPM package info. + */ + export interface IPackage { + name: string; + version: string; + description: string; + main?: string; + typings?: string; + scripts: Record; + repository: { type: "git"; url: string }; + author: string; + license: string; + bugs: { url: string }; + homepage: string; + devDependencies?: Record; + dependencies: Record; + publishConfig?: { registry: string }; + files?: string[]; + } +} diff --git a/test/features/query/src/controllers/BbsArticlesController.ts b/test/features/query/src/controllers/BbsArticlesController.ts new file mode 100644 index 000000000..20fc55222 --- /dev/null +++ b/test/features/query/src/controllers/BbsArticlesController.ts @@ -0,0 +1,31 @@ +import { Controller } from "@nestjs/common"; +import typia from "typia"; + +import { TypedQuery, TypedRoute } from "@nestia/core"; + +import { IBbsArticle } from "@api/lib/structures/IBbsArticle"; +import { IPage } from "@api/lib/structures/IPage"; + +@Controller("bbs/articles") +export class BbsArticlesController { + @TypedRoute.Get() + public async index( + @TypedQuery() query: IPage.IRequest, + ): Promise> { + const limit: number = query.limit ?? 100; + const current: number = query.page ?? 1; + const records: number = limit * (current + 3) + 5; + + return { + pagination: { + current, + limit, + records, + pages: Math.ceil(records / limit), + }, + data: new Array(limit) + .fill("") + .map(() => typia.random()), + }; + } +} diff --git a/test/features/query/src/controllers/HealthController.ts b/test/features/query/src/controllers/HealthController.ts new file mode 100644 index 000000000..a9ce3563b --- /dev/null +++ b/test/features/query/src/controllers/HealthController.ts @@ -0,0 +1,9 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +@Controller("health") +export class HealthController { + @core.TypedRoute.Get() + public get(): void {} +} diff --git a/test/features/query/src/controllers/PerformanceController.ts b/test/features/query/src/controllers/PerformanceController.ts new file mode 100644 index 000000000..798d64fae --- /dev/null +++ b/test/features/query/src/controllers/PerformanceController.ts @@ -0,0 +1,17 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +import { IPerformance } from "@api/lib/structures/IPerformance"; + +@Controller("performance") +export class PerformanceController { + @core.TypedRoute.Get() + public async get(): Promise { + return { + cpu: process.cpuUsage(), + memory: process.memoryUsage(), + resource: process.resourceUsage(), + }; + } +} diff --git a/test/features/query/src/test/features/test_api_health_check.ts b/test/features/query/src/test/features/test_api_health_check.ts new file mode 100644 index 000000000..c34703c71 --- /dev/null +++ b/test/features/query/src/test/features/test_api_health_check.ts @@ -0,0 +1,5 @@ +import api from "@api"; + +export const test_api_monitor_health_check = ( + connection: api.IConnection, +): Promise => api.functional.health.get(connection); diff --git a/test/features/query/src/test/features/test_api_performance.ts b/test/features/query/src/test/features/test_api_performance.ts new file mode 100644 index 000000000..55b6d2ca7 --- /dev/null +++ b/test/features/query/src/test/features/test_api_performance.ts @@ -0,0 +1,13 @@ +import typia from "typia"; + +import api from "@api"; +import { IPerformance } from "@api/lib/structures/IPerformance"; + +export const test_api_monitor_performance = async ( + connection: api.IConnection, +): Promise => { + const performance: IPerformance = await api.functional.performance.get( + connection, + ); + typia.assert(performance); +}; diff --git a/test/features/query/src/test/features/test_api_query.ts b/test/features/query/src/test/features/test_api_query.ts new file mode 100644 index 000000000..cd76742f5 --- /dev/null +++ b/test/features/query/src/test/features/test_api_query.ts @@ -0,0 +1,16 @@ +import typia from "typia"; + +import api from "@api"; +import { IBbsArticle } from "@api/lib/structures/IBbsArticle"; +import { IPage } from "@api/lib/structures/IPage"; + +export const test_api_query = async ( + connection: api.IConnection, +): Promise => { + const page: IPage = + await api.functional.bbs.articles.index(connection, { + page: 1, + limit: 100, + }); + typia.assert(page); +}; diff --git a/test/features/query/src/test/features/test_api_query_invalid.ts b/test/features/query/src/test/features/test_api_query_invalid.ts new file mode 100644 index 000000000..860189b9a --- /dev/null +++ b/test/features/query/src/test/features/test_api_query_invalid.ts @@ -0,0 +1,16 @@ +import typia from "typia"; + +import api from "@api"; +import { IBbsArticle } from "@api/lib/structures/IBbsArticle"; +import { IPage } from "@api/lib/structures/IPage"; + +export const test_api_query_invalid = async ( + connection: api.IConnection, +): Promise => { + const page: IPage = + await api.functional.bbs.articles.index(connection, { + page: "1" as any, + limit: 100, + }); + typia.assert(page); +}; diff --git a/test/features/query/src/test/features/test_api_query_null.ts b/test/features/query/src/test/features/test_api_query_null.ts new file mode 100644 index 000000000..a42d3ff7c --- /dev/null +++ b/test/features/query/src/test/features/test_api_query_null.ts @@ -0,0 +1,16 @@ +import typia from "typia"; + +import api from "@api"; +import { IBbsArticle } from "@api/lib/structures/IBbsArticle"; +import { IPage } from "@api/lib/structures/IPage"; + +export const test_api_query_null = async ( + connection: api.IConnection, +): Promise => { + const page: IPage = + await api.functional.bbs.articles.index(connection, { + page: 1, + limit: null, + }); + typia.assert(page); +}; diff --git a/test/features/query/src/test/features/test_api_query_undefined.ts b/test/features/query/src/test/features/test_api_query_undefined.ts new file mode 100644 index 000000000..42989b710 --- /dev/null +++ b/test/features/query/src/test/features/test_api_query_undefined.ts @@ -0,0 +1,13 @@ +import typia from "typia"; + +import api from "@api"; +import { IBbsArticle } from "@api/lib/structures/IBbsArticle"; +import { IPage } from "@api/lib/structures/IPage"; + +export const test_api_query_undefined = async ( + connection: api.IConnection, +): Promise => { + const page: IPage = + await api.functional.bbs.articles.index(connection, {}); + typia.assert(page); +}; diff --git a/test/features/query/src/test/index.ts b/test/features/query/src/test/index.ts new file mode 100644 index 000000000..e89842739 --- /dev/null +++ b/test/features/query/src/test/index.ts @@ -0,0 +1,39 @@ +import { DynamicExecutor } from "@nestia/e2e"; + +import { Backend } from "../Backend"; + +async function main(): Promise { + const server: Backend = new Backend(); + await server.open(); + + const report: DynamicExecutor.IReport = await DynamicExecutor.validate({ + prefix: "test", + parameters: () => [ + { + host: "http://127.0.0.1:37000", + encryption: { + key: "A".repeat(32), + iv: "B".repeat(16), + }, + }, + ], + })(`${__dirname}/features`); + await server.close(); + + const exceptions: Error[] = report.executions + .filter((exec) => exec.error !== null) + .map((exec) => exec.error!); + if (exceptions.length === 0) { + console.log("Success"); + console.log("Elapsed time", report.time.toLocaleString(), `ms`); + } else { + // for (const exp of exceptions) console.log(exp); + console.log("Failed"); + console.log("Elapsed time", report.time.toLocaleString(), `ms`); + process.exit(-1); + } +} +main().catch((exp) => { + console.log(exp); + process.exit(-1); +}); diff --git a/test/features/query/swagger.json b/test/features/query/swagger.json new file mode 100644 index 000000000..53c138ad6 --- /dev/null +++ b/test/features/query/swagger.json @@ -0,0 +1,624 @@ +{ + "openapi": "3.0.1", + "servers": [ + { + "url": "https://github.com/samchon/nestia", + "description": "insert your server url" + } + ], + "info": { + "version": "0.1.0", + "title": "Generated by nestia - https://github.com/samchon/nestia" + }, + "paths": { + "/bbs/articles": { + "get": { + "tags": [], + "parameters": [ + { + "name": "query", + "in": "query", + "description": "", + "schema": { + "$ref": "#/components/schemas/IPage.IRequest" + }, + "required": true + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IPage_lt_IBbsArticle.ISummary_gt_" + } + } + }, + "x-nestia-encrypted": false + } + }, + "description": "", + "x-nestia-namespace": "bbs.articles.index", + "x-nestia-jsDocTags": [] + } + }, + "/health": { + "get": { + "tags": [], + "parameters": [], + "responses": { + "200": { + "description": "", + "x-nestia-encrypted": false + } + }, + "description": "", + "x-nestia-namespace": "health.get", + "x-nestia-jsDocTags": [] + } + }, + "/performance": { + "get": { + "tags": [], + "parameters": [], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IPerformance" + } + } + }, + "x-nestia-encrypted": false + } + }, + "description": "", + "x-nestia-namespace": "performance.get", + "x-nestia-jsDocTags": [] + } + } + }, + "components": { + "schemas": { + "IPage.IRequest": { + "type": "object", + "properties": { + "page": { + "type": "integer", + "nullable": true, + "x-typia-metaTags": [ + { + "kind": "type", + "value": "uint" + } + ], + "x-typia-jsDocTags": [ + { + "name": "type", + "text": [ + { + "text": "uint", + "kind": "text" + } + ] + } + ], + "x-typia-required": false, + "x-typia-optional": true, + "minimum": 0 + }, + "limit": { + "type": "integer", + "nullable": true, + "x-typia-metaTags": [ + { + "kind": "type", + "value": "uint" + } + ], + "x-typia-jsDocTags": [ + { + "name": "type", + "text": [ + { + "text": "uint", + "kind": "text" + } + ] + } + ], + "x-typia-required": false, + "x-typia-optional": true, + "minimum": 0 + } + }, + "nullable": false, + "description": "Page request data", + "x-typia-jsDocTags": [] + }, + "IPage_lt_IBbsArticle.ISummary_gt_": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/IBbsArticle.ISummary", + "x-typia-required": true, + "x-typia-optional": false + }, + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "pagination": { + "$ref": "#/components/schemas/IPage.IPagination", + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "data", + "pagination" + ], + "x-typia-jsDocTags": [] + }, + "IBbsArticle.ISummary": { + "type": "object", + "properties": { + "id": { + "type": "string", + "nullable": false, + "x-typia-metaTags": [ + { + "kind": "format", + "value": "uuid" + } + ], + "x-typia-jsDocTags": [ + { + "name": "format", + "text": [ + { + "text": "uuid", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "format": "uuid" + }, + "writer": { + "type": "string", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "title": { + "type": "string", + "nullable": false, + "x-typia-metaTags": [ + { + "kind": "minLength", + "value": 3 + }, + { + "kind": "maxLength", + "value": 50 + } + ], + "x-typia-jsDocTags": [ + { + "name": "minLength", + "text": [ + { + "text": "3", + "kind": "text" + } + ] + }, + { + "name": "maxLength", + "text": [ + { + "text": "50", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "minLength": 3, + "maxLength": 50 + }, + "created_at": { + "type": "string", + "nullable": false, + "x-typia-metaTags": [ + { + "kind": "format", + "value": "datetime" + } + ], + "x-typia-jsDocTags": [ + { + "name": "format", + "text": [ + { + "text": "date-time", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "format": "date-time" + } + }, + "nullable": false, + "required": [ + "id", + "writer", + "title", + "created_at" + ], + "x-typia-jsDocTags": [] + }, + "IPage.IPagination": { + "type": "object", + "properties": { + "current": { + "type": "integer", + "nullable": false, + "x-typia-metaTags": [ + { + "kind": "type", + "value": "uint" + } + ], + "x-typia-jsDocTags": [ + { + "name": "type", + "text": [ + { + "text": "uint", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "minimum": 0 + }, + "limit": { + "type": "integer", + "nullable": false, + "x-typia-metaTags": [ + { + "kind": "type", + "value": "uint" + } + ], + "x-typia-jsDocTags": [ + { + "name": "type", + "text": [ + { + "text": "uint", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "minimum": 0 + }, + "records": { + "type": "integer", + "nullable": false, + "x-typia-metaTags": [ + { + "kind": "type", + "value": "uint" + } + ], + "x-typia-jsDocTags": [ + { + "name": "type", + "text": [ + { + "text": "uint", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "minimum": 0 + }, + "pages": { + "type": "integer", + "nullable": false, + "x-typia-metaTags": [ + { + "kind": "type", + "value": "uint" + } + ], + "x-typia-jsDocTags": [ + { + "name": "type", + "text": [ + { + "text": "uint", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "minimum": 0 + } + }, + "nullable": false, + "required": [ + "current", + "limit", + "records", + "pages" + ], + "description": "Page information.", + "x-typia-jsDocTags": [] + }, + "IPerformance": { + "type": "object", + "properties": { + "cpu": { + "$ref": "#/components/schemas/_singlequote_process_singlequote_.global.NodeJS.CpuUsage", + "x-typia-required": true, + "x-typia-optional": false + }, + "memory": { + "$ref": "#/components/schemas/_singlequote_process_singlequote_.global.NodeJS.MemoryUsage", + "x-typia-required": true, + "x-typia-optional": false + }, + "resource": { + "$ref": "#/components/schemas/_singlequote_process_singlequote_.global.NodeJS.ResourceUsage", + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "cpu", + "memory", + "resource" + ], + "description": "Performance info.", + "x-typia-jsDocTags": [ + { + "name": "author", + "text": [ + { + "text": "Samchon", + "kind": "text" + } + ] + } + ] + }, + "_singlequote_process_singlequote_.global.NodeJS.CpuUsage": { + "type": "object", + "properties": { + "user": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "system": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "user", + "system" + ], + "x-typia-jsDocTags": [] + }, + "_singlequote_process_singlequote_.global.NodeJS.MemoryUsage": { + "type": "object", + "properties": { + "rss": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "heapTotal": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "heapUsed": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "external": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "arrayBuffers": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "rss", + "heapTotal", + "heapUsed", + "external", + "arrayBuffers" + ], + "x-typia-jsDocTags": [] + }, + "_singlequote_process_singlequote_.global.NodeJS.ResourceUsage": { + "type": "object", + "properties": { + "fsRead": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "fsWrite": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "involuntaryContextSwitches": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "ipcReceived": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "ipcSent": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "majorPageFault": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "maxRSS": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "minorPageFault": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "sharedMemorySize": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "signalsCount": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "swappedOut": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "systemCPUTime": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "unsharedDataSize": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "unsharedStackSize": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "userCPUTime": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "voluntaryContextSwitches": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "fsRead", + "fsWrite", + "involuntaryContextSwitches", + "ipcReceived", + "ipcSent", + "majorPageFault", + "maxRSS", + "minorPageFault", + "sharedMemorySize", + "signalsCount", + "swappedOut", + "systemCPUTime", + "unsharedDataSize", + "unsharedStackSize", + "userCPUTime", + "voluntaryContextSwitches" + ], + "x-typia-jsDocTags": [] + } + }, + "securitySchemes": { + "bearer": { + "type": "apiKey", + "in": "header", + "name": "Authorization" + } + } + }, + "security": [ + { + "bearer": [] + } + ] +} \ No newline at end of file diff --git a/test/features/query/tsconfig.json b/test/features/query/tsconfig.json new file mode 100644 index 000000000..e5fe47a95 --- /dev/null +++ b/test/features/query/tsconfig.json @@ -0,0 +1,103 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + /* Language and Environment */ + "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + /* Modules */ + "module": "commonjs", /* Specify what module code is generated. */// "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + "paths": { + "@nestia/core": ["../../../packages/core/src"], + "@nestia/e2e": ["../../../packages/e2e/src"], + "@nestia/fetcher": ["../../../packages/fetcher/src"], + "@nestia/sdk": ["../../../packages/sdk/src"], + "@nestia/sdk/lib/*": ["../../../packages/sdk/src/*"], + "@api": ["./src/api"], + "@api/lib/*": ["./src/api/*"], + }, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. *//* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true, /* Skip type checking all .d.ts files. */ + "plugins": [ + { "transform": "typescript-transform-paths" }, + { "transform": "typia/lib/transform" }, + { "transform": "../../../packages/core/src/transform.ts" }, + ], + } + } \ No newline at end of file diff --git a/test/features/route-error-generic/nestia.config.ts b/test/features/route-error-generic/nestia.config.ts new file mode 100644 index 000000000..2594a40d0 --- /dev/null +++ b/test/features/route-error-generic/nestia.config.ts @@ -0,0 +1,15 @@ +import { INestiaConfig } from "@nestia/sdk"; + +export const NESTIA_CONFIG: INestiaConfig = { + input: ["src/controllers"], + output: "src/api", + swagger: { + output: "swagger.json", + security: { + bearer: { + type: "apiKey", + }, + }, + }, +}; +export default NESTIA_CONFIG; diff --git a/test/features/route-error-generic/src/controllers/HealthController.ts b/test/features/route-error-generic/src/controllers/HealthController.ts new file mode 100644 index 000000000..a9ce3563b --- /dev/null +++ b/test/features/route-error-generic/src/controllers/HealthController.ts @@ -0,0 +1,9 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +@Controller("health") +export class HealthController { + @core.TypedRoute.Get() + public get(): void {} +} diff --git a/test/features/route-error-generic/src/controllers/TypedRouteController.ts b/test/features/route-error-generic/src/controllers/TypedRouteController.ts new file mode 100644 index 000000000..57159ba99 --- /dev/null +++ b/test/features/route-error-generic/src/controllers/TypedRouteController.ts @@ -0,0 +1,16 @@ +import { Controller } from "@nestjs/common"; +import typia from "typia"; + +import core from "@nestia/core"; + +@Controller("route") +export class TypedRouteController { + @core.TypedRoute.Get("random") + public async random(): Promise> { + return typia.random>() as any; + } +} + +interface ISomething { + value: T; +} diff --git a/test/features/route-error-generic/tsconfig.json b/test/features/route-error-generic/tsconfig.json new file mode 100644 index 000000000..e74060a2d --- /dev/null +++ b/test/features/route-error-generic/tsconfig.json @@ -0,0 +1,101 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + /* Language and Environment */ + "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + /* Modules */ + "module": "commonjs", /* Specify what module code is generated. */// "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + "paths": { + "@nestia/core": ["../../../packages/core/src"], + "@nestia/e2e": ["../../../packages/e2e/src"], + "@nestia/fetcher": ["../../../packages/fetcher/src"], + "@nestia/sdk": ["../../../packages/sdk/src"], + "@nestia/sdk/lib/*": ["../../../packages/sdk/src/*"], + }, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. *//* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true, /* Skip type checking all .d.ts files. */ + "plugins": [ + { "transform": "typescript-transform-paths" }, + { "transform": "typia/lib/transform" }, + { "transform": "../../../packages/core/src/transform.ts" }, + ], + } + } \ No newline at end of file diff --git a/test/features/route-manual-assert/nestia.config.ts b/test/features/route-manual-assert/nestia.config.ts new file mode 100644 index 000000000..2594a40d0 --- /dev/null +++ b/test/features/route-manual-assert/nestia.config.ts @@ -0,0 +1,15 @@ +import { INestiaConfig } from "@nestia/sdk"; + +export const NESTIA_CONFIG: INestiaConfig = { + input: ["src/controllers"], + output: "src/api", + swagger: { + output: "swagger.json", + security: { + bearer: { + type: "apiKey", + }, + }, + }, +}; +export default NESTIA_CONFIG; diff --git a/test/features/route-manual-assert/src/Backend.ts b/test/features/route-manual-assert/src/Backend.ts new file mode 100644 index 000000000..8ab51b70f --- /dev/null +++ b/test/features/route-manual-assert/src/Backend.ts @@ -0,0 +1,28 @@ +import { INestApplication } from "@nestjs/common"; +import { NestFactory } from "@nestjs/core"; + +import core from "@nestia/core"; + +export class Backend { + private application_?: INestApplication; + + public async open(): Promise { + this.application_ = await NestFactory.create( + await core.EncryptedModule.dynamic(__dirname + "/controllers", { + key: "A".repeat(32), + iv: "B".repeat(16), + }), + { logger: false }, + ); + await this.application_.listen(37_000); + } + + public async close(): Promise { + if (this.application_ === undefined) return; + + const app = this.application_; + await app.close(); + + delete this.application_; + } +} diff --git a/test/features/route-manual-assert/src/api/HttpError.ts b/test/features/route-manual-assert/src/api/HttpError.ts new file mode 100644 index 000000000..5df328ae4 --- /dev/null +++ b/test/features/route-manual-assert/src/api/HttpError.ts @@ -0,0 +1 @@ +export { HttpError } from "@nestia/fetcher"; diff --git a/test/features/route-manual-assert/src/api/IConnection.ts b/test/features/route-manual-assert/src/api/IConnection.ts new file mode 100644 index 000000000..92727cfc2 --- /dev/null +++ b/test/features/route-manual-assert/src/api/IConnection.ts @@ -0,0 +1 @@ +export { IConnection } from "@nestia/fetcher"; diff --git a/test/features/route-manual-assert/src/api/Primitive.ts b/test/features/route-manual-assert/src/api/Primitive.ts new file mode 100644 index 000000000..3c1db5a74 --- /dev/null +++ b/test/features/route-manual-assert/src/api/Primitive.ts @@ -0,0 +1 @@ +export { Primitive } from "@nestia/fetcher"; diff --git a/test/features/route-manual-assert/src/api/functional/health/index.ts b/test/features/route-manual-assert/src/api/functional/health/index.ts new file mode 100644 index 000000000..619581f93 --- /dev/null +++ b/test/features/route-manual-assert/src/api/functional/health/index.ts @@ -0,0 +1,42 @@ +/** + * @packageDocumentation + * @module api.functional.health + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +import { Fetcher } from "@nestia/fetcher"; +import type { IConnection } from "@nestia/fetcher"; + +/** + * @controller HealthController.get() + * @path GET /health + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export function get + ( + connection: IConnection + ): Promise +{ + return Fetcher.fetch + ( + connection, + get.ENCRYPTED, + get.METHOD, + get.path() + ); +} +export namespace get +{ + + export const METHOD = "GET" as const; + export const PATH: string = "/health"; + export const ENCRYPTED: Fetcher.IEncrypted = { + request: false, + response: false, + }; + + export function path(): string + { + return `/health`; + } +} \ No newline at end of file diff --git a/test/features/route-manual-assert/src/api/functional/index.ts b/test/features/route-manual-assert/src/api/functional/index.ts new file mode 100644 index 000000000..43933202c --- /dev/null +++ b/test/features/route-manual-assert/src/api/functional/index.ts @@ -0,0 +1,9 @@ +/** + * @packageDocumentation + * @module api.functional + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +export * as health from "./health"; +export * as performance from "./performance"; +export * as route from "./route"; \ No newline at end of file diff --git a/test/features/route-manual-assert/src/api/functional/manual/index.ts b/test/features/route-manual-assert/src/api/functional/manual/index.ts new file mode 100644 index 000000000..1e1157605 --- /dev/null +++ b/test/features/route-manual-assert/src/api/functional/manual/index.ts @@ -0,0 +1,45 @@ +/** + * @packageDocumentation + * @module api.functional.manual + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +import { Fetcher, Primitive } from "@nestia/fetcher"; +import type { IConnection } from "@nestia/fetcher"; + +import type { IBbsArticle } from "./../../structures/IBbsArticle"; + +/** + * @controller TypedRouteController.random() + * @path GET /manual/random + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export function random + ( + connection: IConnection + ): Promise +{ + return Fetcher.fetch + ( + connection, + random.ENCRYPTED, + random.METHOD, + random.path() + ); +} +export namespace random +{ + export type Output = Primitive; + + export const METHOD = "GET" as const; + export const PATH: string = "/manual/random"; + export const ENCRYPTED: Fetcher.IEncrypted = { + request: false, + response: false, + }; + + export function path(): string + { + return `/manual/random`; + } +} \ No newline at end of file diff --git a/test/features/route-manual-assert/src/api/functional/performance/index.ts b/test/features/route-manual-assert/src/api/functional/performance/index.ts new file mode 100644 index 000000000..9e402a44a --- /dev/null +++ b/test/features/route-manual-assert/src/api/functional/performance/index.ts @@ -0,0 +1,45 @@ +/** + * @packageDocumentation + * @module api.functional.performance + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +import { Fetcher, Primitive } from "@nestia/fetcher"; +import type { IConnection } from "@nestia/fetcher"; + +import type { IPerformance } from "./../../structures/IPerformance"; + +/** + * @controller PerformanceController.get() + * @path GET /performance + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export function get + ( + connection: IConnection + ): Promise +{ + return Fetcher.fetch + ( + connection, + get.ENCRYPTED, + get.METHOD, + get.path() + ); +} +export namespace get +{ + export type Output = Primitive; + + export const METHOD = "GET" as const; + export const PATH: string = "/performance"; + export const ENCRYPTED: Fetcher.IEncrypted = { + request: false, + response: false, + }; + + export function path(): string + { + return `/performance`; + } +} \ No newline at end of file diff --git a/test/features/route-manual-assert/src/api/functional/route/index.ts b/test/features/route-manual-assert/src/api/functional/route/index.ts new file mode 100644 index 000000000..db5470fe9 --- /dev/null +++ b/test/features/route-manual-assert/src/api/functional/route/index.ts @@ -0,0 +1,45 @@ +/** + * @packageDocumentation + * @module api.functional.route + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +import { Fetcher, Primitive } from "@nestia/fetcher"; +import type { IConnection } from "@nestia/fetcher"; + +import type { IBbsArticle } from "./../../structures/IBbsArticle"; + +/** + * @controller TypedRouteController.random() + * @path GET /route/random + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export function random + ( + connection: IConnection + ): Promise +{ + return Fetcher.fetch + ( + connection, + random.ENCRYPTED, + random.METHOD, + random.path() + ); +} +export namespace random +{ + export type Output = Primitive; + + export const METHOD = "GET" as const; + export const PATH: string = "/route/random"; + export const ENCRYPTED: Fetcher.IEncrypted = { + request: false, + response: false, + }; + + export function path(): string + { + return `/route/random`; + } +} \ No newline at end of file diff --git a/test/features/route-manual-assert/src/api/index.ts b/test/features/route-manual-assert/src/api/index.ts new file mode 100644 index 000000000..1896c4fbd --- /dev/null +++ b/test/features/route-manual-assert/src/api/index.ts @@ -0,0 +1,5 @@ +import * as api from "./module"; + +export * from "./module"; + +export default api; diff --git a/test/features/route-manual-assert/src/api/module.ts b/test/features/route-manual-assert/src/api/module.ts new file mode 100644 index 000000000..00239fb3b --- /dev/null +++ b/test/features/route-manual-assert/src/api/module.ts @@ -0,0 +1,5 @@ +export * from "./IConnection"; +export * from "./Primitive"; +export * from "./HttpError"; + +export * as functional from "./functional"; diff --git a/test/features/route-manual-assert/src/api/structures/IBbsArticle.ts b/test/features/route-manual-assert/src/api/structures/IBbsArticle.ts new file mode 100644 index 000000000..a5188f20c --- /dev/null +++ b/test/features/route-manual-assert/src/api/structures/IBbsArticle.ts @@ -0,0 +1,40 @@ +export interface IBbsArticle { + /** + * @format uuid + */ + id: string; + + /** + * @minLength 3 + * @maxLength 50 + */ + title: string; + + body: string; + + files: IAttachmentFile[]; + + /** + * @format date-time + */ + created_at: string; +} + +export interface IAttachmentFile { + /** + * @minLengt 1 + * @maxLength 255 + */ + name: string | null; + + /** + * @minLength 1 + * @maxLength 8 + */ + extension: string | null; + + /** + * @format url + */ + url: string; +} diff --git a/test/features/route-manual-assert/src/api/structures/IPerformance.ts b/test/features/route-manual-assert/src/api/structures/IPerformance.ts new file mode 100644 index 000000000..a9e9336e1 --- /dev/null +++ b/test/features/route-manual-assert/src/api/structures/IPerformance.ts @@ -0,0 +1,10 @@ +/** + * Performance info. + * + * @author Samchon + */ +export interface IPerformance { + cpu: NodeJS.CpuUsage; + memory: NodeJS.MemoryUsage; + resource: NodeJS.ResourceUsage; +} diff --git a/test/features/route-manual-assert/src/api/structures/ISystem.ts b/test/features/route-manual-assert/src/api/structures/ISystem.ts new file mode 100644 index 000000000..68f05ca92 --- /dev/null +++ b/test/features/route-manual-assert/src/api/structures/ISystem.ts @@ -0,0 +1,81 @@ +/** + * System Information. + * + * @author Jeongho Nam + */ +export interface ISystem { + /** + * Random Unique ID. + */ + uid: number; + + /** + * `process.argv` + */ + arguments: string[]; + + /** + * Git commit info. + */ + commit: ISystem.ICommit; + + /** + * `package.json` + */ + package: ISystem.IPackage; + + /** + * Creation time of this server. + */ + created_at: string; +} + +export namespace ISystem { + /** + * Git commit info. + */ + export interface ICommit { + shortHash: string; + branch: string; + hash: string; + subject: string; + sanitizedSubject: string; + body: string; + author: ICommit.IUser; + committer: ICommit.IUser; + authored_at: string; + commited_at: string; + notes?: string; + tags: string[]; + } + export namespace ICommit { + /** + * Git user account info. + */ + export interface IUser { + name: string; + email: string; + } + } + + /** + * NPM package info. + */ + export interface IPackage { + name: string; + version: string; + description: string; + main?: string; + typings?: string; + scripts: Record; + repository: { type: "git"; url: string }; + author: string; + license: string; + bugs: { url: string }; + homepage: string; + devDependencies?: Record; + dependencies: Record; + publishConfig?: { registry: string }; + files?: string[]; + } +} diff --git a/test/features/route-manual-assert/src/controllers/HealthController.ts b/test/features/route-manual-assert/src/controllers/HealthController.ts new file mode 100644 index 000000000..a9ce3563b --- /dev/null +++ b/test/features/route-manual-assert/src/controllers/HealthController.ts @@ -0,0 +1,9 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +@Controller("health") +export class HealthController { + @core.TypedRoute.Get() + public get(): void {} +} diff --git a/test/features/route-manual-assert/src/controllers/PerformanceController.ts b/test/features/route-manual-assert/src/controllers/PerformanceController.ts new file mode 100644 index 000000000..798d64fae --- /dev/null +++ b/test/features/route-manual-assert/src/controllers/PerformanceController.ts @@ -0,0 +1,17 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +import { IPerformance } from "@api/lib/structures/IPerformance"; + +@Controller("performance") +export class PerformanceController { + @core.TypedRoute.Get() + public async get(): Promise { + return { + cpu: process.cpuUsage(), + memory: process.memoryUsage(), + resource: process.resourceUsage(), + }; + } +} diff --git a/test/features/route-manual-assert/src/controllers/TypedRouteController.ts b/test/features/route-manual-assert/src/controllers/TypedRouteController.ts new file mode 100644 index 000000000..be96a0e78 --- /dev/null +++ b/test/features/route-manual-assert/src/controllers/TypedRouteController.ts @@ -0,0 +1,22 @@ +import { Controller } from "@nestjs/common"; +import typia from "typia"; + +import core from "@nestia/core"; + +import { IBbsArticle } from "@api/lib/structures/IBbsArticle"; + +@Controller("route") +export class TypedRouteController { + @core.TypedRoute.Get("random", { + type: "assert", + assert: typia.createAssertStringify(), + }) + public async random(): Promise { + return { + ...typia.random(), + ...{ + dummy: 1, + }, + }; + } +} diff --git a/test/features/route-manual-assert/src/test/features/test_api_health_check.ts b/test/features/route-manual-assert/src/test/features/test_api_health_check.ts new file mode 100644 index 000000000..c34703c71 --- /dev/null +++ b/test/features/route-manual-assert/src/test/features/test_api_health_check.ts @@ -0,0 +1,5 @@ +import api from "@api"; + +export const test_api_monitor_health_check = ( + connection: api.IConnection, +): Promise => api.functional.health.get(connection); diff --git a/test/features/route-manual-assert/src/test/features/test_api_performance.ts b/test/features/route-manual-assert/src/test/features/test_api_performance.ts new file mode 100644 index 000000000..55b6d2ca7 --- /dev/null +++ b/test/features/route-manual-assert/src/test/features/test_api_performance.ts @@ -0,0 +1,13 @@ +import typia from "typia"; + +import api from "@api"; +import { IPerformance } from "@api/lib/structures/IPerformance"; + +export const test_api_monitor_performance = async ( + connection: api.IConnection, +): Promise => { + const performance: IPerformance = await api.functional.performance.get( + connection, + ); + typia.assert(performance); +}; diff --git a/test/features/route-manual-assert/src/test/features/test_api_route.ts b/test/features/route-manual-assert/src/test/features/test_api_route.ts new file mode 100644 index 000000000..94451eee7 --- /dev/null +++ b/test/features/route-manual-assert/src/test/features/test_api_route.ts @@ -0,0 +1,11 @@ +import typia from "typia"; + +import api from "@api"; +import { IBbsArticle } from "@api/lib/structures/IBbsArticle"; + +export const test_api_route = async ( + connection: api.IConnection, +): Promise => { + const article: IBbsArticle = await api.functional.route.random(connection); + typia.assertEquals(article); +}; diff --git a/test/features/route-manual-assert/src/test/index.ts b/test/features/route-manual-assert/src/test/index.ts new file mode 100644 index 000000000..e89842739 --- /dev/null +++ b/test/features/route-manual-assert/src/test/index.ts @@ -0,0 +1,39 @@ +import { DynamicExecutor } from "@nestia/e2e"; + +import { Backend } from "../Backend"; + +async function main(): Promise { + const server: Backend = new Backend(); + await server.open(); + + const report: DynamicExecutor.IReport = await DynamicExecutor.validate({ + prefix: "test", + parameters: () => [ + { + host: "http://127.0.0.1:37000", + encryption: { + key: "A".repeat(32), + iv: "B".repeat(16), + }, + }, + ], + })(`${__dirname}/features`); + await server.close(); + + const exceptions: Error[] = report.executions + .filter((exec) => exec.error !== null) + .map((exec) => exec.error!); + if (exceptions.length === 0) { + console.log("Success"); + console.log("Elapsed time", report.time.toLocaleString(), `ms`); + } else { + // for (const exp of exceptions) console.log(exp); + console.log("Failed"); + console.log("Elapsed time", report.time.toLocaleString(), `ms`); + process.exit(-1); + } +} +main().catch((exp) => { + console.log(exp); + process.exit(-1); +}); diff --git a/test/features/route-manual-assert/swagger.json b/test/features/route-manual-assert/swagger.json new file mode 100644 index 000000000..fe7bc27dd --- /dev/null +++ b/test/features/route-manual-assert/swagger.json @@ -0,0 +1,540 @@ +{ + "openapi": "3.0.1", + "servers": [ + { + "url": "https://github.com/samchon/nestia", + "description": "insert your server url" + } + ], + "info": { + "version": "0.1.0", + "title": "Generated by nestia - https://github.com/samchon/nestia" + }, + "paths": { + "/health": { + "get": { + "tags": [], + "parameters": [], + "responses": { + "200": { + "description": "", + "x-nestia-encrypted": false + } + }, + "description": "", + "x-nestia-namespace": "health.get", + "x-nestia-jsDocTags": [] + } + }, + "/performance": { + "get": { + "tags": [], + "parameters": [], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IPerformance" + } + } + }, + "x-nestia-encrypted": false + } + }, + "description": "", + "x-nestia-namespace": "performance.get", + "x-nestia-jsDocTags": [] + } + }, + "/route/random": { + "get": { + "tags": [], + "parameters": [], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IBbsArticle" + } + } + }, + "x-nestia-encrypted": false + } + }, + "description": "", + "x-nestia-namespace": "route.random.random", + "x-nestia-jsDocTags": [] + } + } + }, + "components": { + "schemas": { + "IPerformance": { + "type": "object", + "properties": { + "cpu": { + "$ref": "#/components/schemas/_singlequote_process_singlequote_.global.NodeJS.CpuUsage", + "x-typia-required": true, + "x-typia-optional": false + }, + "memory": { + "$ref": "#/components/schemas/_singlequote_process_singlequote_.global.NodeJS.MemoryUsage", + "x-typia-required": true, + "x-typia-optional": false + }, + "resource": { + "$ref": "#/components/schemas/_singlequote_process_singlequote_.global.NodeJS.ResourceUsage", + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "cpu", + "memory", + "resource" + ], + "description": "Performance info.", + "x-typia-jsDocTags": [ + { + "name": "author", + "text": [ + { + "text": "Samchon", + "kind": "text" + } + ] + } + ] + }, + "_singlequote_process_singlequote_.global.NodeJS.CpuUsage": { + "type": "object", + "properties": { + "user": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "system": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "user", + "system" + ], + "x-typia-jsDocTags": [] + }, + "_singlequote_process_singlequote_.global.NodeJS.MemoryUsage": { + "type": "object", + "properties": { + "rss": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "heapTotal": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "heapUsed": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "external": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "arrayBuffers": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "rss", + "heapTotal", + "heapUsed", + "external", + "arrayBuffers" + ], + "x-typia-jsDocTags": [] + }, + "_singlequote_process_singlequote_.global.NodeJS.ResourceUsage": { + "type": "object", + "properties": { + "fsRead": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "fsWrite": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "involuntaryContextSwitches": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "ipcReceived": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "ipcSent": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "majorPageFault": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "maxRSS": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "minorPageFault": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "sharedMemorySize": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "signalsCount": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "swappedOut": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "systemCPUTime": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "unsharedDataSize": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "unsharedStackSize": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "userCPUTime": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "voluntaryContextSwitches": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "fsRead", + "fsWrite", + "involuntaryContextSwitches", + "ipcReceived", + "ipcSent", + "majorPageFault", + "maxRSS", + "minorPageFault", + "sharedMemorySize", + "signalsCount", + "swappedOut", + "systemCPUTime", + "unsharedDataSize", + "unsharedStackSize", + "userCPUTime", + "voluntaryContextSwitches" + ], + "x-typia-jsDocTags": [] + }, + "IBbsArticle": { + "type": "object", + "properties": { + "id": { + "type": "string", + "nullable": false, + "x-typia-metaTags": [ + { + "kind": "format", + "value": "uuid" + } + ], + "x-typia-jsDocTags": [ + { + "name": "format", + "text": [ + { + "text": "uuid", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "format": "uuid" + }, + "title": { + "type": "string", + "nullable": false, + "x-typia-metaTags": [ + { + "kind": "minLength", + "value": 3 + }, + { + "kind": "maxLength", + "value": 50 + } + ], + "x-typia-jsDocTags": [ + { + "name": "minLength", + "text": [ + { + "text": "3", + "kind": "text" + } + ] + }, + { + "name": "maxLength", + "text": [ + { + "text": "50", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "minLength": 3, + "maxLength": 50 + }, + "body": { + "type": "string", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "files": { + "type": "array", + "items": { + "$ref": "#/components/schemas/IAttachmentFile", + "x-typia-required": true, + "x-typia-optional": false + }, + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "created_at": { + "type": "string", + "nullable": false, + "x-typia-metaTags": [ + { + "kind": "format", + "value": "datetime" + } + ], + "x-typia-jsDocTags": [ + { + "name": "format", + "text": [ + { + "text": "date-time", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "format": "date-time" + } + }, + "nullable": false, + "required": [ + "id", + "title", + "body", + "files", + "created_at" + ], + "x-typia-jsDocTags": [] + }, + "IAttachmentFile": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "x-typia-metaTags": [ + { + "kind": "maxLength", + "value": 255 + } + ], + "x-typia-jsDocTags": [ + { + "name": "minLengt", + "text": [ + { + "text": "1", + "kind": "text" + } + ] + }, + { + "name": "maxLength", + "text": [ + { + "text": "255", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "maxLength": 255 + }, + "extension": { + "type": "string", + "nullable": true, + "x-typia-metaTags": [ + { + "kind": "minLength", + "value": 1 + }, + { + "kind": "maxLength", + "value": 8 + } + ], + "x-typia-jsDocTags": [ + { + "name": "minLength", + "text": [ + { + "text": "1", + "kind": "text" + } + ] + }, + { + "name": "maxLength", + "text": [ + { + "text": "8", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "minLength": 1, + "maxLength": 8 + }, + "url": { + "type": "string", + "nullable": false, + "x-typia-metaTags": [ + { + "kind": "format", + "value": "url" + } + ], + "x-typia-jsDocTags": [ + { + "name": "format", + "text": [ + { + "text": "url", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "format": "url" + } + }, + "nullable": false, + "required": [ + "name", + "extension", + "url" + ], + "x-typia-jsDocTags": [] + } + }, + "securitySchemes": { + "bearer": { + "type": "apiKey", + "in": "header", + "name": "Authorization" + } + } + }, + "security": [ + { + "bearer": [] + } + ] +} \ No newline at end of file diff --git a/test/features/route-manual-assert/tsconfig.json b/test/features/route-manual-assert/tsconfig.json new file mode 100644 index 000000000..e5fe47a95 --- /dev/null +++ b/test/features/route-manual-assert/tsconfig.json @@ -0,0 +1,103 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + /* Language and Environment */ + "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + /* Modules */ + "module": "commonjs", /* Specify what module code is generated. */// "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + "paths": { + "@nestia/core": ["../../../packages/core/src"], + "@nestia/e2e": ["../../../packages/e2e/src"], + "@nestia/fetcher": ["../../../packages/fetcher/src"], + "@nestia/sdk": ["../../../packages/sdk/src"], + "@nestia/sdk/lib/*": ["../../../packages/sdk/src/*"], + "@api": ["./src/api"], + "@api/lib/*": ["./src/api/*"], + }, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. *//* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true, /* Skip type checking all .d.ts files. */ + "plugins": [ + { "transform": "typescript-transform-paths" }, + { "transform": "typia/lib/transform" }, + { "transform": "../../../packages/core/src/transform.ts" }, + ], + } + } \ No newline at end of file diff --git a/test/features/route-manual-is/nestia.config.ts b/test/features/route-manual-is/nestia.config.ts new file mode 100644 index 000000000..2594a40d0 --- /dev/null +++ b/test/features/route-manual-is/nestia.config.ts @@ -0,0 +1,15 @@ +import { INestiaConfig } from "@nestia/sdk"; + +export const NESTIA_CONFIG: INestiaConfig = { + input: ["src/controllers"], + output: "src/api", + swagger: { + output: "swagger.json", + security: { + bearer: { + type: "apiKey", + }, + }, + }, +}; +export default NESTIA_CONFIG; diff --git a/test/features/route-manual-is/src/Backend.ts b/test/features/route-manual-is/src/Backend.ts new file mode 100644 index 000000000..8ab51b70f --- /dev/null +++ b/test/features/route-manual-is/src/Backend.ts @@ -0,0 +1,28 @@ +import { INestApplication } from "@nestjs/common"; +import { NestFactory } from "@nestjs/core"; + +import core from "@nestia/core"; + +export class Backend { + private application_?: INestApplication; + + public async open(): Promise { + this.application_ = await NestFactory.create( + await core.EncryptedModule.dynamic(__dirname + "/controllers", { + key: "A".repeat(32), + iv: "B".repeat(16), + }), + { logger: false }, + ); + await this.application_.listen(37_000); + } + + public async close(): Promise { + if (this.application_ === undefined) return; + + const app = this.application_; + await app.close(); + + delete this.application_; + } +} diff --git a/test/features/route-manual-is/src/api/HttpError.ts b/test/features/route-manual-is/src/api/HttpError.ts new file mode 100644 index 000000000..5df328ae4 --- /dev/null +++ b/test/features/route-manual-is/src/api/HttpError.ts @@ -0,0 +1 @@ +export { HttpError } from "@nestia/fetcher"; diff --git a/test/features/route-manual-is/src/api/IConnection.ts b/test/features/route-manual-is/src/api/IConnection.ts new file mode 100644 index 000000000..92727cfc2 --- /dev/null +++ b/test/features/route-manual-is/src/api/IConnection.ts @@ -0,0 +1 @@ +export { IConnection } from "@nestia/fetcher"; diff --git a/test/features/route-manual-is/src/api/Primitive.ts b/test/features/route-manual-is/src/api/Primitive.ts new file mode 100644 index 000000000..3c1db5a74 --- /dev/null +++ b/test/features/route-manual-is/src/api/Primitive.ts @@ -0,0 +1 @@ +export { Primitive } from "@nestia/fetcher"; diff --git a/test/features/route-manual-is/src/api/functional/health/index.ts b/test/features/route-manual-is/src/api/functional/health/index.ts new file mode 100644 index 000000000..619581f93 --- /dev/null +++ b/test/features/route-manual-is/src/api/functional/health/index.ts @@ -0,0 +1,42 @@ +/** + * @packageDocumentation + * @module api.functional.health + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +import { Fetcher } from "@nestia/fetcher"; +import type { IConnection } from "@nestia/fetcher"; + +/** + * @controller HealthController.get() + * @path GET /health + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export function get + ( + connection: IConnection + ): Promise +{ + return Fetcher.fetch + ( + connection, + get.ENCRYPTED, + get.METHOD, + get.path() + ); +} +export namespace get +{ + + export const METHOD = "GET" as const; + export const PATH: string = "/health"; + export const ENCRYPTED: Fetcher.IEncrypted = { + request: false, + response: false, + }; + + export function path(): string + { + return `/health`; + } +} \ No newline at end of file diff --git a/test/features/route-manual-is/src/api/functional/index.ts b/test/features/route-manual-is/src/api/functional/index.ts new file mode 100644 index 000000000..43933202c --- /dev/null +++ b/test/features/route-manual-is/src/api/functional/index.ts @@ -0,0 +1,9 @@ +/** + * @packageDocumentation + * @module api.functional + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +export * as health from "./health"; +export * as performance from "./performance"; +export * as route from "./route"; \ No newline at end of file diff --git a/test/features/route-manual-is/src/api/functional/manual/index.ts b/test/features/route-manual-is/src/api/functional/manual/index.ts new file mode 100644 index 000000000..1e1157605 --- /dev/null +++ b/test/features/route-manual-is/src/api/functional/manual/index.ts @@ -0,0 +1,45 @@ +/** + * @packageDocumentation + * @module api.functional.manual + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +import { Fetcher, Primitive } from "@nestia/fetcher"; +import type { IConnection } from "@nestia/fetcher"; + +import type { IBbsArticle } from "./../../structures/IBbsArticle"; + +/** + * @controller TypedRouteController.random() + * @path GET /manual/random + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export function random + ( + connection: IConnection + ): Promise +{ + return Fetcher.fetch + ( + connection, + random.ENCRYPTED, + random.METHOD, + random.path() + ); +} +export namespace random +{ + export type Output = Primitive; + + export const METHOD = "GET" as const; + export const PATH: string = "/manual/random"; + export const ENCRYPTED: Fetcher.IEncrypted = { + request: false, + response: false, + }; + + export function path(): string + { + return `/manual/random`; + } +} \ No newline at end of file diff --git a/test/features/route-manual-is/src/api/functional/performance/index.ts b/test/features/route-manual-is/src/api/functional/performance/index.ts new file mode 100644 index 000000000..9e402a44a --- /dev/null +++ b/test/features/route-manual-is/src/api/functional/performance/index.ts @@ -0,0 +1,45 @@ +/** + * @packageDocumentation + * @module api.functional.performance + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +import { Fetcher, Primitive } from "@nestia/fetcher"; +import type { IConnection } from "@nestia/fetcher"; + +import type { IPerformance } from "./../../structures/IPerformance"; + +/** + * @controller PerformanceController.get() + * @path GET /performance + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export function get + ( + connection: IConnection + ): Promise +{ + return Fetcher.fetch + ( + connection, + get.ENCRYPTED, + get.METHOD, + get.path() + ); +} +export namespace get +{ + export type Output = Primitive; + + export const METHOD = "GET" as const; + export const PATH: string = "/performance"; + export const ENCRYPTED: Fetcher.IEncrypted = { + request: false, + response: false, + }; + + export function path(): string + { + return `/performance`; + } +} \ No newline at end of file diff --git a/test/features/route-manual-is/src/api/functional/route/index.ts b/test/features/route-manual-is/src/api/functional/route/index.ts new file mode 100644 index 000000000..db5470fe9 --- /dev/null +++ b/test/features/route-manual-is/src/api/functional/route/index.ts @@ -0,0 +1,45 @@ +/** + * @packageDocumentation + * @module api.functional.route + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +import { Fetcher, Primitive } from "@nestia/fetcher"; +import type { IConnection } from "@nestia/fetcher"; + +import type { IBbsArticle } from "./../../structures/IBbsArticle"; + +/** + * @controller TypedRouteController.random() + * @path GET /route/random + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export function random + ( + connection: IConnection + ): Promise +{ + return Fetcher.fetch + ( + connection, + random.ENCRYPTED, + random.METHOD, + random.path() + ); +} +export namespace random +{ + export type Output = Primitive; + + export const METHOD = "GET" as const; + export const PATH: string = "/route/random"; + export const ENCRYPTED: Fetcher.IEncrypted = { + request: false, + response: false, + }; + + export function path(): string + { + return `/route/random`; + } +} \ No newline at end of file diff --git a/test/features/route-manual-is/src/api/index.ts b/test/features/route-manual-is/src/api/index.ts new file mode 100644 index 000000000..1896c4fbd --- /dev/null +++ b/test/features/route-manual-is/src/api/index.ts @@ -0,0 +1,5 @@ +import * as api from "./module"; + +export * from "./module"; + +export default api; diff --git a/test/features/route-manual-is/src/api/module.ts b/test/features/route-manual-is/src/api/module.ts new file mode 100644 index 000000000..00239fb3b --- /dev/null +++ b/test/features/route-manual-is/src/api/module.ts @@ -0,0 +1,5 @@ +export * from "./IConnection"; +export * from "./Primitive"; +export * from "./HttpError"; + +export * as functional from "./functional"; diff --git a/test/features/route-manual-is/src/api/structures/IBbsArticle.ts b/test/features/route-manual-is/src/api/structures/IBbsArticle.ts new file mode 100644 index 000000000..a5188f20c --- /dev/null +++ b/test/features/route-manual-is/src/api/structures/IBbsArticle.ts @@ -0,0 +1,40 @@ +export interface IBbsArticle { + /** + * @format uuid + */ + id: string; + + /** + * @minLength 3 + * @maxLength 50 + */ + title: string; + + body: string; + + files: IAttachmentFile[]; + + /** + * @format date-time + */ + created_at: string; +} + +export interface IAttachmentFile { + /** + * @minLengt 1 + * @maxLength 255 + */ + name: string | null; + + /** + * @minLength 1 + * @maxLength 8 + */ + extension: string | null; + + /** + * @format url + */ + url: string; +} diff --git a/test/features/route-manual-is/src/api/structures/IPerformance.ts b/test/features/route-manual-is/src/api/structures/IPerformance.ts new file mode 100644 index 000000000..a9e9336e1 --- /dev/null +++ b/test/features/route-manual-is/src/api/structures/IPerformance.ts @@ -0,0 +1,10 @@ +/** + * Performance info. + * + * @author Samchon + */ +export interface IPerformance { + cpu: NodeJS.CpuUsage; + memory: NodeJS.MemoryUsage; + resource: NodeJS.ResourceUsage; +} diff --git a/test/features/route-manual-is/src/api/structures/ISystem.ts b/test/features/route-manual-is/src/api/structures/ISystem.ts new file mode 100644 index 000000000..68f05ca92 --- /dev/null +++ b/test/features/route-manual-is/src/api/structures/ISystem.ts @@ -0,0 +1,81 @@ +/** + * System Information. + * + * @author Jeongho Nam + */ +export interface ISystem { + /** + * Random Unique ID. + */ + uid: number; + + /** + * `process.argv` + */ + arguments: string[]; + + /** + * Git commit info. + */ + commit: ISystem.ICommit; + + /** + * `package.json` + */ + package: ISystem.IPackage; + + /** + * Creation time of this server. + */ + created_at: string; +} + +export namespace ISystem { + /** + * Git commit info. + */ + export interface ICommit { + shortHash: string; + branch: string; + hash: string; + subject: string; + sanitizedSubject: string; + body: string; + author: ICommit.IUser; + committer: ICommit.IUser; + authored_at: string; + commited_at: string; + notes?: string; + tags: string[]; + } + export namespace ICommit { + /** + * Git user account info. + */ + export interface IUser { + name: string; + email: string; + } + } + + /** + * NPM package info. + */ + export interface IPackage { + name: string; + version: string; + description: string; + main?: string; + typings?: string; + scripts: Record; + repository: { type: "git"; url: string }; + author: string; + license: string; + bugs: { url: string }; + homepage: string; + devDependencies?: Record; + dependencies: Record; + publishConfig?: { registry: string }; + files?: string[]; + } +} diff --git a/test/features/route-manual-is/src/controllers/HealthController.ts b/test/features/route-manual-is/src/controllers/HealthController.ts new file mode 100644 index 000000000..a9ce3563b --- /dev/null +++ b/test/features/route-manual-is/src/controllers/HealthController.ts @@ -0,0 +1,9 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +@Controller("health") +export class HealthController { + @core.TypedRoute.Get() + public get(): void {} +} diff --git a/test/features/route-manual-is/src/controllers/PerformanceController.ts b/test/features/route-manual-is/src/controllers/PerformanceController.ts new file mode 100644 index 000000000..798d64fae --- /dev/null +++ b/test/features/route-manual-is/src/controllers/PerformanceController.ts @@ -0,0 +1,17 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +import { IPerformance } from "@api/lib/structures/IPerformance"; + +@Controller("performance") +export class PerformanceController { + @core.TypedRoute.Get() + public async get(): Promise { + return { + cpu: process.cpuUsage(), + memory: process.memoryUsage(), + resource: process.resourceUsage(), + }; + } +} diff --git a/test/features/route-manual-is/src/controllers/TypedRouteController.ts b/test/features/route-manual-is/src/controllers/TypedRouteController.ts new file mode 100644 index 000000000..eb15129ef --- /dev/null +++ b/test/features/route-manual-is/src/controllers/TypedRouteController.ts @@ -0,0 +1,22 @@ +import { Controller } from "@nestjs/common"; +import typia from "typia"; + +import core from "@nestia/core"; + +import { IBbsArticle } from "@api/lib/structures/IBbsArticle"; + +@Controller("route") +export class TypedRouteController { + @core.TypedRoute.Get("random", { + type: "is", + is: typia.createIsStringify(), + }) + public async random(): Promise { + return { + ...typia.random(), + ...{ + dummy: 1, + }, + }; + } +} diff --git a/test/features/route-manual-is/src/test/features/test_api_health_check.ts b/test/features/route-manual-is/src/test/features/test_api_health_check.ts new file mode 100644 index 000000000..c34703c71 --- /dev/null +++ b/test/features/route-manual-is/src/test/features/test_api_health_check.ts @@ -0,0 +1,5 @@ +import api from "@api"; + +export const test_api_monitor_health_check = ( + connection: api.IConnection, +): Promise => api.functional.health.get(connection); diff --git a/test/features/route-manual-is/src/test/features/test_api_performance.ts b/test/features/route-manual-is/src/test/features/test_api_performance.ts new file mode 100644 index 000000000..55b6d2ca7 --- /dev/null +++ b/test/features/route-manual-is/src/test/features/test_api_performance.ts @@ -0,0 +1,13 @@ +import typia from "typia"; + +import api from "@api"; +import { IPerformance } from "@api/lib/structures/IPerformance"; + +export const test_api_monitor_performance = async ( + connection: api.IConnection, +): Promise => { + const performance: IPerformance = await api.functional.performance.get( + connection, + ); + typia.assert(performance); +}; diff --git a/test/features/route-manual-is/src/test/features/test_api_route.ts b/test/features/route-manual-is/src/test/features/test_api_route.ts new file mode 100644 index 000000000..94451eee7 --- /dev/null +++ b/test/features/route-manual-is/src/test/features/test_api_route.ts @@ -0,0 +1,11 @@ +import typia from "typia"; + +import api from "@api"; +import { IBbsArticle } from "@api/lib/structures/IBbsArticle"; + +export const test_api_route = async ( + connection: api.IConnection, +): Promise => { + const article: IBbsArticle = await api.functional.route.random(connection); + typia.assertEquals(article); +}; diff --git a/test/features/route-manual-is/src/test/index.ts b/test/features/route-manual-is/src/test/index.ts new file mode 100644 index 000000000..e89842739 --- /dev/null +++ b/test/features/route-manual-is/src/test/index.ts @@ -0,0 +1,39 @@ +import { DynamicExecutor } from "@nestia/e2e"; + +import { Backend } from "../Backend"; + +async function main(): Promise { + const server: Backend = new Backend(); + await server.open(); + + const report: DynamicExecutor.IReport = await DynamicExecutor.validate({ + prefix: "test", + parameters: () => [ + { + host: "http://127.0.0.1:37000", + encryption: { + key: "A".repeat(32), + iv: "B".repeat(16), + }, + }, + ], + })(`${__dirname}/features`); + await server.close(); + + const exceptions: Error[] = report.executions + .filter((exec) => exec.error !== null) + .map((exec) => exec.error!); + if (exceptions.length === 0) { + console.log("Success"); + console.log("Elapsed time", report.time.toLocaleString(), `ms`); + } else { + // for (const exp of exceptions) console.log(exp); + console.log("Failed"); + console.log("Elapsed time", report.time.toLocaleString(), `ms`); + process.exit(-1); + } +} +main().catch((exp) => { + console.log(exp); + process.exit(-1); +}); diff --git a/test/features/route-manual-is/swagger.json b/test/features/route-manual-is/swagger.json new file mode 100644 index 000000000..fe7bc27dd --- /dev/null +++ b/test/features/route-manual-is/swagger.json @@ -0,0 +1,540 @@ +{ + "openapi": "3.0.1", + "servers": [ + { + "url": "https://github.com/samchon/nestia", + "description": "insert your server url" + } + ], + "info": { + "version": "0.1.0", + "title": "Generated by nestia - https://github.com/samchon/nestia" + }, + "paths": { + "/health": { + "get": { + "tags": [], + "parameters": [], + "responses": { + "200": { + "description": "", + "x-nestia-encrypted": false + } + }, + "description": "", + "x-nestia-namespace": "health.get", + "x-nestia-jsDocTags": [] + } + }, + "/performance": { + "get": { + "tags": [], + "parameters": [], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IPerformance" + } + } + }, + "x-nestia-encrypted": false + } + }, + "description": "", + "x-nestia-namespace": "performance.get", + "x-nestia-jsDocTags": [] + } + }, + "/route/random": { + "get": { + "tags": [], + "parameters": [], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IBbsArticle" + } + } + }, + "x-nestia-encrypted": false + } + }, + "description": "", + "x-nestia-namespace": "route.random.random", + "x-nestia-jsDocTags": [] + } + } + }, + "components": { + "schemas": { + "IPerformance": { + "type": "object", + "properties": { + "cpu": { + "$ref": "#/components/schemas/_singlequote_process_singlequote_.global.NodeJS.CpuUsage", + "x-typia-required": true, + "x-typia-optional": false + }, + "memory": { + "$ref": "#/components/schemas/_singlequote_process_singlequote_.global.NodeJS.MemoryUsage", + "x-typia-required": true, + "x-typia-optional": false + }, + "resource": { + "$ref": "#/components/schemas/_singlequote_process_singlequote_.global.NodeJS.ResourceUsage", + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "cpu", + "memory", + "resource" + ], + "description": "Performance info.", + "x-typia-jsDocTags": [ + { + "name": "author", + "text": [ + { + "text": "Samchon", + "kind": "text" + } + ] + } + ] + }, + "_singlequote_process_singlequote_.global.NodeJS.CpuUsage": { + "type": "object", + "properties": { + "user": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "system": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "user", + "system" + ], + "x-typia-jsDocTags": [] + }, + "_singlequote_process_singlequote_.global.NodeJS.MemoryUsage": { + "type": "object", + "properties": { + "rss": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "heapTotal": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "heapUsed": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "external": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "arrayBuffers": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "rss", + "heapTotal", + "heapUsed", + "external", + "arrayBuffers" + ], + "x-typia-jsDocTags": [] + }, + "_singlequote_process_singlequote_.global.NodeJS.ResourceUsage": { + "type": "object", + "properties": { + "fsRead": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "fsWrite": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "involuntaryContextSwitches": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "ipcReceived": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "ipcSent": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "majorPageFault": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "maxRSS": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "minorPageFault": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "sharedMemorySize": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "signalsCount": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "swappedOut": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "systemCPUTime": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "unsharedDataSize": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "unsharedStackSize": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "userCPUTime": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "voluntaryContextSwitches": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "fsRead", + "fsWrite", + "involuntaryContextSwitches", + "ipcReceived", + "ipcSent", + "majorPageFault", + "maxRSS", + "minorPageFault", + "sharedMemorySize", + "signalsCount", + "swappedOut", + "systemCPUTime", + "unsharedDataSize", + "unsharedStackSize", + "userCPUTime", + "voluntaryContextSwitches" + ], + "x-typia-jsDocTags": [] + }, + "IBbsArticle": { + "type": "object", + "properties": { + "id": { + "type": "string", + "nullable": false, + "x-typia-metaTags": [ + { + "kind": "format", + "value": "uuid" + } + ], + "x-typia-jsDocTags": [ + { + "name": "format", + "text": [ + { + "text": "uuid", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "format": "uuid" + }, + "title": { + "type": "string", + "nullable": false, + "x-typia-metaTags": [ + { + "kind": "minLength", + "value": 3 + }, + { + "kind": "maxLength", + "value": 50 + } + ], + "x-typia-jsDocTags": [ + { + "name": "minLength", + "text": [ + { + "text": "3", + "kind": "text" + } + ] + }, + { + "name": "maxLength", + "text": [ + { + "text": "50", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "minLength": 3, + "maxLength": 50 + }, + "body": { + "type": "string", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "files": { + "type": "array", + "items": { + "$ref": "#/components/schemas/IAttachmentFile", + "x-typia-required": true, + "x-typia-optional": false + }, + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "created_at": { + "type": "string", + "nullable": false, + "x-typia-metaTags": [ + { + "kind": "format", + "value": "datetime" + } + ], + "x-typia-jsDocTags": [ + { + "name": "format", + "text": [ + { + "text": "date-time", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "format": "date-time" + } + }, + "nullable": false, + "required": [ + "id", + "title", + "body", + "files", + "created_at" + ], + "x-typia-jsDocTags": [] + }, + "IAttachmentFile": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "x-typia-metaTags": [ + { + "kind": "maxLength", + "value": 255 + } + ], + "x-typia-jsDocTags": [ + { + "name": "minLengt", + "text": [ + { + "text": "1", + "kind": "text" + } + ] + }, + { + "name": "maxLength", + "text": [ + { + "text": "255", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "maxLength": 255 + }, + "extension": { + "type": "string", + "nullable": true, + "x-typia-metaTags": [ + { + "kind": "minLength", + "value": 1 + }, + { + "kind": "maxLength", + "value": 8 + } + ], + "x-typia-jsDocTags": [ + { + "name": "minLength", + "text": [ + { + "text": "1", + "kind": "text" + } + ] + }, + { + "name": "maxLength", + "text": [ + { + "text": "8", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "minLength": 1, + "maxLength": 8 + }, + "url": { + "type": "string", + "nullable": false, + "x-typia-metaTags": [ + { + "kind": "format", + "value": "url" + } + ], + "x-typia-jsDocTags": [ + { + "name": "format", + "text": [ + { + "text": "url", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "format": "url" + } + }, + "nullable": false, + "required": [ + "name", + "extension", + "url" + ], + "x-typia-jsDocTags": [] + } + }, + "securitySchemes": { + "bearer": { + "type": "apiKey", + "in": "header", + "name": "Authorization" + } + } + }, + "security": [ + { + "bearer": [] + } + ] +} \ No newline at end of file diff --git a/test/features/route-manual-is/tsconfig.json b/test/features/route-manual-is/tsconfig.json new file mode 100644 index 000000000..e5fe47a95 --- /dev/null +++ b/test/features/route-manual-is/tsconfig.json @@ -0,0 +1,103 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + /* Language and Environment */ + "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + /* Modules */ + "module": "commonjs", /* Specify what module code is generated. */// "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + "paths": { + "@nestia/core": ["../../../packages/core/src"], + "@nestia/e2e": ["../../../packages/e2e/src"], + "@nestia/fetcher": ["../../../packages/fetcher/src"], + "@nestia/sdk": ["../../../packages/sdk/src"], + "@nestia/sdk/lib/*": ["../../../packages/sdk/src/*"], + "@api": ["./src/api"], + "@api/lib/*": ["./src/api/*"], + }, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. *//* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true, /* Skip type checking all .d.ts files. */ + "plugins": [ + { "transform": "typescript-transform-paths" }, + { "transform": "typia/lib/transform" }, + { "transform": "../../../packages/core/src/transform.ts" }, + ], + } + } \ No newline at end of file diff --git a/test/features/route-manual-stringify/nestia.config.ts b/test/features/route-manual-stringify/nestia.config.ts new file mode 100644 index 000000000..2594a40d0 --- /dev/null +++ b/test/features/route-manual-stringify/nestia.config.ts @@ -0,0 +1,15 @@ +import { INestiaConfig } from "@nestia/sdk"; + +export const NESTIA_CONFIG: INestiaConfig = { + input: ["src/controllers"], + output: "src/api", + swagger: { + output: "swagger.json", + security: { + bearer: { + type: "apiKey", + }, + }, + }, +}; +export default NESTIA_CONFIG; diff --git a/test/features/route-manual-stringify/src/Backend.ts b/test/features/route-manual-stringify/src/Backend.ts new file mode 100644 index 000000000..8ab51b70f --- /dev/null +++ b/test/features/route-manual-stringify/src/Backend.ts @@ -0,0 +1,28 @@ +import { INestApplication } from "@nestjs/common"; +import { NestFactory } from "@nestjs/core"; + +import core from "@nestia/core"; + +export class Backend { + private application_?: INestApplication; + + public async open(): Promise { + this.application_ = await NestFactory.create( + await core.EncryptedModule.dynamic(__dirname + "/controllers", { + key: "A".repeat(32), + iv: "B".repeat(16), + }), + { logger: false }, + ); + await this.application_.listen(37_000); + } + + public async close(): Promise { + if (this.application_ === undefined) return; + + const app = this.application_; + await app.close(); + + delete this.application_; + } +} diff --git a/test/features/route-manual-stringify/src/api/HttpError.ts b/test/features/route-manual-stringify/src/api/HttpError.ts new file mode 100644 index 000000000..5df328ae4 --- /dev/null +++ b/test/features/route-manual-stringify/src/api/HttpError.ts @@ -0,0 +1 @@ +export { HttpError } from "@nestia/fetcher"; diff --git a/test/features/route-manual-stringify/src/api/IConnection.ts b/test/features/route-manual-stringify/src/api/IConnection.ts new file mode 100644 index 000000000..92727cfc2 --- /dev/null +++ b/test/features/route-manual-stringify/src/api/IConnection.ts @@ -0,0 +1 @@ +export { IConnection } from "@nestia/fetcher"; diff --git a/test/features/route-manual-stringify/src/api/Primitive.ts b/test/features/route-manual-stringify/src/api/Primitive.ts new file mode 100644 index 000000000..3c1db5a74 --- /dev/null +++ b/test/features/route-manual-stringify/src/api/Primitive.ts @@ -0,0 +1 @@ +export { Primitive } from "@nestia/fetcher"; diff --git a/test/features/route-manual-stringify/src/api/functional/health/index.ts b/test/features/route-manual-stringify/src/api/functional/health/index.ts new file mode 100644 index 000000000..619581f93 --- /dev/null +++ b/test/features/route-manual-stringify/src/api/functional/health/index.ts @@ -0,0 +1,42 @@ +/** + * @packageDocumentation + * @module api.functional.health + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +import { Fetcher } from "@nestia/fetcher"; +import type { IConnection } from "@nestia/fetcher"; + +/** + * @controller HealthController.get() + * @path GET /health + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export function get + ( + connection: IConnection + ): Promise +{ + return Fetcher.fetch + ( + connection, + get.ENCRYPTED, + get.METHOD, + get.path() + ); +} +export namespace get +{ + + export const METHOD = "GET" as const; + export const PATH: string = "/health"; + export const ENCRYPTED: Fetcher.IEncrypted = { + request: false, + response: false, + }; + + export function path(): string + { + return `/health`; + } +} \ No newline at end of file diff --git a/test/features/route-manual-stringify/src/api/functional/index.ts b/test/features/route-manual-stringify/src/api/functional/index.ts new file mode 100644 index 000000000..43933202c --- /dev/null +++ b/test/features/route-manual-stringify/src/api/functional/index.ts @@ -0,0 +1,9 @@ +/** + * @packageDocumentation + * @module api.functional + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +export * as health from "./health"; +export * as performance from "./performance"; +export * as route from "./route"; \ No newline at end of file diff --git a/test/features/route-manual-stringify/src/api/functional/manual/index.ts b/test/features/route-manual-stringify/src/api/functional/manual/index.ts new file mode 100644 index 000000000..1e1157605 --- /dev/null +++ b/test/features/route-manual-stringify/src/api/functional/manual/index.ts @@ -0,0 +1,45 @@ +/** + * @packageDocumentation + * @module api.functional.manual + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +import { Fetcher, Primitive } from "@nestia/fetcher"; +import type { IConnection } from "@nestia/fetcher"; + +import type { IBbsArticle } from "./../../structures/IBbsArticle"; + +/** + * @controller TypedRouteController.random() + * @path GET /manual/random + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export function random + ( + connection: IConnection + ): Promise +{ + return Fetcher.fetch + ( + connection, + random.ENCRYPTED, + random.METHOD, + random.path() + ); +} +export namespace random +{ + export type Output = Primitive; + + export const METHOD = "GET" as const; + export const PATH: string = "/manual/random"; + export const ENCRYPTED: Fetcher.IEncrypted = { + request: false, + response: false, + }; + + export function path(): string + { + return `/manual/random`; + } +} \ No newline at end of file diff --git a/test/features/route-manual-stringify/src/api/functional/performance/index.ts b/test/features/route-manual-stringify/src/api/functional/performance/index.ts new file mode 100644 index 000000000..9e402a44a --- /dev/null +++ b/test/features/route-manual-stringify/src/api/functional/performance/index.ts @@ -0,0 +1,45 @@ +/** + * @packageDocumentation + * @module api.functional.performance + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +import { Fetcher, Primitive } from "@nestia/fetcher"; +import type { IConnection } from "@nestia/fetcher"; + +import type { IPerformance } from "./../../structures/IPerformance"; + +/** + * @controller PerformanceController.get() + * @path GET /performance + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export function get + ( + connection: IConnection + ): Promise +{ + return Fetcher.fetch + ( + connection, + get.ENCRYPTED, + get.METHOD, + get.path() + ); +} +export namespace get +{ + export type Output = Primitive; + + export const METHOD = "GET" as const; + export const PATH: string = "/performance"; + export const ENCRYPTED: Fetcher.IEncrypted = { + request: false, + response: false, + }; + + export function path(): string + { + return `/performance`; + } +} \ No newline at end of file diff --git a/test/features/route-manual-stringify/src/api/functional/route/index.ts b/test/features/route-manual-stringify/src/api/functional/route/index.ts new file mode 100644 index 000000000..66a4fe002 --- /dev/null +++ b/test/features/route-manual-stringify/src/api/functional/route/index.ts @@ -0,0 +1,45 @@ +/** + * @packageDocumentation + * @module api.functional.route + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +import { Fetcher, Primitive } from "@nestia/fetcher"; +import type { IConnection } from "@nestia/fetcher"; + +import type { IBbsArticle } from "./../../structures/IBbsArticle"; + +/** + * @controller ManualRouteController.random() + * @path GET /route/random + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export function random + ( + connection: IConnection + ): Promise +{ + return Fetcher.fetch + ( + connection, + random.ENCRYPTED, + random.METHOD, + random.path() + ); +} +export namespace random +{ + export type Output = Primitive; + + export const METHOD = "GET" as const; + export const PATH: string = "/route/random"; + export const ENCRYPTED: Fetcher.IEncrypted = { + request: false, + response: false, + }; + + export function path(): string + { + return `/route/random`; + } +} \ No newline at end of file diff --git a/test/features/route-manual-stringify/src/api/index.ts b/test/features/route-manual-stringify/src/api/index.ts new file mode 100644 index 000000000..1896c4fbd --- /dev/null +++ b/test/features/route-manual-stringify/src/api/index.ts @@ -0,0 +1,5 @@ +import * as api from "./module"; + +export * from "./module"; + +export default api; diff --git a/test/features/route-manual-stringify/src/api/module.ts b/test/features/route-manual-stringify/src/api/module.ts new file mode 100644 index 000000000..00239fb3b --- /dev/null +++ b/test/features/route-manual-stringify/src/api/module.ts @@ -0,0 +1,5 @@ +export * from "./IConnection"; +export * from "./Primitive"; +export * from "./HttpError"; + +export * as functional from "./functional"; diff --git a/test/features/route-manual-stringify/src/api/structures/IBbsArticle.ts b/test/features/route-manual-stringify/src/api/structures/IBbsArticle.ts new file mode 100644 index 000000000..a5188f20c --- /dev/null +++ b/test/features/route-manual-stringify/src/api/structures/IBbsArticle.ts @@ -0,0 +1,40 @@ +export interface IBbsArticle { + /** + * @format uuid + */ + id: string; + + /** + * @minLength 3 + * @maxLength 50 + */ + title: string; + + body: string; + + files: IAttachmentFile[]; + + /** + * @format date-time + */ + created_at: string; +} + +export interface IAttachmentFile { + /** + * @minLengt 1 + * @maxLength 255 + */ + name: string | null; + + /** + * @minLength 1 + * @maxLength 8 + */ + extension: string | null; + + /** + * @format url + */ + url: string; +} diff --git a/test/features/route-manual-stringify/src/api/structures/IPerformance.ts b/test/features/route-manual-stringify/src/api/structures/IPerformance.ts new file mode 100644 index 000000000..a9e9336e1 --- /dev/null +++ b/test/features/route-manual-stringify/src/api/structures/IPerformance.ts @@ -0,0 +1,10 @@ +/** + * Performance info. + * + * @author Samchon + */ +export interface IPerformance { + cpu: NodeJS.CpuUsage; + memory: NodeJS.MemoryUsage; + resource: NodeJS.ResourceUsage; +} diff --git a/test/features/route-manual-stringify/src/api/structures/ISystem.ts b/test/features/route-manual-stringify/src/api/structures/ISystem.ts new file mode 100644 index 000000000..68f05ca92 --- /dev/null +++ b/test/features/route-manual-stringify/src/api/structures/ISystem.ts @@ -0,0 +1,81 @@ +/** + * System Information. + * + * @author Jeongho Nam + */ +export interface ISystem { + /** + * Random Unique ID. + */ + uid: number; + + /** + * `process.argv` + */ + arguments: string[]; + + /** + * Git commit info. + */ + commit: ISystem.ICommit; + + /** + * `package.json` + */ + package: ISystem.IPackage; + + /** + * Creation time of this server. + */ + created_at: string; +} + +export namespace ISystem { + /** + * Git commit info. + */ + export interface ICommit { + shortHash: string; + branch: string; + hash: string; + subject: string; + sanitizedSubject: string; + body: string; + author: ICommit.IUser; + committer: ICommit.IUser; + authored_at: string; + commited_at: string; + notes?: string; + tags: string[]; + } + export namespace ICommit { + /** + * Git user account info. + */ + export interface IUser { + name: string; + email: string; + } + } + + /** + * NPM package info. + */ + export interface IPackage { + name: string; + version: string; + description: string; + main?: string; + typings?: string; + scripts: Record; + repository: { type: "git"; url: string }; + author: string; + license: string; + bugs: { url: string }; + homepage: string; + devDependencies?: Record; + dependencies: Record; + publishConfig?: { registry: string }; + files?: string[]; + } +} diff --git a/test/features/route-manual-stringify/src/controllers/HealthController.ts b/test/features/route-manual-stringify/src/controllers/HealthController.ts new file mode 100644 index 000000000..a9ce3563b --- /dev/null +++ b/test/features/route-manual-stringify/src/controllers/HealthController.ts @@ -0,0 +1,9 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +@Controller("health") +export class HealthController { + @core.TypedRoute.Get() + public get(): void {} +} diff --git a/test/features/route-manual-stringify/src/controllers/PerformanceController.ts b/test/features/route-manual-stringify/src/controllers/PerformanceController.ts new file mode 100644 index 000000000..798d64fae --- /dev/null +++ b/test/features/route-manual-stringify/src/controllers/PerformanceController.ts @@ -0,0 +1,17 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +import { IPerformance } from "@api/lib/structures/IPerformance"; + +@Controller("performance") +export class PerformanceController { + @core.TypedRoute.Get() + public async get(): Promise { + return { + cpu: process.cpuUsage(), + memory: process.memoryUsage(), + resource: process.resourceUsage(), + }; + } +} diff --git a/test/features/route-manual-stringify/src/controllers/TypedRouteController.ts b/test/features/route-manual-stringify/src/controllers/TypedRouteController.ts new file mode 100644 index 000000000..a9b3dc3c3 --- /dev/null +++ b/test/features/route-manual-stringify/src/controllers/TypedRouteController.ts @@ -0,0 +1,22 @@ +import { Controller } from "@nestjs/common"; +import typia from "typia"; + +import core from "@nestia/core"; + +import { IBbsArticle } from "@api/lib/structures/IBbsArticle"; + +@Controller("route") +export class ManualRouteController { + @core.TypedRoute.Get("random", { + type: "stringify", + stringify: typia.createStringify(), + }) + public async random(): Promise { + return { + ...typia.random(), + ...{ + dummy: 1, + }, + }; + } +} diff --git a/test/features/route-manual-stringify/src/test/features/test_api_health_check.ts b/test/features/route-manual-stringify/src/test/features/test_api_health_check.ts new file mode 100644 index 000000000..c34703c71 --- /dev/null +++ b/test/features/route-manual-stringify/src/test/features/test_api_health_check.ts @@ -0,0 +1,5 @@ +import api from "@api"; + +export const test_api_monitor_health_check = ( + connection: api.IConnection, +): Promise => api.functional.health.get(connection); diff --git a/test/features/route-manual-stringify/src/test/features/test_api_performance.ts b/test/features/route-manual-stringify/src/test/features/test_api_performance.ts new file mode 100644 index 000000000..55b6d2ca7 --- /dev/null +++ b/test/features/route-manual-stringify/src/test/features/test_api_performance.ts @@ -0,0 +1,13 @@ +import typia from "typia"; + +import api from "@api"; +import { IPerformance } from "@api/lib/structures/IPerformance"; + +export const test_api_monitor_performance = async ( + connection: api.IConnection, +): Promise => { + const performance: IPerformance = await api.functional.performance.get( + connection, + ); + typia.assert(performance); +}; diff --git a/test/features/route-manual-stringify/src/test/features/test_api_route.ts b/test/features/route-manual-stringify/src/test/features/test_api_route.ts new file mode 100644 index 000000000..94451eee7 --- /dev/null +++ b/test/features/route-manual-stringify/src/test/features/test_api_route.ts @@ -0,0 +1,11 @@ +import typia from "typia"; + +import api from "@api"; +import { IBbsArticle } from "@api/lib/structures/IBbsArticle"; + +export const test_api_route = async ( + connection: api.IConnection, +): Promise => { + const article: IBbsArticle = await api.functional.route.random(connection); + typia.assertEquals(article); +}; diff --git a/test/features/route-manual-stringify/src/test/index.ts b/test/features/route-manual-stringify/src/test/index.ts new file mode 100644 index 000000000..e89842739 --- /dev/null +++ b/test/features/route-manual-stringify/src/test/index.ts @@ -0,0 +1,39 @@ +import { DynamicExecutor } from "@nestia/e2e"; + +import { Backend } from "../Backend"; + +async function main(): Promise { + const server: Backend = new Backend(); + await server.open(); + + const report: DynamicExecutor.IReport = await DynamicExecutor.validate({ + prefix: "test", + parameters: () => [ + { + host: "http://127.0.0.1:37000", + encryption: { + key: "A".repeat(32), + iv: "B".repeat(16), + }, + }, + ], + })(`${__dirname}/features`); + await server.close(); + + const exceptions: Error[] = report.executions + .filter((exec) => exec.error !== null) + .map((exec) => exec.error!); + if (exceptions.length === 0) { + console.log("Success"); + console.log("Elapsed time", report.time.toLocaleString(), `ms`); + } else { + // for (const exp of exceptions) console.log(exp); + console.log("Failed"); + console.log("Elapsed time", report.time.toLocaleString(), `ms`); + process.exit(-1); + } +} +main().catch((exp) => { + console.log(exp); + process.exit(-1); +}); diff --git a/test/features/route-manual-stringify/swagger.json b/test/features/route-manual-stringify/swagger.json new file mode 100644 index 000000000..fe7bc27dd --- /dev/null +++ b/test/features/route-manual-stringify/swagger.json @@ -0,0 +1,540 @@ +{ + "openapi": "3.0.1", + "servers": [ + { + "url": "https://github.com/samchon/nestia", + "description": "insert your server url" + } + ], + "info": { + "version": "0.1.0", + "title": "Generated by nestia - https://github.com/samchon/nestia" + }, + "paths": { + "/health": { + "get": { + "tags": [], + "parameters": [], + "responses": { + "200": { + "description": "", + "x-nestia-encrypted": false + } + }, + "description": "", + "x-nestia-namespace": "health.get", + "x-nestia-jsDocTags": [] + } + }, + "/performance": { + "get": { + "tags": [], + "parameters": [], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IPerformance" + } + } + }, + "x-nestia-encrypted": false + } + }, + "description": "", + "x-nestia-namespace": "performance.get", + "x-nestia-jsDocTags": [] + } + }, + "/route/random": { + "get": { + "tags": [], + "parameters": [], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IBbsArticle" + } + } + }, + "x-nestia-encrypted": false + } + }, + "description": "", + "x-nestia-namespace": "route.random.random", + "x-nestia-jsDocTags": [] + } + } + }, + "components": { + "schemas": { + "IPerformance": { + "type": "object", + "properties": { + "cpu": { + "$ref": "#/components/schemas/_singlequote_process_singlequote_.global.NodeJS.CpuUsage", + "x-typia-required": true, + "x-typia-optional": false + }, + "memory": { + "$ref": "#/components/schemas/_singlequote_process_singlequote_.global.NodeJS.MemoryUsage", + "x-typia-required": true, + "x-typia-optional": false + }, + "resource": { + "$ref": "#/components/schemas/_singlequote_process_singlequote_.global.NodeJS.ResourceUsage", + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "cpu", + "memory", + "resource" + ], + "description": "Performance info.", + "x-typia-jsDocTags": [ + { + "name": "author", + "text": [ + { + "text": "Samchon", + "kind": "text" + } + ] + } + ] + }, + "_singlequote_process_singlequote_.global.NodeJS.CpuUsage": { + "type": "object", + "properties": { + "user": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "system": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "user", + "system" + ], + "x-typia-jsDocTags": [] + }, + "_singlequote_process_singlequote_.global.NodeJS.MemoryUsage": { + "type": "object", + "properties": { + "rss": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "heapTotal": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "heapUsed": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "external": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "arrayBuffers": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "rss", + "heapTotal", + "heapUsed", + "external", + "arrayBuffers" + ], + "x-typia-jsDocTags": [] + }, + "_singlequote_process_singlequote_.global.NodeJS.ResourceUsage": { + "type": "object", + "properties": { + "fsRead": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "fsWrite": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "involuntaryContextSwitches": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "ipcReceived": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "ipcSent": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "majorPageFault": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "maxRSS": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "minorPageFault": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "sharedMemorySize": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "signalsCount": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "swappedOut": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "systemCPUTime": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "unsharedDataSize": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "unsharedStackSize": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "userCPUTime": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "voluntaryContextSwitches": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "fsRead", + "fsWrite", + "involuntaryContextSwitches", + "ipcReceived", + "ipcSent", + "majorPageFault", + "maxRSS", + "minorPageFault", + "sharedMemorySize", + "signalsCount", + "swappedOut", + "systemCPUTime", + "unsharedDataSize", + "unsharedStackSize", + "userCPUTime", + "voluntaryContextSwitches" + ], + "x-typia-jsDocTags": [] + }, + "IBbsArticle": { + "type": "object", + "properties": { + "id": { + "type": "string", + "nullable": false, + "x-typia-metaTags": [ + { + "kind": "format", + "value": "uuid" + } + ], + "x-typia-jsDocTags": [ + { + "name": "format", + "text": [ + { + "text": "uuid", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "format": "uuid" + }, + "title": { + "type": "string", + "nullable": false, + "x-typia-metaTags": [ + { + "kind": "minLength", + "value": 3 + }, + { + "kind": "maxLength", + "value": 50 + } + ], + "x-typia-jsDocTags": [ + { + "name": "minLength", + "text": [ + { + "text": "3", + "kind": "text" + } + ] + }, + { + "name": "maxLength", + "text": [ + { + "text": "50", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "minLength": 3, + "maxLength": 50 + }, + "body": { + "type": "string", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "files": { + "type": "array", + "items": { + "$ref": "#/components/schemas/IAttachmentFile", + "x-typia-required": true, + "x-typia-optional": false + }, + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "created_at": { + "type": "string", + "nullable": false, + "x-typia-metaTags": [ + { + "kind": "format", + "value": "datetime" + } + ], + "x-typia-jsDocTags": [ + { + "name": "format", + "text": [ + { + "text": "date-time", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "format": "date-time" + } + }, + "nullable": false, + "required": [ + "id", + "title", + "body", + "files", + "created_at" + ], + "x-typia-jsDocTags": [] + }, + "IAttachmentFile": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "x-typia-metaTags": [ + { + "kind": "maxLength", + "value": 255 + } + ], + "x-typia-jsDocTags": [ + { + "name": "minLengt", + "text": [ + { + "text": "1", + "kind": "text" + } + ] + }, + { + "name": "maxLength", + "text": [ + { + "text": "255", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "maxLength": 255 + }, + "extension": { + "type": "string", + "nullable": true, + "x-typia-metaTags": [ + { + "kind": "minLength", + "value": 1 + }, + { + "kind": "maxLength", + "value": 8 + } + ], + "x-typia-jsDocTags": [ + { + "name": "minLength", + "text": [ + { + "text": "1", + "kind": "text" + } + ] + }, + { + "name": "maxLength", + "text": [ + { + "text": "8", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "minLength": 1, + "maxLength": 8 + }, + "url": { + "type": "string", + "nullable": false, + "x-typia-metaTags": [ + { + "kind": "format", + "value": "url" + } + ], + "x-typia-jsDocTags": [ + { + "name": "format", + "text": [ + { + "text": "url", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "format": "url" + } + }, + "nullable": false, + "required": [ + "name", + "extension", + "url" + ], + "x-typia-jsDocTags": [] + } + }, + "securitySchemes": { + "bearer": { + "type": "apiKey", + "in": "header", + "name": "Authorization" + } + } + }, + "security": [ + { + "bearer": [] + } + ] +} \ No newline at end of file diff --git a/test/features/route-manual-stringify/tsconfig.json b/test/features/route-manual-stringify/tsconfig.json new file mode 100644 index 000000000..e5fe47a95 --- /dev/null +++ b/test/features/route-manual-stringify/tsconfig.json @@ -0,0 +1,103 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + /* Language and Environment */ + "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + /* Modules */ + "module": "commonjs", /* Specify what module code is generated. */// "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + "paths": { + "@nestia/core": ["../../../packages/core/src"], + "@nestia/e2e": ["../../../packages/e2e/src"], + "@nestia/fetcher": ["../../../packages/fetcher/src"], + "@nestia/sdk": ["../../../packages/sdk/src"], + "@nestia/sdk/lib/*": ["../../../packages/sdk/src/*"], + "@api": ["./src/api"], + "@api/lib/*": ["./src/api/*"], + }, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. *//* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true, /* Skip type checking all .d.ts files. */ + "plugins": [ + { "transform": "typescript-transform-paths" }, + { "transform": "typia/lib/transform" }, + { "transform": "../../../packages/core/src/transform.ts" }, + ], + } + } \ No newline at end of file diff --git a/test/features/route-manual-validate/nestia.config.ts b/test/features/route-manual-validate/nestia.config.ts new file mode 100644 index 000000000..2594a40d0 --- /dev/null +++ b/test/features/route-manual-validate/nestia.config.ts @@ -0,0 +1,15 @@ +import { INestiaConfig } from "@nestia/sdk"; + +export const NESTIA_CONFIG: INestiaConfig = { + input: ["src/controllers"], + output: "src/api", + swagger: { + output: "swagger.json", + security: { + bearer: { + type: "apiKey", + }, + }, + }, +}; +export default NESTIA_CONFIG; diff --git a/test/features/route-manual-validate/src/Backend.ts b/test/features/route-manual-validate/src/Backend.ts new file mode 100644 index 000000000..8ab51b70f --- /dev/null +++ b/test/features/route-manual-validate/src/Backend.ts @@ -0,0 +1,28 @@ +import { INestApplication } from "@nestjs/common"; +import { NestFactory } from "@nestjs/core"; + +import core from "@nestia/core"; + +export class Backend { + private application_?: INestApplication; + + public async open(): Promise { + this.application_ = await NestFactory.create( + await core.EncryptedModule.dynamic(__dirname + "/controllers", { + key: "A".repeat(32), + iv: "B".repeat(16), + }), + { logger: false }, + ); + await this.application_.listen(37_000); + } + + public async close(): Promise { + if (this.application_ === undefined) return; + + const app = this.application_; + await app.close(); + + delete this.application_; + } +} diff --git a/test/features/route-manual-validate/src/api/HttpError.ts b/test/features/route-manual-validate/src/api/HttpError.ts new file mode 100644 index 000000000..5df328ae4 --- /dev/null +++ b/test/features/route-manual-validate/src/api/HttpError.ts @@ -0,0 +1 @@ +export { HttpError } from "@nestia/fetcher"; diff --git a/test/features/route-manual-validate/src/api/IConnection.ts b/test/features/route-manual-validate/src/api/IConnection.ts new file mode 100644 index 000000000..92727cfc2 --- /dev/null +++ b/test/features/route-manual-validate/src/api/IConnection.ts @@ -0,0 +1 @@ +export { IConnection } from "@nestia/fetcher"; diff --git a/test/features/route-manual-validate/src/api/Primitive.ts b/test/features/route-manual-validate/src/api/Primitive.ts new file mode 100644 index 000000000..3c1db5a74 --- /dev/null +++ b/test/features/route-manual-validate/src/api/Primitive.ts @@ -0,0 +1 @@ +export { Primitive } from "@nestia/fetcher"; diff --git a/test/features/route-manual-validate/src/api/functional/health/index.ts b/test/features/route-manual-validate/src/api/functional/health/index.ts new file mode 100644 index 000000000..619581f93 --- /dev/null +++ b/test/features/route-manual-validate/src/api/functional/health/index.ts @@ -0,0 +1,42 @@ +/** + * @packageDocumentation + * @module api.functional.health + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +import { Fetcher } from "@nestia/fetcher"; +import type { IConnection } from "@nestia/fetcher"; + +/** + * @controller HealthController.get() + * @path GET /health + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export function get + ( + connection: IConnection + ): Promise +{ + return Fetcher.fetch + ( + connection, + get.ENCRYPTED, + get.METHOD, + get.path() + ); +} +export namespace get +{ + + export const METHOD = "GET" as const; + export const PATH: string = "/health"; + export const ENCRYPTED: Fetcher.IEncrypted = { + request: false, + response: false, + }; + + export function path(): string + { + return `/health`; + } +} \ No newline at end of file diff --git a/test/features/route-manual-validate/src/api/functional/index.ts b/test/features/route-manual-validate/src/api/functional/index.ts new file mode 100644 index 000000000..43933202c --- /dev/null +++ b/test/features/route-manual-validate/src/api/functional/index.ts @@ -0,0 +1,9 @@ +/** + * @packageDocumentation + * @module api.functional + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +export * as health from "./health"; +export * as performance from "./performance"; +export * as route from "./route"; \ No newline at end of file diff --git a/test/features/route-manual-validate/src/api/functional/manual/index.ts b/test/features/route-manual-validate/src/api/functional/manual/index.ts new file mode 100644 index 000000000..1e1157605 --- /dev/null +++ b/test/features/route-manual-validate/src/api/functional/manual/index.ts @@ -0,0 +1,45 @@ +/** + * @packageDocumentation + * @module api.functional.manual + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +import { Fetcher, Primitive } from "@nestia/fetcher"; +import type { IConnection } from "@nestia/fetcher"; + +import type { IBbsArticle } from "./../../structures/IBbsArticle"; + +/** + * @controller TypedRouteController.random() + * @path GET /manual/random + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export function random + ( + connection: IConnection + ): Promise +{ + return Fetcher.fetch + ( + connection, + random.ENCRYPTED, + random.METHOD, + random.path() + ); +} +export namespace random +{ + export type Output = Primitive; + + export const METHOD = "GET" as const; + export const PATH: string = "/manual/random"; + export const ENCRYPTED: Fetcher.IEncrypted = { + request: false, + response: false, + }; + + export function path(): string + { + return `/manual/random`; + } +} \ No newline at end of file diff --git a/test/features/route-manual-validate/src/api/functional/performance/index.ts b/test/features/route-manual-validate/src/api/functional/performance/index.ts new file mode 100644 index 000000000..9e402a44a --- /dev/null +++ b/test/features/route-manual-validate/src/api/functional/performance/index.ts @@ -0,0 +1,45 @@ +/** + * @packageDocumentation + * @module api.functional.performance + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +import { Fetcher, Primitive } from "@nestia/fetcher"; +import type { IConnection } from "@nestia/fetcher"; + +import type { IPerformance } from "./../../structures/IPerformance"; + +/** + * @controller PerformanceController.get() + * @path GET /performance + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export function get + ( + connection: IConnection + ): Promise +{ + return Fetcher.fetch + ( + connection, + get.ENCRYPTED, + get.METHOD, + get.path() + ); +} +export namespace get +{ + export type Output = Primitive; + + export const METHOD = "GET" as const; + export const PATH: string = "/performance"; + export const ENCRYPTED: Fetcher.IEncrypted = { + request: false, + response: false, + }; + + export function path(): string + { + return `/performance`; + } +} \ No newline at end of file diff --git a/test/features/route-manual-validate/src/api/functional/route/index.ts b/test/features/route-manual-validate/src/api/functional/route/index.ts new file mode 100644 index 000000000..66a4fe002 --- /dev/null +++ b/test/features/route-manual-validate/src/api/functional/route/index.ts @@ -0,0 +1,45 @@ +/** + * @packageDocumentation + * @module api.functional.route + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +import { Fetcher, Primitive } from "@nestia/fetcher"; +import type { IConnection } from "@nestia/fetcher"; + +import type { IBbsArticle } from "./../../structures/IBbsArticle"; + +/** + * @controller ManualRouteController.random() + * @path GET /route/random + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export function random + ( + connection: IConnection + ): Promise +{ + return Fetcher.fetch + ( + connection, + random.ENCRYPTED, + random.METHOD, + random.path() + ); +} +export namespace random +{ + export type Output = Primitive; + + export const METHOD = "GET" as const; + export const PATH: string = "/route/random"; + export const ENCRYPTED: Fetcher.IEncrypted = { + request: false, + response: false, + }; + + export function path(): string + { + return `/route/random`; + } +} \ No newline at end of file diff --git a/test/features/route-manual-validate/src/api/index.ts b/test/features/route-manual-validate/src/api/index.ts new file mode 100644 index 000000000..1896c4fbd --- /dev/null +++ b/test/features/route-manual-validate/src/api/index.ts @@ -0,0 +1,5 @@ +import * as api from "./module"; + +export * from "./module"; + +export default api; diff --git a/test/features/route-manual-validate/src/api/module.ts b/test/features/route-manual-validate/src/api/module.ts new file mode 100644 index 000000000..00239fb3b --- /dev/null +++ b/test/features/route-manual-validate/src/api/module.ts @@ -0,0 +1,5 @@ +export * from "./IConnection"; +export * from "./Primitive"; +export * from "./HttpError"; + +export * as functional from "./functional"; diff --git a/test/features/route-manual-validate/src/api/structures/IBbsArticle.ts b/test/features/route-manual-validate/src/api/structures/IBbsArticle.ts new file mode 100644 index 000000000..a5188f20c --- /dev/null +++ b/test/features/route-manual-validate/src/api/structures/IBbsArticle.ts @@ -0,0 +1,40 @@ +export interface IBbsArticle { + /** + * @format uuid + */ + id: string; + + /** + * @minLength 3 + * @maxLength 50 + */ + title: string; + + body: string; + + files: IAttachmentFile[]; + + /** + * @format date-time + */ + created_at: string; +} + +export interface IAttachmentFile { + /** + * @minLengt 1 + * @maxLength 255 + */ + name: string | null; + + /** + * @minLength 1 + * @maxLength 8 + */ + extension: string | null; + + /** + * @format url + */ + url: string; +} diff --git a/test/features/route-manual-validate/src/api/structures/IPerformance.ts b/test/features/route-manual-validate/src/api/structures/IPerformance.ts new file mode 100644 index 000000000..a9e9336e1 --- /dev/null +++ b/test/features/route-manual-validate/src/api/structures/IPerformance.ts @@ -0,0 +1,10 @@ +/** + * Performance info. + * + * @author Samchon + */ +export interface IPerformance { + cpu: NodeJS.CpuUsage; + memory: NodeJS.MemoryUsage; + resource: NodeJS.ResourceUsage; +} diff --git a/test/features/route-manual-validate/src/api/structures/ISystem.ts b/test/features/route-manual-validate/src/api/structures/ISystem.ts new file mode 100644 index 000000000..68f05ca92 --- /dev/null +++ b/test/features/route-manual-validate/src/api/structures/ISystem.ts @@ -0,0 +1,81 @@ +/** + * System Information. + * + * @author Jeongho Nam + */ +export interface ISystem { + /** + * Random Unique ID. + */ + uid: number; + + /** + * `process.argv` + */ + arguments: string[]; + + /** + * Git commit info. + */ + commit: ISystem.ICommit; + + /** + * `package.json` + */ + package: ISystem.IPackage; + + /** + * Creation time of this server. + */ + created_at: string; +} + +export namespace ISystem { + /** + * Git commit info. + */ + export interface ICommit { + shortHash: string; + branch: string; + hash: string; + subject: string; + sanitizedSubject: string; + body: string; + author: ICommit.IUser; + committer: ICommit.IUser; + authored_at: string; + commited_at: string; + notes?: string; + tags: string[]; + } + export namespace ICommit { + /** + * Git user account info. + */ + export interface IUser { + name: string; + email: string; + } + } + + /** + * NPM package info. + */ + export interface IPackage { + name: string; + version: string; + description: string; + main?: string; + typings?: string; + scripts: Record; + repository: { type: "git"; url: string }; + author: string; + license: string; + bugs: { url: string }; + homepage: string; + devDependencies?: Record; + dependencies: Record; + publishConfig?: { registry: string }; + files?: string[]; + } +} diff --git a/test/features/route-manual-validate/src/controllers/HealthController.ts b/test/features/route-manual-validate/src/controllers/HealthController.ts new file mode 100644 index 000000000..a9ce3563b --- /dev/null +++ b/test/features/route-manual-validate/src/controllers/HealthController.ts @@ -0,0 +1,9 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +@Controller("health") +export class HealthController { + @core.TypedRoute.Get() + public get(): void {} +} diff --git a/test/features/route-manual-validate/src/controllers/PerformanceController.ts b/test/features/route-manual-validate/src/controllers/PerformanceController.ts new file mode 100644 index 000000000..798d64fae --- /dev/null +++ b/test/features/route-manual-validate/src/controllers/PerformanceController.ts @@ -0,0 +1,17 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +import { IPerformance } from "@api/lib/structures/IPerformance"; + +@Controller("performance") +export class PerformanceController { + @core.TypedRoute.Get() + public async get(): Promise { + return { + cpu: process.cpuUsage(), + memory: process.memoryUsage(), + resource: process.resourceUsage(), + }; + } +} diff --git a/test/features/route-manual-validate/src/controllers/TypedRouteController.ts b/test/features/route-manual-validate/src/controllers/TypedRouteController.ts new file mode 100644 index 000000000..1c6583944 --- /dev/null +++ b/test/features/route-manual-validate/src/controllers/TypedRouteController.ts @@ -0,0 +1,22 @@ +import { Controller } from "@nestjs/common"; +import typia from "typia"; + +import core from "@nestia/core"; + +import { IBbsArticle } from "@api/lib/structures/IBbsArticle"; + +@Controller("route") +export class ManualRouteController { + @core.TypedRoute.Get("random", { + type: "validate", + validate: typia.createValidateStringify(), + }) + public async random(): Promise { + return { + ...typia.random(), + ...{ + dummy: 1, + }, + }; + } +} diff --git a/test/features/route-manual-validate/src/test/features/test_api_health_check.ts b/test/features/route-manual-validate/src/test/features/test_api_health_check.ts new file mode 100644 index 000000000..c34703c71 --- /dev/null +++ b/test/features/route-manual-validate/src/test/features/test_api_health_check.ts @@ -0,0 +1,5 @@ +import api from "@api"; + +export const test_api_monitor_health_check = ( + connection: api.IConnection, +): Promise => api.functional.health.get(connection); diff --git a/test/features/route-manual-validate/src/test/features/test_api_performance.ts b/test/features/route-manual-validate/src/test/features/test_api_performance.ts new file mode 100644 index 000000000..55b6d2ca7 --- /dev/null +++ b/test/features/route-manual-validate/src/test/features/test_api_performance.ts @@ -0,0 +1,13 @@ +import typia from "typia"; + +import api from "@api"; +import { IPerformance } from "@api/lib/structures/IPerformance"; + +export const test_api_monitor_performance = async ( + connection: api.IConnection, +): Promise => { + const performance: IPerformance = await api.functional.performance.get( + connection, + ); + typia.assert(performance); +}; diff --git a/test/features/route-manual-validate/src/test/features/test_api_route.ts b/test/features/route-manual-validate/src/test/features/test_api_route.ts new file mode 100644 index 000000000..94451eee7 --- /dev/null +++ b/test/features/route-manual-validate/src/test/features/test_api_route.ts @@ -0,0 +1,11 @@ +import typia from "typia"; + +import api from "@api"; +import { IBbsArticle } from "@api/lib/structures/IBbsArticle"; + +export const test_api_route = async ( + connection: api.IConnection, +): Promise => { + const article: IBbsArticle = await api.functional.route.random(connection); + typia.assertEquals(article); +}; diff --git a/test/features/route-manual-validate/src/test/index.ts b/test/features/route-manual-validate/src/test/index.ts new file mode 100644 index 000000000..e89842739 --- /dev/null +++ b/test/features/route-manual-validate/src/test/index.ts @@ -0,0 +1,39 @@ +import { DynamicExecutor } from "@nestia/e2e"; + +import { Backend } from "../Backend"; + +async function main(): Promise { + const server: Backend = new Backend(); + await server.open(); + + const report: DynamicExecutor.IReport = await DynamicExecutor.validate({ + prefix: "test", + parameters: () => [ + { + host: "http://127.0.0.1:37000", + encryption: { + key: "A".repeat(32), + iv: "B".repeat(16), + }, + }, + ], + })(`${__dirname}/features`); + await server.close(); + + const exceptions: Error[] = report.executions + .filter((exec) => exec.error !== null) + .map((exec) => exec.error!); + if (exceptions.length === 0) { + console.log("Success"); + console.log("Elapsed time", report.time.toLocaleString(), `ms`); + } else { + // for (const exp of exceptions) console.log(exp); + console.log("Failed"); + console.log("Elapsed time", report.time.toLocaleString(), `ms`); + process.exit(-1); + } +} +main().catch((exp) => { + console.log(exp); + process.exit(-1); +}); diff --git a/test/features/route-manual-validate/swagger.json b/test/features/route-manual-validate/swagger.json new file mode 100644 index 000000000..fe7bc27dd --- /dev/null +++ b/test/features/route-manual-validate/swagger.json @@ -0,0 +1,540 @@ +{ + "openapi": "3.0.1", + "servers": [ + { + "url": "https://github.com/samchon/nestia", + "description": "insert your server url" + } + ], + "info": { + "version": "0.1.0", + "title": "Generated by nestia - https://github.com/samchon/nestia" + }, + "paths": { + "/health": { + "get": { + "tags": [], + "parameters": [], + "responses": { + "200": { + "description": "", + "x-nestia-encrypted": false + } + }, + "description": "", + "x-nestia-namespace": "health.get", + "x-nestia-jsDocTags": [] + } + }, + "/performance": { + "get": { + "tags": [], + "parameters": [], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IPerformance" + } + } + }, + "x-nestia-encrypted": false + } + }, + "description": "", + "x-nestia-namespace": "performance.get", + "x-nestia-jsDocTags": [] + } + }, + "/route/random": { + "get": { + "tags": [], + "parameters": [], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IBbsArticle" + } + } + }, + "x-nestia-encrypted": false + } + }, + "description": "", + "x-nestia-namespace": "route.random.random", + "x-nestia-jsDocTags": [] + } + } + }, + "components": { + "schemas": { + "IPerformance": { + "type": "object", + "properties": { + "cpu": { + "$ref": "#/components/schemas/_singlequote_process_singlequote_.global.NodeJS.CpuUsage", + "x-typia-required": true, + "x-typia-optional": false + }, + "memory": { + "$ref": "#/components/schemas/_singlequote_process_singlequote_.global.NodeJS.MemoryUsage", + "x-typia-required": true, + "x-typia-optional": false + }, + "resource": { + "$ref": "#/components/schemas/_singlequote_process_singlequote_.global.NodeJS.ResourceUsage", + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "cpu", + "memory", + "resource" + ], + "description": "Performance info.", + "x-typia-jsDocTags": [ + { + "name": "author", + "text": [ + { + "text": "Samchon", + "kind": "text" + } + ] + } + ] + }, + "_singlequote_process_singlequote_.global.NodeJS.CpuUsage": { + "type": "object", + "properties": { + "user": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "system": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "user", + "system" + ], + "x-typia-jsDocTags": [] + }, + "_singlequote_process_singlequote_.global.NodeJS.MemoryUsage": { + "type": "object", + "properties": { + "rss": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "heapTotal": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "heapUsed": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "external": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "arrayBuffers": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "rss", + "heapTotal", + "heapUsed", + "external", + "arrayBuffers" + ], + "x-typia-jsDocTags": [] + }, + "_singlequote_process_singlequote_.global.NodeJS.ResourceUsage": { + "type": "object", + "properties": { + "fsRead": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "fsWrite": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "involuntaryContextSwitches": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "ipcReceived": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "ipcSent": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "majorPageFault": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "maxRSS": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "minorPageFault": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "sharedMemorySize": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "signalsCount": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "swappedOut": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "systemCPUTime": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "unsharedDataSize": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "unsharedStackSize": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "userCPUTime": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "voluntaryContextSwitches": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "fsRead", + "fsWrite", + "involuntaryContextSwitches", + "ipcReceived", + "ipcSent", + "majorPageFault", + "maxRSS", + "minorPageFault", + "sharedMemorySize", + "signalsCount", + "swappedOut", + "systemCPUTime", + "unsharedDataSize", + "unsharedStackSize", + "userCPUTime", + "voluntaryContextSwitches" + ], + "x-typia-jsDocTags": [] + }, + "IBbsArticle": { + "type": "object", + "properties": { + "id": { + "type": "string", + "nullable": false, + "x-typia-metaTags": [ + { + "kind": "format", + "value": "uuid" + } + ], + "x-typia-jsDocTags": [ + { + "name": "format", + "text": [ + { + "text": "uuid", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "format": "uuid" + }, + "title": { + "type": "string", + "nullable": false, + "x-typia-metaTags": [ + { + "kind": "minLength", + "value": 3 + }, + { + "kind": "maxLength", + "value": 50 + } + ], + "x-typia-jsDocTags": [ + { + "name": "minLength", + "text": [ + { + "text": "3", + "kind": "text" + } + ] + }, + { + "name": "maxLength", + "text": [ + { + "text": "50", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "minLength": 3, + "maxLength": 50 + }, + "body": { + "type": "string", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "files": { + "type": "array", + "items": { + "$ref": "#/components/schemas/IAttachmentFile", + "x-typia-required": true, + "x-typia-optional": false + }, + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "created_at": { + "type": "string", + "nullable": false, + "x-typia-metaTags": [ + { + "kind": "format", + "value": "datetime" + } + ], + "x-typia-jsDocTags": [ + { + "name": "format", + "text": [ + { + "text": "date-time", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "format": "date-time" + } + }, + "nullable": false, + "required": [ + "id", + "title", + "body", + "files", + "created_at" + ], + "x-typia-jsDocTags": [] + }, + "IAttachmentFile": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "x-typia-metaTags": [ + { + "kind": "maxLength", + "value": 255 + } + ], + "x-typia-jsDocTags": [ + { + "name": "minLengt", + "text": [ + { + "text": "1", + "kind": "text" + } + ] + }, + { + "name": "maxLength", + "text": [ + { + "text": "255", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "maxLength": 255 + }, + "extension": { + "type": "string", + "nullable": true, + "x-typia-metaTags": [ + { + "kind": "minLength", + "value": 1 + }, + { + "kind": "maxLength", + "value": 8 + } + ], + "x-typia-jsDocTags": [ + { + "name": "minLength", + "text": [ + { + "text": "1", + "kind": "text" + } + ] + }, + { + "name": "maxLength", + "text": [ + { + "text": "8", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "minLength": 1, + "maxLength": 8 + }, + "url": { + "type": "string", + "nullable": false, + "x-typia-metaTags": [ + { + "kind": "format", + "value": "url" + } + ], + "x-typia-jsDocTags": [ + { + "name": "format", + "text": [ + { + "text": "url", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "format": "url" + } + }, + "nullable": false, + "required": [ + "name", + "extension", + "url" + ], + "x-typia-jsDocTags": [] + } + }, + "securitySchemes": { + "bearer": { + "type": "apiKey", + "in": "header", + "name": "Authorization" + } + } + }, + "security": [ + { + "bearer": [] + } + ] +} \ No newline at end of file diff --git a/test/features/route-manual-validate/tsconfig.json b/test/features/route-manual-validate/tsconfig.json new file mode 100644 index 000000000..e5fe47a95 --- /dev/null +++ b/test/features/route-manual-validate/tsconfig.json @@ -0,0 +1,103 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + /* Language and Environment */ + "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + /* Modules */ + "module": "commonjs", /* Specify what module code is generated. */// "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + "paths": { + "@nestia/core": ["../../../packages/core/src"], + "@nestia/e2e": ["../../../packages/e2e/src"], + "@nestia/fetcher": ["../../../packages/fetcher/src"], + "@nestia/sdk": ["../../../packages/sdk/src"], + "@nestia/sdk/lib/*": ["../../../packages/sdk/src/*"], + "@api": ["./src/api"], + "@api/lib/*": ["./src/api/*"], + }, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. *//* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true, /* Skip type checking all .d.ts files. */ + "plugins": [ + { "transform": "typescript-transform-paths" }, + { "transform": "typia/lib/transform" }, + { "transform": "../../../packages/core/src/transform.ts" }, + ], + } + } \ No newline at end of file diff --git a/test/features/route/nestia.config.ts b/test/features/route/nestia.config.ts new file mode 100644 index 000000000..2594a40d0 --- /dev/null +++ b/test/features/route/nestia.config.ts @@ -0,0 +1,15 @@ +import { INestiaConfig } from "@nestia/sdk"; + +export const NESTIA_CONFIG: INestiaConfig = { + input: ["src/controllers"], + output: "src/api", + swagger: { + output: "swagger.json", + security: { + bearer: { + type: "apiKey", + }, + }, + }, +}; +export default NESTIA_CONFIG; diff --git a/test/features/route/src/Backend.ts b/test/features/route/src/Backend.ts new file mode 100644 index 000000000..8ab51b70f --- /dev/null +++ b/test/features/route/src/Backend.ts @@ -0,0 +1,28 @@ +import { INestApplication } from "@nestjs/common"; +import { NestFactory } from "@nestjs/core"; + +import core from "@nestia/core"; + +export class Backend { + private application_?: INestApplication; + + public async open(): Promise { + this.application_ = await NestFactory.create( + await core.EncryptedModule.dynamic(__dirname + "/controllers", { + key: "A".repeat(32), + iv: "B".repeat(16), + }), + { logger: false }, + ); + await this.application_.listen(37_000); + } + + public async close(): Promise { + if (this.application_ === undefined) return; + + const app = this.application_; + await app.close(); + + delete this.application_; + } +} diff --git a/test/features/route/src/api/HttpError.ts b/test/features/route/src/api/HttpError.ts new file mode 100644 index 000000000..5df328ae4 --- /dev/null +++ b/test/features/route/src/api/HttpError.ts @@ -0,0 +1 @@ +export { HttpError } from "@nestia/fetcher"; diff --git a/test/features/route/src/api/IConnection.ts b/test/features/route/src/api/IConnection.ts new file mode 100644 index 000000000..92727cfc2 --- /dev/null +++ b/test/features/route/src/api/IConnection.ts @@ -0,0 +1 @@ +export { IConnection } from "@nestia/fetcher"; diff --git a/test/features/route/src/api/Primitive.ts b/test/features/route/src/api/Primitive.ts new file mode 100644 index 000000000..3c1db5a74 --- /dev/null +++ b/test/features/route/src/api/Primitive.ts @@ -0,0 +1 @@ +export { Primitive } from "@nestia/fetcher"; diff --git a/test/features/route/src/api/functional/health/index.ts b/test/features/route/src/api/functional/health/index.ts new file mode 100644 index 000000000..619581f93 --- /dev/null +++ b/test/features/route/src/api/functional/health/index.ts @@ -0,0 +1,42 @@ +/** + * @packageDocumentation + * @module api.functional.health + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +import { Fetcher } from "@nestia/fetcher"; +import type { IConnection } from "@nestia/fetcher"; + +/** + * @controller HealthController.get() + * @path GET /health + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export function get + ( + connection: IConnection + ): Promise +{ + return Fetcher.fetch + ( + connection, + get.ENCRYPTED, + get.METHOD, + get.path() + ); +} +export namespace get +{ + + export const METHOD = "GET" as const; + export const PATH: string = "/health"; + export const ENCRYPTED: Fetcher.IEncrypted = { + request: false, + response: false, + }; + + export function path(): string + { + return `/health`; + } +} \ No newline at end of file diff --git a/test/features/route/src/api/functional/index.ts b/test/features/route/src/api/functional/index.ts new file mode 100644 index 000000000..43933202c --- /dev/null +++ b/test/features/route/src/api/functional/index.ts @@ -0,0 +1,9 @@ +/** + * @packageDocumentation + * @module api.functional + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +export * as health from "./health"; +export * as performance from "./performance"; +export * as route from "./route"; \ No newline at end of file diff --git a/test/features/route/src/api/functional/performance/index.ts b/test/features/route/src/api/functional/performance/index.ts new file mode 100644 index 000000000..9e402a44a --- /dev/null +++ b/test/features/route/src/api/functional/performance/index.ts @@ -0,0 +1,45 @@ +/** + * @packageDocumentation + * @module api.functional.performance + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +import { Fetcher, Primitive } from "@nestia/fetcher"; +import type { IConnection } from "@nestia/fetcher"; + +import type { IPerformance } from "./../../structures/IPerformance"; + +/** + * @controller PerformanceController.get() + * @path GET /performance + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export function get + ( + connection: IConnection + ): Promise +{ + return Fetcher.fetch + ( + connection, + get.ENCRYPTED, + get.METHOD, + get.path() + ); +} +export namespace get +{ + export type Output = Primitive; + + export const METHOD = "GET" as const; + export const PATH: string = "/performance"; + export const ENCRYPTED: Fetcher.IEncrypted = { + request: false, + response: false, + }; + + export function path(): string + { + return `/performance`; + } +} \ No newline at end of file diff --git a/test/features/route/src/api/functional/route/index.ts b/test/features/route/src/api/functional/route/index.ts new file mode 100644 index 000000000..db5470fe9 --- /dev/null +++ b/test/features/route/src/api/functional/route/index.ts @@ -0,0 +1,45 @@ +/** + * @packageDocumentation + * @module api.functional.route + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +import { Fetcher, Primitive } from "@nestia/fetcher"; +import type { IConnection } from "@nestia/fetcher"; + +import type { IBbsArticle } from "./../../structures/IBbsArticle"; + +/** + * @controller TypedRouteController.random() + * @path GET /route/random + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export function random + ( + connection: IConnection + ): Promise +{ + return Fetcher.fetch + ( + connection, + random.ENCRYPTED, + random.METHOD, + random.path() + ); +} +export namespace random +{ + export type Output = Primitive; + + export const METHOD = "GET" as const; + export const PATH: string = "/route/random"; + export const ENCRYPTED: Fetcher.IEncrypted = { + request: false, + response: false, + }; + + export function path(): string + { + return `/route/random`; + } +} \ No newline at end of file diff --git a/test/features/route/src/api/index.ts b/test/features/route/src/api/index.ts new file mode 100644 index 000000000..1896c4fbd --- /dev/null +++ b/test/features/route/src/api/index.ts @@ -0,0 +1,5 @@ +import * as api from "./module"; + +export * from "./module"; + +export default api; diff --git a/test/features/route/src/api/module.ts b/test/features/route/src/api/module.ts new file mode 100644 index 000000000..00239fb3b --- /dev/null +++ b/test/features/route/src/api/module.ts @@ -0,0 +1,5 @@ +export * from "./IConnection"; +export * from "./Primitive"; +export * from "./HttpError"; + +export * as functional from "./functional"; diff --git a/test/features/route/src/api/structures/IBbsArticle.ts b/test/features/route/src/api/structures/IBbsArticle.ts new file mode 100644 index 000000000..a5188f20c --- /dev/null +++ b/test/features/route/src/api/structures/IBbsArticle.ts @@ -0,0 +1,40 @@ +export interface IBbsArticle { + /** + * @format uuid + */ + id: string; + + /** + * @minLength 3 + * @maxLength 50 + */ + title: string; + + body: string; + + files: IAttachmentFile[]; + + /** + * @format date-time + */ + created_at: string; +} + +export interface IAttachmentFile { + /** + * @minLengt 1 + * @maxLength 255 + */ + name: string | null; + + /** + * @minLength 1 + * @maxLength 8 + */ + extension: string | null; + + /** + * @format url + */ + url: string; +} diff --git a/test/features/route/src/api/structures/IPerformance.ts b/test/features/route/src/api/structures/IPerformance.ts new file mode 100644 index 000000000..a9e9336e1 --- /dev/null +++ b/test/features/route/src/api/structures/IPerformance.ts @@ -0,0 +1,10 @@ +/** + * Performance info. + * + * @author Samchon + */ +export interface IPerformance { + cpu: NodeJS.CpuUsage; + memory: NodeJS.MemoryUsage; + resource: NodeJS.ResourceUsage; +} diff --git a/test/features/route/src/api/structures/ISystem.ts b/test/features/route/src/api/structures/ISystem.ts new file mode 100644 index 000000000..68f05ca92 --- /dev/null +++ b/test/features/route/src/api/structures/ISystem.ts @@ -0,0 +1,81 @@ +/** + * System Information. + * + * @author Jeongho Nam + */ +export interface ISystem { + /** + * Random Unique ID. + */ + uid: number; + + /** + * `process.argv` + */ + arguments: string[]; + + /** + * Git commit info. + */ + commit: ISystem.ICommit; + + /** + * `package.json` + */ + package: ISystem.IPackage; + + /** + * Creation time of this server. + */ + created_at: string; +} + +export namespace ISystem { + /** + * Git commit info. + */ + export interface ICommit { + shortHash: string; + branch: string; + hash: string; + subject: string; + sanitizedSubject: string; + body: string; + author: ICommit.IUser; + committer: ICommit.IUser; + authored_at: string; + commited_at: string; + notes?: string; + tags: string[]; + } + export namespace ICommit { + /** + * Git user account info. + */ + export interface IUser { + name: string; + email: string; + } + } + + /** + * NPM package info. + */ + export interface IPackage { + name: string; + version: string; + description: string; + main?: string; + typings?: string; + scripts: Record; + repository: { type: "git"; url: string }; + author: string; + license: string; + bugs: { url: string }; + homepage: string; + devDependencies?: Record; + dependencies: Record; + publishConfig?: { registry: string }; + files?: string[]; + } +} diff --git a/test/features/route/src/controllers/HealthController.ts b/test/features/route/src/controllers/HealthController.ts new file mode 100644 index 000000000..a9ce3563b --- /dev/null +++ b/test/features/route/src/controllers/HealthController.ts @@ -0,0 +1,9 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +@Controller("health") +export class HealthController { + @core.TypedRoute.Get() + public get(): void {} +} diff --git a/test/features/route/src/controllers/PerformanceController.ts b/test/features/route/src/controllers/PerformanceController.ts new file mode 100644 index 000000000..798d64fae --- /dev/null +++ b/test/features/route/src/controllers/PerformanceController.ts @@ -0,0 +1,17 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +import { IPerformance } from "@api/lib/structures/IPerformance"; + +@Controller("performance") +export class PerformanceController { + @core.TypedRoute.Get() + public async get(): Promise { + return { + cpu: process.cpuUsage(), + memory: process.memoryUsage(), + resource: process.resourceUsage(), + }; + } +} diff --git a/test/features/route/src/controllers/TypedRouteController.ts b/test/features/route/src/controllers/TypedRouteController.ts new file mode 100644 index 000000000..f0d3b4c87 --- /dev/null +++ b/test/features/route/src/controllers/TypedRouteController.ts @@ -0,0 +1,19 @@ +import { Controller } from "@nestjs/common"; +import typia from "typia"; + +import core from "@nestia/core"; + +import { IBbsArticle } from "@api/lib/structures/IBbsArticle"; + +@Controller("route") +export class TypedRouteController { + @core.TypedRoute.Get("random") + public async random(): Promise { + return { + ...typia.random(), + ...{ + dummy: 1, + }, + }; + } +} diff --git a/test/features/route/src/test/features/test_api_health_check.ts b/test/features/route/src/test/features/test_api_health_check.ts new file mode 100644 index 000000000..c34703c71 --- /dev/null +++ b/test/features/route/src/test/features/test_api_health_check.ts @@ -0,0 +1,5 @@ +import api from "@api"; + +export const test_api_monitor_health_check = ( + connection: api.IConnection, +): Promise => api.functional.health.get(connection); diff --git a/test/features/route/src/test/features/test_api_performance.ts b/test/features/route/src/test/features/test_api_performance.ts new file mode 100644 index 000000000..55b6d2ca7 --- /dev/null +++ b/test/features/route/src/test/features/test_api_performance.ts @@ -0,0 +1,13 @@ +import typia from "typia"; + +import api from "@api"; +import { IPerformance } from "@api/lib/structures/IPerformance"; + +export const test_api_monitor_performance = async ( + connection: api.IConnection, +): Promise => { + const performance: IPerformance = await api.functional.performance.get( + connection, + ); + typia.assert(performance); +}; diff --git a/test/features/route/src/test/features/test_api_route.ts b/test/features/route/src/test/features/test_api_route.ts new file mode 100644 index 000000000..94451eee7 --- /dev/null +++ b/test/features/route/src/test/features/test_api_route.ts @@ -0,0 +1,11 @@ +import typia from "typia"; + +import api from "@api"; +import { IBbsArticle } from "@api/lib/structures/IBbsArticle"; + +export const test_api_route = async ( + connection: api.IConnection, +): Promise => { + const article: IBbsArticle = await api.functional.route.random(connection); + typia.assertEquals(article); +}; diff --git a/test/features/route/src/test/index.ts b/test/features/route/src/test/index.ts new file mode 100644 index 000000000..e89842739 --- /dev/null +++ b/test/features/route/src/test/index.ts @@ -0,0 +1,39 @@ +import { DynamicExecutor } from "@nestia/e2e"; + +import { Backend } from "../Backend"; + +async function main(): Promise { + const server: Backend = new Backend(); + await server.open(); + + const report: DynamicExecutor.IReport = await DynamicExecutor.validate({ + prefix: "test", + parameters: () => [ + { + host: "http://127.0.0.1:37000", + encryption: { + key: "A".repeat(32), + iv: "B".repeat(16), + }, + }, + ], + })(`${__dirname}/features`); + await server.close(); + + const exceptions: Error[] = report.executions + .filter((exec) => exec.error !== null) + .map((exec) => exec.error!); + if (exceptions.length === 0) { + console.log("Success"); + console.log("Elapsed time", report.time.toLocaleString(), `ms`); + } else { + // for (const exp of exceptions) console.log(exp); + console.log("Failed"); + console.log("Elapsed time", report.time.toLocaleString(), `ms`); + process.exit(-1); + } +} +main().catch((exp) => { + console.log(exp); + process.exit(-1); +}); diff --git a/test/features/route/swagger.json b/test/features/route/swagger.json new file mode 100644 index 000000000..fe7bc27dd --- /dev/null +++ b/test/features/route/swagger.json @@ -0,0 +1,540 @@ +{ + "openapi": "3.0.1", + "servers": [ + { + "url": "https://github.com/samchon/nestia", + "description": "insert your server url" + } + ], + "info": { + "version": "0.1.0", + "title": "Generated by nestia - https://github.com/samchon/nestia" + }, + "paths": { + "/health": { + "get": { + "tags": [], + "parameters": [], + "responses": { + "200": { + "description": "", + "x-nestia-encrypted": false + } + }, + "description": "", + "x-nestia-namespace": "health.get", + "x-nestia-jsDocTags": [] + } + }, + "/performance": { + "get": { + "tags": [], + "parameters": [], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IPerformance" + } + } + }, + "x-nestia-encrypted": false + } + }, + "description": "", + "x-nestia-namespace": "performance.get", + "x-nestia-jsDocTags": [] + } + }, + "/route/random": { + "get": { + "tags": [], + "parameters": [], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IBbsArticle" + } + } + }, + "x-nestia-encrypted": false + } + }, + "description": "", + "x-nestia-namespace": "route.random.random", + "x-nestia-jsDocTags": [] + } + } + }, + "components": { + "schemas": { + "IPerformance": { + "type": "object", + "properties": { + "cpu": { + "$ref": "#/components/schemas/_singlequote_process_singlequote_.global.NodeJS.CpuUsage", + "x-typia-required": true, + "x-typia-optional": false + }, + "memory": { + "$ref": "#/components/schemas/_singlequote_process_singlequote_.global.NodeJS.MemoryUsage", + "x-typia-required": true, + "x-typia-optional": false + }, + "resource": { + "$ref": "#/components/schemas/_singlequote_process_singlequote_.global.NodeJS.ResourceUsage", + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "cpu", + "memory", + "resource" + ], + "description": "Performance info.", + "x-typia-jsDocTags": [ + { + "name": "author", + "text": [ + { + "text": "Samchon", + "kind": "text" + } + ] + } + ] + }, + "_singlequote_process_singlequote_.global.NodeJS.CpuUsage": { + "type": "object", + "properties": { + "user": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "system": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "user", + "system" + ], + "x-typia-jsDocTags": [] + }, + "_singlequote_process_singlequote_.global.NodeJS.MemoryUsage": { + "type": "object", + "properties": { + "rss": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "heapTotal": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "heapUsed": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "external": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "arrayBuffers": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "rss", + "heapTotal", + "heapUsed", + "external", + "arrayBuffers" + ], + "x-typia-jsDocTags": [] + }, + "_singlequote_process_singlequote_.global.NodeJS.ResourceUsage": { + "type": "object", + "properties": { + "fsRead": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "fsWrite": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "involuntaryContextSwitches": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "ipcReceived": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "ipcSent": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "majorPageFault": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "maxRSS": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "minorPageFault": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "sharedMemorySize": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "signalsCount": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "swappedOut": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "systemCPUTime": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "unsharedDataSize": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "unsharedStackSize": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "userCPUTime": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "voluntaryContextSwitches": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "fsRead", + "fsWrite", + "involuntaryContextSwitches", + "ipcReceived", + "ipcSent", + "majorPageFault", + "maxRSS", + "minorPageFault", + "sharedMemorySize", + "signalsCount", + "swappedOut", + "systemCPUTime", + "unsharedDataSize", + "unsharedStackSize", + "userCPUTime", + "voluntaryContextSwitches" + ], + "x-typia-jsDocTags": [] + }, + "IBbsArticle": { + "type": "object", + "properties": { + "id": { + "type": "string", + "nullable": false, + "x-typia-metaTags": [ + { + "kind": "format", + "value": "uuid" + } + ], + "x-typia-jsDocTags": [ + { + "name": "format", + "text": [ + { + "text": "uuid", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "format": "uuid" + }, + "title": { + "type": "string", + "nullable": false, + "x-typia-metaTags": [ + { + "kind": "minLength", + "value": 3 + }, + { + "kind": "maxLength", + "value": 50 + } + ], + "x-typia-jsDocTags": [ + { + "name": "minLength", + "text": [ + { + "text": "3", + "kind": "text" + } + ] + }, + { + "name": "maxLength", + "text": [ + { + "text": "50", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "minLength": 3, + "maxLength": 50 + }, + "body": { + "type": "string", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "files": { + "type": "array", + "items": { + "$ref": "#/components/schemas/IAttachmentFile", + "x-typia-required": true, + "x-typia-optional": false + }, + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "created_at": { + "type": "string", + "nullable": false, + "x-typia-metaTags": [ + { + "kind": "format", + "value": "datetime" + } + ], + "x-typia-jsDocTags": [ + { + "name": "format", + "text": [ + { + "text": "date-time", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "format": "date-time" + } + }, + "nullable": false, + "required": [ + "id", + "title", + "body", + "files", + "created_at" + ], + "x-typia-jsDocTags": [] + }, + "IAttachmentFile": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "x-typia-metaTags": [ + { + "kind": "maxLength", + "value": 255 + } + ], + "x-typia-jsDocTags": [ + { + "name": "minLengt", + "text": [ + { + "text": "1", + "kind": "text" + } + ] + }, + { + "name": "maxLength", + "text": [ + { + "text": "255", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "maxLength": 255 + }, + "extension": { + "type": "string", + "nullable": true, + "x-typia-metaTags": [ + { + "kind": "minLength", + "value": 1 + }, + { + "kind": "maxLength", + "value": 8 + } + ], + "x-typia-jsDocTags": [ + { + "name": "minLength", + "text": [ + { + "text": "1", + "kind": "text" + } + ] + }, + { + "name": "maxLength", + "text": [ + { + "text": "8", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "minLength": 1, + "maxLength": 8 + }, + "url": { + "type": "string", + "nullable": false, + "x-typia-metaTags": [ + { + "kind": "format", + "value": "url" + } + ], + "x-typia-jsDocTags": [ + { + "name": "format", + "text": [ + { + "text": "url", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "format": "url" + } + }, + "nullable": false, + "required": [ + "name", + "extension", + "url" + ], + "x-typia-jsDocTags": [] + } + }, + "securitySchemes": { + "bearer": { + "type": "apiKey", + "in": "header", + "name": "Authorization" + } + } + }, + "security": [ + { + "bearer": [] + } + ] +} \ No newline at end of file diff --git a/test/features/route/tsconfig.json b/test/features/route/tsconfig.json new file mode 100644 index 000000000..e5fe47a95 --- /dev/null +++ b/test/features/route/tsconfig.json @@ -0,0 +1,103 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + /* Language and Environment */ + "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + /* Modules */ + "module": "commonjs", /* Specify what module code is generated. */// "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + "paths": { + "@nestia/core": ["../../../packages/core/src"], + "@nestia/e2e": ["../../../packages/e2e/src"], + "@nestia/fetcher": ["../../../packages/fetcher/src"], + "@nestia/sdk": ["../../../packages/sdk/src"], + "@nestia/sdk/lib/*": ["../../../packages/sdk/src/*"], + "@api": ["./src/api"], + "@api/lib/*": ["./src/api/*"], + }, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. *//* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true, /* Skip type checking all .d.ts files. */ + "plugins": [ + { "transform": "typescript-transform-paths" }, + { "transform": "typia/lib/transform" }, + { "transform": "../../../packages/core/src/transform.ts" }, + ], + } + } \ No newline at end of file diff --git a/test/features/status/nestia.config.ts b/test/features/status/nestia.config.ts new file mode 100644 index 000000000..2594a40d0 --- /dev/null +++ b/test/features/status/nestia.config.ts @@ -0,0 +1,15 @@ +import { INestiaConfig } from "@nestia/sdk"; + +export const NESTIA_CONFIG: INestiaConfig = { + input: ["src/controllers"], + output: "src/api", + swagger: { + output: "swagger.json", + security: { + bearer: { + type: "apiKey", + }, + }, + }, +}; +export default NESTIA_CONFIG; diff --git a/test/features/status/src/Backend.ts b/test/features/status/src/Backend.ts new file mode 100644 index 000000000..8ab51b70f --- /dev/null +++ b/test/features/status/src/Backend.ts @@ -0,0 +1,28 @@ +import { INestApplication } from "@nestjs/common"; +import { NestFactory } from "@nestjs/core"; + +import core from "@nestia/core"; + +export class Backend { + private application_?: INestApplication; + + public async open(): Promise { + this.application_ = await NestFactory.create( + await core.EncryptedModule.dynamic(__dirname + "/controllers", { + key: "A".repeat(32), + iv: "B".repeat(16), + }), + { logger: false }, + ); + await this.application_.listen(37_000); + } + + public async close(): Promise { + if (this.application_ === undefined) return; + + const app = this.application_; + await app.close(); + + delete this.application_; + } +} diff --git a/test/features/status/src/api/HttpError.ts b/test/features/status/src/api/HttpError.ts new file mode 100644 index 000000000..5df328ae4 --- /dev/null +++ b/test/features/status/src/api/HttpError.ts @@ -0,0 +1 @@ +export { HttpError } from "@nestia/fetcher"; diff --git a/test/features/status/src/api/IConnection.ts b/test/features/status/src/api/IConnection.ts new file mode 100644 index 000000000..92727cfc2 --- /dev/null +++ b/test/features/status/src/api/IConnection.ts @@ -0,0 +1 @@ +export { IConnection } from "@nestia/fetcher"; diff --git a/test/features/status/src/api/Primitive.ts b/test/features/status/src/api/Primitive.ts new file mode 100644 index 000000000..3c1db5a74 --- /dev/null +++ b/test/features/status/src/api/Primitive.ts @@ -0,0 +1 @@ +export { Primitive } from "@nestia/fetcher"; diff --git a/test/features/status/src/api/functional/health/index.ts b/test/features/status/src/api/functional/health/index.ts new file mode 100644 index 000000000..619581f93 --- /dev/null +++ b/test/features/status/src/api/functional/health/index.ts @@ -0,0 +1,42 @@ +/** + * @packageDocumentation + * @module api.functional.health + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +import { Fetcher } from "@nestia/fetcher"; +import type { IConnection } from "@nestia/fetcher"; + +/** + * @controller HealthController.get() + * @path GET /health + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export function get + ( + connection: IConnection + ): Promise +{ + return Fetcher.fetch + ( + connection, + get.ENCRYPTED, + get.METHOD, + get.path() + ); +} +export namespace get +{ + + export const METHOD = "GET" as const; + export const PATH: string = "/health"; + export const ENCRYPTED: Fetcher.IEncrypted = { + request: false, + response: false, + }; + + export function path(): string + { + return `/health`; + } +} \ No newline at end of file diff --git a/test/features/status/src/api/functional/index.ts b/test/features/status/src/api/functional/index.ts new file mode 100644 index 000000000..84bbbce72 --- /dev/null +++ b/test/features/status/src/api/functional/index.ts @@ -0,0 +1,9 @@ +/** + * @packageDocumentation + * @module api.functional + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +export * as health from "./health"; +export * as performance from "./performance"; +export * as status from "./status"; \ No newline at end of file diff --git a/test/features/status/src/api/functional/performance/index.ts b/test/features/status/src/api/functional/performance/index.ts new file mode 100644 index 000000000..9e402a44a --- /dev/null +++ b/test/features/status/src/api/functional/performance/index.ts @@ -0,0 +1,45 @@ +/** + * @packageDocumentation + * @module api.functional.performance + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +import { Fetcher, Primitive } from "@nestia/fetcher"; +import type { IConnection } from "@nestia/fetcher"; + +import type { IPerformance } from "./../../structures/IPerformance"; + +/** + * @controller PerformanceController.get() + * @path GET /performance + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export function get + ( + connection: IConnection + ): Promise +{ + return Fetcher.fetch + ( + connection, + get.ENCRYPTED, + get.METHOD, + get.path() + ); +} +export namespace get +{ + export type Output = Primitive; + + export const METHOD = "GET" as const; + export const PATH: string = "/performance"; + export const ENCRYPTED: Fetcher.IEncrypted = { + request: false, + response: false, + }; + + export function path(): string + { + return `/performance`; + } +} \ No newline at end of file diff --git a/packages/sdk/demo/status/src/api/functional/index.ts b/test/features/status/src/api/functional/status/index.ts similarity index 55% rename from packages/sdk/demo/status/src/api/functional/index.ts rename to test/features/status/src/api/functional/status/index.ts index 30c30329a..a4d6edca7 100644 --- a/packages/sdk/demo/status/src/api/functional/index.ts +++ b/test/features/status/src/api/functional/status/index.ts @@ -1,36 +1,38 @@ /** * @packageDocumentation - * @module api.functional + * @module api.functional.status * @nestia Generated by Nestia - https://github.com/samchon/nestia */ //================================================================ -import { Fetcher } from "@nestia/fetcher"; +import { Fetcher, Primitive } from "@nestia/fetcher"; import type { IConnection } from "@nestia/fetcher"; +import type { IBbsArticle } from "./../../structures/IBbsArticle"; + /** - * @controller StatusController.status() - * @path GET /status + * @controller StatusController.random() + * @path GET /status/random * @nestia Generated by Nestia - https://github.com/samchon/nestia */ -export function status +export function random ( connection: IConnection - ): Promise + ): Promise { return Fetcher.fetch ( connection, - status.ENCRYPTED, - status.METHOD, - status.path() + random.ENCRYPTED, + random.METHOD, + random.path() ); } -export namespace status +export namespace random { - export type Output = number; + export type Output = Primitive; export const METHOD = "GET" as const; - export const PATH: string = "/status"; + export const PATH: string = "/status/random"; export const ENCRYPTED: Fetcher.IEncrypted = { request: false, response: false, @@ -39,6 +41,6 @@ export namespace status export function path(): string { - return `/status`; + return `/status/random`; } } \ No newline at end of file diff --git a/test/features/status/src/api/index.ts b/test/features/status/src/api/index.ts new file mode 100644 index 000000000..1896c4fbd --- /dev/null +++ b/test/features/status/src/api/index.ts @@ -0,0 +1,5 @@ +import * as api from "./module"; + +export * from "./module"; + +export default api; diff --git a/test/features/status/src/api/module.ts b/test/features/status/src/api/module.ts new file mode 100644 index 000000000..00239fb3b --- /dev/null +++ b/test/features/status/src/api/module.ts @@ -0,0 +1,5 @@ +export * from "./IConnection"; +export * from "./Primitive"; +export * from "./HttpError"; + +export * as functional from "./functional"; diff --git a/test/features/status/src/api/structures/IBbsArticle.ts b/test/features/status/src/api/structures/IBbsArticle.ts new file mode 100644 index 000000000..a5188f20c --- /dev/null +++ b/test/features/status/src/api/structures/IBbsArticle.ts @@ -0,0 +1,40 @@ +export interface IBbsArticle { + /** + * @format uuid + */ + id: string; + + /** + * @minLength 3 + * @maxLength 50 + */ + title: string; + + body: string; + + files: IAttachmentFile[]; + + /** + * @format date-time + */ + created_at: string; +} + +export interface IAttachmentFile { + /** + * @minLengt 1 + * @maxLength 255 + */ + name: string | null; + + /** + * @minLength 1 + * @maxLength 8 + */ + extension: string | null; + + /** + * @format url + */ + url: string; +} diff --git a/test/features/status/src/api/structures/IPerformance.ts b/test/features/status/src/api/structures/IPerformance.ts new file mode 100644 index 000000000..a9e9336e1 --- /dev/null +++ b/test/features/status/src/api/structures/IPerformance.ts @@ -0,0 +1,10 @@ +/** + * Performance info. + * + * @author Samchon + */ +export interface IPerformance { + cpu: NodeJS.CpuUsage; + memory: NodeJS.MemoryUsage; + resource: NodeJS.ResourceUsage; +} diff --git a/test/features/status/src/api/structures/ISystem.ts b/test/features/status/src/api/structures/ISystem.ts new file mode 100644 index 000000000..68f05ca92 --- /dev/null +++ b/test/features/status/src/api/structures/ISystem.ts @@ -0,0 +1,81 @@ +/** + * System Information. + * + * @author Jeongho Nam + */ +export interface ISystem { + /** + * Random Unique ID. + */ + uid: number; + + /** + * `process.argv` + */ + arguments: string[]; + + /** + * Git commit info. + */ + commit: ISystem.ICommit; + + /** + * `package.json` + */ + package: ISystem.IPackage; + + /** + * Creation time of this server. + */ + created_at: string; +} + +export namespace ISystem { + /** + * Git commit info. + */ + export interface ICommit { + shortHash: string; + branch: string; + hash: string; + subject: string; + sanitizedSubject: string; + body: string; + author: ICommit.IUser; + committer: ICommit.IUser; + authored_at: string; + commited_at: string; + notes?: string; + tags: string[]; + } + export namespace ICommit { + /** + * Git user account info. + */ + export interface IUser { + name: string; + email: string; + } + } + + /** + * NPM package info. + */ + export interface IPackage { + name: string; + version: string; + description: string; + main?: string; + typings?: string; + scripts: Record; + repository: { type: "git"; url: string }; + author: string; + license: string; + bugs: { url: string }; + homepage: string; + devDependencies?: Record; + dependencies: Record; + publishConfig?: { registry: string }; + files?: string[]; + } +} diff --git a/test/features/status/src/controllers/HealthController.ts b/test/features/status/src/controllers/HealthController.ts new file mode 100644 index 000000000..a9ce3563b --- /dev/null +++ b/test/features/status/src/controllers/HealthController.ts @@ -0,0 +1,9 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +@Controller("health") +export class HealthController { + @core.TypedRoute.Get() + public get(): void {} +} diff --git a/test/features/status/src/controllers/PerformanceController.ts b/test/features/status/src/controllers/PerformanceController.ts new file mode 100644 index 000000000..798d64fae --- /dev/null +++ b/test/features/status/src/controllers/PerformanceController.ts @@ -0,0 +1,17 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +import { IPerformance } from "@api/lib/structures/IPerformance"; + +@Controller("performance") +export class PerformanceController { + @core.TypedRoute.Get() + public async get(): Promise { + return { + cpu: process.cpuUsage(), + memory: process.memoryUsage(), + resource: process.resourceUsage(), + }; + } +} diff --git a/test/features/status/src/controllers/StatusController.ts b/test/features/status/src/controllers/StatusController.ts new file mode 100644 index 000000000..751b89d07 --- /dev/null +++ b/test/features/status/src/controllers/StatusController.ts @@ -0,0 +1,15 @@ +import { Controller, HttpCode } from "@nestjs/common"; +import typia from "typia"; + +import core from "@nestia/core"; + +import { IBbsArticle } from "@api/lib/structures/IBbsArticle"; + +@Controller("status") +export class StatusController { + @HttpCode(300) + @core.TypedRoute.Get("random") + public async random(): Promise { + return typia.random(); + } +} diff --git a/test/features/status/src/test/features/test_api_health_check.ts b/test/features/status/src/test/features/test_api_health_check.ts new file mode 100644 index 000000000..c34703c71 --- /dev/null +++ b/test/features/status/src/test/features/test_api_health_check.ts @@ -0,0 +1,5 @@ +import api from "@api"; + +export const test_api_monitor_health_check = ( + connection: api.IConnection, +): Promise => api.functional.health.get(connection); diff --git a/test/features/status/src/test/features/test_api_performance.ts b/test/features/status/src/test/features/test_api_performance.ts new file mode 100644 index 000000000..55b6d2ca7 --- /dev/null +++ b/test/features/status/src/test/features/test_api_performance.ts @@ -0,0 +1,13 @@ +import typia from "typia"; + +import api from "@api"; +import { IPerformance } from "@api/lib/structures/IPerformance"; + +export const test_api_monitor_performance = async ( + connection: api.IConnection, +): Promise => { + const performance: IPerformance = await api.functional.performance.get( + connection, + ); + typia.assert(performance); +}; diff --git a/test/features/status/src/test/features/test_api_status.ts b/test/features/status/src/test/features/test_api_status.ts new file mode 100644 index 000000000..bc57d0900 --- /dev/null +++ b/test/features/status/src/test/features/test_api_status.ts @@ -0,0 +1,17 @@ +import typia from "typia"; + +import api from "@api"; +import { IBbsArticle } from "@api/lib/structures/IBbsArticle"; + +import { TestValidator } from "../../../../../../packages/e2e/src/TestValidator"; + +export const test_api_status = async ( + connection: api.IConnection, +): Promise => { + TestValidator.equals("status")(300)( + api.functional.status.random.ENCRYPTED.status!, + ); + + const article: IBbsArticle = await api.functional.status.random(connection); + typia.assertEquals(article); +}; diff --git a/test/features/status/src/test/index.ts b/test/features/status/src/test/index.ts new file mode 100644 index 000000000..e89842739 --- /dev/null +++ b/test/features/status/src/test/index.ts @@ -0,0 +1,39 @@ +import { DynamicExecutor } from "@nestia/e2e"; + +import { Backend } from "../Backend"; + +async function main(): Promise { + const server: Backend = new Backend(); + await server.open(); + + const report: DynamicExecutor.IReport = await DynamicExecutor.validate({ + prefix: "test", + parameters: () => [ + { + host: "http://127.0.0.1:37000", + encryption: { + key: "A".repeat(32), + iv: "B".repeat(16), + }, + }, + ], + })(`${__dirname}/features`); + await server.close(); + + const exceptions: Error[] = report.executions + .filter((exec) => exec.error !== null) + .map((exec) => exec.error!); + if (exceptions.length === 0) { + console.log("Success"); + console.log("Elapsed time", report.time.toLocaleString(), `ms`); + } else { + // for (const exp of exceptions) console.log(exp); + console.log("Failed"); + console.log("Elapsed time", report.time.toLocaleString(), `ms`); + process.exit(-1); + } +} +main().catch((exp) => { + console.log(exp); + process.exit(-1); +}); diff --git a/test/features/status/swagger.json b/test/features/status/swagger.json new file mode 100644 index 000000000..51888663d --- /dev/null +++ b/test/features/status/swagger.json @@ -0,0 +1,540 @@ +{ + "openapi": "3.0.1", + "servers": [ + { + "url": "https://github.com/samchon/nestia", + "description": "insert your server url" + } + ], + "info": { + "version": "0.1.0", + "title": "Generated by nestia - https://github.com/samchon/nestia" + }, + "paths": { + "/health": { + "get": { + "tags": [], + "parameters": [], + "responses": { + "200": { + "description": "", + "x-nestia-encrypted": false + } + }, + "description": "", + "x-nestia-namespace": "health.get", + "x-nestia-jsDocTags": [] + } + }, + "/performance": { + "get": { + "tags": [], + "parameters": [], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IPerformance" + } + } + }, + "x-nestia-encrypted": false + } + }, + "description": "", + "x-nestia-namespace": "performance.get", + "x-nestia-jsDocTags": [] + } + }, + "/status/random": { + "get": { + "tags": [], + "parameters": [], + "responses": { + "300": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IBbsArticle" + } + } + }, + "x-nestia-encrypted": false + } + }, + "description": "", + "x-nestia-namespace": "status.random.random", + "x-nestia-jsDocTags": [] + } + } + }, + "components": { + "schemas": { + "IPerformance": { + "type": "object", + "properties": { + "cpu": { + "$ref": "#/components/schemas/_singlequote_process_singlequote_.global.NodeJS.CpuUsage", + "x-typia-required": true, + "x-typia-optional": false + }, + "memory": { + "$ref": "#/components/schemas/_singlequote_process_singlequote_.global.NodeJS.MemoryUsage", + "x-typia-required": true, + "x-typia-optional": false + }, + "resource": { + "$ref": "#/components/schemas/_singlequote_process_singlequote_.global.NodeJS.ResourceUsage", + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "cpu", + "memory", + "resource" + ], + "description": "Performance info.", + "x-typia-jsDocTags": [ + { + "name": "author", + "text": [ + { + "text": "Samchon", + "kind": "text" + } + ] + } + ] + }, + "_singlequote_process_singlequote_.global.NodeJS.CpuUsage": { + "type": "object", + "properties": { + "user": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "system": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "user", + "system" + ], + "x-typia-jsDocTags": [] + }, + "_singlequote_process_singlequote_.global.NodeJS.MemoryUsage": { + "type": "object", + "properties": { + "rss": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "heapTotal": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "heapUsed": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "external": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "arrayBuffers": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "rss", + "heapTotal", + "heapUsed", + "external", + "arrayBuffers" + ], + "x-typia-jsDocTags": [] + }, + "_singlequote_process_singlequote_.global.NodeJS.ResourceUsage": { + "type": "object", + "properties": { + "fsRead": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "fsWrite": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "involuntaryContextSwitches": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "ipcReceived": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "ipcSent": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "majorPageFault": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "maxRSS": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "minorPageFault": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "sharedMemorySize": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "signalsCount": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "swappedOut": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "systemCPUTime": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "unsharedDataSize": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "unsharedStackSize": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "userCPUTime": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "voluntaryContextSwitches": { + "type": "number", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + } + }, + "nullable": false, + "required": [ + "fsRead", + "fsWrite", + "involuntaryContextSwitches", + "ipcReceived", + "ipcSent", + "majorPageFault", + "maxRSS", + "minorPageFault", + "sharedMemorySize", + "signalsCount", + "swappedOut", + "systemCPUTime", + "unsharedDataSize", + "unsharedStackSize", + "userCPUTime", + "voluntaryContextSwitches" + ], + "x-typia-jsDocTags": [] + }, + "IBbsArticle": { + "type": "object", + "properties": { + "id": { + "type": "string", + "nullable": false, + "x-typia-metaTags": [ + { + "kind": "format", + "value": "uuid" + } + ], + "x-typia-jsDocTags": [ + { + "name": "format", + "text": [ + { + "text": "uuid", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "format": "uuid" + }, + "title": { + "type": "string", + "nullable": false, + "x-typia-metaTags": [ + { + "kind": "minLength", + "value": 3 + }, + { + "kind": "maxLength", + "value": 50 + } + ], + "x-typia-jsDocTags": [ + { + "name": "minLength", + "text": [ + { + "text": "3", + "kind": "text" + } + ] + }, + { + "name": "maxLength", + "text": [ + { + "text": "50", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "minLength": 3, + "maxLength": 50 + }, + "body": { + "type": "string", + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "files": { + "type": "array", + "items": { + "$ref": "#/components/schemas/IAttachmentFile", + "x-typia-required": true, + "x-typia-optional": false + }, + "nullable": false, + "x-typia-required": true, + "x-typia-optional": false + }, + "created_at": { + "type": "string", + "nullable": false, + "x-typia-metaTags": [ + { + "kind": "format", + "value": "datetime" + } + ], + "x-typia-jsDocTags": [ + { + "name": "format", + "text": [ + { + "text": "date-time", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "format": "date-time" + } + }, + "nullable": false, + "required": [ + "id", + "title", + "body", + "files", + "created_at" + ], + "x-typia-jsDocTags": [] + }, + "IAttachmentFile": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "x-typia-metaTags": [ + { + "kind": "maxLength", + "value": 255 + } + ], + "x-typia-jsDocTags": [ + { + "name": "minLengt", + "text": [ + { + "text": "1", + "kind": "text" + } + ] + }, + { + "name": "maxLength", + "text": [ + { + "text": "255", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "maxLength": 255 + }, + "extension": { + "type": "string", + "nullable": true, + "x-typia-metaTags": [ + { + "kind": "minLength", + "value": 1 + }, + { + "kind": "maxLength", + "value": 8 + } + ], + "x-typia-jsDocTags": [ + { + "name": "minLength", + "text": [ + { + "text": "1", + "kind": "text" + } + ] + }, + { + "name": "maxLength", + "text": [ + { + "text": "8", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "minLength": 1, + "maxLength": 8 + }, + "url": { + "type": "string", + "nullable": false, + "x-typia-metaTags": [ + { + "kind": "format", + "value": "url" + } + ], + "x-typia-jsDocTags": [ + { + "name": "format", + "text": [ + { + "text": "url", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "format": "url" + } + }, + "nullable": false, + "required": [ + "name", + "extension", + "url" + ], + "x-typia-jsDocTags": [] + } + }, + "securitySchemes": { + "bearer": { + "type": "apiKey", + "in": "header", + "name": "Authorization" + } + } + }, + "security": [ + { + "bearer": [] + } + ] +} \ No newline at end of file diff --git a/test/features/status/tsconfig.json b/test/features/status/tsconfig.json new file mode 100644 index 000000000..e5fe47a95 --- /dev/null +++ b/test/features/status/tsconfig.json @@ -0,0 +1,103 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + /* Language and Environment */ + "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + /* Modules */ + "module": "commonjs", /* Specify what module code is generated. */// "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + "paths": { + "@nestia/core": ["../../../packages/core/src"], + "@nestia/e2e": ["../../../packages/e2e/src"], + "@nestia/fetcher": ["../../../packages/fetcher/src"], + "@nestia/sdk": ["../../../packages/sdk/src"], + "@nestia/sdk/lib/*": ["../../../packages/sdk/src/*"], + "@api": ["./src/api"], + "@api/lib/*": ["./src/api/*"], + }, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. *//* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true, /* Skip type checking all .d.ts files. */ + "plugins": [ + { "transform": "typescript-transform-paths" }, + { "transform": "typia/lib/transform" }, + { "transform": "../../../packages/core/src/transform.ts" }, + ], + } + } \ No newline at end of file diff --git a/test/package.json b/test/package.json new file mode 100644 index 000000000..8515ce1d0 --- /dev/null +++ b/test/package.json @@ -0,0 +1,70 @@ +{ + "private": true, + "name": "@nestia/test", + "version": "0.0.0", + "description": "Test program of Nestia", + "main": "index.js", + "scripts": { + "generate": "node executable/generate", + "setup": "node executable/setup", + "start": "node executable/start", + "prepare": "ts-patch install" + }, + "repository": { + "type": "git", + "url": "https://github.com/samchon/nestia" + }, + "keywords": [ + "nestia", + "test" + ], + "author": "Jeongho Nam", + "license": "MIT", + "bugs": { + "url": "https://github.com/samchon/nestia/issues" + }, + "homepage": "https://nestia.io", + "devDependencies": { + "@nestjs/common": ">= 7.0.1", + "@nestjs/core": ">= 7.0.1", + "@nestjs/platform-express": ">= 7.0.1", + "@trivago/prettier-plugin-sort-imports": "^4.0.0", + "@types/cli": "^0.11.21", + "@types/express": "^4.17.15", + "@types/glob": "^7.2.0", + "@types/inquirer": "^9.0.3", + "@types/node": "^18.11.15", + "@types/reflect-metadata": "^0.1.0", + "@types/uuid": "^9.0.0", + "@typescript-eslint/eslint-plugin": "^5.46.1", + "@typescript-eslint/parser": "^5.46.1", + "chalk": "^4.1.2", + "cli": "^1.0.1", + "commander": "^10.0.0", + "comment-json": "^4.2.3", + "detect-ts-node": "^1.0.5", + "eslint": "^8.29.0", + "eslint-plugin-deprecation": "^1.4.1", + "git-last-commit": "^1.0.1", + "glob": "^7.2.0", + "import2": "^1.0.3", + "inquirer": "^8.2.5", + "node-fetch": "^2.6.7", + "path-to-regexp": "^6.2.1", + "prettier": "^2.8.1", + "raw-body": ">= 2.0.0", + "reflect-metadata": ">= 0.1.12", + "rimraf": "^3.0.2", + "rxjs": ">= 6.0.0", + "tgrid": "^0.8.7", + "ts-node": "^10.9.1", + "ts-patch": "v2.1.0", + "tsconfck": "^2.0.1", + "tsconfig-paths": "^4.1.1", + "tstl": "^2.5.13", + "typescript": "^4.9.5", + "typescript-transform-paths": "^3.4.4", + "typia": "^3.8.1", + "uuid": "^9.0.0" + } +} \ No newline at end of file diff --git a/test/prettier.config.js b/test/prettier.config.js new file mode 100644 index 000000000..aa2c2336c --- /dev/null +++ b/test/prettier.config.js @@ -0,0 +1,16 @@ +module.exports = { + parser: "typescript", + printWidth: 80, + semi: true, + tabWidth: 4, + trailingComma: "all", + importOrder: [ + "", + "@nestia(.*)$", + "@api(.*)$", + "^[./]", + ], + importOrderSeparation: true, + importOrderSortSpecifiers: true, + importOrderParserPlugins: ["decorators-legacy", "typescript"], +}; \ No newline at end of file diff --git a/test/template/error/nestia.config.ts b/test/template/error/nestia.config.ts new file mode 100644 index 000000000..2594a40d0 --- /dev/null +++ b/test/template/error/nestia.config.ts @@ -0,0 +1,15 @@ +import { INestiaConfig } from "@nestia/sdk"; + +export const NESTIA_CONFIG: INestiaConfig = { + input: ["src/controllers"], + output: "src/api", + swagger: { + output: "swagger.json", + security: { + bearer: { + type: "apiKey", + }, + }, + }, +}; +export default NESTIA_CONFIG; diff --git a/test/template/error/src/controllers/HealthController.ts b/test/template/error/src/controllers/HealthController.ts new file mode 100644 index 000000000..a9ce3563b --- /dev/null +++ b/test/template/error/src/controllers/HealthController.ts @@ -0,0 +1,9 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +@Controller("health") +export class HealthController { + @core.TypedRoute.Get() + public get(): void {} +} diff --git a/test/template/error/tsconfig.json b/test/template/error/tsconfig.json new file mode 100644 index 000000000..e74060a2d --- /dev/null +++ b/test/template/error/tsconfig.json @@ -0,0 +1,101 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + /* Language and Environment */ + "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + /* Modules */ + "module": "commonjs", /* Specify what module code is generated. */// "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + "paths": { + "@nestia/core": ["../../../packages/core/src"], + "@nestia/e2e": ["../../../packages/e2e/src"], + "@nestia/fetcher": ["../../../packages/fetcher/src"], + "@nestia/sdk": ["../../../packages/sdk/src"], + "@nestia/sdk/lib/*": ["../../../packages/sdk/src/*"], + }, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. *//* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true, /* Skip type checking all .d.ts files. */ + "plugins": [ + { "transform": "typescript-transform-paths" }, + { "transform": "typia/lib/transform" }, + { "transform": "../../../packages/core/src/transform.ts" }, + ], + } + } \ No newline at end of file diff --git a/test/template/success/nestia.config.ts b/test/template/success/nestia.config.ts new file mode 100644 index 000000000..2594a40d0 --- /dev/null +++ b/test/template/success/nestia.config.ts @@ -0,0 +1,15 @@ +import { INestiaConfig } from "@nestia/sdk"; + +export const NESTIA_CONFIG: INestiaConfig = { + input: ["src/controllers"], + output: "src/api", + swagger: { + output: "swagger.json", + security: { + bearer: { + type: "apiKey", + }, + }, + }, +}; +export default NESTIA_CONFIG; diff --git a/test/template/success/src/Backend.ts b/test/template/success/src/Backend.ts new file mode 100644 index 000000000..8ab51b70f --- /dev/null +++ b/test/template/success/src/Backend.ts @@ -0,0 +1,28 @@ +import { INestApplication } from "@nestjs/common"; +import { NestFactory } from "@nestjs/core"; + +import core from "@nestia/core"; + +export class Backend { + private application_?: INestApplication; + + public async open(): Promise { + this.application_ = await NestFactory.create( + await core.EncryptedModule.dynamic(__dirname + "/controllers", { + key: "A".repeat(32), + iv: "B".repeat(16), + }), + { logger: false }, + ); + await this.application_.listen(37_000); + } + + public async close(): Promise { + if (this.application_ === undefined) return; + + const app = this.application_; + await app.close(); + + delete this.application_; + } +} diff --git a/test/template/success/src/api/HttpError.ts b/test/template/success/src/api/HttpError.ts new file mode 100644 index 000000000..5df328ae4 --- /dev/null +++ b/test/template/success/src/api/HttpError.ts @@ -0,0 +1 @@ +export { HttpError } from "@nestia/fetcher"; diff --git a/test/template/success/src/api/IConnection.ts b/test/template/success/src/api/IConnection.ts new file mode 100644 index 000000000..92727cfc2 --- /dev/null +++ b/test/template/success/src/api/IConnection.ts @@ -0,0 +1 @@ +export { IConnection } from "@nestia/fetcher"; diff --git a/test/template/success/src/api/Primitive.ts b/test/template/success/src/api/Primitive.ts new file mode 100644 index 000000000..3c1db5a74 --- /dev/null +++ b/test/template/success/src/api/Primitive.ts @@ -0,0 +1 @@ +export { Primitive } from "@nestia/fetcher"; diff --git a/packages/core/test/api/functional/monitors/system/index.ts b/test/template/success/src/api/functional/health/index.ts similarity index 55% rename from packages/core/test/api/functional/monitors/system/index.ts rename to test/template/success/src/api/functional/health/index.ts index 759227b5d..81049fd56 100644 --- a/packages/core/test/api/functional/monitors/system/index.ts +++ b/test/template/success/src/api/functional/health/index.ts @@ -1,33 +1,29 @@ /** * @packageDocumentation - * @module api.functional.monitors.system + * @module api.functional.health * @nestia Generated by Nestia - https://github.com/samchon/nestia */ //================================================================ -import { Fetcher, Primitive } from "@nestia/fetcher"; +import { Fetcher } from "@nestia/fetcher"; import type { IConnection } from "@nestia/fetcher"; -import type { ISystem } from "./../../../structures/ISystem"; - /** - * @controller SystemController.get() - * @path GET /monitors/system + * @controller HealthController.get() + * @path GET /health * @nestia Generated by Nestia - https://github.com/samchon/nestia */ -export function get(connection: IConnection): Promise { +export function get(connection: IConnection): Promise { return Fetcher.fetch(connection, get.ENCRYPTED, get.METHOD, get.path()); } export namespace get { - export type Output = Primitive; - export const METHOD = "GET" as const; - export const PATH: string = "/monitors/system"; + export const PATH: string = "/health"; export const ENCRYPTED: Fetcher.IEncrypted = { request: false, - response: true, + response: false, }; export function path(): string { - return `/monitors/system`; + return `/health`; } } diff --git a/packages/sdk/demo/generic/src/api/functional/index.ts b/test/template/success/src/api/functional/index.ts similarity index 69% rename from packages/sdk/demo/generic/src/api/functional/index.ts rename to test/template/success/src/api/functional/index.ts index 828f7e075..9e6869080 100644 --- a/packages/sdk/demo/generic/src/api/functional/index.ts +++ b/test/template/success/src/api/functional/index.ts @@ -1,7 +1,8 @@ /** * @packageDocumentation * @module api.functional - * @nestia Generated by Nestia - https://github.com/samchon/nestia + * @nestia Generated by Nestia - https://github.com/samchon/nestia */ //================================================================ -export * as consumers from "./consumers"; \ No newline at end of file +export * as health from "./health"; +export * as performance from "./performance"; diff --git a/packages/core/test/api/functional/system/index.ts b/test/template/success/src/api/functional/performance/index.ts similarity index 63% rename from packages/core/test/api/functional/system/index.ts rename to test/template/success/src/api/functional/performance/index.ts index ae6a87e68..24dbd7fde 100644 --- a/packages/core/test/api/functional/system/index.ts +++ b/test/template/success/src/api/functional/performance/index.ts @@ -1,33 +1,33 @@ /** * @packageDocumentation - * @module api.functional.system + * @module api.functional.performance * @nestia Generated by Nestia - https://github.com/samchon/nestia */ //================================================================ -import { Fetcher, Primitive } from "@nestia/fetcher"; +import { Fetcher } from "@nestia/fetcher"; import type { IConnection } from "@nestia/fetcher"; -import type { ISystem } from "./../../structures/ISystem"; +import type { IPerformance } from "../../structures/IPerformance"; /** - * @controller SystemController.get() - * @path GET /system + * @controller PerformanceController.get() + * @path GET /performance * @nestia Generated by Nestia - https://github.com/samchon/nestia */ export function get(connection: IConnection): Promise { return Fetcher.fetch(connection, get.ENCRYPTED, get.METHOD, get.path()); } export namespace get { - export type Output = Primitive; + export type Output = IPerformance; export const METHOD = "GET" as const; - export const PATH: string = "/system"; + export const PATH: string = "/performance"; export const ENCRYPTED: Fetcher.IEncrypted = { request: false, - response: true, + response: false, }; export function path(): string { - return `/system`; + return `/performance`; } } diff --git a/test/template/success/src/api/index.ts b/test/template/success/src/api/index.ts new file mode 100644 index 000000000..1896c4fbd --- /dev/null +++ b/test/template/success/src/api/index.ts @@ -0,0 +1,5 @@ +import * as api from "./module"; + +export * from "./module"; + +export default api; diff --git a/test/template/success/src/api/module.ts b/test/template/success/src/api/module.ts new file mode 100644 index 000000000..00239fb3b --- /dev/null +++ b/test/template/success/src/api/module.ts @@ -0,0 +1,5 @@ +export * from "./IConnection"; +export * from "./Primitive"; +export * from "./HttpError"; + +export * as functional from "./functional"; diff --git a/test/template/success/src/api/structures/IPerformance.ts b/test/template/success/src/api/structures/IPerformance.ts new file mode 100644 index 000000000..a9e9336e1 --- /dev/null +++ b/test/template/success/src/api/structures/IPerformance.ts @@ -0,0 +1,10 @@ +/** + * Performance info. + * + * @author Samchon + */ +export interface IPerformance { + cpu: NodeJS.CpuUsage; + memory: NodeJS.MemoryUsage; + resource: NodeJS.ResourceUsage; +} diff --git a/test/template/success/src/api/structures/ISystem.ts b/test/template/success/src/api/structures/ISystem.ts new file mode 100644 index 000000000..68f05ca92 --- /dev/null +++ b/test/template/success/src/api/structures/ISystem.ts @@ -0,0 +1,81 @@ +/** + * System Information. + * + * @author Jeongho Nam + */ +export interface ISystem { + /** + * Random Unique ID. + */ + uid: number; + + /** + * `process.argv` + */ + arguments: string[]; + + /** + * Git commit info. + */ + commit: ISystem.ICommit; + + /** + * `package.json` + */ + package: ISystem.IPackage; + + /** + * Creation time of this server. + */ + created_at: string; +} + +export namespace ISystem { + /** + * Git commit info. + */ + export interface ICommit { + shortHash: string; + branch: string; + hash: string; + subject: string; + sanitizedSubject: string; + body: string; + author: ICommit.IUser; + committer: ICommit.IUser; + authored_at: string; + commited_at: string; + notes?: string; + tags: string[]; + } + export namespace ICommit { + /** + * Git user account info. + */ + export interface IUser { + name: string; + email: string; + } + } + + /** + * NPM package info. + */ + export interface IPackage { + name: string; + version: string; + description: string; + main?: string; + typings?: string; + scripts: Record; + repository: { type: "git"; url: string }; + author: string; + license: string; + bugs: { url: string }; + homepage: string; + devDependencies?: Record; + dependencies: Record; + publishConfig?: { registry: string }; + files?: string[]; + } +} diff --git a/test/template/success/src/controllers/HealthController.ts b/test/template/success/src/controllers/HealthController.ts new file mode 100644 index 000000000..a9ce3563b --- /dev/null +++ b/test/template/success/src/controllers/HealthController.ts @@ -0,0 +1,9 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +@Controller("health") +export class HealthController { + @core.TypedRoute.Get() + public get(): void {} +} diff --git a/test/template/success/src/controllers/PerformanceController.ts b/test/template/success/src/controllers/PerformanceController.ts new file mode 100644 index 000000000..798d64fae --- /dev/null +++ b/test/template/success/src/controllers/PerformanceController.ts @@ -0,0 +1,17 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +import { IPerformance } from "@api/lib/structures/IPerformance"; + +@Controller("performance") +export class PerformanceController { + @core.TypedRoute.Get() + public async get(): Promise { + return { + cpu: process.cpuUsage(), + memory: process.memoryUsage(), + resource: process.resourceUsage(), + }; + } +} diff --git a/test/template/success/src/test/features/test_api_health_check.ts b/test/template/success/src/test/features/test_api_health_check.ts new file mode 100644 index 000000000..c34703c71 --- /dev/null +++ b/test/template/success/src/test/features/test_api_health_check.ts @@ -0,0 +1,5 @@ +import api from "@api"; + +export const test_api_monitor_health_check = ( + connection: api.IConnection, +): Promise => api.functional.health.get(connection); diff --git a/test/template/success/src/test/features/test_api_performance.ts b/test/template/success/src/test/features/test_api_performance.ts new file mode 100644 index 000000000..55b6d2ca7 --- /dev/null +++ b/test/template/success/src/test/features/test_api_performance.ts @@ -0,0 +1,13 @@ +import typia from "typia"; + +import api from "@api"; +import { IPerformance } from "@api/lib/structures/IPerformance"; + +export const test_api_monitor_performance = async ( + connection: api.IConnection, +): Promise => { + const performance: IPerformance = await api.functional.performance.get( + connection, + ); + typia.assert(performance); +}; diff --git a/test/template/success/src/test/index.ts b/test/template/success/src/test/index.ts new file mode 100644 index 000000000..e89842739 --- /dev/null +++ b/test/template/success/src/test/index.ts @@ -0,0 +1,39 @@ +import { DynamicExecutor } from "@nestia/e2e"; + +import { Backend } from "../Backend"; + +async function main(): Promise { + const server: Backend = new Backend(); + await server.open(); + + const report: DynamicExecutor.IReport = await DynamicExecutor.validate({ + prefix: "test", + parameters: () => [ + { + host: "http://127.0.0.1:37000", + encryption: { + key: "A".repeat(32), + iv: "B".repeat(16), + }, + }, + ], + })(`${__dirname}/features`); + await server.close(); + + const exceptions: Error[] = report.executions + .filter((exec) => exec.error !== null) + .map((exec) => exec.error!); + if (exceptions.length === 0) { + console.log("Success"); + console.log("Elapsed time", report.time.toLocaleString(), `ms`); + } else { + // for (const exp of exceptions) console.log(exp); + console.log("Failed"); + console.log("Elapsed time", report.time.toLocaleString(), `ms`); + process.exit(-1); + } +} +main().catch((exp) => { + console.log(exp); + process.exit(-1); +}); diff --git a/test/template/success/tsconfig.json b/test/template/success/tsconfig.json new file mode 100644 index 000000000..e5fe47a95 --- /dev/null +++ b/test/template/success/tsconfig.json @@ -0,0 +1,103 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + /* Language and Environment */ + "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + /* Modules */ + "module": "commonjs", /* Specify what module code is generated. */// "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + "paths": { + "@nestia/core": ["../../../packages/core/src"], + "@nestia/e2e": ["../../../packages/e2e/src"], + "@nestia/fetcher": ["../../../packages/fetcher/src"], + "@nestia/sdk": ["../../../packages/sdk/src"], + "@nestia/sdk/lib/*": ["../../../packages/sdk/src/*"], + "@api": ["./src/api"], + "@api/lib/*": ["./src/api/*"], + }, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. *//* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true, /* Skip type checking all .d.ts files. */ + "plugins": [ + { "transform": "typescript-transform-paths" }, + { "transform": "typia/lib/transform" }, + { "transform": "../../../packages/core/src/transform.ts" }, + ], + } + } \ No newline at end of file