@nestia/migrate 0.13.15 → 0.13.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/MigrateApplication.js +21 -21
- package/lib/bundles/NEST_TEMPLATE.js +20 -5
- package/lib/bundles/NEST_TEMPLATE.js.map +1 -1
- package/lib/bundles/SDK_TEMPLATE.js +1 -1
- package/lib/bundles/SDK_TEMPLATE.js.map +1 -1
- package/lib/utils/StringUtil.js +5 -4
- package/lib/utils/StringUtil.js.map +1 -1
- package/package.json +9 -6
- package/src/bundles/NEST_TEMPLATE.ts +20 -5
- package/src/bundles/SDK_TEMPLATE.ts +1 -1
- package/src/utils/StringUtil.ts +5 -4
@@ -805,7 +805,7 @@ class MigrateApplication {
|
|
805
805
|
const $join = typia_1.default.validate.join;
|
806
806
|
const $vo0 = (input, _path, _exceptionable = true) => ["string" === typeof input.openapi && RegExp(/^3\.1\.[+-]?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?$/).test(input.openapi) || $report(_exceptionable, {
|
807
807
|
path: _path + ".openapi",
|
808
|
-
expected: "`
|
808
|
+
expected: "`3.1.${number}`",
|
809
809
|
value: input.openapi
|
810
810
|
}), undefined === input.servers || (Array.isArray(input.servers) || $report(_exceptionable, {
|
811
811
|
path: _path + ".servers",
|
@@ -2065,7 +2065,7 @@ class MigrateApplication {
|
|
2065
2065
|
}).every(flag => flag)].every(flag => flag);
|
2066
2066
|
const $vo44 = (input, _path, _exceptionable = true) => ["string" === typeof input.$ref && RegExp(/^#\/components\/pathItems\/(.*)/).test(input.$ref) || $report(_exceptionable, {
|
2067
2067
|
path: _path + ".$ref",
|
2068
|
-
expected: "
|
2068
|
+
expected: "`#/components/pathItems/${string}`",
|
2069
2069
|
value: input.$ref
|
2070
2070
|
}), undefined === input.title || "string" === typeof input.title || $report(_exceptionable, {
|
2071
2071
|
path: _path + ".title",
|
@@ -2091,15 +2091,15 @@ class MigrateApplication {
|
|
2091
2091
|
})].every(flag => flag);
|
2092
2092
|
const $vo46 = (input, _path, _exceptionable = true) => [(null !== input.swagger || $report(_exceptionable, {
|
2093
2093
|
path: _path + ".swagger",
|
2094
|
-
expected: "(\"2.0\" | `
|
2094
|
+
expected: "(\"2.0\" | `2.0.${number}`)",
|
2095
2095
|
value: input.swagger
|
2096
2096
|
})) && (undefined !== input.swagger || $report(_exceptionable, {
|
2097
2097
|
path: _path + ".swagger",
|
2098
|
-
expected: "(\"2.0\" | `
|
2098
|
+
expected: "(\"2.0\" | `2.0.${number}`)",
|
2099
2099
|
value: input.swagger
|
2100
2100
|
})) && ("2.0" === input.swagger || "string" === typeof input.swagger && RegExp(/^2\.0\.[+-]?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?$/).test(input.swagger) || $report(_exceptionable, {
|
2101
2101
|
path: _path + ".swagger",
|
2102
|
-
expected: "(\"2.0\" | `
|
2102
|
+
expected: "(\"2.0\" | `2.0.${number}`)",
|
2103
2103
|
value: input.swagger
|
2104
2104
|
})), undefined === input.info || ("object" === typeof input.info && null !== input.info || $report(_exceptionable, {
|
2105
2105
|
path: _path + ".info",
|
@@ -3608,7 +3608,7 @@ class MigrateApplication {
|
|
3608
3608
|
})].every(flag => flag);
|
3609
3609
|
const $vo86 = (input, _path, _exceptionable = true) => ["string" === typeof input.$ref && RegExp(/^#\/parameters\/(.*)/).test(input.$ref) || $report(_exceptionable, {
|
3610
3610
|
path: _path + ".$ref",
|
3611
|
-
expected: "
|
3611
|
+
expected: "`#/parameters/${string}`",
|
3612
3612
|
value: input.$ref
|
3613
3613
|
}), undefined === input.title || "string" === typeof input.title || $report(_exceptionable, {
|
3614
3614
|
path: _path + ".title",
|
@@ -3694,7 +3694,7 @@ class MigrateApplication {
|
|
3694
3694
|
})].every(flag => flag);
|
3695
3695
|
const $vo88 = (input, _path, _exceptionable = true) => ["string" === typeof input.$ref && RegExp(/^#\/definitions\/parameters\/(.*)/).test(input.$ref) || $report(_exceptionable, {
|
3696
3696
|
path: _path + ".$ref",
|
3697
|
-
expected: "
|
3697
|
+
expected: "`#/definitions/parameters/${string}`",
|
3698
3698
|
value: input.$ref
|
3699
3699
|
}), undefined === input.title || "string" === typeof input.title || $report(_exceptionable, {
|
3700
3700
|
path: _path + ".title",
|
@@ -3725,7 +3725,7 @@ class MigrateApplication {
|
|
3725
3725
|
}).every(flag => flag)].every(flag => flag);
|
3726
3726
|
const $vo90 = (input, _path, _exceptionable = true) => ["string" === typeof input.$ref && RegExp(/^#\/definitions\/responses\/(.*)/).test(input.$ref) || $report(_exceptionable, {
|
3727
3727
|
path: _path + ".$ref",
|
3728
|
-
expected: "
|
3728
|
+
expected: "`#/definitions/responses/${string}`",
|
3729
3729
|
value: input.$ref
|
3730
3730
|
}), undefined === input.title || "string" === typeof input.title || $report(_exceptionable, {
|
3731
3731
|
path: _path + ".title",
|
@@ -3751,15 +3751,15 @@ class MigrateApplication {
|
|
3751
3751
|
})].every(flag => flag);
|
3752
3752
|
const $vo92 = (input, _path, _exceptionable = true) => [(null !== input.openapi || $report(_exceptionable, {
|
3753
3753
|
path: _path + ".openapi",
|
3754
|
-
expected: "(\"3.0\" | `
|
3754
|
+
expected: "(\"3.0\" | `3.0.${number}`)",
|
3755
3755
|
value: input.openapi
|
3756
3756
|
})) && (undefined !== input.openapi || $report(_exceptionable, {
|
3757
3757
|
path: _path + ".openapi",
|
3758
|
-
expected: "(\"3.0\" | `
|
3758
|
+
expected: "(\"3.0\" | `3.0.${number}`)",
|
3759
3759
|
value: input.openapi
|
3760
3760
|
})) && ("3.0" === input.openapi || "string" === typeof input.openapi && RegExp(/^3\.0\.[+-]?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?$/).test(input.openapi) || $report(_exceptionable, {
|
3761
3761
|
path: _path + ".openapi",
|
3762
|
-
expected: "(\"3.0\" | `
|
3762
|
+
expected: "(\"3.0\" | `3.0.${number}`)",
|
3763
3763
|
value: input.openapi
|
3764
3764
|
})), undefined === input.servers || (Array.isArray(input.servers) || $report(_exceptionable, {
|
3765
3765
|
path: _path + ".servers",
|
@@ -4587,7 +4587,7 @@ class MigrateApplication {
|
|
4587
4587
|
})].every(flag => flag);
|
4588
4588
|
const $vo119 = (input, _path, _exceptionable = true) => ["string" === typeof input.$ref && RegExp(/^#\/components\/headers\/(.*)/).test(input.$ref) || $report(_exceptionable, {
|
4589
4589
|
path: _path + ".$ref",
|
4590
|
-
expected: "
|
4590
|
+
expected: "`#/components/headers/${string}`",
|
4591
4591
|
value: input.$ref
|
4592
4592
|
}), undefined === input.title || "string" === typeof input.title || $report(_exceptionable, {
|
4593
4593
|
path: _path + ".title",
|
@@ -4986,7 +4986,7 @@ class MigrateApplication {
|
|
4986
4986
|
})].every(flag => flag);
|
4987
4987
|
const $vo137 = (input, _path, _exceptionable = true) => ["string" === typeof input.$ref && RegExp(/^#\/components\/parameters\/(.*)/).test(input.$ref) || $report(_exceptionable, {
|
4988
4988
|
path: _path + ".$ref",
|
4989
|
-
expected: "
|
4989
|
+
expected: "`#/components/parameters/${string}`",
|
4990
4990
|
value: input.$ref
|
4991
4991
|
}), undefined === input.title || "string" === typeof input.title || $report(_exceptionable, {
|
4992
4992
|
path: _path + ".title",
|
@@ -5096,7 +5096,7 @@ class MigrateApplication {
|
|
5096
5096
|
})].every(flag => flag);
|
5097
5097
|
const $vo139 = (input, _path, _exceptionable = true) => ["string" === typeof input.$ref && RegExp(/^#\/components\/requestBodies\/(.*)/).test(input.$ref) || $report(_exceptionable, {
|
5098
5098
|
path: _path + ".$ref",
|
5099
|
-
expected: "
|
5099
|
+
expected: "`#/components/requestBodies/${string}`",
|
5100
5100
|
value: input.$ref
|
5101
5101
|
}), undefined === input.title || "string" === typeof input.title || $report(_exceptionable, {
|
5102
5102
|
path: _path + ".title",
|
@@ -5127,7 +5127,7 @@ class MigrateApplication {
|
|
5127
5127
|
}).every(flag => flag)].every(flag => flag);
|
5128
5128
|
const $vo141 = (input, _path, _exceptionable = true) => ["string" === typeof input.$ref && RegExp(/^#\/components\/responses\/(.*)/).test(input.$ref) || $report(_exceptionable, {
|
5129
5129
|
path: _path + ".$ref",
|
5130
|
-
expected: "
|
5130
|
+
expected: "`#/components/responses/${string}`",
|
5131
5131
|
value: input.$ref
|
5132
5132
|
}), undefined === input.title || "string" === typeof input.title || $report(_exceptionable, {
|
5133
5133
|
path: _path + ".title",
|
@@ -5153,7 +5153,7 @@ class MigrateApplication {
|
|
5153
5153
|
})].every(flag => flag);
|
5154
5154
|
const $vo143 = (input, _path, _exceptionable = true) => ["string" === typeof input.openapi && RegExp(/^3\.1\.[+-]?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?$/).test(input.openapi) || $report(_exceptionable, {
|
5155
5155
|
path: _path + ".openapi",
|
5156
|
-
expected: "`
|
5156
|
+
expected: "`3.1.${number}`",
|
5157
5157
|
value: input.openapi
|
5158
5158
|
}), undefined === input.servers || (Array.isArray(input.servers) || $report(_exceptionable, {
|
5159
5159
|
path: _path + ".servers",
|
@@ -6390,7 +6390,7 @@ class MigrateApplication {
|
|
6390
6390
|
})].every(flag => flag);
|
6391
6391
|
const $vo169 = (input, _path, _exceptionable = true) => ["string" === typeof input.$ref && RegExp(/^#\/components\/headers\/(.*)/).test(input.$ref) || $report(_exceptionable, {
|
6392
6392
|
path: _path + ".$ref",
|
6393
|
-
expected: "
|
6393
|
+
expected: "`#/components/headers/${string}`",
|
6394
6394
|
value: input.$ref
|
6395
6395
|
}), undefined === input.title || "string" === typeof input.title || $report(_exceptionable, {
|
6396
6396
|
path: _path + ".title",
|
@@ -6407,7 +6407,7 @@ class MigrateApplication {
|
|
6407
6407
|
})].every(flag => flag);
|
6408
6408
|
const $vo170 = (input, _path, _exceptionable = true) => ["string" === typeof input.$ref && RegExp(/^#\/components\/parameters\/(.*)/).test(input.$ref) || $report(_exceptionable, {
|
6409
6409
|
path: _path + ".$ref",
|
6410
|
-
expected: "
|
6410
|
+
expected: "`#/components/parameters/${string}`",
|
6411
6411
|
value: input.$ref
|
6412
6412
|
}), undefined === input.title || "string" === typeof input.title || $report(_exceptionable, {
|
6413
6413
|
path: _path + ".title",
|
@@ -6557,7 +6557,7 @@ class MigrateApplication {
|
|
6557
6557
|
})].every(flag => flag);
|
6558
6558
|
const $vo175 = (input, _path, _exceptionable = true) => ["string" === typeof input.$ref && RegExp(/^#\/components\/requestBodies\/(.*)/).test(input.$ref) || $report(_exceptionable, {
|
6559
6559
|
path: _path + ".$ref",
|
6560
|
-
expected: "
|
6560
|
+
expected: "`#/components/requestBodies/${string}`",
|
6561
6561
|
value: input.$ref
|
6562
6562
|
}), undefined === input.title || "string" === typeof input.title || $report(_exceptionable, {
|
6563
6563
|
path: _path + ".title",
|
@@ -6644,7 +6644,7 @@ class MigrateApplication {
|
|
6644
6644
|
})].every(flag => flag);
|
6645
6645
|
const $vo180 = (input, _path, _exceptionable = true) => ["string" === typeof input.$ref && RegExp(/^#\/components\/responses\/(.*)/).test(input.$ref) || $report(_exceptionable, {
|
6646
6646
|
path: _path + ".$ref",
|
6647
|
-
expected: "
|
6647
|
+
expected: "`#/components/responses/${string}`",
|
6648
6648
|
value: input.$ref
|
6649
6649
|
}), undefined === input.title || "string" === typeof input.title || $report(_exceptionable, {
|
6650
6650
|
path: _path + ".title",
|
@@ -6910,7 +6910,7 @@ class MigrateApplication {
|
|
6910
6910
|
}).every(flag => flag)].every(flag => flag);
|
6911
6911
|
const $vo196 = (input, _path, _exceptionable = true) => ["string" === typeof input.$ref && RegExp(/^#\/components\/pathItems\/(.*)/).test(input.$ref) || $report(_exceptionable, {
|
6912
6912
|
path: _path + ".$ref",
|
6913
|
-
expected: "
|
6913
|
+
expected: "`#/components/pathItems/${string}`",
|
6914
6914
|
value: input.$ref
|
6915
6915
|
}), undefined === input.title || "string" === typeof input.title || $report(_exceptionable, {
|
6916
6916
|
path: _path + ".title",
|
@@ -37,6 +37,11 @@ exports.NEST_TEMPLATE = [
|
|
37
37
|
"file": "settings.json",
|
38
38
|
"content": "{\r\n \"editor.tabSize\": 2,\r\n \"editor.formatOnSave\": true,\r\n \"[javascript][typescript]\": {\r\n \"editor.defaultFormatter\": \"esbenp.prettier-vscode\",\r\n \"editor.codeActionsOnSave\": {\r\n \"source.fixAll.eslint\": \"explicit\"\r\n },\r\n }\r\n}"
|
39
39
|
},
|
40
|
+
{
|
41
|
+
"location": "docs/benchmarks",
|
42
|
+
"file": "AMD Ryzen 9 7940HS w Radeon 780M Graphics.md",
|
43
|
+
"content": "# Benchmark Report\r\n> Generated by [`@nestia/e2e`](https://github.com/samchon/nestia)\r\n\r\n - Specifications\r\n - CPU: AMD Ryzen 9 7940HS w/ Radeon 780M Graphics \r\n - RAM: 31 GB\r\n - NodeJS Version: v20.10.0\r\n - Backend Server: 1 core / 1 thread\r\n - Arguments\r\n - Count: 1,024\r\n - Threads: 4\r\n - Simultaneous: 32\r\n - Time\r\n - Start: 2024-06-21T13:24:13.810Z\r\n - Complete: 2024-06-21T13:24:16.611Z\r\n - Elapsed: 2,801 ms\r\n\r\nType | Count | Success | Mean. | Stdev. | Minimum | Maximum\r\n----|----|----|----|----|----|----\r\nTotal | 3,955 | 3,955 | 20.34 | 24.96 | 2 | 152\r\n\r\n> Unit: milliseconds\r\n\r\n## Endpoints\r\nType | Count | Success | Mean. | Stdev. | Minimum | Maximum\r\n----|----|----|----|----|----|----\r\nPATCH /bbs/articles/:section | 656 | 656 | 50.46 | 40.03 | 2 | 152\r\nGET /bbs/articles/:section/:id | 43 | 43 | 18.39 | 5.2 | 9 | 31\r\nPUT /bbs/articles/:section/:id | 22 | 22 | 16.77 | 3.46 | 12 | 28\r\nPOST /bbs/articles/:section | 3,234 | 3,234 | 14.28 | 14.68 | 6 | 132\r\n\r\n> Unit: milliseconds\r\n\r\n## Failures\r\nMethod | Path | Count | Failures\r\n-------|------|-------|----------"
|
44
|
+
},
|
40
45
|
{
|
41
46
|
"location": "",
|
42
47
|
"file": "LICENSE",
|
@@ -50,7 +55,7 @@ exports.NEST_TEMPLATE = [
|
|
50
55
|
{
|
51
56
|
"location": "",
|
52
57
|
"file": "package.json",
|
53
|
-
"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 \"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.
|
58
|
+
"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.2.5\",\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.0\",\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.0\",\r\n \"typescript\": \"<5.5.0\",\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.2.5\",\r\n \"@nestia/fetcher\": \"^3.2.5\",\r\n \"@nestjs/common\": \"^10.3.9\",\r\n \"@nestjs/core\": \"^10.3.9\",\r\n \"@nestjs/platform-express\": \"^10.3.9\",\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.1\",\r\n \"tstl\": \"^3.0.0\",\r\n \"typia\": \"^6.2.1\",\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}"
|
54
59
|
},
|
55
60
|
{
|
56
61
|
"location": "packages/api",
|
@@ -65,7 +70,7 @@ exports.NEST_TEMPLATE = [
|
|
65
70
|
{
|
66
71
|
"location": "packages/api",
|
67
72
|
"file": "package.json",
|
68
|
-
"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 \"
|
73
|
+
"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.2.5\",\r\n \"tgrid\": \"^1.0.1\",\r\n \"typia\": \"^6.2.1\"\r\n }\r\n}"
|
69
74
|
},
|
70
75
|
{
|
71
76
|
"location": "packages/api",
|
@@ -85,7 +90,7 @@ exports.NEST_TEMPLATE = [
|
|
85
90
|
{
|
86
91
|
"location": "",
|
87
92
|
"file": "README.md",
|
88
|
-
"content": "# Nestia Template\r\n## Outline\r\n[](https://github.com/samchon/nestia-start/actions?query=workflow%3Abuild)\r\n\r\nA template repository for backend projects using [nestia](https://github.com/samchon/nestia).\r\n\r\nYou can create a new project from this boilerplate by running below command:\r\n\r\n```bash\r\nnpx nestia start <directory>\r\n```\r\n\r\nFor reference, this is a minimal boilerplate project concentrating only on [nestia](https://github.com/samchon/nestia) SDK generation. \r\n\r\nIf you wanna much detailed boilerplate project, visit [`@samchon/backend`](https://github.com/samchon/backend).\r\n\r\n\r\n\r\n\r\n## Directories and Files\r\nThis template project has categorized directories like below.\r\n\r\nAs you can see from the below, all of the Backend source files are placed into the [src](src/) directory. When you build the TypeScript source files, compiled files would be placed into the `lib` directory following the [tsconfig.json](tsconfig.json) configuration. Otherwise you build client [SDK](#32-sdk) library for npm publishing and their compiled files would be placed into the [packages](packages) directory.\r\n\r\n - [packages/api/](packages/api): SDK module built by `npm run build:api`\r\n - [src/](src): Backend source directory\r\n - [src/api/](src/api/): Client SDK that would be published to the `@ORGANIZATION/PROJECT-api`\r\n - [**src/api/functional/**](src/api/functional/): API functions generated by the [`nestia`](https://github.com/samchon/nestia)\r\n - [**src/api/structures/**](src/api/structures/): DTO structures\r\n - [src/controllers/](src/controllers/): Controller classes of the Main Program\r\n - [**test/**](test): Test Automation Program\r\n - [nestia.config.ts](nestia.config.ts): Configuration file of [`nestia`](https://github.com/samchon/nestia)\r\n - [package.json](package.json): NPM configuration\r\n - [tsconfig.json](tsconfig.json): TypeScript configuration for the main program\r\n - [tsconfig.api.json](tsconfig.api.json): TypeScript configuration for the SDK generation\r\n\r\n\r\n\r\n\r\n## NPM Run Commands\r\nList of the run commands defined in the [package.json](package.json) are like below:\r\n\r\n - `build`: Build everything\r\n - `build:api`: Build client SDK libray for the client developers\r\n - `build:main`: Build main program (`src` directory)\r\n - `build:sdk`: Build SDK into main program only\r\n - `build:swagger`: Build Swagger Documents\r\n - `build:test` Build test automation program (`test` directory)\r\n - `dev`: Incremental build for development (test program)\r\n - `eslint` & `eslint:fix` & `prettier`: Prettier and ESLint execution\r\n - `start`: Start local NestJS server\r\n - `test`: Run test automation program\r\n\r\n\r\n\r\n\r\n## Specialization\r\nTransform this template project to be yours.\r\n\r\nWhen you've created a new backend project through this template project, you can specialize it to be suitable for you by changing some words. Replace below words through IDE specific function like `Edit > Replace in Files` (*Ctrl + Shift + H*), who've been supported by the VSCode.\r\n\r\n| Before | After\r\n|-----------------|----------------------------------------\r\n| ORGANIZATION | Your account or corporation name\r\n| PROJECT | Your own project name\r\n| AUTHOR | Author name\r\n| https://github.com/samchon/nestia-start | Your repository URL\r\n\r\n\r\n\r\n\r\n## Test Driven Development\r\nWith [nestia](https://github.com/samchon/nestia) helps to accomplish TDD (Test Driven Development). \r\n\r\nJust define DTOs and API controllers' methods (only declarations) first. After the definitions, and build SDK (Software Development Kit) through [nestia](https://github.com/samchon/nestia) (`npm run build:sdk`). After buildling those SDK, develop test automation program using the SDK, following use-case scenarios in the framework of client side.\r\n\r\nDuring the test automation program development, you can find that which API is mis-designed or which requirement analysis is not exact. Development of the main program must be the last step after such validation process during TDD.\r\n\r\n> Visit the [samchon/backend](https://github.com/samchon/backend), then you may find much detailed story about this TDD.\r\n>\r\n> 1. Definitions\r\n> 2. SDK\r\n> 3. Test Automation Program\r\n> 4. Main Program\r\n\r\n```typescript\r\nimport
|
93
|
+
"content": "# Nestia Template\r\n## Outline\r\n[](https://github.com/samchon/nestia-start/actions?query=workflow%3Abuild)\r\n\r\nA template repository for backend projects using [nestia](https://github.com/samchon/nestia).\r\n\r\nYou can create a new project from this boilerplate by running below command:\r\n\r\n```bash\r\nnpx nestia start <directory>\r\n```\r\n\r\nFor reference, this is a minimal boilerplate project concentrating only on [nestia](https://github.com/samchon/nestia) SDK generation. \r\n\r\nIf you wanna much detailed boilerplate project, visit [`@samchon/backend`](https://github.com/samchon/backend).\r\n\r\n\r\n\r\n\r\n## Directories and Files\r\nThis template project has categorized directories like below.\r\n\r\nAs you can see from the below, all of the Backend source files are placed into the [src](src/) directory. When you build the TypeScript source files, compiled files would be placed into the `lib` directory following the [tsconfig.json](tsconfig.json) configuration. Otherwise you build client [SDK](#32-sdk) library for npm publishing and their compiled files would be placed into the [packages](packages) directory.\r\n\r\n - [packages/api/](packages/api): SDK module built by `npm run build:api`\r\n - [src/](src): Backend source directory\r\n - [src/api/](src/api/): Client SDK that would be published to the `@ORGANIZATION/PROJECT-api`\r\n - [**src/api/functional/**](src/api/functional/): API functions generated by the [`nestia`](https://github.com/samchon/nestia)\r\n - [**src/api/structures/**](src/api/structures/): DTO structures\r\n - [src/controllers/](src/controllers/): Controller classes of the Main Program\r\n - [**test/**](test): Test Automation Program\r\n - [nestia.config.ts](nestia.config.ts): Configuration file of [`nestia`](https://github.com/samchon/nestia)\r\n - [package.json](package.json): NPM configuration\r\n - [tsconfig.json](tsconfig.json): TypeScript configuration for the main program\r\n - [tsconfig.api.json](tsconfig.api.json): TypeScript configuration for the SDK generation\r\n\r\n\r\n\r\n\r\n## NPM Run Commands\r\nList of the run commands defined in the [package.json](package.json) are like below:\r\n\r\n - `build`: Build everything\r\n - `build:api`: Build client SDK libray for the client developers\r\n - `build:main`: Build main program (`src` directory)\r\n - `build:sdk`: Build SDK into main program only\r\n - `build:swagger`: Build Swagger Documents\r\n - `build:test` Build test automation program (`test` directory)\r\n - `dev`: Incremental build for development (test program)\r\n - `eslint` & `eslint:fix` & `prettier`: Prettier and ESLint execution\r\n - `start`: Start local NestJS server\r\n - `test`: Run test automation program\r\n - `benchmark`: Run performance benchmark program\r\n\r\n\r\n\r\n\r\n## Specialization\r\nTransform this template project to be yours.\r\n\r\nWhen you've created a new backend project through this template project, you can specialize it to be suitable for you by changing some words. Replace below words through IDE specific function like `Edit > Replace in Files` (*Ctrl + Shift + H*), who've been supported by the VSCode.\r\n\r\n| Before | After\r\n|-----------------|----------------------------------------\r\n| ORGANIZATION | Your account or corporation name\r\n| PROJECT | Your own project name\r\n| AUTHOR | Author name\r\n| https://github.com/samchon/nestia-start | Your repository URL\r\n\r\n\r\n\r\n\r\n## Test Driven Development\r\nWith [nestia](https://github.com/samchon/nestia) helps to accomplish TDD (Test Driven Development). \r\n\r\nJust define DTOs and API controllers' methods (only declarations) first. After the definitions, and build SDK (Software Development Kit) through [nestia](https://github.com/samchon/nestia) (`npm run build:sdk`). After buildling those SDK, develop test automation program using the SDK, following use-case scenarios in the framework of client side.\r\n\r\nDuring the test automation program development, you can find that which API is mis-designed or which requirement analysis is not exact. Development of the main program must be the last step after such validation process during TDD.\r\n\r\n> Visit the [samchon/backend](https://github.com/samchon/backend), then you may find much detailed story about this TDD.\r\n>\r\n> 1. Definitions\r\n> 2. SDK\r\n> 3. Test Automation Program\r\n> 4. Main Program\r\n\r\n```typescript\r\nimport {\r\n ArrayUtil,\r\n GaffComparator,\r\n RandomGenerator,\r\n TestValidator,\r\n} from \"@nestia/e2e\";\r\n\r\nimport api from \"@ORGANIZATION/PROJECT-api/lib/index\";\r\nimport { IBbsArticle } from \"@ORGANIZATION/PROJECT-api/lib/structures/bbs/IBbsArticle\";\r\nimport { IPage } from \"@ORGANIZATION/PROJECT-api/lib/structures/common/IPage\";\r\n\r\nexport async function test_api_bbs_article_index_sort(\r\n connection: api.IConnection,\r\n): Promise<void> {\r\n // GENERATE 100 ARTICLES\r\n const section: string = \"general\";\r\n await ArrayUtil.asyncRepeat(100)(() =>\r\n api.functional.bbs.articles.create(connection, section, {\r\n writer: RandomGenerator.name(),\r\n title: RandomGenerator.paragraph(5)(),\r\n body: RandomGenerator.content(8)()(),\r\n format: \"txt\",\r\n files: [],\r\n password: RandomGenerator.alphabets(8),\r\n }),\r\n );\r\n\r\n // PREPARE VALIDATOR\r\n const validator = TestValidator.sort(\"BbsArticleProvider.index()\")(async (\r\n sort: IPage.Sort<IBbsArticle.IRequest.SortableColumns>,\r\n ) => {\r\n const page: IPage<IBbsArticle.ISummary> =\r\n await api.functional.bbs.articles.index(connection, section, {\r\n limit: 100,\r\n sort,\r\n });\r\n return page.data;\r\n });\r\n\r\n // DO VALIDATE\r\n const components = [\r\n validator(\"created_at\")(GaffComparator.dates((x) => x.created_at)),\r\n validator(\"updated_at\")(GaffComparator.dates((x) => x.updated_at)),\r\n validator(\"title\")(GaffComparator.strings((x) => x.title)),\r\n validator(\"writer\")(GaffComparator.strings((x) => x.writer)),\r\n validator(\r\n \"writer\",\r\n \"title\",\r\n )(GaffComparator.strings((x) => [x.writer, x.title])),\r\n ];\r\n for (const comp of components) {\r\n await comp(\"+\", false);\r\n await comp(\"-\", false);\r\n }\r\n}\r\n```\r\n\r\nFor reference, if you run `npm run benchmark` command, your test functions defined in the [test/features/api](test/features/api) directory would be utilized for performance benchmarking. If you want to see the performance bench result earlier, visit below link please:\r\n\r\n - [docs/benchmarks/AMD Ryzen 9 7940HS w Radeon 780M Graphics.md](https://github.com/samchon/nestia-start/blob/master/docs/benchmarks/AMD%20Ryzen%209%207940HS%20w%20Radeon%20780M%20Graphics.md)"
|
89
94
|
},
|
90
95
|
{
|
91
96
|
"location": "src/api",
|
@@ -162,15 +167,25 @@ exports.NEST_TEMPLATE = [
|
|
162
167
|
"file": "MapUtil.ts",
|
163
168
|
"content": "export namespace MapUtil {\r\n export function take<Key, T>(\r\n dict: Map<Key, T>,\r\n key: Key,\r\n generator: () => T,\r\n ): T {\r\n const oldbie: T | undefined = dict.get(key);\r\n if (oldbie) return oldbie;\r\n\r\n const value: T = generator();\r\n dict.set(key, value);\r\n return value;\r\n }\r\n}\r\n"
|
164
169
|
},
|
170
|
+
{
|
171
|
+
"location": "test/benchmark",
|
172
|
+
"file": "index.ts",
|
173
|
+
"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"
|
174
|
+
},
|
175
|
+
{
|
176
|
+
"location": "test/benchmark",
|
177
|
+
"file": "servant.ts",
|
178
|
+
"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"
|
179
|
+
},
|
165
180
|
{
|
166
181
|
"location": "test/helpers",
|
167
182
|
"file": "ArgumentParser.ts",
|
168
|
-
"content": "import commander from \"commander\";\r\nimport * as inquirer from \"inquirer\";\r\n\r\nexport namespace ArgumentParser {\r\n export type Inquiry<T> = (\r\n command: commander.Command,\r\n prompt: (opt?: inquirer.StreamOptions) => inquirer.PromptModule,\r\n action: (closure: (options: Partial<T>) => Promise<T>) => Promise<T>,\r\n ) => Promise<T>;\r\n\r\n export interface Prompt {\r\n select: (\r\n name: string,\r\n ) => (\r\n message: string,\r\n ) => <Choice extends string>(choices: Choice[]) => Promise<Choice>;\r\n boolean: (name: string) => (message: string) => Promise<boolean>;\r\n }\r\n\r\n export const parse = async <T>(\r\n inquiry: (\r\n command: commander.Command,\r\n prompt: Prompt,\r\n action: (closure: (options: Partial<T>) => Promise<T>) => Promise<T>,\r\n ) => Promise<T>,\r\n ): Promise<T> => {\r\n // TAKE OPTIONS\r\n const action = (closure: (options: Partial<T>) => Promise<T>) =>\r\n new Promise<T>((resolve, reject) => {\r\n commander.program.action(async (options) => {\r\n try {\r\n resolve(await closure(options));\r\n } catch (exp) {\r\n reject(exp);\r\n }\r\n });\r\n commander.program.parseAsync().catch(reject);\r\n });\r\n\r\n const select =\r\n (name: string) =>\r\n (message: string) =>\r\n async <Choice extends string>(choices: Choice[]): Promise<Choice> =>\r\n (\r\n await inquirer.createPromptModule()({\r\n type: \"list\",\r\n name,\r\n message,\r\n choices,\r\n })\r\n )[name];\r\n const boolean = (name: string) => async (message: string) =>\r\n (\r\n await inquirer.createPromptModule()({\r\n type: \"confirm\",\r\n name,\r\n message,\r\n })\r\n )[name] as boolean;\r\n\r\n const output: T | Error = await (async () => {\r\n try {\r\n return await inquiry(commander.program
|
183
|
+
"content": "import commander from \"commander\";\r\nimport * as inquirer from \"inquirer\";\r\n\r\nexport namespace ArgumentParser {\r\n export type Inquiry<T> = (\r\n command: commander.Command,\r\n prompt: (opt?: inquirer.StreamOptions) => inquirer.PromptModule,\r\n action: (closure: (options: Partial<T>) => Promise<T>) => Promise<T>,\r\n ) => Promise<T>;\r\n\r\n export interface Prompt {\r\n select: (\r\n name: string,\r\n ) => (\r\n message: string,\r\n ) => <Choice extends string>(choices: Choice[]) => Promise<Choice>;\r\n boolean: (name: string) => (message: string) => Promise<boolean>;\r\n number: (name: string) => (message: string) => Promise<number>;\r\n }\r\n\r\n export const parse = async <T>(\r\n inquiry: (\r\n command: commander.Command,\r\n prompt: Prompt,\r\n action: (closure: (options: Partial<T>) => Promise<T>) => Promise<T>,\r\n ) => Promise<T>,\r\n ): Promise<T> => {\r\n // TAKE OPTIONS\r\n const action = (closure: (options: Partial<T>) => Promise<T>) =>\r\n new Promise<T>((resolve, reject) => {\r\n commander.program.action(async (options) => {\r\n try {\r\n resolve(await closure(options));\r\n } catch (exp) {\r\n reject(exp);\r\n }\r\n });\r\n commander.program.parseAsync().catch(reject);\r\n });\r\n\r\n const select =\r\n (name: string) =>\r\n (message: string) =>\r\n async <Choice extends string>(choices: Choice[]): Promise<Choice> =>\r\n (\r\n await inquirer.createPromptModule()({\r\n type: \"list\",\r\n name,\r\n message,\r\n choices,\r\n })\r\n )[name];\r\n const boolean = (name: string) => async (message: string) =>\r\n (\r\n await inquirer.createPromptModule()({\r\n type: \"confirm\",\r\n name,\r\n message,\r\n })\r\n )[name] as boolean;\r\n const number = (name: string) => async (message: string) =>\r\n Number(\r\n (\r\n await inquirer.createPromptModule()({\r\n type: \"number\",\r\n name,\r\n message,\r\n })\r\n )[name],\r\n );\r\n\r\n const output: T | Error = await (async () => {\r\n try {\r\n return await inquiry(\r\n commander.program,\r\n { select, boolean, number },\r\n action,\r\n );\r\n } catch (error) {\r\n return error as Error;\r\n }\r\n })();\r\n\r\n // RETURNS\r\n if (output instanceof Error) throw output;\r\n return output;\r\n };\r\n}\r\n"
|
169
184
|
},
|
170
185
|
{
|
171
186
|
"location": "test",
|
172
187
|
"file": "index.ts",
|
173
|
-
"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,
|
188
|
+
"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"
|
174
189
|
},
|
175
190
|
{
|
176
191
|
"location": "test",
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"NEST_TEMPLATE.js","sourceRoot":"","sources":["../../src/bundles/NEST_TEMPLATE.ts"],"names":[],"mappings":";;;AAAa,QAAA,aAAa,GAAG;IAC3B;QACE,UAAU,EAAE,EAAE;QACd,MAAM,EAAE,MAAM;QACd,SAAS,EAAE,+CAA+C;KAC3D;IACD;QACE,UAAU,EAAE,EAAE;QACd,MAAM,EAAE,eAAe;QACvB,SAAS,EAAE,m1BAAm1B;KAC/1B;IACD;QACE,UAAU,EAAE,mBAAmB;QAC/B,MAAM,EAAE,WAAW;QACnB,SAAS,EAAE,k+BAAk+B;KAC9+B;IACD;QACE,UAAU,EAAE,EAAE;QACd,MAAM,EAAE,YAAY;QACpB,SAAS,EAAE,iHAAiH;KAC7H;IACD;QACE,UAAU,EAAE,EAAE;QACd,MAAM,EAAE,iBAAiB;QACzB,SAAS,EAAE,iIAAiI;KAC7I;IACD;QACE,UAAU,EAAE,SAAS;QACrB,MAAM,EAAE,aAAa;QACrB,SAAS,EAAE,irCAAirC;KAC7rC;IACD;QACE,UAAU,EAAE,SAAS;QACrB,MAAM,EAAE,eAAe;QACvB,SAAS,EAAE,qRAAqR;KACjS;IACD;QACE,UAAU,EAAE,EAAE;QACd,MAAM,EAAE,SAAS;QACjB,SAAS,EAAE,inCAAinC;KAC7nC;IACD;QACE,UAAU,EAAE,EAAE;QACd,MAAM,EAAE,kBAAkB;QAC1B,SAAS,EAAE,woBAAwoB;KACppB;IACD;QACE,UAAU,EAAE,EAAE;QACd,MAAM,EAAE,cAAc;QACtB,SAAS,EAAE
|
1
|
+
{"version":3,"file":"NEST_TEMPLATE.js","sourceRoot":"","sources":["../../src/bundles/NEST_TEMPLATE.ts"],"names":[],"mappings":"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"}
|
@@ -30,7 +30,7 @@ exports.SDK_TEMPLATE = [
|
|
30
30
|
{
|
31
31
|
"location": "",
|
32
32
|
"file": "package.json",
|
33
|
-
"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.2.1\",\r\n \"typia\": \"^6.1
|
33
|
+
"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.2.5\",\r\n \"tgrid\": \"^1.0.1\",\r\n \"typia\": \"^6.2.1\"\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.0\",\r\n \"typescript\": \"<5.5.0\",\r\n \"typescript-transform-paths\": \"^3.4.6\"\r\n }\r\n}"
|
34
34
|
},
|
35
35
|
{
|
36
36
|
"location": "",
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"SDK_TEMPLATE.js","sourceRoot":"","sources":["../../src/bundles/SDK_TEMPLATE.ts"],"names":[],"mappings":";;;AAAa,QAAA,YAAY,GAAG;IAC1B;QACE,UAAU,EAAE,EAAE;QACd,MAAM,EAAE,YAAY;QACpB,SAAS,EAAE,mFAAmF;KAC/F;IACD;QACE,UAAU,EAAE,SAAS;QACrB,MAAM,EAAE,aAAa;QACrB,SAAS,EAAE,oxBAAoxB;KAChyB;IACD;QACE,UAAU,EAAE,SAAS;QACrB,MAAM,EAAE,eAAe;QACvB,SAAS,EAAE,sRAAsR;KAClS;IACD;QACE,UAAU,EAAE,EAAE;QACd,MAAM,EAAE,UAAU;QAClB,SAAS,EAAE,4rBAA4rB;KACxsB;IACD;QACE,UAAU,EAAE,EAAE;QACd,MAAM,EAAE,SAAS;QACjB,SAAS,EAAE,inCAAinC;KAC7nC;IACD;QACE,UAAU,EAAE,EAAE;QACd,MAAM,EAAE,cAAc;QACtB,SAAS,EAAE,
|
1
|
+
{"version":3,"file":"SDK_TEMPLATE.js","sourceRoot":"","sources":["../../src/bundles/SDK_TEMPLATE.ts"],"names":[],"mappings":";;;AAAa,QAAA,YAAY,GAAG;IAC1B;QACE,UAAU,EAAE,EAAE;QACd,MAAM,EAAE,YAAY;QACpB,SAAS,EAAE,mFAAmF;KAC/F;IACD;QACE,UAAU,EAAE,SAAS;QACrB,MAAM,EAAE,aAAa;QACrB,SAAS,EAAE,oxBAAoxB;KAChyB;IACD;QACE,UAAU,EAAE,SAAS;QACrB,MAAM,EAAE,eAAe;QACvB,SAAS,EAAE,sRAAsR;KAClS;IACD;QACE,UAAU,EAAE,EAAE;QACd,MAAM,EAAE,UAAU;QAClB,SAAS,EAAE,4rBAA4rB;KACxsB;IACD;QACE,UAAU,EAAE,EAAE;QACd,MAAM,EAAE,SAAS;QACjB,SAAS,EAAE,inCAAinC;KAC7nC;IACD;QACE,UAAU,EAAE,EAAE;QACd,MAAM,EAAE,cAAc;QACtB,SAAS,EAAE,wvEAAwvE;KACpwE;IACD;QACE,UAAU,EAAE,EAAE;QACd,MAAM,EAAE,oBAAoB;QAC5B,SAAS,EAAE,geAAge;KAC5e;IACD;QACE,UAAU,EAAE,EAAE;QACd,MAAM,EAAE,WAAW;QACnB,SAAS,EAAE,oyHAAoyH;KAChzH;IACD;QACE,UAAU,EAAE,EAAE;QACd,MAAM,EAAE,kBAAkB;QAC1B,SAAS,EAAE,wqBAAwqB;KACprB;IACD;QACE,UAAU,EAAE,KAAK;QACjB,MAAM,EAAE,cAAc;QACtB,SAAS,EAAE,oDAAoD;KAChE;IACD;QACE,UAAU,EAAE,KAAK;QACjB,MAAM,EAAE,gBAAgB;QACxB,SAAS,EAAE,2DAA2D;KACvE;IACD;QACE,UAAU,EAAE,KAAK;QACjB,MAAM,EAAE,UAAU;QAClB,SAAS,EAAE,kGAAkG;KAC9G;IACD;QACE,UAAU,EAAE,KAAK;QACjB,MAAM,EAAE,WAAW;QACnB,SAAS,EAAE,kIAAkI;KAC9I;IACD;QACE,UAAU,EAAE,KAAK;QACjB,MAAM,EAAE,cAAc;QACtB,SAAS,EAAE,yDAAyD;KACrE;IACD;QACE,UAAU,EAAE,EAAE;QACd,MAAM,EAAE,cAAc;QACtB,SAAS,EAAE,0hsDAA0hsD;KACtisD;IACD;QACE,UAAU,EAAE,MAAM;QAClB,MAAM,EAAE,UAAU;QAClB,SAAS,EAAE,i6EAAi6E;KAC76E;IACD;QACE,UAAU,EAAE,MAAM;QAClB,MAAM,EAAE,WAAW;QACnB,SAAS,EAAE,EAAE;KACd;IACD;QACE,UAAU,EAAE,MAAM;QAClB,MAAM,EAAE,UAAU;QAClB,SAAS,EAAE,uxBAAuxB;KACnyB;IACD;QACE,UAAU,EAAE,MAAM;QAClB,MAAM,EAAE,YAAY;QACpB,SAAS,EAAE,+lBAA+lB;KAC3mB;IACD;QACE,UAAU,EAAE,MAAM;QAClB,MAAM,EAAE,eAAe;QACvB,SAAS,EAAE,uMAAuM;KACnN;IACD;QACE,UAAU,EAAE,MAAM;QAClB,MAAM,EAAE,eAAe;QACvB,SAAS,EAAE,odAAod;KAChe;IACD;QACE,UAAU,EAAE,YAAY;QACxB,MAAM,EAAE,mBAAmB;QAC3B,SAAS,EAAE,gtEAAgtE;KAC5tE;IACD;QACE,UAAU,EAAE,EAAE;QACd,MAAM,EAAE,eAAe;QACvB,SAAS,EAAE,24WAA24W;KACv5W;CACF,CAAA"}
|
package/lib/utils/StringUtil.js
CHANGED
@@ -44,10 +44,11 @@ var StringUtil;
|
|
44
44
|
StringUtil.escapeNonVariableSymbols = (str) => {
|
45
45
|
for (const [before, after] of VARIABLE_REPLACERS)
|
46
46
|
str = str.split(before).join(after);
|
47
|
-
for (let i = 0; i <= 9; ++i)
|
48
|
-
str
|
49
|
-
|
50
|
-
|
47
|
+
for (let i = 0; i <= 9; ++i)
|
48
|
+
if (str[0] === i.toString()) {
|
49
|
+
str = "_" + str;
|
50
|
+
break;
|
51
|
+
}
|
51
52
|
str = str.trim();
|
52
53
|
if (str === "")
|
53
54
|
return "_empty_";
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"StringUtil.js","sourceRoot":"","sources":["../../src/utils/StringUtil.ts"],"names":[],"mappings":";;;AAAA,uEAAoE;AAEpE,IAAiB,UAAU,
|
1
|
+
{"version":3,"file":"StringUtil.js","sourceRoot":"","sources":["../../src/utils/StringUtil.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@nestia/migrate",
|
3
|
-
"version": "0.13.
|
3
|
+
"version": "0.13.17",
|
4
4
|
"description": "Migration program from swagger to NestJS",
|
5
5
|
"main": "lib/index.js",
|
6
6
|
"typings": "lib/index.d.ts",
|
@@ -36,18 +36,20 @@
|
|
36
36
|
},
|
37
37
|
"homepage": "https://nestia.io",
|
38
38
|
"devDependencies": {
|
39
|
-
"@nestia/core": "^3.2.
|
40
|
-
"@nestia/e2e": "^0.
|
41
|
-
"@nestia/fetcher": "^3.2.
|
39
|
+
"@nestia/core": "^3.2.5",
|
40
|
+
"@nestia/e2e": "^0.6.0",
|
41
|
+
"@nestia/fetcher": "^3.2.5",
|
42
42
|
"@nestjs/common": "^10.3.8",
|
43
43
|
"@nestjs/core": "^10.3.8",
|
44
44
|
"@nestjs/platform-express": "^10.3.8",
|
45
45
|
"@nestjs/platform-fastify": "^10.3.8",
|
46
46
|
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
|
47
|
+
"@types/cli-progress": "^3.11.5",
|
47
48
|
"@types/express": "^4.17.21",
|
48
49
|
"@types/inquirer": "^9.0.7",
|
49
50
|
"@types/node": "^20.3.3",
|
50
51
|
"@types/swagger-ui-express": "^4.1.6",
|
52
|
+
"cli-progress": "^3.12.0",
|
51
53
|
"dotenv": "^16.3.1",
|
52
54
|
"dotenv-expand": "^10.0.0",
|
53
55
|
"express": "^4.19.2",
|
@@ -55,6 +57,7 @@
|
|
55
57
|
"serialize-error": "^4.1.0",
|
56
58
|
"source-map-support": "^0.5.21",
|
57
59
|
"swagger-ui-express": "^5.0.0",
|
60
|
+
"tgrid": "^1.0.1",
|
58
61
|
"ts-node": "^10.9.1",
|
59
62
|
"ts-patch": "^3.1.0",
|
60
63
|
"typescript-transform-paths": "^3.4.6"
|
@@ -65,8 +68,8 @@
|
|
65
68
|
"inquirer": "8.2.5",
|
66
69
|
"prettier": "^3.2.5",
|
67
70
|
"tstl": "^3.0.0",
|
68
|
-
"typescript": "
|
69
|
-
"typia": "^6.
|
71
|
+
"typescript": "<5.5.0",
|
72
|
+
"typia": "^6.2.1"
|
70
73
|
},
|
71
74
|
"files": [
|
72
75
|
"lib",
|
@@ -34,6 +34,11 @@ export const NEST_TEMPLATE = [
|
|
34
34
|
"file": "settings.json",
|
35
35
|
"content": "{\r\n \"editor.tabSize\": 2,\r\n \"editor.formatOnSave\": true,\r\n \"[javascript][typescript]\": {\r\n \"editor.defaultFormatter\": \"esbenp.prettier-vscode\",\r\n \"editor.codeActionsOnSave\": {\r\n \"source.fixAll.eslint\": \"explicit\"\r\n },\r\n }\r\n}"
|
36
36
|
},
|
37
|
+
{
|
38
|
+
"location": "docs/benchmarks",
|
39
|
+
"file": "AMD Ryzen 9 7940HS w Radeon 780M Graphics.md",
|
40
|
+
"content": "# Benchmark Report\r\n> Generated by [`@nestia/e2e`](https://github.com/samchon/nestia)\r\n\r\n - Specifications\r\n - CPU: AMD Ryzen 9 7940HS w/ Radeon 780M Graphics \r\n - RAM: 31 GB\r\n - NodeJS Version: v20.10.0\r\n - Backend Server: 1 core / 1 thread\r\n - Arguments\r\n - Count: 1,024\r\n - Threads: 4\r\n - Simultaneous: 32\r\n - Time\r\n - Start: 2024-06-21T13:24:13.810Z\r\n - Complete: 2024-06-21T13:24:16.611Z\r\n - Elapsed: 2,801 ms\r\n\r\nType | Count | Success | Mean. | Stdev. | Minimum | Maximum\r\n----|----|----|----|----|----|----\r\nTotal | 3,955 | 3,955 | 20.34 | 24.96 | 2 | 152\r\n\r\n> Unit: milliseconds\r\n\r\n## Endpoints\r\nType | Count | Success | Mean. | Stdev. | Minimum | Maximum\r\n----|----|----|----|----|----|----\r\nPATCH /bbs/articles/:section | 656 | 656 | 50.46 | 40.03 | 2 | 152\r\nGET /bbs/articles/:section/:id | 43 | 43 | 18.39 | 5.2 | 9 | 31\r\nPUT /bbs/articles/:section/:id | 22 | 22 | 16.77 | 3.46 | 12 | 28\r\nPOST /bbs/articles/:section | 3,234 | 3,234 | 14.28 | 14.68 | 6 | 132\r\n\r\n> Unit: milliseconds\r\n\r\n## Failures\r\nMethod | Path | Count | Failures\r\n-------|------|-------|----------"
|
41
|
+
},
|
37
42
|
{
|
38
43
|
"location": "",
|
39
44
|
"file": "LICENSE",
|
@@ -47,7 +52,7 @@ export const NEST_TEMPLATE = [
|
|
47
52
|
{
|
48
53
|
"location": "",
|
49
54
|
"file": "package.json",
|
50
|
-
"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 \"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.
|
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.2.5\",\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.0\",\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.0\",\r\n \"typescript\": \"<5.5.0\",\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.2.5\",\r\n \"@nestia/fetcher\": \"^3.2.5\",\r\n \"@nestjs/common\": \"^10.3.9\",\r\n \"@nestjs/core\": \"^10.3.9\",\r\n \"@nestjs/platform-express\": \"^10.3.9\",\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.1\",\r\n \"tstl\": \"^3.0.0\",\r\n \"typia\": \"^6.2.1\",\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}"
|
51
56
|
},
|
52
57
|
{
|
53
58
|
"location": "packages/api",
|
@@ -62,7 +67,7 @@ export const NEST_TEMPLATE = [
|
|
62
67
|
{
|
63
68
|
"location": "packages/api",
|
64
69
|
"file": "package.json",
|
65
|
-
"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 \"
|
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.2.5\",\r\n \"tgrid\": \"^1.0.1\",\r\n \"typia\": \"^6.2.1\"\r\n }\r\n}"
|
66
71
|
},
|
67
72
|
{
|
68
73
|
"location": "packages/api",
|
@@ -82,7 +87,7 @@ export const NEST_TEMPLATE = [
|
|
82
87
|
{
|
83
88
|
"location": "",
|
84
89
|
"file": "README.md",
|
85
|
-
"content": "# Nestia Template\r\n## Outline\r\n[](https://github.com/samchon/nestia-start/actions?query=workflow%3Abuild)\r\n\r\nA template repository for backend projects using [nestia](https://github.com/samchon/nestia).\r\n\r\nYou can create a new project from this boilerplate by running below command:\r\n\r\n```bash\r\nnpx nestia start <directory>\r\n```\r\n\r\nFor reference, this is a minimal boilerplate project concentrating only on [nestia](https://github.com/samchon/nestia) SDK generation. \r\n\r\nIf you wanna much detailed boilerplate project, visit [`@samchon/backend`](https://github.com/samchon/backend).\r\n\r\n\r\n\r\n\r\n## Directories and Files\r\nThis template project has categorized directories like below.\r\n\r\nAs you can see from the below, all of the Backend source files are placed into the [src](src/) directory. When you build the TypeScript source files, compiled files would be placed into the `lib` directory following the [tsconfig.json](tsconfig.json) configuration. Otherwise you build client [SDK](#32-sdk) library for npm publishing and their compiled files would be placed into the [packages](packages) directory.\r\n\r\n - [packages/api/](packages/api): SDK module built by `npm run build:api`\r\n - [src/](src): Backend source directory\r\n - [src/api/](src/api/): Client SDK that would be published to the `@ORGANIZATION/PROJECT-api`\r\n - [**src/api/functional/**](src/api/functional/): API functions generated by the [`nestia`](https://github.com/samchon/nestia)\r\n - [**src/api/structures/**](src/api/structures/): DTO structures\r\n - [src/controllers/](src/controllers/): Controller classes of the Main Program\r\n - [**test/**](test): Test Automation Program\r\n - [nestia.config.ts](nestia.config.ts): Configuration file of [`nestia`](https://github.com/samchon/nestia)\r\n - [package.json](package.json): NPM configuration\r\n - [tsconfig.json](tsconfig.json): TypeScript configuration for the main program\r\n - [tsconfig.api.json](tsconfig.api.json): TypeScript configuration for the SDK generation\r\n\r\n\r\n\r\n\r\n## NPM Run Commands\r\nList of the run commands defined in the [package.json](package.json) are like below:\r\n\r\n - `build`: Build everything\r\n - `build:api`: Build client SDK libray for the client developers\r\n - `build:main`: Build main program (`src` directory)\r\n - `build:sdk`: Build SDK into main program only\r\n - `build:swagger`: Build Swagger Documents\r\n - `build:test` Build test automation program (`test` directory)\r\n - `dev`: Incremental build for development (test program)\r\n - `eslint` & `eslint:fix` & `prettier`: Prettier and ESLint execution\r\n - `start`: Start local NestJS server\r\n - `test`: Run test automation program\r\n\r\n\r\n\r\n\r\n## Specialization\r\nTransform this template project to be yours.\r\n\r\nWhen you've created a new backend project through this template project, you can specialize it to be suitable for you by changing some words. Replace below words through IDE specific function like `Edit > Replace in Files` (*Ctrl + Shift + H*), who've been supported by the VSCode.\r\n\r\n| Before | After\r\n|-----------------|----------------------------------------\r\n| ORGANIZATION | Your account or corporation name\r\n| PROJECT | Your own project name\r\n| AUTHOR | Author name\r\n| https://github.com/samchon/nestia-start | Your repository URL\r\n\r\n\r\n\r\n\r\n## Test Driven Development\r\nWith [nestia](https://github.com/samchon/nestia) helps to accomplish TDD (Test Driven Development). \r\n\r\nJust define DTOs and API controllers' methods (only declarations) first. After the definitions, and build SDK (Software Development Kit) through [nestia](https://github.com/samchon/nestia) (`npm run build:sdk`). After buildling those SDK, develop test automation program using the SDK, following use-case scenarios in the framework of client side.\r\n\r\nDuring the test automation program development, you can find that which API is mis-designed or which requirement analysis is not exact. Development of the main program must be the last step after such validation process during TDD.\r\n\r\n> Visit the [samchon/backend](https://github.com/samchon/backend), then you may find much detailed story about this TDD.\r\n>\r\n> 1. Definitions\r\n> 2. SDK\r\n> 3. Test Automation Program\r\n> 4. Main Program\r\n\r\n```typescript\r\nimport
|
90
|
+
"content": "# Nestia Template\r\n## Outline\r\n[](https://github.com/samchon/nestia-start/actions?query=workflow%3Abuild)\r\n\r\nA template repository for backend projects using [nestia](https://github.com/samchon/nestia).\r\n\r\nYou can create a new project from this boilerplate by running below command:\r\n\r\n```bash\r\nnpx nestia start <directory>\r\n```\r\n\r\nFor reference, this is a minimal boilerplate project concentrating only on [nestia](https://github.com/samchon/nestia) SDK generation. \r\n\r\nIf you wanna much detailed boilerplate project, visit [`@samchon/backend`](https://github.com/samchon/backend).\r\n\r\n\r\n\r\n\r\n## Directories and Files\r\nThis template project has categorized directories like below.\r\n\r\nAs you can see from the below, all of the Backend source files are placed into the [src](src/) directory. When you build the TypeScript source files, compiled files would be placed into the `lib` directory following the [tsconfig.json](tsconfig.json) configuration. Otherwise you build client [SDK](#32-sdk) library for npm publishing and their compiled files would be placed into the [packages](packages) directory.\r\n\r\n - [packages/api/](packages/api): SDK module built by `npm run build:api`\r\n - [src/](src): Backend source directory\r\n - [src/api/](src/api/): Client SDK that would be published to the `@ORGANIZATION/PROJECT-api`\r\n - [**src/api/functional/**](src/api/functional/): API functions generated by the [`nestia`](https://github.com/samchon/nestia)\r\n - [**src/api/structures/**](src/api/structures/): DTO structures\r\n - [src/controllers/](src/controllers/): Controller classes of the Main Program\r\n - [**test/**](test): Test Automation Program\r\n - [nestia.config.ts](nestia.config.ts): Configuration file of [`nestia`](https://github.com/samchon/nestia)\r\n - [package.json](package.json): NPM configuration\r\n - [tsconfig.json](tsconfig.json): TypeScript configuration for the main program\r\n - [tsconfig.api.json](tsconfig.api.json): TypeScript configuration for the SDK generation\r\n\r\n\r\n\r\n\r\n## NPM Run Commands\r\nList of the run commands defined in the [package.json](package.json) are like below:\r\n\r\n - `build`: Build everything\r\n - `build:api`: Build client SDK libray for the client developers\r\n - `build:main`: Build main program (`src` directory)\r\n - `build:sdk`: Build SDK into main program only\r\n - `build:swagger`: Build Swagger Documents\r\n - `build:test` Build test automation program (`test` directory)\r\n - `dev`: Incremental build for development (test program)\r\n - `eslint` & `eslint:fix` & `prettier`: Prettier and ESLint execution\r\n - `start`: Start local NestJS server\r\n - `test`: Run test automation program\r\n - `benchmark`: Run performance benchmark program\r\n\r\n\r\n\r\n\r\n## Specialization\r\nTransform this template project to be yours.\r\n\r\nWhen you've created a new backend project through this template project, you can specialize it to be suitable for you by changing some words. Replace below words through IDE specific function like `Edit > Replace in Files` (*Ctrl + Shift + H*), who've been supported by the VSCode.\r\n\r\n| Before | After\r\n|-----------------|----------------------------------------\r\n| ORGANIZATION | Your account or corporation name\r\n| PROJECT | Your own project name\r\n| AUTHOR | Author name\r\n| https://github.com/samchon/nestia-start | Your repository URL\r\n\r\n\r\n\r\n\r\n## Test Driven Development\r\nWith [nestia](https://github.com/samchon/nestia) helps to accomplish TDD (Test Driven Development). \r\n\r\nJust define DTOs and API controllers' methods (only declarations) first. After the definitions, and build SDK (Software Development Kit) through [nestia](https://github.com/samchon/nestia) (`npm run build:sdk`). After buildling those SDK, develop test automation program using the SDK, following use-case scenarios in the framework of client side.\r\n\r\nDuring the test automation program development, you can find that which API is mis-designed or which requirement analysis is not exact. Development of the main program must be the last step after such validation process during TDD.\r\n\r\n> Visit the [samchon/backend](https://github.com/samchon/backend), then you may find much detailed story about this TDD.\r\n>\r\n> 1. Definitions\r\n> 2. SDK\r\n> 3. Test Automation Program\r\n> 4. Main Program\r\n\r\n```typescript\r\nimport {\r\n ArrayUtil,\r\n GaffComparator,\r\n RandomGenerator,\r\n TestValidator,\r\n} from \"@nestia/e2e\";\r\n\r\nimport api from \"@ORGANIZATION/PROJECT-api/lib/index\";\r\nimport { IBbsArticle } from \"@ORGANIZATION/PROJECT-api/lib/structures/bbs/IBbsArticle\";\r\nimport { IPage } from \"@ORGANIZATION/PROJECT-api/lib/structures/common/IPage\";\r\n\r\nexport async function test_api_bbs_article_index_sort(\r\n connection: api.IConnection,\r\n): Promise<void> {\r\n // GENERATE 100 ARTICLES\r\n const section: string = \"general\";\r\n await ArrayUtil.asyncRepeat(100)(() =>\r\n api.functional.bbs.articles.create(connection, section, {\r\n writer: RandomGenerator.name(),\r\n title: RandomGenerator.paragraph(5)(),\r\n body: RandomGenerator.content(8)()(),\r\n format: \"txt\",\r\n files: [],\r\n password: RandomGenerator.alphabets(8),\r\n }),\r\n );\r\n\r\n // PREPARE VALIDATOR\r\n const validator = TestValidator.sort(\"BbsArticleProvider.index()\")(async (\r\n sort: IPage.Sort<IBbsArticle.IRequest.SortableColumns>,\r\n ) => {\r\n const page: IPage<IBbsArticle.ISummary> =\r\n await api.functional.bbs.articles.index(connection, section, {\r\n limit: 100,\r\n sort,\r\n });\r\n return page.data;\r\n });\r\n\r\n // DO VALIDATE\r\n const components = [\r\n validator(\"created_at\")(GaffComparator.dates((x) => x.created_at)),\r\n validator(\"updated_at\")(GaffComparator.dates((x) => x.updated_at)),\r\n validator(\"title\")(GaffComparator.strings((x) => x.title)),\r\n validator(\"writer\")(GaffComparator.strings((x) => x.writer)),\r\n validator(\r\n \"writer\",\r\n \"title\",\r\n )(GaffComparator.strings((x) => [x.writer, x.title])),\r\n ];\r\n for (const comp of components) {\r\n await comp(\"+\", false);\r\n await comp(\"-\", false);\r\n }\r\n}\r\n```\r\n\r\nFor reference, if you run `npm run benchmark` command, your test functions defined in the [test/features/api](test/features/api) directory would be utilized for performance benchmarking. If you want to see the performance bench result earlier, visit below link please:\r\n\r\n - [docs/benchmarks/AMD Ryzen 9 7940HS w Radeon 780M Graphics.md](https://github.com/samchon/nestia-start/blob/master/docs/benchmarks/AMD%20Ryzen%209%207940HS%20w%20Radeon%20780M%20Graphics.md)"
|
86
91
|
},
|
87
92
|
{
|
88
93
|
"location": "src/api",
|
@@ -159,15 +164,25 @@ export const NEST_TEMPLATE = [
|
|
159
164
|
"file": "MapUtil.ts",
|
160
165
|
"content": "export namespace MapUtil {\r\n export function take<Key, T>(\r\n dict: Map<Key, T>,\r\n key: Key,\r\n generator: () => T,\r\n ): T {\r\n const oldbie: T | undefined = dict.get(key);\r\n if (oldbie) return oldbie;\r\n\r\n const value: T = generator();\r\n dict.set(key, value);\r\n return value;\r\n }\r\n}\r\n"
|
161
166
|
},
|
167
|
+
{
|
168
|
+
"location": "test/benchmark",
|
169
|
+
"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"
|
171
|
+
},
|
172
|
+
{
|
173
|
+
"location": "test/benchmark",
|
174
|
+
"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"
|
176
|
+
},
|
162
177
|
{
|
163
178
|
"location": "test/helpers",
|
164
179
|
"file": "ArgumentParser.ts",
|
165
|
-
"content": "import commander from \"commander\";\r\nimport * as inquirer from \"inquirer\";\r\n\r\nexport namespace ArgumentParser {\r\n export type Inquiry<T> = (\r\n command: commander.Command,\r\n prompt: (opt?: inquirer.StreamOptions) => inquirer.PromptModule,\r\n action: (closure: (options: Partial<T>) => Promise<T>) => Promise<T>,\r\n ) => Promise<T>;\r\n\r\n export interface Prompt {\r\n select: (\r\n name: string,\r\n ) => (\r\n message: string,\r\n ) => <Choice extends string>(choices: Choice[]) => Promise<Choice>;\r\n boolean: (name: string) => (message: string) => Promise<boolean>;\r\n }\r\n\r\n export const parse = async <T>(\r\n inquiry: (\r\n command: commander.Command,\r\n prompt: Prompt,\r\n action: (closure: (options: Partial<T>) => Promise<T>) => Promise<T>,\r\n ) => Promise<T>,\r\n ): Promise<T> => {\r\n // TAKE OPTIONS\r\n const action = (closure: (options: Partial<T>) => Promise<T>) =>\r\n new Promise<T>((resolve, reject) => {\r\n commander.program.action(async (options) => {\r\n try {\r\n resolve(await closure(options));\r\n } catch (exp) {\r\n reject(exp);\r\n }\r\n });\r\n commander.program.parseAsync().catch(reject);\r\n });\r\n\r\n const select =\r\n (name: string) =>\r\n (message: string) =>\r\n async <Choice extends string>(choices: Choice[]): Promise<Choice> =>\r\n (\r\n await inquirer.createPromptModule()({\r\n type: \"list\",\r\n name,\r\n message,\r\n choices,\r\n })\r\n )[name];\r\n const boolean = (name: string) => async (message: string) =>\r\n (\r\n await inquirer.createPromptModule()({\r\n type: \"confirm\",\r\n name,\r\n message,\r\n })\r\n )[name] as boolean;\r\n\r\n const output: T | Error = await (async () => {\r\n try {\r\n return await inquiry(commander.program
|
180
|
+
"content": "import commander from \"commander\";\r\nimport * as inquirer from \"inquirer\";\r\n\r\nexport namespace ArgumentParser {\r\n export type Inquiry<T> = (\r\n command: commander.Command,\r\n prompt: (opt?: inquirer.StreamOptions) => inquirer.PromptModule,\r\n action: (closure: (options: Partial<T>) => Promise<T>) => Promise<T>,\r\n ) => Promise<T>;\r\n\r\n export interface Prompt {\r\n select: (\r\n name: string,\r\n ) => (\r\n message: string,\r\n ) => <Choice extends string>(choices: Choice[]) => Promise<Choice>;\r\n boolean: (name: string) => (message: string) => Promise<boolean>;\r\n number: (name: string) => (message: string) => Promise<number>;\r\n }\r\n\r\n export const parse = async <T>(\r\n inquiry: (\r\n command: commander.Command,\r\n prompt: Prompt,\r\n action: (closure: (options: Partial<T>) => Promise<T>) => Promise<T>,\r\n ) => Promise<T>,\r\n ): Promise<T> => {\r\n // TAKE OPTIONS\r\n const action = (closure: (options: Partial<T>) => Promise<T>) =>\r\n new Promise<T>((resolve, reject) => {\r\n commander.program.action(async (options) => {\r\n try {\r\n resolve(await closure(options));\r\n } catch (exp) {\r\n reject(exp);\r\n }\r\n });\r\n commander.program.parseAsync().catch(reject);\r\n });\r\n\r\n const select =\r\n (name: string) =>\r\n (message: string) =>\r\n async <Choice extends string>(choices: Choice[]): Promise<Choice> =>\r\n (\r\n await inquirer.createPromptModule()({\r\n type: \"list\",\r\n name,\r\n message,\r\n choices,\r\n })\r\n )[name];\r\n const boolean = (name: string) => async (message: string) =>\r\n (\r\n await inquirer.createPromptModule()({\r\n type: \"confirm\",\r\n name,\r\n message,\r\n })\r\n )[name] as boolean;\r\n const number = (name: string) => async (message: string) =>\r\n Number(\r\n (\r\n await inquirer.createPromptModule()({\r\n type: \"number\",\r\n name,\r\n message,\r\n })\r\n )[name],\r\n );\r\n\r\n const output: T | Error = await (async () => {\r\n try {\r\n return await inquiry(\r\n commander.program,\r\n { select, boolean, number },\r\n action,\r\n );\r\n } catch (error) {\r\n return error as Error;\r\n }\r\n })();\r\n\r\n // RETURNS\r\n if (output instanceof Error) throw output;\r\n return output;\r\n };\r\n}\r\n"
|
166
181
|
},
|
167
182
|
{
|
168
183
|
"location": "test",
|
169
184
|
"file": "index.ts",
|
170
|
-
"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,
|
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"
|
171
186
|
},
|
172
187
|
{
|
173
188
|
"location": "test",
|
@@ -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.2.1\",\r\n \"typia\": \"^6.1
|
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.2.5\",\r\n \"tgrid\": \"^1.0.1\",\r\n \"typia\": \"^6.2.1\"\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.0\",\r\n \"typescript\": \"<5.5.0\",\r\n \"typescript-transform-paths\": \"^3.4.6\"\r\n }\r\n}"
|
31
31
|
},
|
32
32
|
{
|
33
33
|
"location": "",
|
package/src/utils/StringUtil.ts
CHANGED
@@ -61,10 +61,11 @@ export namespace StringUtil {
|
|
61
61
|
export const escapeNonVariableSymbols = (str: string): string => {
|
62
62
|
for (const [before, after] of VARIABLE_REPLACERS)
|
63
63
|
str = str.split(before).join(after);
|
64
|
-
for (let i: number = 0; i <= 9; ++i)
|
65
|
-
str
|
66
|
-
|
67
|
-
|
64
|
+
for (let i: number = 0; i <= 9; ++i)
|
65
|
+
if (str[0] === i.toString()) {
|
66
|
+
str = "_" + str;
|
67
|
+
break;
|
68
|
+
}
|
68
69
|
str = str.trim();
|
69
70
|
if (str === "") return "_empty_";
|
70
71
|
return str;
|