@nestia/migrate 0.14.2 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -52,7 +52,7 @@ export const NEST_TEMPLATE = [
52
52
  {
53
53
  "location": "",
54
54
  "file": "package.json",
55
- "content": "{\r\n \"private\": true,\r\n \"name\": \"@ORGANIZATION/PROJECT\",\r\n \"version\": \"0.1.0\",\r\n \"description\": \"Starter kit of Nestia\",\r\n \"main\": \"lib/index.js\",\r\n \"scripts\": {\r\n \"benchmark\": \"node bin/test/benchmark\",\r\n \"test\": \"node bin/test\",\r\n \"test:webpack\": \"npm run webpack && node bin/test/webpack.js\",\r\n \"------------------------BUILDS------------------------\": \"\",\r\n \"build\": \"npm run build:sdk && npm run build:main && npm run build:test\",\r\n \"build:api\": \"rimraf packages/api/lib && npm run build:sdk && tsc -p packages/api/tsconfig.json\",\r\n \"build:main\": \"rimraf lib && tsc\",\r\n \"build:sdk\": \"rimraf src/api/functional && nestia sdk\",\r\n \"build:swagger\": \"npx nestia swagger\",\r\n \"build:test\": \"rimraf bin && tsc -p test/tsconfig.json\",\r\n \"dev\": \"npm run build:test -- --watch\",\r\n \"eslint\": \"eslint src && eslint test\",\r\n \"eslint:fix\": \"eslint --fix src && eslint --fix test\",\r\n \"prepare\": \"ts-patch install && typia patch\",\r\n \"prettier\": \"prettier src --write && prettier test --write\",\r\n \"------------------------WEBPACK------------------------\": \"\",\r\n \"webpack\": \"rimraf dist && webpack\",\r\n \"webpack:start\": \"cd dist && node dist/server\",\r\n \"------------------------DEPLOYS------------------------\": \"\",\r\n \"package:api\": \"npm run build:swagger && npm run build:api && cd packages/api && npm publish\",\r\n \"start\": \"node lib/executable/server\",\r\n \"start:swagger\": \"ts-node src/executable/swagger.ts\"\r\n },\r\n \"repository\": {\r\n \"type\": \"git\",\r\n \"url\": \"https://github.com/samchon/nestia-start\"\r\n },\r\n \"keywords\": [\r\n \"nestia\",\r\n \"template\",\r\n \"boilerplate\"\r\n ],\r\n \"author\": \"AUTHOR\",\r\n \"license\": \"MIT\",\r\n \"bugs\": {\r\n \"url\": \"https://github.com/samchon/nestia-start/issues\"\r\n },\r\n \"homepage\": \"https://github.com/samchon/nestia-start#readme\",\r\n \"devDependencies\": {\r\n \"@nestia/e2e\": \"^0.6.0\",\r\n \"@nestia/sdk\": \"^3.5.0\",\r\n \"@trivago/prettier-plugin-sort-imports\": \"^4.3.0\",\r\n \"@types/cli\": \"^0.11.21\",\r\n \"@types/cli-progress\": \"^3.11.5\",\r\n \"@types/express\": \"^4.17.21\",\r\n \"@types/inquirer\": \"^8.2.5\",\r\n \"@types/node\": \"^18.11.0\",\r\n \"@types/uuid\": \"^8.3.4\",\r\n \"@typescript-eslint/eslint-plugin\": \"^6.19.1\",\r\n \"@typescript-eslint/parser\": \"^6.19.1\",\r\n \"chalk\": \"^4.1.0\",\r\n \"cli\": \"^1.0.1\",\r\n \"cli-progress\": \"^3.12.0\",\r\n \"copy-webpack-plugin\": \"^11.0.0\",\r\n \"eslint-plugin-deprecation\": \"^2.0.0\",\r\n \"express\": \"^4.18.2\",\r\n \"nestia\": \"^5.3.1\",\r\n \"prettier\": \"^3.2.4\",\r\n \"prettier-plugin-prisma\": \"^5.0.0\",\r\n \"rimraf\": \"^3.0.2\",\r\n \"source-map-support\": \"^0.5.21\",\r\n \"swagger-ui-express\": \"^5.0.0\",\r\n \"ts-loader\": \"^9.5.1\",\r\n \"ts-node\": \"^10.9.1\",\r\n \"ts-patch\": \"^3.2.1\",\r\n \"typescript\": \"^5.5.3\",\r\n \"typescript-transform-paths\": \"^3.4.6\",\r\n \"webpack\": \"^5.89.0\",\r\n \"webpack-cli\": \"^5.1.4\",\r\n \"write-file-webpack-plugin\": \"^4.5.1\"\r\n },\r\n \"dependencies\": {\r\n \"@nestia/core\": \"^3.5.0\",\r\n \"@nestia/fetcher\": \"^3.5.0\",\r\n \"@nestjs/common\": \"^10.3.10\",\r\n \"@nestjs/core\": \"^10.3.10\",\r\n \"@nestjs/platform-express\": \"^10.3.10\",\r\n \"commander\": \"10.0.0\",\r\n \"dotenv\": \"^16.3.1\",\r\n \"dotenv-expand\": \"^10.0.0\",\r\n \"inquirer\": \"8.2.5\",\r\n \"serialize-error\": \"^4.1.0\",\r\n \"tgrid\": \"^1.0.2\",\r\n \"tstl\": \"^3.0.0\",\r\n \"typia\": \"^6.4.2\",\r\n \"uuid\": \"^9.0.0\"\r\n },\r\n \"stackblitz\": {\r\n \"startCommand\": \"npm run prepare && npm run build:test && npm run test\"\r\n }\r\n}"
55
+ "content": "{\r\n \"private\": true,\r\n \"name\": \"@ORGANIZATION/PROJECT\",\r\n \"version\": \"0.1.0\",\r\n \"description\": \"Starter kit of Nestia\",\r\n \"main\": \"lib/index.js\",\r\n \"scripts\": {\r\n \"benchmark\": \"node bin/test/benchmark\",\r\n \"test\": \"node bin/test\",\r\n \"test:webpack\": \"npm run webpack && node bin/test/webpack.js\",\r\n \"------------------------BUILDS------------------------\": \"\",\r\n \"build\": \"npm run build:sdk && npm run build:main && npm run build:test\",\r\n \"build:api\": \"rimraf packages/api/lib && npm run build:sdk && rimraf packages/api/lib && tsc -p packages/api/tsconfig.json && rollup -c packages/api/rollup.config.js\",\r\n \"build:main\": \"rimraf lib && tsc\",\r\n \"build:sdk\": \"rimraf src/api/functional && nestia sdk\",\r\n \"build:swagger\": \"npx nestia swagger\",\r\n \"build:test\": \"rimraf bin && tsc -p test/tsconfig.json\",\r\n \"dev\": \"npm run build:test -- --watch\",\r\n \"eslint\": \"eslint src && eslint test\",\r\n \"eslint:fix\": \"eslint --fix src && eslint --fix test\",\r\n \"prepare\": \"ts-patch install && typia patch\",\r\n \"prettier\": \"prettier src --write && prettier test --write\",\r\n \"------------------------WEBPACK------------------------\": \"\",\r\n \"webpack\": \"rimraf dist && webpack\",\r\n \"webpack:start\": \"cd dist && node dist/server\",\r\n \"------------------------DEPLOYS------------------------\": \"\",\r\n \"package:api\": \"npm run build:swagger && npm run build:api && cd packages/api && npm publish\",\r\n \"start\": \"node lib/executable/server\",\r\n \"start:swagger\": \"ts-node src/executable/swagger.ts\"\r\n },\r\n \"repository\": {\r\n \"type\": \"git\",\r\n \"url\": \"https://github.com/samchon/nestia-start\"\r\n },\r\n \"keywords\": [\r\n \"nestia\",\r\n \"template\",\r\n \"boilerplate\"\r\n ],\r\n \"author\": \"AUTHOR\",\r\n \"license\": \"MIT\",\r\n \"bugs\": {\r\n \"url\": \"https://github.com/samchon/nestia-start/issues\"\r\n },\r\n \"homepage\": \"https://github.com/samchon/nestia-start#readme\",\r\n \"devDependencies\": {\r\n \"@nestia/benchmark\": \"^0.1.1\",\r\n \"@nestia/e2e\": \"^0.7.0\",\r\n \"@nestia/sdk\": \"^3.7.0\",\r\n \"@rollup/plugin-terser\": \"^0.4.4\",\r\n \"@rollup/plugin-typescript\": \"^11.1.6\",\r\n \"@trivago/prettier-plugin-sort-imports\": \"^4.3.0\",\r\n \"@types/cli\": \"^0.11.21\",\r\n \"@types/cli-progress\": \"^3.11.5\",\r\n \"@types/express\": \"^4.17.21\",\r\n \"@types/inquirer\": \"^8.2.5\",\r\n \"@types/node\": \"^18.11.0\",\r\n \"@types/uuid\": \"^8.3.4\",\r\n \"@typescript-eslint/eslint-plugin\": \"^6.19.1\",\r\n \"@typescript-eslint/parser\": \"^6.19.1\",\r\n \"chalk\": \"^4.1.2\",\r\n \"cli\": \"^1.0.1\",\r\n \"cli-progress\": \"^3.12.0\",\r\n \"copy-webpack-plugin\": \"^11.0.0\",\r\n \"eslint-plugin-deprecation\": \"^2.0.0\",\r\n \"express\": \"^4.18.2\",\r\n \"nestia\": \"^5.3.1\",\r\n \"prettier\": \"^3.2.4\",\r\n \"prettier-plugin-prisma\": \"^5.0.0\",\r\n \"rimraf\": \"^3.0.2\",\r\n \"rollup\": \"^4.18.0\",\r\n \"source-map-support\": \"^0.5.21\",\r\n \"swagger-ui-express\": \"^5.0.0\",\r\n \"ts-loader\": \"^9.5.1\",\r\n \"ts-node\": \"^10.9.1\",\r\n \"ts-patch\": \"^3.2.1\",\r\n \"typescript\": \"^5.5.3\",\r\n \"typescript-transform-paths\": \"^3.4.6\",\r\n \"webpack\": \"^5.89.0\",\r\n \"webpack-cli\": \"^5.1.4\",\r\n \"write-file-webpack-plugin\": \"^4.5.1\"\r\n },\r\n \"dependencies\": {\r\n \"@nestia/core\": \"^3.7.0\",\r\n \"@nestia/fetcher\": \"^3.7.0\",\r\n \"@nestjs/common\": \"^10.3.10\",\r\n \"@nestjs/core\": \"^10.3.10\",\r\n \"@nestjs/platform-express\": \"^10.3.10\",\r\n \"commander\": \"10.0.0\",\r\n \"dotenv\": \"^16.3.1\",\r\n \"dotenv-expand\": \"^10.0.0\",\r\n \"inquirer\": \"8.2.5\",\r\n \"serialize-error\": \"^4.1.0\",\r\n \"tgrid\": \"^1.0.2\",\r\n \"tstl\": \"^3.0.0\",\r\n \"typia\": \"^6.5.0\",\r\n \"uuid\": \"^9.0.0\"\r\n },\r\n \"stackblitz\": {\r\n \"startCommand\": \"npm run prepare && npm run build:test && npm run test\"\r\n }\r\n}"
56
56
  },
57
57
  {
58
58
  "location": "packages/api",
@@ -67,13 +67,18 @@ export const NEST_TEMPLATE = [
67
67
  {
68
68
  "location": "packages/api",
69
69
  "file": "package.json",
70
- "content": "{\r\n \"name\": \"@ORGANIZATION/PROJECT-api\",\r\n \"version\": \"0.1.0\",\r\n \"description\": \"SDK library generated by Nestia\",\r\n \"main\": \"lib/index.js\",\r\n \"typings\": \"lib/index.d.ts\",\r\n \"scripts\": {\r\n \"build\": \"npm run build:sdk && npm run compile\",\r\n \"build:sdk\": \"rimraf ../../src/api/functional && cd ../.. && npx nestia sdk && cd packages/api\",\r\n \"compile\": \"rimraf lib && tsc\",\r\n \"deploy\": \"npm run build && npm publish\",\r\n \"prepare\": \"ts-patch install && typia patch\"\r\n },\r\n \"repository\": {\r\n \"type\": \"git\",\r\n \"url\": \"https://github.com/samchon/nestia\"\r\n },\r\n \"author\": \"Jeongho Nam\",\r\n \"license\": \"MIT\",\r\n \"bugs\": {\r\n \"url\": \"https://github.com/samchon/nestia/issues\"\r\n },\r\n \"homepage\": \"https://nestia.io\",\r\n \"files\": [\r\n \"lib\",\r\n \"swagger.json\",\r\n \"package.json\",\r\n \"README.md\"\r\n ],\r\n \"dependencies\": {\r\n \"@nestia/fetcher\": \"^3.5.0\",\r\n \"tgrid\": \"^1.0.2\",\r\n \"typia\": \"^6.4.2\"\r\n }\r\n}"
70
+ "content": "{\r\n \"name\": \"@ORGANIZATION/PROJECT-api\",\r\n \"version\": \"0.1.0\",\r\n \"description\": \"SDK library generated by Nestia\",\r\n \"main\": \"lib/index.js\",\r\n \"module\": \"lib/index.mjs\",\r\n \"typings\": \"lib/index.d.ts\",\r\n \"repository\": {\r\n \"type\": \"git\",\r\n \"url\": \"https://github.com/samchon/nestia\"\r\n },\r\n \"author\": \"Jeongho Nam\",\r\n \"license\": \"MIT\",\r\n \"bugs\": {\r\n \"url\": \"https://github.com/samchon/nestia/issues\"\r\n },\r\n \"homepage\": \"https://nestia.io\",\r\n \"files\": [\r\n \"lib\",\r\n \"swagger.json\",\r\n \"package.json\",\r\n \"README.md\"\r\n ],\r\n \"dependencies\": {\r\n \"@nestia/fetcher\": \"^3.7.0\",\r\n \"tgrid\": \"^1.0.2\",\r\n \"typia\": \"^6.5.0\"\r\n }\r\n}"
71
71
  },
72
72
  {
73
73
  "location": "packages/api",
74
74
  "file": "README.md",
75
75
  "content": "# SDK Library\r\nThis is a SDK library generated by [`nestia`](https://nestia.io).\r\n\r\nWith this SDK library, you can easily and safely interact with backend server.\r\n\r\nJust import and call some API functions like gif image below:\r\n\r\n![nestia-sdk-demo](https://user-images.githubusercontent.com/13158709/215004990-368c589d-7101-404e-b81b-fbc936382f05.gif)\r\n\r\n> Left is server code, and right is client code utilizing the SDK\r\n\r\n\r\n\r\n\r\n# What [`Nestia`](https://nestia.io) is:\r\n![Nestia Logo](https://nestia.io/logo.png)\r\n\r\n[![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/samchon/nestia/blob/master/LICENSE)\r\n[![npm version](https://img.shields.io/npm/v/@nestia/core.svg)](https://www.npmjs.com/package/@nestia/core)\r\n[![Downloads](https://img.shields.io/npm/dm/@nestia/core.svg)](https://www.npmjs.com/package/@nestia/core)\r\n[![Build Status](https://github.com/samchon/nestia/workflows/build/badge.svg)](https://github.com/samchon/nestia/actions?query=workflow%3Abuild)\r\n[![Guide Documents](https://img.shields.io/badge/guide-documents-forestgreen)](https://nestia.io/docs/)\r\n\r\nNestia is a set of helper libraries for NestJS, supporting below features:\r\n\r\n - `@nestia/core`: super-fast decorators\r\n - `@nestia/sdk`:\r\n - Swagger generator evolved than ever\r\n - SDK library generator for clients\r\n - Mockup Simulator for client applications\r\n - Automatic E2E test functions generator\r\n - `@nestia/migrate`: migration from Swagger to NestJS\r\n - `nestia`: just CLI (command line interface) tool\r\n\r\n> **Note**\r\n> \r\n> - **Only one line** required, with pure TypeScript type\r\n> - Enhance performance **30x** up\r\n> - Runtime validator is **20,000x faster** than `class-validator`\r\n> - JSON serialization is **200x faster** than `class-transformer`\r\n> - Software Development Kit\r\n> - SDK is a collection of `fetch` functions with type definitions like [tRPC](https://trpc.io/)\r\n> - Mockup simulator means embedded backend simulator in SDK\r\n> - similar with [msw](https://mswjs.io/), but fully automated"
76
76
  },
77
+ {
78
+ "location": "packages/api",
79
+ "file": "rollup.config.js",
80
+ "content": "const typescript = require(\"@rollup/plugin-typescript\");\r\nconst terser = require(\"@rollup/plugin-terser\");\r\n\r\nmodule.exports = {\r\n input: `${__dirname}/../../src/api/index.ts`,\r\n output: {\r\n dir: `${__dirname}/lib`,\r\n format: \"esm\",\r\n entryFileNames: \"[name].mjs\",\r\n sourcemap: true,\r\n },\r\n plugins: [\r\n typescript({\r\n tsconfig: `${__dirname}/tsconfig.json`,\r\n module: \"ESNext\",\r\n target: \"ESNext\",\r\n }),\r\n terser({\r\n format: {\r\n comments: \"some\",\r\n beautify: true,\r\n ecma: \"2020\",\r\n },\r\n compress: false,\r\n mangle: false,\r\n module: true,\r\n }),\r\n ],\r\n};\r\n"
81
+ },
77
82
  {
78
83
  "location": "packages/api",
79
84
  "file": "tsconfig.json",
@@ -167,12 +172,12 @@ export const NEST_TEMPLATE = [
167
172
  {
168
173
  "location": "test/benchmark",
169
174
  "file": "index.ts",
170
- "content": "import { DynamicBenchmarker } from \"@nestia/e2e\";\r\nimport cliProgress from \"cli-progress\";\r\nimport fs from \"fs\";\r\nimport os from \"os\";\r\nimport { IPointer } from \"tstl\";\r\n\r\nimport { MyBackend } from \"../../src/MyBackend\";\r\nimport { MyConfiguration } from \"../../src/MyConfiguration\";\r\nimport { MyGlobal } from \"../../src/MyGlobal\";\r\nimport { ArgumentParser } from \"../helpers/ArgumentParser\";\r\n\r\ninterface IOptions {\r\n include?: string[];\r\n exclude?: string[];\r\n count: number;\r\n threads: number;\r\n simultaneous: number;\r\n}\r\n\r\nconst getOptions = () =>\r\n ArgumentParser.parse<IOptions>(async (command, prompt, action) => {\r\n // command.option(\"--mode <string>\", \"target mode\");\r\n // command.option(\"--reset <true|false>\", \"reset local DB or not\");\r\n command.option(\"--include <string...>\", \"include feature files\");\r\n command.option(\"--exclude <string...>\", \"exclude feature files\");\r\n command.option(\"--count <number>\", \"number of requests to make\");\r\n command.option(\"--threads <number>\", \"number of threads to use\");\r\n command.option(\r\n \"--simultaneous <number>\",\r\n \"number of simultaneous requests to make\",\r\n );\r\n return action(async (options) => {\r\n // if (typeof options.reset === \"string\")\r\n // options.reset = options.reset === \"true\";\r\n // options.mode ??= await prompt.select(\"mode\")(\"Select mode\")([\r\n // \"LOCAL\",\r\n // \"DEV\",\r\n // \"REAL\",\r\n // ]);\r\n // options.reset ??= await prompt.boolean(\"reset\")(\"Reset local DB\");\r\n options.count = Number(\r\n options.count ??\r\n (await prompt.number(\"count\")(\"Number of requests to make\")),\r\n );\r\n options.threads = Number(\r\n options.threads ??\r\n (await prompt.number(\"threads\")(\"Number of threads to use\")),\r\n );\r\n options.simultaneous = Number(\r\n options.simultaneous ??\r\n (await prompt.number(\"simultaneous\")(\r\n \"Number of simultaneous requests to make\",\r\n )),\r\n );\r\n return options as IOptions;\r\n });\r\n });\r\n\r\nconst main = async (): Promise<void> => {\r\n // CONFIGURATIONS\r\n const options: IOptions = await getOptions();\r\n MyGlobal.testing = true;\r\n\r\n // BACKEND SERVER\r\n const backend: MyBackend = new MyBackend();\r\n await backend.open();\r\n\r\n // DO BENCHMARK\r\n const prev: IPointer<number> = { value: 0 };\r\n const bar: cliProgress.SingleBar = new cliProgress.SingleBar(\r\n {},\r\n cliProgress.Presets.shades_classic,\r\n );\r\n bar.start(options.count, 0);\r\n\r\n const report: DynamicBenchmarker.IReport = await DynamicBenchmarker.master({\r\n servant: `${__dirname}/servant.js`,\r\n count: options.count,\r\n threads: options.threads,\r\n simultaneous: options.simultaneous,\r\n filter: (func) =>\r\n (!options.include?.length ||\r\n (options.include ?? []).some((str) => func.includes(str))) &&\r\n (!options.exclude?.length ||\r\n (options.exclude ?? []).every((str) => !func.includes(str))),\r\n progress: (value: number) => {\r\n if (value >= 100 + prev.value) {\r\n bar.update(value);\r\n prev.value = value;\r\n }\r\n },\r\n stdio: \"ignore\",\r\n });\r\n bar.stop();\r\n\r\n // DOCUMENTATION\r\n try {\r\n await fs.promises.mkdir(`${MyConfiguration.ROOT}/docs/benchmarks`, {\r\n recursive: true,\r\n });\r\n } catch {}\r\n await fs.promises.writeFile(\r\n `${MyConfiguration.ROOT}/docs/benchmarks/${os\r\n .cpus()[0]\r\n .model.trim()\r\n .split(\"\\\\\")\r\n .join(\"\")\r\n .split(\"/\")\r\n .join(\"\")}.md`,\r\n DynamicBenchmarker.markdown(report),\r\n \"utf8\",\r\n );\r\n\r\n // CLOSE\r\n await backend.close();\r\n};\r\nmain().catch((exp) => {\r\n console.error(exp);\r\n process.exit(-1);\r\n});\r\n"
175
+ "content": "import { DynamicBenchmarker } from \"@nestia/benchmark\";\r\nimport cliProgress from \"cli-progress\";\r\nimport fs from \"fs\";\r\nimport os from \"os\";\r\nimport { IPointer } from \"tstl\";\r\n\r\nimport { MyBackend } from \"../../src/MyBackend\";\r\nimport { MyConfiguration } from \"../../src/MyConfiguration\";\r\nimport { MyGlobal } from \"../../src/MyGlobal\";\r\nimport { ArgumentParser } from \"../helpers/ArgumentParser\";\r\n\r\ninterface IOptions {\r\n include?: string[];\r\n exclude?: string[];\r\n count: number;\r\n threads: number;\r\n simultaneous: number;\r\n}\r\n\r\nconst getOptions = () =>\r\n ArgumentParser.parse<IOptions>(async (command, prompt, action) => {\r\n // command.option(\"--mode <string>\", \"target mode\");\r\n // command.option(\"--reset <true|false>\", \"reset local DB or not\");\r\n command.option(\"--include <string...>\", \"include feature files\");\r\n command.option(\"--exclude <string...>\", \"exclude feature files\");\r\n command.option(\"--count <number>\", \"number of requests to make\");\r\n command.option(\"--threads <number>\", \"number of threads to use\");\r\n command.option(\r\n \"--simultaneous <number>\",\r\n \"number of simultaneous requests to make\",\r\n );\r\n return action(async (options) => {\r\n // if (typeof options.reset === \"string\")\r\n // options.reset = options.reset === \"true\";\r\n // options.mode ??= await prompt.select(\"mode\")(\"Select mode\")([\r\n // \"LOCAL\",\r\n // \"DEV\",\r\n // \"REAL\",\r\n // ]);\r\n // options.reset ??= await prompt.boolean(\"reset\")(\"Reset local DB\");\r\n options.count = Number(\r\n options.count ??\r\n (await prompt.number(\"count\")(\"Number of requests to make\")),\r\n );\r\n options.threads = Number(\r\n options.threads ??\r\n (await prompt.number(\"threads\")(\"Number of threads to use\")),\r\n );\r\n options.simultaneous = Number(\r\n options.simultaneous ??\r\n (await prompt.number(\"simultaneous\")(\r\n \"Number of simultaneous requests to make\",\r\n )),\r\n );\r\n return options as IOptions;\r\n });\r\n });\r\n\r\nconst main = async (): Promise<void> => {\r\n // CONFIGURATIONS\r\n const options: IOptions = await getOptions();\r\n MyGlobal.testing = true;\r\n\r\n // BACKEND SERVER\r\n const backend: MyBackend = new MyBackend();\r\n await backend.open();\r\n\r\n // DO BENCHMARK\r\n const prev: IPointer<number> = { value: 0 };\r\n const bar: cliProgress.SingleBar = new cliProgress.SingleBar(\r\n {},\r\n cliProgress.Presets.shades_classic,\r\n );\r\n bar.start(options.count, 0);\r\n\r\n const report: DynamicBenchmarker.IReport = await DynamicBenchmarker.master({\r\n servant: `${__dirname}/servant.js`,\r\n count: options.count,\r\n threads: options.threads,\r\n simultaneous: options.simultaneous,\r\n filter: (func) =>\r\n (!options.include?.length ||\r\n (options.include ?? []).some((str) => func.includes(str))) &&\r\n (!options.exclude?.length ||\r\n (options.exclude ?? []).every((str) => !func.includes(str))),\r\n progress: (value: number) => {\r\n if (value >= 100 + prev.value) {\r\n bar.update(value);\r\n prev.value = value;\r\n }\r\n },\r\n stdio: \"ignore\",\r\n });\r\n bar.stop();\r\n\r\n // DOCUMENTATION\r\n try {\r\n await fs.promises.mkdir(`${MyConfiguration.ROOT}/docs/benchmarks`, {\r\n recursive: true,\r\n });\r\n } catch {}\r\n await fs.promises.writeFile(\r\n `${MyConfiguration.ROOT}/docs/benchmarks/${os\r\n .cpus()[0]\r\n .model.trim()\r\n .split(\"\\\\\")\r\n .join(\"\")\r\n .split(\"/\")\r\n .join(\"\")}.md`,\r\n DynamicBenchmarker.markdown(report),\r\n \"utf8\",\r\n );\r\n\r\n // CLOSE\r\n await backend.close();\r\n};\r\nmain().catch((exp) => {\r\n console.error(exp);\r\n process.exit(-1);\r\n});\r\n"
171
176
  },
172
177
  {
173
178
  "location": "test/benchmark",
174
179
  "file": "servant.ts",
175
- "content": "import { DynamicBenchmarker } from \"@nestia/e2e\";\r\n\r\nimport { MyConfiguration } from \"../../src/MyConfiguration\";\r\n\r\nDynamicBenchmarker.servant({\r\n connection: {\r\n host: `http://127.0.0.1:${MyConfiguration.API_PORT()}`,\r\n },\r\n location: `${__dirname}/../features`,\r\n parameters: (connection) => [connection],\r\n prefix: \"test_api_\",\r\n}).catch((exp) => {\r\n console.error(exp);\r\n process.exit(-1);\r\n});\r\n"
180
+ "content": "import { DynamicBenchmarker } from \"@nestia/benchmark\";\r\n\r\nimport { MyConfiguration } from \"../../src/MyConfiguration\";\r\n\r\nDynamicBenchmarker.servant({\r\n connection: {\r\n host: `http://127.0.0.1:${MyConfiguration.API_PORT()}`,\r\n },\r\n location: `${__dirname}/../features`,\r\n parameters: (connection) => [connection],\r\n prefix: \"test_api_\",\r\n}).catch((exp) => {\r\n console.error(exp);\r\n process.exit(-1);\r\n});\r\n"
176
181
  },
177
182
  {
178
183
  "location": "test/helpers",
@@ -182,7 +187,7 @@ export const NEST_TEMPLATE = [
182
187
  {
183
188
  "location": "test",
184
189
  "file": "index.ts",
185
- "content": "import { DynamicExecutor } from \"@nestia/e2e\";\r\n\r\nimport api from \"@ORGANIZATION/PROJECT-api\";\r\n\r\nimport { MyBackend } from \"../src/MyBackend\";\r\nimport { MyConfiguration } from \"../src/MyConfiguration\";\r\nimport { MyGlobal } from \"../src/MyGlobal\";\r\nimport { ArgumentParser } from \"./helpers/ArgumentParser\";\r\n\r\ninterface IOptions {\r\n include?: string[];\r\n exclude?: string[];\r\n}\r\n\r\nconst getOptions = () =>\r\n ArgumentParser.parse<IOptions>(async (command, _prompt, action) => {\r\n // command.option(\"--mode <string>\", \"target mode\");\r\n // command.option(\"--reset <true|false>\", \"reset local DB or not\");\r\n command.option(\"--include <string...>\", \"include feature files\");\r\n command.option(\"--exclude <string...>\", \"exclude feature files\");\r\n\r\n return action(async (options) => {\r\n // if (typeof options.reset === \"string\")\r\n // options.reset = options.reset === \"true\";\r\n // options.mode ??= await prompt.select(\"mode\")(\"Select mode\")([\r\n // \"LOCAL\",\r\n // \"DEV\",\r\n // \"REAL\",\r\n // ]);\r\n // options.reset ??= await prompt.boolean(\"reset\")(\"Reset local DB\");\r\n return options as IOptions;\r\n });\r\n });\r\n\r\nasync function main(): Promise<void> {\r\n // CONFIGURATIONS\r\n const options: IOptions = await getOptions();\r\n MyGlobal.testing = true;\r\n\r\n // BACKEND SERVER\r\n const backend: MyBackend = new MyBackend();\r\n await backend.open();\r\n\r\n //----\r\n // CLINET CONNECTOR\r\n //----\r\n // DO TEST\r\n const connection: api.IConnection = {\r\n host: `http://127.0.0.1:${MyConfiguration.API_PORT()}`,\r\n };\r\n const report: DynamicExecutor.IReport = await DynamicExecutor.validate({\r\n prefix: \"test\",\r\n parameters: () => [\r\n {\r\n host: connection.host,\r\n encryption: connection.encryption,\r\n },\r\n ],\r\n filter: (func) =>\r\n (!options.include?.length ||\r\n (options.include ?? []).some((str) => func.includes(str))) &&\r\n (!options.exclude?.length ||\r\n (options.exclude ?? []).every((str) => !func.includes(str))),\r\n })(__dirname + \"/features\");\r\n\r\n await backend.close();\r\n\r\n const failures: DynamicExecutor.IReport.IExecution[] =\r\n report.executions.filter((exec) => exec.error !== null);\r\n if (failures.length === 0) {\r\n console.log(\"Success\");\r\n console.log(\"Elapsed time\", report.time.toLocaleString(), `ms`);\r\n } else {\r\n for (const f of failures) console.log(f.error);\r\n process.exit(-1);\r\n }\r\n\r\n console.log(\r\n [\r\n `All: #${report.executions.length}`,\r\n `Success: #${report.executions.length - failures.length}`,\r\n `Failed: #${failures.length}`,\r\n ].join(\"\\n\"),\r\n );\r\n}\r\nmain().catch((exp) => {\r\n console.log(exp);\r\n process.exit(-1);\r\n});\r\n"
190
+ "content": "import { DynamicExecutor } from \"@nestia/e2e\";\r\nimport chalk from \"chalk\";\r\n\r\nimport api from \"@ORGANIZATION/PROJECT-api\";\r\n\r\nimport { MyBackend } from \"../src/MyBackend\";\r\nimport { MyConfiguration } from \"../src/MyConfiguration\";\r\nimport { MyGlobal } from \"../src/MyGlobal\";\r\nimport { ArgumentParser } from \"./helpers/ArgumentParser\";\r\n\r\ninterface IOptions {\r\n include?: string[];\r\n exclude?: string[];\r\n}\r\n\r\nconst getOptions = () =>\r\n ArgumentParser.parse<IOptions>(async (command, _prompt, action) => {\r\n // command.option(\"--mode <string>\", \"target mode\");\r\n // command.option(\"--reset <true|false>\", \"reset local DB or not\");\r\n command.option(\"--include <string...>\", \"include feature files\");\r\n command.option(\"--exclude <string...>\", \"exclude feature files\");\r\n\r\n return action(async (options) => {\r\n // if (typeof options.reset === \"string\")\r\n // options.reset = options.reset === \"true\";\r\n // options.mode ??= await prompt.select(\"mode\")(\"Select mode\")([\r\n // \"LOCAL\",\r\n // \"DEV\",\r\n // \"REAL\",\r\n // ]);\r\n // options.reset ??= await prompt.boolean(\"reset\")(\"Reset local DB\");\r\n return options as IOptions;\r\n });\r\n });\r\n\r\nasync function main(): Promise<void> {\r\n // CONFIGURATIONS\r\n const options: IOptions = await getOptions();\r\n MyGlobal.testing = true;\r\n\r\n // BACKEND SERVER\r\n const backend: MyBackend = new MyBackend();\r\n await backend.open();\r\n\r\n //----\r\n // CLINET CONNECTOR\r\n //----\r\n // DO TEST\r\n const connection: api.IConnection = {\r\n host: `http://127.0.0.1:${MyConfiguration.API_PORT()}`,\r\n };\r\n const report: DynamicExecutor.IReport = await DynamicExecutor.validate({\r\n prefix: \"test\",\r\n location: __dirname + \"/features\",\r\n parameters: () => [\r\n {\r\n host: connection.host,\r\n encryption: connection.encryption,\r\n },\r\n ],\r\n filter: (func) =>\r\n (!options.include?.length ||\r\n (options.include ?? []).some((str) => func.includes(str))) &&\r\n (!options.exclude?.length ||\r\n (options.exclude ?? []).every((str) => !func.includes(str))),\r\n onComplete: (exec) => {\r\n if (exec.error === null) {\r\n const elapsed: number =\r\n new Date(exec.completed_at).getTime() -\r\n new Date(exec.started_at).getTime();\r\n console.log(\r\n ` - ${exec.name}: ${chalk.green(elapsed.toLocaleString())} ms`,\r\n );\r\n } else console.log(` - ${exec.name}: ${chalk.red(exec.error.name)}`);\r\n },\r\n });\r\n await backend.close();\r\n\r\n const failures: DynamicExecutor.IExecution[] = report.executions.filter(\r\n (exec) => exec.error !== null,\r\n );\r\n if (failures.length === 0) {\r\n console.log(\"Success\");\r\n console.log(\"Elapsed time\", report.time.toLocaleString(), `ms`);\r\n } else {\r\n for (const f of failures) console.log(f.error);\r\n process.exit(-1);\r\n }\r\n\r\n console.log(\r\n [\r\n `All: #${report.executions.length}`,\r\n `Success: #${report.executions.length - failures.length}`,\r\n `Failed: #${failures.length}`,\r\n ].join(\"\\n\"),\r\n );\r\n}\r\nmain().catch((exp) => {\r\n console.log(exp);\r\n process.exit(-1);\r\n});\r\n"
186
191
  },
187
192
  {
188
193
  "location": "test",
@@ -192,7 +197,7 @@ export const NEST_TEMPLATE = [
192
197
  {
193
198
  "location": "test",
194
199
  "file": "webpack.ts",
195
- "content": "import { DynamicExecutor } from \"@nestia/e2e\";\r\nimport cp from \"child_process\";\r\nimport { sleep_for } from \"tstl\";\r\n\r\nimport { MyConfiguration } from \"../src/MyConfiguration\";\r\nimport api from \"../src/api\";\r\n\r\nconst main = async (): Promise<void> => {\r\n // OPEN BUNDLED SERVER\r\n const backend = cp.fork(`${MyConfiguration.ROOT}/dist/server.js`, {\r\n cwd: `${MyConfiguration.ROOT}/dist`,\r\n });\r\n await sleep_for(2_500);\r\n\r\n // DO TEST\r\n const connection: api.IConnection = {\r\n host: `http://127.0.0.1:${MyConfiguration.API_PORT()}`,\r\n };\r\n const report: DynamicExecutor.IReport = await DynamicExecutor.validate({\r\n prefix: \"test\",\r\n parameters: () => [\r\n {\r\n host: connection.host,\r\n encryption: connection.encryption,\r\n },\r\n ],\r\n })(__dirname + \"/features\");\r\n\r\n backend.kill();\r\n\r\n const failures: DynamicExecutor.IReport.IExecution[] =\r\n report.executions.filter((exec) => exec.error !== null);\r\n if (failures.length === 0) {\r\n console.log(\"Success\");\r\n console.log(\"Elapsed time\", report.time.toLocaleString(), `ms`);\r\n } else {\r\n for (const f of failures) console.log(f.error);\r\n process.exit(-1);\r\n }\r\n};\r\nmain().catch((exp) => {\r\n console.log(exp);\r\n process.exit(-1);\r\n});\r\n"
200
+ "content": "import { DynamicExecutor } from \"@nestia/e2e\";\r\nimport chalk from \"chalk\";\r\nimport cp from \"child_process\";\r\nimport { sleep_for } from \"tstl\";\r\n\r\nimport { MyConfiguration } from \"../src/MyConfiguration\";\r\nimport api from \"../src/api\";\r\n\r\nconst main = async (): Promise<void> => {\r\n // OPEN BUNDLED SERVER\r\n const backend = cp.fork(`${MyConfiguration.ROOT}/dist/server.js`, {\r\n cwd: `${MyConfiguration.ROOT}/dist`,\r\n });\r\n await sleep_for(2_500);\r\n\r\n // DO TEST\r\n const connection: api.IConnection = {\r\n host: `http://127.0.0.1:${MyConfiguration.API_PORT()}`,\r\n };\r\n const report: DynamicExecutor.IReport = await DynamicExecutor.validate({\r\n prefix: \"test\",\r\n location: __dirname + \"/features\",\r\n parameters: () => [\r\n {\r\n host: connection.host,\r\n encryption: connection.encryption,\r\n },\r\n ],\r\n onComplete: (exec) => {\r\n if (exec.error === null) {\r\n const elapsed: number =\r\n new Date(exec.completed_at).getTime() -\r\n new Date(exec.started_at).getTime();\r\n console.log(\r\n ` - ${exec.name}: ${chalk.green(elapsed.toLocaleString())} ms`,\r\n );\r\n } else console.log(` - ${exec.name}: ${chalk.red(exec.error.name)}`);\r\n },\r\n });\r\n\r\n backend.kill();\r\n\r\n const failures: DynamicExecutor.IExecution[] = report.executions.filter(\r\n (exec) => exec.error !== null,\r\n );\r\n if (failures.length === 0) {\r\n console.log(\"Success\");\r\n console.log(\"Elapsed time\", report.time.toLocaleString(), `ms`);\r\n } else {\r\n for (const f of failures) console.log(f.error);\r\n process.exit(-1);\r\n }\r\n};\r\nmain().catch((exp) => {\r\n console.log(exp);\r\n process.exit(-1);\r\n});\r\n"
196
201
  },
197
202
  {
198
203
  "location": "",
@@ -27,7 +27,7 @@ export const SDK_TEMPLATE = [
27
27
  {
28
28
  "location": "",
29
29
  "file": "package.json",
30
- "content": "{\r\n \"name\": \"@ORGANIZATION/PROJECT-api\",\r\n \"version\": \"0.1.0\",\r\n \"description\": \"SDK library generated by Nestia\",\r\n \"main\": \"lib/index.js\",\r\n \"typings\": \"lib/index.d.ts\",\r\n \"exports\": {\r\n \".\": {\r\n \"types\": \"./lib/index.d.ts\",\r\n \"require\": \"./lib/index.js\",\r\n \"import\": \"./lib/index.mjs\"\r\n }\r\n },\r\n \"scripts\": {\r\n \"build\": \"rimraf lib && tsc && rollup -c\",\r\n \"build:test\": \"rimraf bin && tsc --project test/tsconfig.json\",\r\n \"deploy\": \"npm run build && npm publish\",\r\n \"dev\": \"npm run build:test -- --watch\",\r\n \"hello\": \"node hello\",\r\n \"prepare\": \"ts-patch install && typia patch\",\r\n \"start\": \"ts-node test/start.ts\",\r\n \"swagger\": \"ts-node test/swagger.ts\",\r\n \"test\": \"ts-node test/index.ts\",\r\n \"test:simulate\": \"ts-node test/index.ts --simulate true\",\r\n \"test:manual\": \"ts-node test/manual.ts\"\r\n },\r\n \"repository\": {\r\n \"type\": \"git\",\r\n \"url\": \"https://github.com/samchon/nestia\"\r\n },\r\n \"author\": \"Jeongho Nam\",\r\n \"license\": \"MIT\",\r\n \"bugs\": {\r\n \"url\": \"https://github.com/samchon/nestia/issues\"\r\n },\r\n \"homepage\": \"https://nestia.io\",\r\n \"files\": [\r\n \"lib\",\r\n \"swagger.json\",\r\n \"package.json\",\r\n \"README.md\"\r\n ],\r\n \"dependencies\": {\r\n \"@nestia/fetcher\": \"^3.5.0\",\r\n \"tgrid\": \"^1.0.2\",\r\n \"typia\": \"^6.4.2\"\r\n },\r\n \"devDependencies\": {\r\n \"@nestia/e2e\": \"^0.6.0\",\r\n \"@rollup/plugin-terser\": \"^0.4.4\",\r\n \"@rollup/plugin-typescript\": \"^11.1.6\",\r\n \"@trivago/prettier-plugin-sort-imports\": \"^4.3.0\",\r\n \"@types/express\": \"^4.17.21\",\r\n \"@types/inquirer\": \"8.2.5\",\r\n \"@types/swagger-ui-express\": \"^4.1.6\",\r\n \"commander\": \"^10.0.0\",\r\n \"express\": \"^4.19.2\",\r\n \"inquirer\": \"8.2.5\",\r\n \"prettier\": \"^3.2.5\",\r\n \"rimraf\": \"^5.0.5\",\r\n \"rollup\": \"^4.13.2\",\r\n \"swagger-ui-express\": \"^5.0.0\",\r\n \"ts-node\": \"^10.9.2\",\r\n \"ts-patch\": \"^3.2.1\",\r\n \"typescript\": \"^5.5.3\",\r\n \"typescript-transform-paths\": \"^3.4.6\"\r\n }\r\n}"
30
+ "content": "{\r\n \"name\": \"@ORGANIZATION/PROJECT-api\",\r\n \"version\": \"0.1.0\",\r\n \"description\": \"SDK library generated by Nestia\",\r\n \"main\": \"lib/index.js\",\r\n \"module\": \"lib/index.mjs\",\r\n \"typings\": \"lib/index.d.ts\",\r\n \"scripts\": {\r\n \"build\": \"rimraf lib && tsc && rollup -c\",\r\n \"build:test\": \"rimraf bin && tsc --project test/tsconfig.json\",\r\n \"deploy\": \"npm run build && npm publish\",\r\n \"dev\": \"npm run build:test -- --watch\",\r\n \"hello\": \"node hello\",\r\n \"prepare\": \"ts-patch install && typia patch\",\r\n \"start\": \"ts-node test/start.ts\",\r\n \"swagger\": \"ts-node test/swagger.ts\",\r\n \"test\": \"ts-node test/index.ts\",\r\n \"test:simulate\": \"ts-node test/index.ts --simulate true\",\r\n \"test:manual\": \"ts-node test/manual.ts\"\r\n },\r\n \"repository\": {\r\n \"type\": \"git\",\r\n \"url\": \"https://github.com/samchon/nestia\"\r\n },\r\n \"author\": \"Jeongho Nam\",\r\n \"license\": \"MIT\",\r\n \"bugs\": {\r\n \"url\": \"https://github.com/samchon/nestia/issues\"\r\n },\r\n \"homepage\": \"https://nestia.io\",\r\n \"files\": [\r\n \"lib\",\r\n \"swagger.json\",\r\n \"package.json\",\r\n \"README.md\"\r\n ],\r\n \"dependencies\": {\r\n \"@nestia/fetcher\": \"^3.7.0\",\r\n \"tgrid\": \"^1.0.2\",\r\n \"typia\": \"^6.5.0\"\r\n },\r\n \"devDependencies\": {\r\n \"@nestia/e2e\": \"^0.7.0\",\r\n \"@rollup/plugin-terser\": \"^0.4.4\",\r\n \"@rollup/plugin-typescript\": \"^11.1.6\",\r\n \"@trivago/prettier-plugin-sort-imports\": \"^4.3.0\",\r\n \"@types/express\": \"^4.17.21\",\r\n \"@types/inquirer\": \"8.2.5\",\r\n \"@types/swagger-ui-express\": \"^4.1.6\",\r\n \"chalk\": \"4.1.2\",\r\n \"commander\": \"^10.0.0\",\r\n \"express\": \"^4.19.2\",\r\n \"inquirer\": \"8.2.5\",\r\n \"prettier\": \"^3.2.5\",\r\n \"rimraf\": \"^5.0.5\",\r\n \"rollup\": \"^4.13.2\",\r\n \"swagger-ui-express\": \"^5.0.0\",\r\n \"ts-node\": \"^10.9.2\",\r\n \"ts-patch\": \"^3.2.1\",\r\n \"typescript\": \"^5.5.3\",\r\n \"typescript-transform-paths\": \"^3.4.6\"\r\n }\r\n}"
31
31
  },
32
32
  {
33
33
  "location": "",
@@ -77,7 +77,7 @@ export const SDK_TEMPLATE = [
77
77
  {
78
78
  "location": "test",
79
79
  "file": "index.ts",
80
- "content": "import { DynamicExecutor } from \"@nestia/e2e\";\r\nimport { ArgumentParser } from \"./utils/ArgumentParser\";\r\nimport { TestGlobal } from \"./TestGlobal\";\r\n\r\ninterface IOptions {\r\n simulate: boolean;\r\n include?: string[];\r\n exclude?: string[];\r\n trace: boolean;\r\n}\r\n\r\nconst getOptions = () =>\r\n ArgumentParser.parse<IOptions>(async (command, prompt, action) => {\r\n command.option(\"--simulate <boolean>\", \"Mockup Simultator\");\r\n command.option(\"--include <string...>\", \"include feature files\");\r\n command.option(\"--exclude <string...>\", \"exclude feature files\");\r\n command.option(\"--trace <boolean>\", \"trace detailed errors\");\r\n\r\n return action(async (options) => {\r\n if (typeof options.simulate === \"string\")\r\n options.simulate = options.simulate === \"true\";\r\n options.simulate ??= await prompt.boolean(\"simulate\")(\"Mockup Simulator\");\r\n options.trace = options.trace !== (\"false\" as any);\r\n return options as IOptions;\r\n });\r\n });\r\n\r\nconst main = async (): Promise<void> => {\r\n // DO TEST\r\n const options: IOptions = await getOptions();\r\n const report: DynamicExecutor.IReport = await DynamicExecutor.validate({\r\n prefix: \"test\",\r\n parameters: () => [\r\n {\r\n ...TestGlobal.connection(),\r\n simulate: options.simulate,\r\n },\r\n ],\r\n filter: (func) =>\r\n (!options.include?.length ||\r\n (options.include ?? []).some((str) => func.includes(str))) &&\r\n (!options.exclude?.length ||\r\n (options.exclude ?? []).every((str) => !func.includes(str))),\r\n extension: __filename.substring(__filename.length - 2),\r\n })(__dirname + \"/features\");\r\n\r\n // REPORT EXCEPTIONS\r\n const exceptions: Error[] = report.executions\r\n .filter((exec) => exec.error !== null)\r\n .map((exec) => exec.error!);\r\n if (exceptions.length === 0) {\r\n console.log(\"Success\");\r\n console.log(\"Elapsed time\", report.time.toLocaleString(), `ms`);\r\n } else {\r\n if (options.trace !== false) for (const exp of exceptions) console.log(exp);\r\n console.log(\"Failed\");\r\n console.log(\"Elapsed time\", report.time.toLocaleString(), `ms`);\r\n }\r\n\r\n // TERMINATE\r\n if (exceptions.length) process.exit(-1);\r\n else process.exit(0);\r\n};\r\nmain().catch((exp) => {\r\n console.log(exp);\r\n process.exit(-1);\r\n});\r\n"
80
+ "content": "import { DynamicExecutor } from \"@nestia/e2e\";\r\nimport chalk from \"chalk\";\r\n\r\nimport { TestGlobal } from \"./TestGlobal\";\r\nimport { ArgumentParser } from \"./utils/ArgumentParser\";\r\n\r\ninterface IOptions {\r\n simulate: boolean;\r\n include?: string[];\r\n exclude?: string[];\r\n trace: boolean;\r\n}\r\n\r\nconst getOptions = () =>\r\n ArgumentParser.parse<IOptions>(async (command, prompt, action) => {\r\n command.option(\"--simulate <boolean>\", \"Mockup Simultator\");\r\n command.option(\"--include <string...>\", \"include feature files\");\r\n command.option(\"--exclude <string...>\", \"exclude feature files\");\r\n command.option(\"--trace <boolean>\", \"trace detailed errors\");\r\n\r\n return action(async (options) => {\r\n if (typeof options.simulate === \"string\")\r\n options.simulate = options.simulate === \"true\";\r\n options.simulate ??= await prompt.boolean(\"simulate\")(\"Mockup Simulator\");\r\n options.trace = options.trace !== (\"false\" as any);\r\n return options as IOptions;\r\n });\r\n });\r\n\r\nconst main = async (): Promise<void> => {\r\n // DO TEST\r\n const options: IOptions = await getOptions();\r\n const report: DynamicExecutor.IReport = await DynamicExecutor.validate({\r\n prefix: \"test\",\r\n location: __dirname + \"/features\",\r\n extension: __filename.substring(__filename.length - 2),\r\n parameters: () => [\r\n {\r\n ...TestGlobal.connection(),\r\n simulate: options.simulate,\r\n },\r\n ],\r\n filter: (func) =>\r\n (!options.include?.length ||\r\n (options.include ?? []).some((str) => func.includes(str))) &&\r\n (!options.exclude?.length ||\r\n (options.exclude ?? []).every((str) => !func.includes(str))),\r\n onComplete: (exec) => {\r\n if (exec.error === null) {\r\n const elapsed: number =\r\n new Date(exec.completed_at).getTime() -\r\n new Date(exec.started_at).getTime();\r\n console.log(\r\n ` - ${exec.name}: ${chalk.green(elapsed.toLocaleString())} ms`,\r\n );\r\n } else console.log(` - ${exec.name}: ${chalk.red(exec.error.name)}`);\r\n },\r\n });\r\n\r\n // REPORT EXCEPTIONS\r\n const exceptions: Error[] = report.executions\r\n .filter((exec) => exec.error !== null)\r\n .map((exec) => exec.error!);\r\n if (exceptions.length === 0) {\r\n console.log(\"Success\");\r\n console.log(\"Elapsed time\", report.time.toLocaleString(), `ms`);\r\n } else {\r\n if (options.trace !== false) for (const exp of exceptions) console.log(exp);\r\n console.log(\"Failed\");\r\n console.log(\"Elapsed time\", report.time.toLocaleString(), `ms`);\r\n }\r\n\r\n // TERMINATE\r\n if (exceptions.length) process.exit(-1);\r\n else process.exit(0);\r\n};\r\nmain().catch((exp) => {\r\n console.log(exp);\r\n process.exit(-1);\r\n});\r\n"
81
81
  },
82
82
  {
83
83
  "location": "test",
@@ -2,6 +2,7 @@ import { OpenApi } from "@samchon/openapi";
2
2
  import ts from "typescript";
3
3
  import { ExpressionFactory } from "typia/lib/factories/ExpressionFactory";
4
4
  import { IdentifierFactory } from "typia/lib/factories/IdentifierFactory";
5
+ import { LiteralFactory } from "typia/lib/factories/LiteralFactory";
5
6
  import { TypeFactory } from "typia/lib/factories/TypeFactory";
6
7
 
7
8
  import { IMigrateRoute } from "../structures/IMigrateRoute";
@@ -87,6 +88,17 @@ export namespace MigrateNestMethodProgrammer {
87
88
  name: instance,
88
89
  }),
89
90
  );
91
+
92
+ // EXAMPLES
93
+ const decorators: ts.Decorator[] = [];
94
+ if (route.success)
95
+ decorators.push(
96
+ ...writeExampleDecorators("Response")(importer)(
97
+ route.success.media(),
98
+ ),
99
+ );
100
+
101
+ // ROUTER
90
102
  const router = (instance: string) =>
91
103
  ts.factory.createDecorator(
92
104
  ts.factory.createCallExpression(
@@ -97,8 +109,6 @@ export namespace MigrateNestMethodProgrammer {
97
109
  [ts.factory.createStringLiteral(route.path)],
98
110
  ),
99
111
  );
100
-
101
- const decorators: ts.Decorator[] = [];
102
112
  if (route.success?.["x-nestia-encrypted"])
103
113
  decorators.push(router("EncryptedRoute"));
104
114
  else if (route.success?.type === "text/plain")
@@ -142,8 +152,12 @@ export namespace MigrateNestMethodProgrammer {
142
152
  isNaN(Number(key))
143
153
  ? ts.factory.createStringLiteral(key)
144
154
  : ExpressionFactory.number(Number(key)),
145
- ...(value.description?.length
146
- ? [ts.factory.createStringLiteral(value.description)]
155
+ ...(value.response().description?.length
156
+ ? [
157
+ ts.factory.createStringLiteral(
158
+ value.response().description!,
159
+ ),
160
+ ]
147
161
  : []),
148
162
  ],
149
163
  ),
@@ -156,9 +170,10 @@ export namespace MigrateNestMethodProgrammer {
156
170
  (components: OpenApi.IComponents) =>
157
171
  (importer: MigrateImportProgrammer) =>
158
172
  (route: IMigrateRoute): ts.ParameterDeclaration[] => [
159
- ...route.parameters.map(({ key, schema: value }) =>
173
+ ...route.parameters.map((p) =>
160
174
  ts.factory.createParameterDeclaration(
161
175
  [
176
+ ...writeExampleDecorators("Parameter")(importer)(p.parameter()),
162
177
  ts.factory.createDecorator(
163
178
  ts.factory.createCallExpression(
164
179
  ts.factory.createIdentifier(
@@ -169,28 +184,36 @@ export namespace MigrateNestMethodProgrammer {
169
184
  }),
170
185
  ),
171
186
  undefined,
172
- [ts.factory.createStringLiteral(key)],
187
+ [ts.factory.createStringLiteral(p.key)],
173
188
  ),
174
189
  ),
175
190
  ],
176
191
  undefined,
177
- key,
192
+ p.key,
178
193
  undefined,
179
- MigrateSchemaProgrammer.write(components)(importer)(value),
194
+ MigrateSchemaProgrammer.write(components)(importer)(p.schema),
180
195
  ),
181
196
  ),
182
197
  ...(route.headers
183
198
  ? [
184
199
  writeDtoParameter({ method: "TypedHeaders", variable: "headers" })(
185
200
  components,
186
- )(importer)(route.headers.schema),
201
+ )(importer)({
202
+ schema: route.headers.schema,
203
+ example: route.headers.example(),
204
+ examples: route.headers.examples(),
205
+ }),
187
206
  ]
188
207
  : []),
189
208
  ...(route.query
190
209
  ? [
191
210
  writeDtoParameter({ method: "TypedQuery", variable: "query" })(
192
211
  components,
193
- )(importer)(route.query.schema),
212
+ )(importer)({
213
+ schema: route.query.schema,
214
+ example: route.query.example(),
215
+ examples: route.query.examples(),
216
+ }),
194
217
  ]
195
218
  : []),
196
219
  ...(route.body
@@ -208,7 +231,11 @@ export namespace MigrateNestMethodProgrammer {
208
231
  ? ["TypedFormData", "Body"]
209
232
  : "TypedBody",
210
233
  variable: "body",
211
- })(components)(importer)(route.body.schema),
234
+ })(components)(importer)({
235
+ schema: route.body.schema,
236
+ example: route.body.media().example,
237
+ examples: route.body.media().examples,
238
+ }),
212
239
  ]
213
240
  : []),
214
241
  ];
@@ -217,7 +244,11 @@ export namespace MigrateNestMethodProgrammer {
217
244
  (accessor: { method: string | [string, string]; variable: string }) =>
218
245
  (components: OpenApi.IComponents) =>
219
246
  (importer: MigrateImportProgrammer) =>
220
- (schema: OpenApi.IJsonSchema): ts.ParameterDeclaration => {
247
+ (props: {
248
+ schema: OpenApi.IJsonSchema;
249
+ example?: any;
250
+ examples?: Record<string, any>;
251
+ }): ts.ParameterDeclaration => {
221
252
  const instance = ts.factory.createIdentifier(
222
253
  importer.external({
223
254
  type: "instance",
@@ -230,6 +261,7 @@ export namespace MigrateNestMethodProgrammer {
230
261
  );
231
262
  return ts.factory.createParameterDeclaration(
232
263
  [
264
+ ...writeExampleDecorators("Parameter")(importer)(props),
233
265
  ts.factory.createDecorator(
234
266
  ts.factory.createCallExpression(
235
267
  typeof accessor.method === "string"
@@ -243,7 +275,55 @@ export namespace MigrateNestMethodProgrammer {
243
275
  undefined,
244
276
  accessor.variable,
245
277
  undefined,
246
- MigrateSchemaProgrammer.write(components)(importer)(schema),
278
+ MigrateSchemaProgrammer.write(components)(importer)(props.schema),
247
279
  );
248
280
  };
281
+
282
+ const writeExampleDecorators =
283
+ (kind: "Response" | "Parameter") =>
284
+ (importer: MigrateImportProgrammer) =>
285
+ (media: {
286
+ example?: any;
287
+ examples?: Record<string, any>;
288
+ }): ts.Decorator[] => [
289
+ ...(media.example !== undefined
290
+ ? [
291
+ ts.factory.createDecorator(
292
+ ts.factory.createCallExpression(
293
+ IdentifierFactory.access(
294
+ ts.factory.createIdentifier(
295
+ importer.external({
296
+ type: "instance",
297
+ library: "@nestia/core",
298
+ name: "SwaggerExample",
299
+ }),
300
+ ),
301
+ )(kind),
302
+ [],
303
+ [LiteralFactory.generate(media.example)],
304
+ ),
305
+ ),
306
+ ]
307
+ : []),
308
+ ...Object.entries(media.examples ?? {}).map(([key, value]) =>
309
+ ts.factory.createDecorator(
310
+ ts.factory.createCallExpression(
311
+ IdentifierFactory.access(
312
+ ts.factory.createIdentifier(
313
+ importer.external({
314
+ type: "instance",
315
+ library: "@nestia/core",
316
+ name: "SwaggerExample",
317
+ }),
318
+ ),
319
+ )(kind),
320
+ [],
321
+ [
322
+ ts.factory.createStringLiteral(key),
323
+ LiteralFactory.generate(value),
324
+ ],
325
+ ),
326
+ ),
327
+ ),
328
+ ];
249
329
  }